changeset 10793:34709091de6d

6886081 Solaris needs reparse point support (PSARC 2009/387) PSARC 2009/387 Pathname Reparse Points
author Dai Ngo <dai.ngo@sun.com>
date Wed, 14 Oct 2009 11:15:07 -0500
parents 809cb9af791e
children 59136e704f5c
files usr/src/Makefile.lint usr/src/cmd/fs.d/Makefile usr/src/cmd/fs.d/reparsed/Makefile usr/src/cmd/fs.d/reparsed/reparsed.c usr/src/cmd/fs.d/reparsed/reparsed.xml usr/src/common/fsreparse/fs_reparse.c usr/src/common/xattr/xattr_common.c usr/src/lib/Makefile usr/src/lib/libreparse/Makefile usr/src/lib/libreparse/Makefile.com usr/src/lib/libreparse/amd64/Makefile usr/src/lib/libreparse/common/fs_reparse_lib.c usr/src/lib/libreparse/common/llib-lreparse usr/src/lib/libreparse/common/mapfile-vers usr/src/lib/libreparse/common/rp_plugin.h usr/src/lib/libreparse/i386/Makefile usr/src/lib/libreparse/sparc/Makefile usr/src/lib/libreparse/sparcv9/Makefile usr/src/lib/libsecdb/auth_attr.txt usr/src/lib/libsecdb/help/auths/Makefile usr/src/lib/libsecdb/help/auths/SmfReparseStates.html usr/src/lib/libsecdb/help/profiles/Makefile usr/src/lib/libsecdb/help/profiles/RtReparseMngmnt.html usr/src/lib/libsecdb/prof_attr.txt usr/src/lib/libzpool/common/sys/zfs_context.h usr/src/pkgdefs/SUNW0on/prototype_com usr/src/pkgdefs/SUNWarc/prototype_com usr/src/pkgdefs/SUNWarc/prototype_i386 usr/src/pkgdefs/SUNWarc/prototype_sparc usr/src/pkgdefs/SUNWcsl/prototype_com usr/src/pkgdefs/SUNWcsl/prototype_i386 usr/src/pkgdefs/SUNWcsl/prototype_sparc usr/src/pkgdefs/SUNWcsr/prototype_com usr/src/pkgdefs/SUNWcsu/prototype_com usr/src/pkgdefs/SUNWhea/prototype_com usr/src/uts/common/Makefile.files usr/src/uts/common/Makefile.rules usr/src/uts/common/fs/Makefile usr/src/uts/common/fs/fs_reparse.h usr/src/uts/common/fs/fs_subr.c usr/src/uts/common/fs/vfs.c usr/src/uts/common/fs/vnode.c usr/src/uts/common/fs/xattr.c usr/src/uts/common/fs/zfs/sys/zfs_znode.h usr/src/uts/common/fs/zfs/zfs_log.c usr/src/uts/common/fs/zfs/zfs_replay.c usr/src/uts/common/fs/zfs/zfs_vfsops.c usr/src/uts/common/fs/zfs/zfs_vnops.c usr/src/uts/common/fs/zfs/zfs_znode.c usr/src/uts/common/fs/zut/zut.c usr/src/uts/common/sys/attr.h usr/src/uts/common/sys/vfs.h usr/src/uts/common/sys/vnode.h
diffstat 53 files changed, 2192 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/Makefile.lint	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/Makefile.lint	Wed Oct 14 11:15:07 2009 -0500
@@ -405,6 +405,7 @@
 	lib/libraidcfg \
 	lib/librcm \
 	lib/librdc \
+	lib/libreparse \
 	lib/librestart \
 	lib/librstp \
 	lib/librt \
--- a/usr/src/cmd/fs.d/Makefile	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/cmd/fs.d/Makefile	Wed Oct 14 11:15:07 2009 -0500
@@ -43,7 +43,7 @@
 
 SUBDIR1= lofs zfs
 SUBDIR2= dev fd pcfs nfs hsfs proc ctfs udfs ufs tmpfs cachefs \
-		autofs mntfs objfs sharefs smbclnt
+		autofs mntfs objfs sharefs smbclnt reparsed
 SUBDIRS= $(SUBDIR1) $(SUBDIR2)
 I18NDIRS= $(SUBDIR2)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fs.d/reparsed/Makefile	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,60 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#
+include		$(SRC)/Makefile.master
+
+FSTYPE=		reparse
+TYPEPROG=	reparsed
+
+include		../Makefile.fstype
+
+OBJS=		$(TYPEPROG).o
+SRCS=		$(TYPEPROG).c
+POFILE=		$(TYPEPROG).po
+
+CLOBBERFILES += $(TYPEPROG)
+
+CFLAGS +=	$(CCVERBOSE)
+C99MODE=	$(C99_ENABLE)
+
+LDLIBS +=	-lreparse -lnsl
+
+CPPFLAGS +=	-I$(SRC)/uts/common
+
+all:		$(TYPEPROG)
+
+catalog:	$(POFILE)
+
+lint:		lint_SRCS
+
+clean:
+		$(RM) $(OBJS) $(POFILE)
+
+MANIFEST=	reparsed.xml
+ROOTMANIFESTDIR=	$(ROOTSVCNETWORKSHARES)
+$(ROOTMANIFEST) := FILEMODE = 0444
+install:	$(ROOTMANIFEST)
+
+.KEEP_STATE:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fs.d/reparsed/reparsed.c	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,358 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Reparsed daemon
+ */
+
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <memory.h>
+#include <alloca.h>
+#include <ucontext.h>
+#include <errno.h>
+#include <syslog.h>
+#include <string.h>
+#include <strings.h>
+#include <door.h>
+#include <wait.h>
+#include <libintl.h>
+#include <locale.h>
+#include <sys/param.h>
+#include <sys/systeminfo.h>
+#include <sys/thread.h>
+#include <rpc/xdr.h>
+#include <priv.h>
+#include <sys/fs_reparse.h>
+#include <priv_utils.h>
+#include <rpcsvc/daemon_utils.h>
+
+#define	REPARSED_CMD_OPTS	"v"
+#define	DOOR_RESULT_BUFSZ	(MAXPATHLEN + sizeof (reparsed_door_res_t))
+#define	SAFETY_BUFFER		8*1024
+
+static char *MyName;
+static int verbose = 0;
+
+static int start_reparsed_svcs();
+static void daemonize(void);
+static void reparsed_door_call_error(int error, int buflen);
+static void reparsed_doorfunc(void *cookie, char *argp, size_t arg_size,
+			door_desc_t *dp, uint_t n_desc);
+
+static void
+usage()
+{
+	syslog(LOG_ERR, "Usage: %s", MyName);
+	syslog(LOG_ERR, "\t[-v]\t\tverbose error messages)");
+	exit(1);
+}
+
+static void
+warn_hup(int i)
+{
+	syslog(LOG_ERR, "SIGHUP received: ignored");
+	(void) signal(SIGHUP, warn_hup);
+}
+
+/*
+ * Processing for daemonization
+ */
+static void
+daemonize(void)
+{
+	switch (fork()) {
+	case -1:
+		syslog(LOG_ERR, "reparsed: can't fork - errno %d", errno);
+		exit(2);
+		/* NOTREACHED */
+	case 0:		/* child */
+		break;
+
+	default:	/* parent */
+		_exit(0);
+	}
+	(void) chdir("/");
+
+	/*
+	 * Close stdin, stdout, and stderr.
+	 * Open again to redirect input+output
+	 */
+	(void) close(0);
+	(void) close(1);
+	(void) close(2);
+	(void) open("/dev/null", O_RDONLY);
+	(void) open("/dev/null", O_WRONLY);
+	(void) dup(1);
+	(void) setsid();
+}
+
+int
+main(int argc, char *argv[])
+{
+	pid_t pid;
+	int c, error;
+	struct rlimit rlset;
+	char *defval;
+
+	/*
+	 * There is no check for non-global zone and Trusted Extensions.
+	 * Reparsed works in both of these environments as long as the
+	 * services that use reparsed are supported.
+	 */
+
+	MyName = argv[0];
+	if (geteuid() != 0) {
+		syslog(LOG_ERR, "%s must be run as root", MyName);
+		exit(1);
+	}
+
+	while ((c = getopt(argc, argv, REPARSED_CMD_OPTS)) != EOF) {
+		switch (c) {
+		case 'v':
+			verbose++;
+			break;
+		default:
+			usage();
+		}
+	}
+
+	daemonize();
+	openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON);
+
+	(void) _create_daemon_lock(REPARSED, DAEMON_UID, DAEMON_GID);
+	(void) enable_extended_FILE_stdio(-1, -1);
+	switch (_enter_daemon_lock(REPARSED)) {
+	case 0:
+		break;
+	case -1:
+		syslog(LOG_ERR, "Error locking for %s", REPARSED);
+		exit(2);
+	default:
+		/* daemon was already running */
+		exit(0);
+	}
+
+	(void) signal(SIGHUP, warn_hup);
+
+	/*
+	 * Make the process a privilege aware daemon.
+	 * Only "basic" privileges are required.
+	 *
+	 */
+	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 0, 0,
+	    (char *)NULL) == -1) {
+		syslog(LOG_ERR, "should be run with sufficient privileges");
+		exit(3);
+	}
+
+	/*
+	 * Clear basic privileges not required by reparsed.
+	 */
+	__fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION,
+	    PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL);
+
+	return (start_reparsed_svcs());
+}
+
+static void
+reparsed_door_call_error(int error, int buflen)
+{
+	reparsed_door_res_t rpd_res;
+
+	memset(&rpd_res, 0, sizeof (reparsed_door_res_t));
+	rpd_res.res_status = error;
+	rpd_res.res_len = buflen;
+	door_return((char *)&rpd_res, sizeof (reparsed_door_res_t), NULL, 0);
+
+	(void) door_return(NULL, 0, NULL, 0);
+	/* NOTREACHED */
+}
+
+/*
+ *  reparsed_doorfunc
+ *
+ *  argp:  "service_type:service_data" string
+ *  dp & n_desc: not used.
+ */
+static void
+reparsed_doorfunc(void *cookie, char *argp, size_t arg_size,
+    door_desc_t *dp, uint_t n_desc)
+{
+	int err;
+	size_t bufsz;
+	char *svc_type, *svc_data;
+	char *cp, *buf, *sbuf, res_buf[DOOR_RESULT_BUFSZ];
+	reparsed_door_res_t *resp;
+
+	if ((argp == NULL) || (arg_size == 0)) {
+		reparsed_door_call_error(EINVAL, 0);
+		/* NOTREACHED */
+	}
+
+	if (verbose)
+		syslog(LOG_NOTICE, "reparsed_door: [%s, %d]", argp, arg_size);
+
+	if ((svc_type = strdup(argp)) == NULL) {
+		reparsed_door_call_error(ENOMEM, 0);
+		/* NOTREACHED */
+	}
+
+	/*
+	 * Door argument string comes in "service_type:service_data" format.
+	 * Need to break it into separate "service_type" and "service_data"
+	 * string before passing them to reparse_deref() to process them.
+	 */
+	if ((cp = strchr(svc_type, ':')) == NULL) {
+		free(svc_type);
+		reparsed_door_call_error(EINVAL, 0);
+		/* NOTREACHED */
+	}
+	*cp++ = '\0';
+	svc_data = cp;
+
+	/*
+	 * Setup buffer for reparse_deref(). 'bufsz' is the actual
+	 * buffer size to hold the result returned by reparse_deref().
+	 */
+	resp = (reparsed_door_res_t *)res_buf;
+	buf = resp->res_data;
+	bufsz = sizeof (res_buf) - sizeof (reparsed_door_res_t);
+
+	/*
+	 * reparse_deref() calls the service type plugin library to process
+	 * the service data. The plugin library function should understand
+	 * the context of the service data and should be the one to XDR the
+	 * results before returning it to the caller.
+	 */
+	err = reparse_deref(svc_type, svc_data, buf, &bufsz);
+
+	if (verbose)
+		syslog(LOG_NOTICE,
+		    "reparsed_deref(svc_type: %s, data: %s, size: %d) -> %d",
+		    svc_type, svc_data, bufsz, err);
+
+	switch (err) {
+	case 0:
+		break;
+
+	case EOVERFLOW:
+		/*
+		 * bufsz was returned with size needed by reparse_deref().
+		 *
+		 * We cannot use malloc() here because door_return() never
+		 * returns, and memory allocated by malloc() would get leaked.
+		 */
+		sbuf = alloca(bufsz + sizeof (reparsed_door_res_t));
+		if (sbuf == NULL || stack_inbounds(buf) == 0 ||
+		    stack_inbounds(buf + sizeof (reparsed_door_res_t) +
+		    SAFETY_BUFFER - 1) == 0) {
+			free(svc_type);
+			reparsed_door_call_error(ENOMEM, 0);
+			/* NOTREACHED */
+		}
+
+		resp = (reparsed_door_res_t *)sbuf;
+		if ((err = reparse_deref(svc_type, svc_data, resp->res_data,
+		    &bufsz)) == 0)
+			break;
+
+		/* fall through */
+
+	default:
+		free(svc_type);
+		reparsed_door_call_error(err, 0);
+		/* NOTREACHED */
+	}
+
+	free(svc_type);
+
+	if (verbose)
+		syslog(LOG_NOTICE, "reparsed_door_return <buf=%s> size=%d",
+		    buf, bufsz);
+
+	resp->res_status = 0;
+	resp->res_len = bufsz;
+	(void) door_return((char *)resp, bufsz + sizeof (reparsed_door_res_t),
+	    NULL, 0);
+
+	(void) door_return(NULL, 0, NULL, 0);
+	/* NOTREACHED */
+}
+
+static int
+start_reparsed_svcs()
+{
+	int doorfd;
+	int dfd;
+
+	if ((doorfd = door_create(reparsed_doorfunc, NULL,
+	    DOOR_REFUSE_DESC|DOOR_NO_CANCEL)) == -1) {
+		syslog(LOG_ERR, "Unable to create door");
+		return (1);
+	}
+
+	/*
+	 * Create a file system path for the door
+	 */
+	if ((dfd = open(REPARSED_DOOR, O_RDWR|O_CREAT|O_TRUNC,
+	    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) {
+		syslog(LOG_ERR, "unable to open %s", REPARSED_DOOR);
+		(void) close(doorfd);
+		return (1);
+	}
+
+	/*
+	 * Clean up any stale associations
+	 */
+	(void) fdetach(REPARSED_DOOR);
+
+	/*
+	 * Register in the kernel namespace for door_ki_open().
+	 */
+	if (fattach(doorfd, REPARSED_DOOR) == -1) {
+		syslog(LOG_ERR, "Unable to fattach door %s", REPARSED_DOOR);
+		(void) close(doorfd);
+		(void) close(dfd);
+		return (1);
+	}
+	(void) close(dfd);
+
+	/*
+	 * Wait for incoming calls
+	 */
+	/*CONSTCOND*/
+	while (1)
+		(void) pause();
+
+	syslog(LOG_ERR, "Door server exited");
+	return (10);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/fs.d/reparsed/reparsed.xml	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,108 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+ Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+	NOTE:  This service manifest is not editable; its contents will
+	be overwritten by package or patch operations, including
+	operating system upgrade.  Make customizations in a different
+	file.
+
+	Note: if this service is modified to consist of anything other
+	than a single instance named 'default', you must make changes to
+	$SRC/head/rpcsvc/daemon_utils.h and libnsl:open_daemon_lock().
+-->
+
+<service_bundle type='manifest' name='SUNWcsr:reparse'>
+
+<service
+	name='system/filesystem/reparse'
+	type='service'
+	version='1'>
+
+	<create_default_instance enabled='false' />
+
+	<single_instance />
+
+	<dependency name='network'
+	    grouping='require_any'
+	    restart_on='error'
+	    type='service'>
+		<service_fmri value='svc:/milestone/network' />
+	</dependency>
+
+	<dependency name='name-services'
+	    grouping='require_all'
+	    restart_on='refresh'
+	    type='service'>
+		<service_fmri value='svc:/milestone/name-services' />
+	</dependency>
+
+	<dependency name='filesystem-minimal'
+	    grouping='require_all'
+	    restart_on='error'
+	    type='service'>
+	    	<service_fmri value='svc:/system/filesystem/minimal' />
+	</dependency>
+
+	<exec_method
+	    type='method'
+	    name='start'
+	    exec='/usr/lib/reparse/reparsed'
+	    timeout_seconds='60' />
+
+	<exec_method
+	    type='method'
+	    name='stop'
+	    exec=':kill'
+	    timeout_seconds='60' />
+
+	<property_group name='general' type='framework'>
+		<!-- to start stop reparse service -->
+		<propval name='action_authorization' type='astring'
+			value='solaris.smf.manage.reparse' />
+		<propval name='value_authorization' type='astring'
+			value='solaris.smf.manage.reparse' />
+	</property_group>
+
+	<property_group name='application' type='framework'>
+		<stability value='Evolving' />
+		<propval name='auto_enable' type='boolean' value='true' />
+	</property_group>
+
+	<stability value='Stable' />
+
+	<template>
+		<common_name>
+			<loctext xml:lang='C'>
+				Reparse Point daemon
+			</loctext>
+		</common_name>
+		<documentation>
+			<manpage title='reparsed' section='1M'
+				manpath='/usr/share/man' />
+		</documentation>
+	</template>
+</service>
+
+</service_bundle>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/fsreparse/fs_reparse.c	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,328 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+
+#ifdef _KERNEL
+#include <sys/sunddi.h>
+#include <fs/fs_reparse.h>
+#else
+#include <string.h>
+#include <limits.h>
+#include <sys/fs_reparse.h>
+
+#define	strfree(str)		free((str))
+#endif
+
+static char *reparse_skipspace(char *cp);
+static int reparse_create_nvlist(const char *string, nvlist_t *nvl);
+static int reparse_add_nvpair(char *token, nvlist_t *nvl);
+static boolean_t reparse_validate_svctype(char *svc_str);
+static int reparse_validate_create_nvlist(const char *string, nvlist_t *nvl);
+
+/* array of characters not allowed in service type string */
+static char svctype_invalid_chars[] = { '{', '}', 0 };
+
+/*
+ * reparse_init()
+ *
+ * Function to allocate a new name-value pair list.
+ * Caller needs to call reparse_free() to free memory
+ * used by the list when done.
+ *
+ * Return pointer to new list else return NULL.
+ */
+nvlist_t *
+reparse_init(void)
+{
+	nvlist_t *nvl;
+
+	/*
+	 * Service type is unique, only one entry
+	 * of each service type is allowed
+	 */
+	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0))
+		return (NULL);
+
+	return (nvl);
+}
+
+/*
+ * reparse_free()
+ *
+ * Function to free memory of a nvlist allocated previously
+ * by reparse_init().
+ */
+void
+reparse_free(nvlist_t *nvl)
+{
+	if (nvl)
+		nvlist_free(nvl);
+}
+
+/*
+ * reparse_parse()
+ *
+ * Parse the specified string and populate the nvlist with the svc_types
+ * and data from the 'string'.  The string could be read from the reparse
+ * point symlink body. This routine will allocate memory that must be
+ * freed by reparse_free().
+ *
+ * If ok return 0 and the nvlist is populated, otherwise return error code.
+ */
+int
+reparse_parse(const char *string, nvlist_t *nvl)
+{
+	int err;
+
+	if (string == NULL || nvl == NULL)
+		return (EINVAL);
+
+	if ((err = reparse_validate(string)) != 0)
+		return (err);
+
+	if ((err = reparse_create_nvlist(string, nvl)) != 0)
+		return (err);
+
+	return (0);
+}
+
+static char *
+reparse_skipspace(char *cp)
+{
+	while ((*cp) && (*cp == ' ' || *cp == '\t'))
+		cp++;
+	return (cp);
+}
+
+static boolean_t
+reparse_validate_svctype(char *svc_str)
+{
+	int nx, ix, len;
+
+	if (svc_str == NULL)
+		return (B_FALSE);
+
+	len = strlen(svc_str);
+	for (ix = 0; ix < len; ix++) {
+		for (nx = 0; nx < sizeof (svctype_invalid_chars); nx++) {
+			if (svc_str[ix] == svctype_invalid_chars[nx])
+				return (B_FALSE);
+		}
+	}
+	return (B_TRUE);
+}
+
+static boolean_t
+reparse_validate_svc_token(char *svc_token)
+{
+	char save_c, *cp;
+
+	if (svc_token == NULL)
+		return (B_FALSE);
+	if ((cp = strchr(svc_token, ':')) == NULL)
+		return (B_FALSE);
+
+	save_c = *cp;
+	*cp = '\0';
+
+	/*
+	 * make sure service type and service data are non-empty string.
+	 */
+	if (strlen(svc_token) == 0 || strlen(cp + 1) == 0) {
+		*cp = save_c;
+		return (B_FALSE);
+	}
+
+	*cp = save_c;
+	return (B_TRUE);
+}
+
+/*
+ * Format of reparse data:
+ * @{REPARSE@{servicetype:data} [@{servicetype:data}] ...}
+ * REPARSE_TAG_STR@{REPARSE_TOKEN} [@{REPARSE_TOKEN}] ... REPARSE_TAG_END
+ *
+ * Validating reparse data:
+ *	. check for valid length of reparse data
+ *	. check for valid reparse data format
+ * Return 0 if OK else return error code.
+ */
+int
+reparse_validate(const char *string)
+{
+	return (reparse_validate_create_nvlist(string, NULL));
+}
+
+/*
+ * reparse_validate_create_nvlist
+ *
+ * dual-purpose function:
+ *     . Validate a reparse data string.
+ *     . Validate a reparse data string and parse the data
+ *	 into a nvlist.
+ */
+static int
+reparse_validate_create_nvlist(const char *string, nvlist_t *nvl)
+{
+	int err, tcnt;
+	char *reparse_data, save_c, save_e, *save_e_ptr, *cp, *s_str, *e_str;
+
+	if (string == NULL)
+		return (EINVAL);
+
+	if (strlen(string) >= MAXREPARSELEN)
+		return (ENAMETOOLONG);
+
+	if ((reparse_data = strdup(string)) == NULL)
+		return (ENOMEM);
+
+	/* check FS_REPARSE_TAG_STR */
+	if (strncmp(reparse_data, FS_REPARSE_TAG_STR,
+	    strlen(FS_REPARSE_TAG_STR))) {
+		strfree(reparse_data);
+		return (EINVAL);
+	}
+
+	/* locate FS_REPARSE_TAG_END_CHAR */
+	if ((cp = strrchr(reparse_data, FS_REPARSE_TAG_END_CHAR)) == NULL) {
+		strfree(reparse_data);
+		return (EINVAL);
+	}
+	save_e = *cp;
+	save_e_ptr = cp;
+	*cp = '\0';
+
+	e_str = cp;
+	cp++;		/* should point to NULL, or spaces */
+
+	cp = reparse_skipspace(cp);
+	if (*cp) {
+		*save_e_ptr = save_e;
+		strfree(reparse_data);
+		return (EINVAL);
+	}
+
+	/* skip FS_REPARSE_TAG_STR */
+	s_str = reparse_data + strlen(FS_REPARSE_TAG_STR);
+
+	/* skip spaces after FS_REPARSE_TAG_STR */
+	s_str = reparse_skipspace(s_str);
+
+	tcnt = 0;
+	while (s_str < e_str) {
+		/* check FS_TOKEN_START_STR */
+		if (strncmp(s_str, FS_TOKEN_START_STR,
+		    strlen(FS_TOKEN_START_STR))) {
+			*save_e_ptr = save_e;
+			strfree(reparse_data);
+			return (EINVAL);
+		}
+
+		/* skip over FS_TOKEN_START_STR */
+		s_str += strlen(FS_TOKEN_START_STR);
+
+		/* locate FS_TOKEN_END_STR */
+		if ((cp = strstr(s_str, FS_TOKEN_END_STR)) == NULL) {
+			*save_e_ptr = save_e;
+			strfree(reparse_data);
+			return (EINVAL);
+		}
+
+		tcnt++;
+		save_c = *cp;
+		*cp = '\0';
+
+		/* check for valid characters in service type */
+		if (reparse_validate_svctype(s_str) == B_FALSE) {
+			*cp = save_c;
+			*save_e_ptr = save_e;
+			strfree(reparse_data);
+			return (EINVAL);
+		}
+
+		if (strlen(s_str) == 0) {
+			*cp = save_c;
+			*save_e_ptr = save_e;
+			strfree(reparse_data);
+			return (EINVAL);
+		}
+
+		if (reparse_validate_svc_token(s_str) == B_FALSE) {
+			*cp = save_c;
+			*save_e_ptr = save_e;
+			strfree(reparse_data);
+			return (EINVAL);
+		}
+
+		/* create a nvpair entry */
+		if (nvl != NULL &&
+		    (err = reparse_add_nvpair(s_str, nvl)) != 0) {
+			*cp = save_c;
+			*save_e_ptr = save_e;
+			strfree(reparse_data);
+			return (err);
+		}
+
+		*cp = save_c;
+
+		/* skip over FS_TOKEN_END_STR */
+		cp += strlen(FS_TOKEN_END_STR);
+		cp = reparse_skipspace(cp);
+		s_str = cp;
+	}
+	*save_e_ptr = save_e;
+	strfree(reparse_data);
+
+	return (tcnt ? 0 : EINVAL);
+}
+
+static int
+reparse_add_nvpair(char *token, nvlist_t *nvl)
+{
+	int err;
+	char save_c, *cp;
+
+	if ((cp = strchr(token, ':')) == NULL)
+		return (EINVAL);
+
+	save_c = *cp;
+	*cp = '\0';
+	err = nvlist_add_string(nvl, token, cp + 1);
+	*cp = save_c;
+
+	return (err);
+}
+
+static int
+reparse_create_nvlist(const char *string, nvlist_t *nvl)
+{
+	if (nvl == NULL)
+		return (EINVAL);
+
+	return (reparse_validate_create_nvlist(string, nvl));
+}
--- a/usr/src/common/xattr/xattr_common.c	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/common/xattr/xattr_common.c	Wed Oct 14 11:15:07 2009 -0500
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/attr.h>
 #if defined(_KERNEL)
 #include <sys/systm.h>
@@ -63,6 +61,8 @@
 	{ A_OWNERSID, O_NONE, XATTR_VIEW_READWRITE, DATA_TYPE_NVLIST },
 	{ A_GROUPSID, O_NONE, XATTR_VIEW_READWRITE, DATA_TYPE_NVLIST },
 	{ A_FSID, O_NONE, XATTR_VIEW_READONLY, DATA_TYPE_UINT64 },
+	{ A_REPARSE_POINT, O_REPARSE_POINT, XATTR_VIEW_READONLY,
+	    DATA_TYPE_BOOLEAN_VALUE },
 };
 
 const char *
--- a/usr/src/lib/Makefile	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/lib/Makefile	Wed Oct 14 11:15:07 2009 -0500
@@ -261,6 +261,7 @@
 	libsun_ima	\
 	mpapi		\
 	librstp		\
+	libreparse	\
 	$($(MACH)_SUBDIRS)
 
 i386_SUBDIRS=		\
@@ -359,7 +360,8 @@
 	mpss		\
 	pam_modules	\
 	pyzfs		\
-	rpcsec_gss
+	rpcsec_gss	\
+	libreparse
 MSGSUBDIRS += \
 	$($(MACH)_MSGSUBDIRS)
 
@@ -491,6 +493,7 @@
 	libsun_ima	\
 	mpapi		\
 	mms		\
+	libreparse	\
 	$($(MACH)_HDRSUBDIRS)
 
 $(CLOSED_BUILD)HDRSUBDIRS += \
@@ -637,6 +640,7 @@
 mpapi:		libpthread libdevinfo libsysevent libnvpair
 libgrubmgmt:	libdevinfo libzfs libfstyp
 pyzfs:		libnvpair libsec libidmap libzfs
+libreparse:	libnvpair
 
 #
 # The reason this rule checks for the existence of the
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libreparse/Makefile	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,60 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.lib
+
+HDRS=		rp_plugin.h
+HDRDIR=		common
+
+SUBDIRS=		$(MACH)
+$(BUILD64)SUBDIRS +=	$(MACH64)
+POFILE=		libreparse.po
+MSGFILES=	common/fs_reparse_lib.c
+
+all :=		TARGET = all
+clean :=	TARGET = clean
+clobber :=	TARGET = clobber
+install :=	TARGET = install
+lint :=		TARGET = lint
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+install_h:	$(ROOTHDRS)
+
+check:		$(CHECKHDRS)
+
+$(POFILE):	pofile_MSGFILES
+
+_msg:		$(MSGDOMAINPOFILE)
+
+$(SUBDIRS): FRC
+	@cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include $(SRC)/lib/Makefile.targ
+include $(SRC)/Makefile.msg.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libreparse/Makefile.com	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,57 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+LIBRARY=	libreparse.a
+VERS=		.1
+
+LOCOBJS =	fs_reparse_lib.o
+COMOBJS =	fs_reparse.o
+OBJECTS =	$(LOCOBJS) $(COMOBJS)
+COMDIR =	$(SRC)/common/fsreparse
+
+include ../../Makefile.lib
+
+SRCDIR =	../common
+SRCS =		$(LOCOBJS:%.o=$(SRCDIR)/%.c) $(COMOBJS:%.o=$(COMDIR)/%.c)
+
+LIBS =		$(DYNLIB) $(LINTLIB)
+LDLIBS += 	-lc -lnvpair
+
+CFLAGS +=	$(CCVERBOSE)
+CPPFLAGS +=	-I$(COMDIR) -D_FILE_OFFSET_BITS=64
+
+$(LINTLIB) :=	SRCS = $(SRCDIR)/$(LINTSRC)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+include ../../Makefile.targ
+
+pics/%.o: $(COMDIR)/%.c
+	$(COMPILE.c) -o $@ $<
+	$(POST_PROCESS_O)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libreparse/amd64/Makefile	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libreparse/common/fs_reparse_lib.c	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,437 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <strings.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <limits.h>
+#include <libnvpair.h>
+#include <dlfcn.h>
+#include <libintl.h>
+#include <sys/systeminfo.h>
+#include <sys/fs_reparse.h>
+#include "rp_plugin.h"
+
+#define	MAXISALEN	257	/* based on sysinfo(2) man page */
+
+static rp_proto_handle_t rp_proto_handle;
+static rp_proto_plugin_t *rp_proto_list;
+
+int rp_plugin_init(void);
+static void proto_plugin_fini(void);
+static rp_plugin_ops_t *rp_find_protocol(const char *svctype);
+
+extern int errno;
+static int rp_plugin_inited = 0;
+
+/*
+ * reparse_create()
+ *
+ * Create a symlink at the specified 'path' as a reparse point.
+ * This function will fail if path refers to an existing file system
+ * object or an object named string already exists at the given path.
+ *
+ * return 0 if ok else return error code.
+ */
+int
+reparse_create(const char *path, const char *string)
+{
+	int err;
+	struct stat sbuf;
+
+	if (path == NULL || string == NULL)
+		return (EINVAL);
+
+	if ((err = reparse_validate(string)) != 0)
+		return (err);
+
+	/* check if object exists */
+	if (lstat(path, &sbuf) == 0)
+		return (EEXIST);
+
+	return (symlink(string, path) ? errno : 0);
+}
+
+/*
+ * reparse_unparse()
+ *
+ * Convert an nvlist back to a string format suitable to write
+ * to the reparse point symlink body.  The string returned is in
+ * allocated memory and must be freed by the caller.
+ *
+ * return 0 if ok else return error code.
+ */
+int
+reparse_unparse(nvlist_t *nvl, char **stringp)
+{
+	int err, buflen;
+	char *buf, *stype, *val;
+	nvpair_t *curr;
+
+	if (nvl == NULL || stringp == NULL ||
+	    ((curr = nvlist_next_nvpair(nvl, NULL)) == NULL))
+		return (EINVAL);
+
+	buflen = SYMLINK_MAX;
+	if ((buf = malloc(buflen)) == NULL)
+		return (ENOMEM);
+
+	err = 0;
+	(void) snprintf(buf, buflen, "%s", FS_REPARSE_TAG_STR);
+	while (curr != NULL) {
+		if (!(stype = nvpair_name(curr))) {
+			err = EINVAL;
+			break;
+		}
+		if ((strlcat(buf, FS_TOKEN_START_STR, buflen) >= buflen) ||
+		    (strlcat(buf, stype, buflen) >= buflen) ||
+		    (strlcat(buf, ":", buflen) >= buflen) ||
+		    (nvpair_value_string(curr, &val) != 0) ||
+		    (strlcat(buf, val, buflen) >= buflen) ||
+		    (strlcat(buf, FS_TOKEN_END_STR, buflen) >= buflen)) {
+			err = E2BIG;
+			break;
+		}
+		curr = nvlist_next_nvpair(nvl, curr);
+	}
+	if (err != 0) {
+		free(buf);
+		return (err);
+	}
+	if (strlcat(buf, FS_REPARSE_TAG_END_STR, buflen) >= buflen) {
+		free(buf);
+		return (E2BIG);
+	}
+
+	*stringp = buf;
+	return (0);
+}
+
+/*
+ * reparse_deref()
+ *
+ * Accepts the service-specific item from the reparse point and returns
+ * the service-specific data requested.  The caller specifies the size
+ * of the buffer provided via *bufsz.
+ *
+ * if ok return 0 and *bufsz is updated to contain the actual length of
+ * the returned results, else return error code. If the error code is
+ * EOVERFLOW; results do not fit in the buffer, *bufsz will be updated
+ * to contain the number of bytes needed to hold the results.
+ */
+int
+reparse_deref(const char *svc_type, const char *svc_data, char *buf,
+    size_t *bufsz)
+{
+	rp_plugin_ops_t *ops;
+
+	if ((svc_type == NULL) || (svc_data == NULL) || (buf == NULL) ||
+	    (bufsz == NULL))
+		return (EINVAL);
+
+	ops = rp_find_protocol(svc_type);
+	if ((ops != NULL) && (ops->rpo_deref != NULL))
+		return (ops->rpo_deref(svc_type, svc_data, buf, bufsz));
+
+	/* no plugin, return error */
+	return (ENOTSUP);
+}
+
+/*
+ * reparse_delete()
+ *
+ * Delete a reparse point at a given pathname.  It will fail if
+ * a reparse point does not exist at the given path or the pathname
+ * is not a symlink.
+ *
+ * return 0 if ok else return error code.
+ */
+int
+reparse_delete(const char *path)
+{
+	struct stat sbuf;
+
+	if (path == NULL)
+		return (EINVAL);
+
+	/* check if object exists */
+	if (lstat(path, &sbuf) != 0)
+		return (errno);
+
+	if ((sbuf.st_mode & S_IFLNK) != S_IFLNK)
+		return (EINVAL);
+
+	return (unlink(path) ? errno : 0);
+}
+
+/*
+ * reparse_add()
+ *
+ * Add a service type entry to a nvlist with a copy of svc_data,
+ * replacing one of the same type if already present.
+ *
+ * return 0 if ok else return error code.
+ */
+int
+reparse_add(nvlist_t *nvl, const char *svc_type, const char *svc_data)
+{
+	int err;
+	char *buf;
+	size_t bufsz;
+	rp_plugin_ops_t *ops;
+
+	if ((nvl == NULL) || (svc_type == NULL) || (svc_data == NULL))
+		return (EINVAL);
+
+	bufsz = SYMLINK_MAX;		/* no need to mess around */
+	if ((buf = malloc(bufsz)) == NULL)
+		return (ENOMEM);
+
+	ops = rp_find_protocol(svc_type);
+	if ((ops != NULL) && (ops->rpo_form != NULL))
+		err = ops->rpo_form(svc_type, svc_data, buf, &bufsz);
+	else
+		err = ENOTSUP;		/* no plugin */
+
+	if (err != 0) {
+		free(buf);
+		return (err);
+	}
+
+	err =  nvlist_add_string(nvl, svc_type, buf);
+	free(buf);
+	return (err);
+}
+
+/*
+ * reparse_remove()
+ *
+ * Remove a service type entry from the nvlist, if present.
+ *
+ * return 0 if ok else return error code.
+ */
+int
+reparse_remove(nvlist_t *nvl, const char *svc_type)
+{
+	if ((nvl == NULL) || (svc_type == NULL))
+		return (EINVAL);
+
+	return (nvlist_remove_all(nvl, svc_type));
+}
+
+/*
+ * Returns true if name is "." or "..", otherwise returns false.
+ */
+static boolean_t
+rp_is_dot_or_dotdot(const char *name)
+{
+	if (*name != '.')
+		return (B_FALSE);
+
+	if (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))
+		return (B_TRUE);
+
+	return (B_FALSE);
+}
+
+static void
+proto_plugin_fini()
+{
+	rp_proto_plugin_t *p;
+
+	/*
+	 * Protocols may call this framework during _fini
+	 */
+	for (p = rp_proto_list; p != NULL; p = p->plugin_next) {
+		if (p->plugin_ops->rpo_fini)
+			p->plugin_ops->rpo_fini();
+	}
+	while ((p = rp_proto_list) != NULL) {
+		rp_proto_list = p->plugin_next;
+		if (p->plugin_handle != NULL)
+			(void) dlclose(p->plugin_handle);
+		free(p);
+	}
+
+	if (rp_proto_handle.rp_ops != NULL) {
+		free(rp_proto_handle.rp_ops);
+		rp_proto_handle.rp_ops = NULL;
+	}
+	rp_proto_handle.rp_num_proto = 0;
+}
+
+/*
+ * rp_plugin_init()
+ *
+ * Initialize the service type specific plugin modules.
+ * For each reparse service type, there should be a plugin library for it.
+ * This function walks /usr/lib/reparse directory for plugin libraries.
+ * For each plugin library found, initialize it and add it to the internal
+ * list of service type plugin. These are used for service type specific
+ * operations.
+ */
+int
+rp_plugin_init()
+{
+	int err, ret = RP_OK;
+	char isa[MAXISALEN], dirpath[MAXPATHLEN], path[MAXPATHLEN];
+	int num_protos = 0;
+	rp_proto_handle_t *rp_hdl;
+	rp_proto_plugin_t *proto, *tmp;
+	rp_plugin_ops_t *plugin_ops;
+	struct stat st;
+	void *dlhandle;
+	DIR *dir;
+	struct dirent *dent;
+
+#if defined(_LP64)
+	if (sysinfo(SI_ARCHITECTURE_64, isa, MAXISALEN) == -1)
+		isa[0] = '\0';
+#else
+	isa[0] = '\0';
+#endif
+
+	(void) snprintf(dirpath, MAXPATHLEN,
+	    "%s/%s", RP_LIB_DIR, isa);
+
+	if ((dir = opendir(dirpath)) == NULL)
+		return (RP_NO_PLUGIN_DIR);
+
+	while ((dent = readdir(dir)) != NULL) {
+		if (rp_is_dot_or_dotdot(dent->d_name))
+			continue;
+
+		(void) snprintf(path, MAXPATHLEN,
+		    "%s/%s", dirpath, dent->d_name);
+
+		/*
+		 * If file doesn't exist, don't try to map it
+		 */
+		if (stat(path, &st) < 0)
+			continue;
+		if ((dlhandle = dlopen(path, RTLD_FIRST|RTLD_LAZY)) == NULL)
+			continue;
+
+		plugin_ops = (rp_plugin_ops_t *)
+		    dlsym(dlhandle, "rp_plugin_ops");
+		if (plugin_ops == NULL) {
+			(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
+			    "Error in plugin ops for service type %s\n%s\n"),
+			    dent->d_name, dlerror());
+			(void) dlclose(dlhandle);
+			continue;
+		}
+		proto = (rp_proto_plugin_t *)
+		    calloc(1, sizeof (rp_proto_plugin_t));
+		if (proto == NULL) {
+			(void) dlclose(dlhandle);
+			(void) fprintf(stderr,
+			    dgettext(TEXT_DOMAIN, "No memory for plugin %s\n"),
+			    dent->d_name);
+			ret = RP_NO_MEMORY;
+			break;
+		}
+
+		proto->plugin_ops = plugin_ops;
+		proto->plugin_handle = dlhandle;
+		num_protos++;
+		proto->plugin_next = rp_proto_list;
+		rp_proto_list = proto;
+	}
+
+	(void) closedir(dir);
+
+	if ((num_protos == 0) && (ret == 0))
+		ret = RP_NO_PLUGIN;
+	/*
+	 * There was an error, so cleanup prior to return of failure.
+	 */
+	if (ret != RP_OK) {
+		proto_plugin_fini();
+		return (ret);
+	}
+
+	rp_proto_handle.rp_ops = (rp_plugin_ops_t **)calloc(num_protos,
+	    sizeof (rp_plugin_ops_t *));
+	if (!rp_proto_handle.rp_ops) {
+		proto_plugin_fini();
+		return (RP_NO_MEMORY);
+	}
+
+	rp_hdl = &rp_proto_handle;
+	rp_hdl->rp_num_proto = 0;
+	for (tmp = rp_proto_list; rp_hdl->rp_num_proto < num_protos &&
+	    tmp != NULL; tmp = tmp->plugin_next) {
+
+		err = RP_OK;
+		if (tmp->plugin_ops->rpo_init != NULL)
+			err = tmp->plugin_ops->rpo_init();
+		if (err != RP_OK)
+			continue;
+		rp_hdl->rp_ops[rp_hdl->rp_num_proto++] = tmp->plugin_ops;
+	}
+
+	return (rp_hdl->rp_num_proto > 0 ? RP_OK : RP_NO_PLUGIN);
+}
+
+
+/*
+ * find_protocol()
+ *
+ * Search the plugin list for the specified protocol and return the
+ * ops vector.  return NULL if protocol is not defined.
+ */
+static rp_plugin_ops_t *
+rp_find_protocol(const char *svc_type)
+{
+	int i;
+	rp_plugin_ops_t *ops = NULL;
+
+	if (svc_type == NULL)
+		return (NULL);
+
+	if (rp_plugin_inited == 0) {
+		if (rp_plugin_init() == RP_OK)
+			rp_plugin_inited = 1;
+		else
+			return (NULL);
+	}
+
+	for (i = 0; i < rp_proto_handle.rp_num_proto; i++) {
+		ops = rp_proto_handle.rp_ops[i];
+		if (ops->rpo_supports_svc(svc_type))
+			return (ops);
+
+	}
+	return (NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libreparse/common/llib-lreparse	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,46 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* LINTLIBRARY */
+/* PROTOLIB1 */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/fs_reparse.h>
+#include "rp_plugin.h"
+
+/*
+ * usr/src/lib/libreparse
+ */
+int reparse_add(nvlist_t *, const char *, const char *);
+int reparse_create(const char *, const char *);
+int reparse_delete(const char *);
+int reparse_deref(const char *, const char *, char *, size_t *);
+void reparse_free(nvlist_t *);
+nvlist_t *reparse_init(void);
+int reparse_parse(const char *, nvlist_t *);
+int reparse_remove(nvlist_t *, const char *);
+int reparse_remove(nvlist_t *, const char *);
+int reparse_unparse(nvlist_t *, char **);
+int reparse_validate(const char *);
+int rp_plugin_init();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libreparse/common/mapfile-vers	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,54 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# MAPFILE HEADER START
+#
+# WARNING:  STOP NOW.  DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+#	usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+
+SUNWprivate {
+    global:
+	reparse_add;
+	reparse_create;
+	reparse_delete;
+	reparse_deref;
+	reparse_free;
+	reparse_init;
+	reparse_parse;
+	reparse_remove;
+	reparse_unparse;
+	reparse_validate;
+	rp_plugin_init;
+    local:
+	*;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libreparse/common/rp_plugin.h	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,75 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _RP_PLUGIN_H
+#define	_RP_PLUGIN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+#define	RP_LIB_DIR	"/usr/lib/reparse"
+#define	RP_PLUGIN_V1	1
+
+/*
+ * some error codes
+ */
+#define	RP_OK			0
+#define	RP_NO_PLUGIN		ENOENT
+#define	RP_NO_MEMORY		ENOMEM
+#define	RP_NO_PLUGIN_DIR	ENOTDIR
+#define	RP_INVALID_PROTOCOL	EINVAL
+
+extern int rp_plugin_init();
+
+typedef struct rp_plugin_ops {
+	int rpo_version;
+	int (*rpo_init)(void);
+	int (*rpo_fini)(void);
+	char *(*rpo_svc_types)(void);
+	boolean_t (*rpo_supports_svc)(const char *);
+	int (*rpo_form)(const char *, const char *, char *, size_t *);
+	int (*rpo_deref)(const char *, const char *, char *, size_t *);
+} rp_plugin_ops_t;
+
+typedef struct rp_proto_plugin {
+	struct rp_proto_plugin *plugin_next;
+	rp_plugin_ops_t *plugin_ops;
+	void *plugin_handle;
+} rp_proto_plugin_t;
+
+typedef struct rp_proto_handle {
+	int rp_num_proto;
+	rp_plugin_ops_t **rp_ops;
+} rp_proto_handle_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _RP_PLUGIN_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libreparse/i386/Makefile	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,28 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libreparse/sparc/Makefile	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,28 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libreparse/sparcv9/Makefile	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
--- a/usr/src/lib/libsecdb/auth_attr.txt	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/lib/libsecdb/auth_attr.txt	Wed Oct 14 11:15:07 2009 -0500
@@ -139,6 +139,7 @@
 solaris.smf.manage.power:::Manage Power Management Service States::help=SmfPowerStates.html
 solaris.smf.manage.smb:::Manage SMB Service States::help=SmfSMBStates.html
 solaris.smf.manage.smbfs:::Manage SMB Client States::help=SmfSMBFSStates.html
+solaris.smf.manage.reparse:::Manage Reparse Service States::help=SmfReparseStates.html
 solaris.smf.manage.rmvolmgr:::Manage Rmvolmgr Service States::help=SmfRmvolmgrStates.html
 solaris.smf.manage.routing:::Manage Routing Service States::help=SmfRoutingStates.html
 solaris.smf.manage.rpc.bind:::Manage RPC Program number mapper::help=SmfRPCBind.html
--- a/usr/src/lib/libsecdb/help/auths/Makefile	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/lib/libsecdb/help/auths/Makefile	Wed Oct 14 11:15:07 2009 -0500
@@ -86,6 +86,7 @@
 	SmfNDMPStates.html \
 	SmfNWAMStates.html \
 	SmfPowerStates.html \
+	SmfReparseStates.html \
 	SmfRoutingStates.html \
 	SmfSendmailStates.html \
 	SmfSshStates.html \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsecdb/help/auths/SmfReparseStates.html	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,37 @@
+<HTML>
+<!--
+    CDDL HEADER START
+
+    The contents of this file are subject to the terms of the
+    Common Development and Distribution License (the "License").
+    You may not use this file except in compliance with the License.
+
+    You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+    or http://www.opensolaris.org/os/licensing.
+    See the License for the specific language governing permissions
+    and limitations under the License.
+
+    When distributing Covered Code, include this CDDL HEADER in each
+    file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+    If applicable, add the following below this CDDL HEADER, with the
+    fields enclosed by brackets "[]" replaced with your own identifying
+    information: Portions Copyright [yyyy] [name of copyright owner]
+
+    CDDL HEADER END
+
+Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+Use is subject to license terms.
+-->
+<!--
+   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+-->
+<BODY>
+When Manage Reparse Service States is in the Authorizations Include
+column, it grants the authorization to enable, disable, or restart
+the Reparse service.
+<p>
+If Manage Reparse Service States is grayed, then you are not entitled
+to Add or Remove this authorization.
+<BR>&nbsp;
+</BODY>
+</HTML>
--- a/usr/src/lib/libsecdb/help/profiles/Makefile	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/lib/libsecdb/help/profiles/Makefile	Wed Oct 14 11:15:07 2009 -0500
@@ -69,6 +69,7 @@
 	RtObAccessMngmnt.html \
 	RtPrntAdmin.html \
 	RtProcManagement.html \
+	RtReparseMngmnt.html \
 	RtRightsDelegate.html \
 	RtSMBMngmnt.html \
 	RtSMBFSMngmnt.html \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libsecdb/help/profiles/RtReparseMngmnt.html	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,37 @@
+<HTML>
+<!--
+    CDDL HEADER START
+
+    The contents of this file are subject to the terms of the
+    Common Development and Distribution License (the "License").
+    You may not use this file except in compliance with the License.
+
+    You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+    or http://www.opensolaris.org/os/licensing.
+    See the License for the specific language governing permissions
+    and limitations under the License.
+
+    When distributing Covered Code, include this CDDL HEADER in each
+    file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+    If applicable, add the following below this CDDL HEADER, with the
+    fields enclosed by brackets "[]" replaced with your own identifying
+    information: Portions Copyright [yyyy] [name of copyright owner]
+
+    CDDL HEADER END
+
+Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+Use is subject to license terms.
+-->
+<!--
+   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+-->
+<BODY>
+When Manage Reparse Service States is in the Authorizations Include
+column, it grants the authorization to enable, disable, or restart
+the Reparse service.
+<p>
+If Manage Reparse Service States is grayed, then you are not entitled
+to Add or Remove this authorization.
+<BR>&nbsp;
+</BODY>
+</HTML>
--- a/usr/src/lib/libsecdb/prof_attr.txt	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/lib/libsecdb/prof_attr.txt	Wed Oct 14 11:15:07 2009 -0500
@@ -72,6 +72,7 @@
 Name Service Security:::Security related name service scripts/commands:help=RtNameServiceSecure.html
 Object Access Management:::Change ownership and permission on files:help=RtObAccessMngmnt.html
 Process Management:::Manage current processes and processors:auths=solaris.smf.manage.cron,solaris.smf.manage.power;help=RtProcManagement.html
+Reparse Management:::Manage the reparse service:auths=solaris.smf.manage.reparse:help=RtReparseMngmnt.html
 Rights Delegation:::Delegate ability to assign rights to users and roles:auths=solaris.role.delegate,solaris.profmgr.delegate,solaris.grant;help=RtRightsDelegate.html
 Rmvolmgr Management:::Manage Removable Volume Manager SMF service:auths=solaris.smf.manage.rmvolmgr;help=RtRmvolmgrMngmnt.html
 Service Management:::Manage services:auths=solaris.smf.manage,solaris.smf.modify
--- a/usr/src/lib/libzpool/common/sys/zfs_context.h	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/lib/libzpool/common/sys/zfs_context.h	Wed Oct 14 11:15:07 2009 -0500
@@ -346,6 +346,7 @@
 	char		*v_path;
 } vnode_t;
 
+#define	AV_SCANSTAMP_SZ	32		/* length of anti-virus scanstamp */
 
 typedef struct xoptattr {
 	timestruc_t	xoa_createtime;	/* Create time of file */
@@ -361,6 +362,8 @@
 	uint8_t		xoa_opaque;
 	uint8_t		xoa_av_quarantined;
 	uint8_t		xoa_av_modified;
+	uint8_t		xoa_av_scanstamp[AV_SCANSTAMP_SZ];
+	uint8_t		xoa_reparse;
 } xoptattr_t;
 
 typedef struct vattr {
--- a/usr/src/pkgdefs/SUNW0on/prototype_com	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/pkgdefs/SUNW0on/prototype_com	Wed Oct 14 11:15:07 2009 -0500
@@ -259,6 +259,7 @@
 f none usr/lib/help/auths/locale/SmfNADDStates.html 444 root bin
 f none usr/lib/help/auths/locale/SmfNWAMStates.html 444 root bin
 f none usr/lib/help/auths/locale/SmfPowerStates.html 444 root bin
+f none usr/lib/help/auths/locale/SmfReparseStates.html 444 root bin
 f none usr/lib/help/auths/locale/SmfRoutingStates.html 444 root bin
 f none usr/lib/help/auths/locale/SmfSendmailStates.html 444 root bin
 f none usr/lib/help/auths/locale/SmfSMBFSStates.html 444 root bin
@@ -380,6 +381,7 @@
 f none usr/lib/help/profiles/locale/RtNetLinkSecure.html 444 root bin
 f none usr/lib/help/profiles/locale/RtObAccessMngmnt.html 444 root bin
 f none usr/lib/help/profiles/locale/RtProcManagement.html 444 root bin
+f none usr/lib/help/profiles/locale/RtReparseMngmnt.html 444 root bin
 f none usr/lib/help/profiles/locale/RtRightsDelegate.html 444 root bin
 f none usr/lib/help/profiles/locale/RtSoftwareInstall.html 444 root bin
 f none usr/lib/help/profiles/locale/RtSMBFSMngmnt.html 444 root bin
--- a/usr/src/pkgdefs/SUNWarc/prototype_com	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/pkgdefs/SUNWarc/prototype_com	Wed Oct 14 11:15:07 2009 -0500
@@ -150,6 +150,8 @@
 s none usr/lib/llib-lposix4.ln=../../lib/llib-lrt.ln
 f none usr/lib/llib-lproject 644 root bin
 f none usr/lib/llib-lproject.ln 644 root bin
+f none usr/lib/llib-lreparse 644 root bin
+f none usr/lib/llib-lreparse.ln 644 root bin
 s none usr/lib/llib-lresolv=../../lib/llib-lresolv
 s none usr/lib/llib-lresolv.ln=../../lib/llib-lresolv.ln
 s none usr/lib/llib-lrpcsvc=../../lib/llib-lrpcsvc
--- a/usr/src/pkgdefs/SUNWarc/prototype_i386	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/pkgdefs/SUNWarc/prototype_i386	Wed Oct 14 11:15:07 2009 -0500
@@ -114,6 +114,7 @@
 f none usr/lib/amd64/llib-l4014.ln 644 root bin
 f none usr/lib/amd64/llib-l450.ln 644 root bin
 s none usr/lib/amd64/llib-lpthread.ln=../../../lib/amd64/llib-lpthread.ln
+f none usr/lib/amd64/llib-lreparse.ln 644 root bin
 s none usr/lib/amd64/llib-lresolv.ln=../../../lib/amd64/llib-lresolv.ln
 s none usr/lib/amd64/llib-lrpcsvc.ln=../../../lib/amd64/llib-lrpcsvc.ln
 s none usr/lib/amd64/llib-lrt.ln=../../../lib/amd64/llib-lrt.ln
--- a/usr/src/pkgdefs/SUNWarc/prototype_sparc	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/pkgdefs/SUNWarc/prototype_sparc	Wed Oct 14 11:15:07 2009 -0500
@@ -18,7 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -110,6 +110,7 @@
 f none usr/lib/sparcv9/llib-l4014.ln 644 root bin
 f none usr/lib/sparcv9/llib-l450.ln 644 root bin
 s none usr/lib/sparcv9/llib-lpthread.ln=../../../lib/sparcv9/llib-lpthread.ln
+f none usr/lib/sparcv9/llib-lreparse.ln 644 root bin
 s none usr/lib/sparcv9/llib-lresolv.ln=../../../lib/sparcv9/llib-lresolv.ln
 s none usr/lib/sparcv9/llib-lrpcsvc.ln=../../../lib/sparcv9/llib-lrpcsvc.ln
 s none usr/lib/sparcv9/llib-lrt.ln=../../../lib/sparcv9/llib-lrt.ln
--- a/usr/src/pkgdefs/SUNWcsl/prototype_com	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/pkgdefs/SUNWcsl/prototype_com	Wed Oct 14 11:15:07 2009 -0500
@@ -210,6 +210,8 @@
 s none usr/lib/libpthread.so.1=../../lib/libpthread.so.1
 s none usr/lib/librcm.so=../../lib/librcm.so.1
 s none usr/lib/librcm.so.1=../../lib/librcm.so.1
+f none usr/lib/libreparse.so.1 755 root bin
+s none usr/lib/libreparse.so=./libreparse.so.1
 s none usr/lib/libresolv.so=../../lib/libresolv.so.2
 s none usr/lib/libresolv.so.1=../../lib/libresolv.so.1
 s none usr/lib/libresolv.so.2=../../lib/libresolv.so.2
--- a/usr/src/pkgdefs/SUNWcsl/prototype_i386	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/pkgdefs/SUNWcsl/prototype_i386	Wed Oct 14 11:15:07 2009 -0500
@@ -298,6 +298,8 @@
 s none usr/lib/amd64/libpthread.so=../../../lib/amd64/libpthread.so.1
 s none usr/lib/amd64/librcm.so.1=../../../lib/amd64/librcm.so.1
 s none usr/lib/amd64/librcm.so=../../../lib/amd64/librcm.so.1
+f none usr/lib/amd64/libreparse.so.1 755 root bin
+s none usr/lib/amd64/libreparse.so=libreparse.so.1
 s none usr/lib/amd64/libresolv.so.2=../../../lib/amd64/libresolv.so.2
 s none usr/lib/amd64/libresolv.so=../../../lib/amd64/libresolv.so.2
 s none usr/lib/amd64/librpcsvc.so.1=../../../lib/amd64/librpcsvc.so.1
--- a/usr/src/pkgdefs/SUNWcsl/prototype_sparc	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/pkgdefs/SUNWcsl/prototype_sparc	Wed Oct 14 11:15:07 2009 -0500
@@ -288,6 +288,8 @@
 s none usr/lib/sparcv9/libpthread.so=../../../lib/sparcv9/libpthread.so.1
 s none usr/lib/sparcv9/librcm.so.1=../../../lib/sparcv9/librcm.so.1
 s none usr/lib/sparcv9/librcm.so=../../../lib/sparcv9/librcm.so.1
+f none usr/lib/sparcv9/libreparse.so.1 755 root bin
+s none usr/lib/sparcv9/libreparse.so=libreparse.so.1
 s none usr/lib/sparcv9/libresolv.so.2=../../../lib/sparcv9/libresolv.so.2
 s none usr/lib/sparcv9/libresolv.so=../../../lib/sparcv9/libresolv.so.2
 s none usr/lib/sparcv9/librestart.so.1=../../../lib/sparcv9/librestart.so.1
--- a/usr/src/pkgdefs/SUNWcsr/prototype_com	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/pkgdefs/SUNWcsr/prototype_com	Wed Oct 14 11:15:07 2009 -0500
@@ -531,6 +531,7 @@
 f manifest var/svc/manifest/network/ssl/kssl-proxy.xml 0444 root sys
 d none var/svc/manifest/network/shares 0755 root sys
 f manifest var/svc/manifest/network/shares/group.xml 0444 root sys
+f manifest var/svc/manifest/network/shares/reparsed.xml 0444 root sys
 d none var/svc/manifest/platform 755 root sys
 d none var/svc/manifest/site 755 root sys
 d none var/svc/manifest/system 755 root sys
--- a/usr/src/pkgdefs/SUNWcsu/prototype_com	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/pkgdefs/SUNWcsu/prototype_com	Wed Oct 14 11:15:07 2009 -0500
@@ -501,6 +501,7 @@
 f none usr/lib/help/auths/locale/C/SmfNADDStates.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfNWAMStates.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfPowerStates.html 444 root bin
+f none usr/lib/help/auths/locale/C/SmfReparseStates.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfRoutingStates.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfSendmailStates.html 444 root bin
 f none usr/lib/help/auths/locale/C/SmfSMBFSStates.html 444 root bin
@@ -604,6 +605,7 @@
 f none usr/lib/help/profiles/locale/C/RtObAccessMngmnt.html 444 root bin
 f none usr/lib/help/profiles/locale/C/RtPrntAdmin.html 444 root bin
 f none usr/lib/help/profiles/locale/C/RtProcManagement.html 444 root bin
+f none usr/lib/help/profiles/locale/C/RtReparseMngmnt.html 444 root bin
 f none usr/lib/help/profiles/locale/C/RtRightsDelegate.html 444 root bin
 f none usr/lib/help/profiles/locale/C/RtSoftwareInstall.html 444 root bin
 f none usr/lib/help/profiles/locale/C/RtSMBFSMngmnt.html 444 root bin
@@ -697,6 +699,8 @@
 f none usr/lib/rcm/modules/SUNW_swap_rcm.so 555 root bin
 f none usr/lib/rcm/rcm_daemon 555 root bin
 d none usr/lib/rcm/scripts 755 root bin
+d none usr/lib/reparse 755 root bin
+f none usr/lib/reparse/reparsed 555 root sys
 s none usr/lib/rsh=../../sbin/sh
 d none usr/lib/saf 755 root bin
 f none usr/lib/saf/listen 755 root sys
--- a/usr/src/pkgdefs/SUNWhea/prototype_com	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/pkgdefs/SUNWhea/prototype_com	Wed Oct 14 11:15:07 2009 -0500
@@ -470,6 +470,7 @@
 f none usr/include/regexpr.h 644 root bin
 f none usr/include/resolv.h 644 root bin
 f none usr/include/rje.h 644 root bin
+f none usr/include/rp_plugin.h 644 root bin
 d none usr/include/iso 755 root bin
 s none usr/include/iso/assert_iso.h=../assert.h
 f none usr/include/iso/ctype_c99.h 644 root bin
@@ -913,6 +914,7 @@
 f none usr/include/sys/fs/ufs_snap.h 644 root bin
 f none usr/include/sys/fs/ufs_trans.h 644 root bin
 f none usr/include/sys/fs/zfs.h 644 root bin
+f none usr/include/sys/fs_reparse.h 644 root bin
 f none usr/include/sys/fs_subr.h 644 root bin
 f none usr/include/sys/fsid.h 644 root bin
 f none usr/include/sys/fssnap.h 644 root bin
--- a/usr/src/uts/common/Makefile.files	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/Makefile.files	Wed Oct 14 11:15:07 2009 -0500
@@ -162,6 +162,7 @@
 		fork.o		\
 		vpm.o		\
 		fsat.o		\
+		fs_reparse.o	\
 		fs_subr.o	\
 		fsflush.o	\
 		ftrace.o	\
--- a/usr/src/uts/common/Makefile.rules	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/Makefile.rules	Wed Oct 14 11:15:07 2009 -0500
@@ -340,6 +340,10 @@
 	$(COMPILE.b) -o $@ $<
 	$(CTFCONVERT_O)
 
+$(OBJS_DIR)/%.o:		$(COMMONBASE)/fsreparse/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
 KMECHKRB5_BASE=$(UTSBASE)/common/gssapi/mechs/krb5
 
 KGSSDFLAGS=-I $(UTSBASE)/common/gssapi/include 
@@ -2530,3 +2534,6 @@
 
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/common/io/yge/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
+
+$(LINTS_DIR)/%.ln:		$(COMMONBASE)/fsreparse/%.c
+	@($(LHEAD) $(LINT.c) $< $(LTAIL))
--- a/usr/src/uts/common/fs/Makefile	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/fs/Makefile	Wed Oct 14 11:15:07 2009 -0500
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -19,17 +18,16 @@
 #
 # CDDL HEADER END
 #
-#
-#ident	"%Z%%M%	%I%	%E% SMI"
-#
-# Copyright (c) 1989 by Sun Microsystems, Inc.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
 #
 # uts/common/fs/Makefile
 #
 # include global definitions
 include ../../../Makefile.master
 
-HDRS=  fs_subr.h
+HDRS=  fs_subr.h  \
+	fs_reparse.h
 
 PROCHDRS=   prdata.h
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/fs/fs_reparse.h	Wed Oct 14 11:15:07 2009 -0500
@@ -0,0 +1,88 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _FS_REPARSE_H
+#define	_FS_REPARSE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef _KERNEL
+#include <sys/time.h>
+#include <sys/nvpair.h>
+#else
+#include <libnvpair.h>
+#endif
+
+#define	FS_REPARSE_TAG_STR		"@{REPARSE"
+#define	FS_REPARSE_TAG_END_CHAR		'}'
+#define	FS_REPARSE_TAG_END_STR		"}"
+#define	FS_TOKEN_START_STR		"@{"
+#define	FS_TOKEN_END_STR		"}"
+
+#define	REPARSED			"svc:/system/filesystem/reparse:default"
+#define	MAXREPARSELEN			MAXPATHLEN
+#define	REPARSED_DOOR			"/var/run/reparsed_door"
+#define	REPARSED_DOORCALL_MAX_RETRY	4
+
+/*
+ * This structure is shared between kernel code and user reparsed daemon.
+ * The 'res_len' must be defined as int, and not size_t, for 32-bit reparsed
+ * binary and 64-bit kernel code to work together.
+ */
+typedef struct reparsed_door_res {
+	int	res_status;
+	int	res_len;
+	char	res_data[1];
+} reparsed_door_res_t;
+
+extern nvlist_t *reparse_init(void);
+extern void reparse_free(nvlist_t *nvl);
+extern int reparse_parse(const char *reparse_data, nvlist_t *nvl);
+extern int reparse_validate(const char *reparse_data);
+
+#ifdef _KERNEL
+extern int reparse_kderef(const char *svc_type, const char *svc_data,
+			char *buf, size_t *bufsz);
+extern int reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl);
+#else
+extern int reparse_add(nvlist_t *nvl, const char *svc_type,
+			const char *svc_data);
+extern int reparse_remove(nvlist_t *nvl, const char *svc_type);
+extern int reparse_unparse(nvlist_t *nvl, char **stringp);
+extern int reparse_create(const char *path, const char *string);
+extern int reparse_delete(const char *path);
+extern int reparse_deref(const char *svc_type, const char *svc_data,
+			char *buf, size_t *bufsz);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _FS_REPARSE_H */
--- a/usr/src/uts/common/fs/fs_subr.c	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/fs/fs_subr.c	Wed Oct 14 11:15:07 2009 -0500
@@ -48,6 +48,8 @@
 #include <sys/cmn_err.h>
 #include <sys/stream.h>
 #include <fs/fs_subr.h>
+#include <fs/fs_reparse.h>
+#include <sys/door.h>
 #include <sys/acl.h>
 #include <sys/share.h>
 #include <sys/file.h>
@@ -55,6 +57,7 @@
 #include <sys/file.h>
 #include <sys/nbmlock.h>
 #include <acl/acl_common.h>
+#include <sys/pathname.h>
 
 static callb_cpr_t *frlock_serialize_blocked(flk_cb_when_t, void *);
 
@@ -64,6 +67,12 @@
 int fs_estale_retry = 5;
 
 /*
+ * supports for reparse point door upcall
+ */
+static door_handle_t reparsed_door;
+static kmutex_t reparsed_door_lock;
+
+/*
  * The associated operation is not supported by the file system.
  */
 int
@@ -838,3 +847,175 @@
 
 	return (ret);
 }
+
+/*
+ * support functions for reparse point
+ */
+/*
+ * reparse_vnode_parse
+ *
+ * Read the symlink data of a reparse point specified by the vnode
+ * and return the reparse data as name-value pair in the nvlist.
+ */
+int
+reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl)
+{
+	int err;
+	char *lkdata;
+	struct uio uio;
+	struct iovec iov;
+
+	if (vp == NULL || nvl == NULL)
+		return (EINVAL);
+
+	lkdata = kmem_alloc(MAXREPARSELEN, KM_SLEEP);
+
+	/*
+	 * Set up io vector to read sym link data
+	 */
+	iov.iov_base = lkdata;
+	iov.iov_len = MAXREPARSELEN;
+	uio.uio_iov = &iov;
+	uio.uio_iovcnt = 1;
+	uio.uio_segflg = UIO_SYSSPACE;
+	uio.uio_extflg = UIO_COPY_CACHED;
+	uio.uio_loffset = (offset_t)0;
+	uio.uio_resid = MAXREPARSELEN;
+
+	if ((err = VOP_READLINK(vp, &uio, kcred, NULL)) == 0) {
+		*(lkdata + MAXREPARSELEN - uio.uio_resid) = '\0';
+		err = reparse_parse(lkdata, nvl);
+	}
+	kmem_free(lkdata, MAXREPARSELEN);	/* done with lkdata */
+
+	return (err);
+}
+
+void
+reparse_point_init()
+{
+	mutex_init(&reparsed_door_lock, NULL, MUTEX_DEFAULT, NULL);
+}
+
+static door_handle_t
+reparse_door_get_handle()
+{
+	door_handle_t dh;
+
+	mutex_enter(&reparsed_door_lock);
+	if ((dh = reparsed_door) == NULL) {
+		if (door_ki_open(REPARSED_DOOR, &reparsed_door) != 0) {
+			reparsed_door = NULL;
+			dh = NULL;
+		} else
+			dh = reparsed_door;
+	}
+	mutex_exit(&reparsed_door_lock);
+	return (dh);
+}
+
+static void
+reparse_door_reset_handle()
+{
+	mutex_enter(&reparsed_door_lock);
+	reparsed_door = NULL;
+	mutex_exit(&reparsed_door_lock);
+}
+
+/*
+ * reparse_kderef
+ *
+ * Accepts the service-specific item from the reparse point and returns
+ * the service-specific data requested.  The caller specifies the size of
+ * the buffer provided via *bufsz; the routine will fail with EOVERFLOW
+ * if the results will not fit in the buffer, in which case, *bufsz will
+ * contain the number of bytes needed to hold the results.
+ *
+ * if ok return 0 and update *bufsize with length of actual result
+ * else return error code.
+ */
+int
+reparse_kderef(const char *svc_type, const char *svc_data, char *buf,
+    size_t *bufsize)
+{
+	int err, retries, need_free;
+	size_t dlen, res_len;
+	char *darg;
+	door_arg_t door_args;
+	reparsed_door_res_t *resp;
+	door_handle_t rp_door;
+
+	if (svc_type == NULL || svc_data == NULL || buf == NULL ||
+	    bufsize == NULL)
+		return (EINVAL);
+
+	/* get reparsed's door handle */
+	if ((rp_door = reparse_door_get_handle()) == NULL)
+		return (EBADF);
+
+	/* setup buffer for door_call args and results */
+	dlen = strlen(svc_type) + strlen(svc_data) + 2;
+	if (*bufsize < dlen) {
+		darg = kmem_alloc(dlen, KM_SLEEP);
+		need_free = 1;
+	} else {
+		darg = buf;	/* use same buffer for door's args & results */
+		need_free = 0;
+	}
+
+	/* build argument string of door call */
+	(void) snprintf(darg, dlen, "%s:%s", svc_type, svc_data);
+
+	/* setup args for door call */
+	door_args.data_ptr = darg;
+	door_args.data_size = dlen;
+	door_args.desc_ptr = NULL;
+	door_args.desc_num = 0;
+	door_args.rbuf = buf;
+	door_args.rsize = *bufsize;
+
+	/* do the door_call */
+	retries = 0;
+	door_ki_hold(rp_door);
+	while ((err = door_ki_upcall_limited(rp_door, &door_args,
+	    NULL, SIZE_MAX, 0)) != 0) {
+		if (err == EAGAIN || err == EINTR) {
+			if (++retries < REPARSED_DOORCALL_MAX_RETRY) {
+				delay(SEC_TO_TICK(1));
+				continue;
+			}
+		} else if (err == EBADF) {
+			/* door server goes away... */
+			reparse_door_reset_handle();
+		}
+		break;
+	}
+	door_ki_rele(rp_door);
+	if (need_free)
+		kmem_free(darg, dlen);		/* done with args buffer */
+
+	if (err != 0)
+		return (err);
+
+	resp = (reparsed_door_res_t *)door_args.rbuf;
+	if ((err = resp->res_status) == 0) {
+		/*
+		 * have to save the length of the results before the
+		 * bcopy below since it's can be an overlap copy that
+		 * overwrites the reparsed_door_res_t structure at
+		 * the beginning of the buffer.
+		 */
+		res_len = (size_t)resp->res_len;
+
+		/* deref call is ok */
+		if (res_len > *bufsize)
+			err = EOVERFLOW;
+		else
+			bcopy(resp->res_data, buf, res_len);
+		*bufsize = res_len;
+	}
+	if (door_args.rbuf != buf)
+		kmem_free(door_args.rbuf, door_args.rsize);
+
+	return (err);
+}
--- a/usr/src/uts/common/fs/vfs.c	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/fs/vfs.c	Wed Oct 14 11:15:07 2009 -0500
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -4252,6 +4252,8 @@
 	}
 
 	xattr_init();
+
+	reparse_point_init();
 }
 
 vfs_t *
--- a/usr/src/uts/common/fs/vnode.c	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/fs/vnode.c	Wed Oct 14 11:15:07 2009 -0500
@@ -64,6 +64,7 @@
 #include <sys/fcntl.h>
 #include <fs/fs_subr.h>
 #include <sys/taskq.h>
+#include <fs/fs_reparse.h>
 
 /* Determine if this vnode is a file that is read-only */
 #define	ISROFILE(vp)	\
@@ -106,6 +107,11 @@
 static void *vsd_realloc(void *, size_t, size_t);
 
 /*
+ * forward declarations for reparse point functions
+ */
+static int fs_reparse_mark(char *target, vattr_t *vap, xvattr_t *xvattr);
+
+/*
  * VSD -- VNODE SPECIFIC DATA
  * The v_data pointer is typically used by a file system to store a
  * pointer to the file system's private node (e.g. ufs inode, nfs rnode).
@@ -3604,6 +3610,7 @@
 	int flags)
 {
 	int	err;
+	xvattr_t xvattr;
 
 	/*
 	 * If this file system doesn't support case-insensitive access
@@ -3616,6 +3623,14 @@
 
 	VOPXID_MAP_CR(dvp, cr);
 
+	/* check for reparse point */
+	if ((vfs_has_feature(dvp->v_vfsp, VFSFT_REPARSE)) &&
+	    (strncmp(target, FS_REPARSE_TAG_STR,
+	    strlen(FS_REPARSE_TAG_STR)) == 0)) {
+		if (!fs_reparse_mark(target, vap, &xvattr))
+			vap = (vattr_t *)&xvattr;
+	}
+
 	err = (*(dvp)->v_op->vop_symlink)
 	    (dvp, linkname, vap, target, cr, ct, flags);
 	VOPSTATS_UPDATE(dvp, symlink);
@@ -4395,3 +4410,34 @@
 	}
 	return (new);
 }
+
+/*
+ * Setup the extensible system attribute for creating a reparse point.
+ * The symlink data 'target' is validated for proper format of a reparse
+ * string and a check also made to make sure the symlink data does not
+ * point to an existing file.
+ *
+ * return 0 if ok else -1.
+ */
+static int
+fs_reparse_mark(char *target, vattr_t *vap, xvattr_t *xvattr)
+{
+	xoptattr_t *xoap;
+
+	if ((!target) || (!vap) || (!xvattr))
+		return (-1);
+
+	/* validate reparse string */
+	if (reparse_validate((const char *)target))
+		return (-1);
+
+	xva_init(xvattr);
+	xvattr->xva_vattr = *vap;
+	xvattr->xva_vattr.va_mask |= AT_XVATTR;
+	xoap = xva_getxoptattr(xvattr);
+	ASSERT(xoap);
+	XVA_SET_REQ(xvattr, XAT_REPARSE);
+	xoap->xoa_reparse = 1;
+
+	return (0);
+}
--- a/usr/src/uts/common/fs/xattr.c	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/fs/xattr.c	Wed Oct 14 11:15:07 2009 -0500
@@ -212,6 +212,9 @@
 			VERIFY(nvlist_add_uint64(nvlp, attr_to_name(attr),
 			    fsid) == 0);
 			break;
+		case F_REPARSE:
+			XVA_SET_REQ(&xvattr, XAT_REPARSE);
+			break;
 		default:
 			break;
 		}
@@ -294,6 +297,11 @@
 			    sizeof (xoap->xoa_createtime) /
 			    sizeof (uint64_t)) == 0);
 		}
+		if (XVA_ISSET_RTN(&xvattr, XAT_REPARSE)) {
+			VERIFY(nvlist_add_boolean_value(nvlp,
+			    attr_to_name(F_REPARSE),
+			    xoap->xoa_reparse) == 0);
+		}
 	}
 	/*
 	 * Check for optional ownersid/groupsid
@@ -667,6 +675,10 @@
 				return (EINVAL);
 			}
 			break;
+		case F_REPARSE:
+			XVA_SET_REQ(&xvattr, XAT_REPARSE);
+			xoap->xoa_reparse = value;
+			break;
 		default:
 			break;
 		}
@@ -807,6 +819,7 @@
 	XVA_SET_REQ(&xvattr, XAT_AV_MODIFIED);
 	XVA_SET_REQ(&xvattr, XAT_AV_QUARANTINED);
 	XVA_SET_REQ(&xvattr, XAT_CREATETIME);
+	XVA_SET_REQ(&xvattr, XAT_REPARSE);
 
 	pdvp = gfs_file_parent(sdvp);
 	error = VOP_GETATTR(pdvp, &xvattr.xva_vattr, 0, cr, ct);
--- a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h	Wed Oct 14 11:15:07 2009 -0500
@@ -57,6 +57,7 @@
 #define	ZFS_OPAQUE		0x0000010000000000
 #define	ZFS_AV_QUARANTINED 	0x0000020000000000
 #define	ZFS_AV_MODIFIED 	0x0000040000000000
+#define	ZFS_REPARSE		0x0000080000000000
 
 #define	ZFS_ATTR_SET(zp, attr, value)	\
 { \
--- a/usr/src/uts/common/fs/zfs/zfs_log.c	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_log.c	Wed Oct 14 11:15:07 2009 -0500
@@ -175,6 +175,9 @@
 		ZFS_TIME_ENCODE(&xoap->xoa_createtime, crtime);
 	if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP))
 		bcopy(xoap->xoa_av_scanstamp, scanstamp, AV_SCANSTAMP_SZ);
+	if (XVA_ISSET_REQ(xvap, XAT_REPARSE))
+		*attrs |= (xoap->xoa_reparse == 0) ? 0 :
+		    XAT0_REPARSE;
 }
 
 static void *
--- a/usr/src/uts/common/fs/zfs/zfs_replay.c	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_replay.c	Wed Oct 14 11:15:07 2009 -0500
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -129,6 +127,8 @@
 		ZFS_TIME_DECODE(&xoap->xoa_createtime, crtime);
 	if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP))
 		bcopy(scanstamp, xoap->xoa_av_scanstamp, AV_SCANSTAMP_SZ);
+	if (XVA_ISSET_REQ(xvap, XAT_REPARSE))
+		xoap->xoa_reparse = ((*attrs & XAT0_REPARSE) != 0);
 }
 
 static int
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c	Wed Oct 14 11:15:07 2009 -0500
@@ -1049,6 +1049,7 @@
 		vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS);
 		vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE);
 		vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER);
+		vfs_set_feature(zfsvfs->z_vfs, VFSFT_REPARSE);
 	}
 }
 
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c	Wed Oct 14 11:15:07 2009 -0500
@@ -2370,6 +2370,12 @@
 			ZFS_TIME_DECODE(&xoap->xoa_createtime, pzp->zp_crtime);
 			XVA_SET_RTN(xvap, XAT_CREATETIME);
 		}
+
+		if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) {
+			xoap->xoa_reparse =
+			    ((pzp->zp_flags & ZFS_REPARSE) != 0);
+			XVA_SET_RTN(xvap, XAT_REPARSE);
+		}
 	}
 
 	ZFS_TIME_DECODE(&vap->va_atime, pzp->zp_atime);
@@ -2671,6 +2677,12 @@
 			}
 		}
 
+		if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) {
+			mutex_exit(&zp->z_lock);
+			ZFS_EXIT(zfsvfs);
+			return (EPERM);
+		}
+
 		if (need_policy == FALSE &&
 		    (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP) ||
 		    XVA_ISSET_REQ(xvap, XAT_OPAQUE))) {
--- a/usr/src/uts/common/fs/zfs/zfs_znode.c	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_znode.c	Wed Oct 14 11:15:07 2009 -0500
@@ -909,6 +909,10 @@
 		zp->z_phys->zp_flags |= ZFS_BONUS_SCANSTAMP;
 		XVA_SET_RTN(xvap, XAT_AV_SCANSTAMP);
 	}
+	if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) {
+		ZFS_ATTR_SET(zp, ZFS_REPARSE, xoap->xoa_reparse);
+		XVA_SET_RTN(xvap, XAT_REPARSE);
+	}
 }
 
 int
--- a/usr/src/uts/common/fs/zut/zut.c	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/fs/zut/zut.c	Wed Oct 14 11:15:07 2009 -0500
@@ -217,6 +217,7 @@
 	XVA_SET_REQ(&xv, XAT_OPAQUE);
 	XVA_SET_REQ(&xv, XAT_AV_QUARANTINED);
 	XVA_SET_REQ(&xv, XAT_AV_MODIFIED);
+	XVA_SET_REQ(&xv, XAT_REPARSE);
 
 	xv.xva_vattr.va_mask |= AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE;
 	if (error = VOP_GETATTR(vp, &xv.xva_vattr, flag, cr, NULL))
@@ -263,6 +264,8 @@
 		*xvs |= (1 << F_AV_QUARANTINED);
 	if (XVA_ISSET_RTN(&xv, XAT_AV_MODIFIED) && xoap->xoa_av_modified)
 		*xvs |= (1 << F_AV_MODIFIED);
+	if (XVA_ISSET_RTN(&xv, XAT_REPARSE) && xoap->xoa_reparse)
+		*xvs |= (1 << F_REPARSE);
 
 	return (0);
 }
--- a/usr/src/uts/common/sys/attr.h	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/sys/attr.h	Wed Oct 14 11:15:07 2009 -0500
@@ -19,15 +19,13 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #ifndef _SYS_ATTR_H
 #define	_SYS_ATTR_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #ifdef	__cplusplus
 extern "C" {
 #endif
@@ -56,6 +54,7 @@
 #define	A_AV_SCANSTAMP		"av_scanstamp"
 #define	A_OWNERSID		"ownersid"
 #define	A_GROUPSID		"groupsid"
+#define	A_REPARSE_POINT		"reparse"
 
 /* Attribute option for utilities */
 #define	O_HIDDEN	 "H"
@@ -68,6 +67,7 @@
 #define	O_NODUMP	 "d"
 #define	O_AV_QUARANTINED "q"
 #define	O_AV_MODIFIED	 "m"
+#define	O_REPARSE_POINT	 "r"
 #define	O_NONE		 ""
 
 /* ownersid and groupsid are composed of two nvpairs */
@@ -92,6 +92,7 @@
 	F_OWNERSID,
 	F_GROUPSID,
 	F_FSID,
+	F_REPARSE,
 	F_ATTR_ALL
 } f_attr_t;
 
--- a/usr/src/uts/common/sys/vfs.h	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/sys/vfs.h	Wed Oct 14 11:15:07 2009 -0500
@@ -297,6 +297,7 @@
 #define	VFSFT_ACEMASKONACCESS	0x100000020	/* Can use ACEMASK for access */
 #define	VFSFT_SYSATTR_VIEWS	0x100000040	/* Supports sysattr view i/f */
 #define	VFSFT_ACCESS_FILTER	0x100000080	/* dirents filtered by access */
+#define	VFSFT_REPARSE		0x100000100	/* Supports reparse point */
 
 /*
  * Argument structure for mount(2).
--- a/usr/src/uts/common/sys/vnode.h	Wed Oct 14 08:12:49 2009 -0700
+++ b/usr/src/uts/common/sys/vnode.h	Wed Oct 14 11:15:07 2009 -0500
@@ -387,6 +387,7 @@
 	uint8_t		xoa_av_quarantined;
 	uint8_t		xoa_av_modified;
 	uint8_t		xoa_av_scanstamp[AV_SCANSTAMP_SZ];
+	uint8_t		xoa_reparse;
 } xoptattr_t;
 
 /*
@@ -565,11 +566,12 @@
 #define	XAT0_AV_QUARANTINED	0x00000400	/* anti-virus quarantine */
 #define	XAT0_AV_MODIFIED	0x00000800	/* anti-virus modified */
 #define	XAT0_AV_SCANSTAMP	0x00001000	/* anti-virus scanstamp */
+#define	XAT0_REPARSE	0x00002000	/* FS reparse point */
 
 #define	XAT0_ALL_ATTRS	(XAT0_CREATETIME|XAT0_ARCHIVE|XAT0_SYSTEM| \
     XAT0_READONLY|XAT0_HIDDEN|XAT0_NOUNLINK|XAT0_IMMUTABLE|XAT0_APPENDONLY| \
     XAT0_NODUMP|XAT0_OPAQUE|XAT0_AV_QUARANTINED| \
-    XAT0_AV_MODIFIED|XAT0_AV_SCANSTAMP)
+    XAT0_AV_MODIFIED|XAT0_AV_SCANSTAMP|XAT0_REPARSE)
 
 /* Support for XAT_* optional attributes */
 #define	XVA_MASK		0xffffffff	/* Used to mask off 32 bits */
@@ -602,6 +604,7 @@
 #define	XAT_AV_QUARANTINED	((XAT0_INDEX << XVA_SHFT) | XAT0_AV_QUARANTINED)
 #define	XAT_AV_MODIFIED		((XAT0_INDEX << XVA_SHFT) | XAT0_AV_MODIFIED)
 #define	XAT_AV_SCANSTAMP	((XAT0_INDEX << XVA_SHFT) | XAT0_AV_SCANSTAMP)
+#define	XAT_REPARSE		((XAT0_INDEX << XVA_SHFT) | XAT0_REPARSE)
 
 /*
  * The returned attribute map array (xva_rtnattrmap[]) is located past the
@@ -1274,6 +1277,9 @@
 /* GFS tunnel for xattrs */
 int xattr_dir_lookup(vnode_t *, vnode_t **, int, cred_t *);
 
+/* Reparse Point */
+void reparse_point_init(void);
+
 /* Context identification */
 u_longlong_t	fs_new_caller_id();