diff options
author | Dai Ngo <dai.ngo@sun.com> | 2009-10-14 11:15:07 -0500 |
---|---|---|
committer | Dai Ngo <dai.ngo@sun.com> | 2009-10-14 11:15:07 -0500 |
commit | 7a286c471efbab8562f7655a82931904703fffe0 (patch) | |
tree | bbd1ea3af4176ce7e295afaa9eb7cb86b95010c0 /usr/src/uts | |
parent | 635216b673cf196ac523ff2a7ab715717e553292 (diff) | |
download | illumos-gate-7a286c471efbab8562f7655a82931904703fffe0.tar.gz |
6886081 Solaris needs reparse point support (PSARC 2009/387)
PSARC 2009/387 Pathname Reparse Points
Diffstat (limited to 'usr/src/uts')
-rw-r--r-- | usr/src/uts/common/Makefile.files | 1 | ||||
-rw-r--r-- | usr/src/uts/common/Makefile.rules | 7 | ||||
-rw-r--r-- | usr/src/uts/common/fs/Makefile | 14 | ||||
-rw-r--r-- | usr/src/uts/common/fs/fs_reparse.h | 88 | ||||
-rw-r--r-- | usr/src/uts/common/fs/fs_subr.c | 181 | ||||
-rw-r--r-- | usr/src/uts/common/fs/vfs.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/fs/vnode.c | 46 | ||||
-rw-r--r-- | usr/src/uts/common/fs/xattr.c | 13 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/zfs_znode.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_log.c | 3 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_replay.c | 6 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_vfsops.c | 1 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_vnops.c | 12 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_znode.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zut/zut.c | 3 | ||||
-rw-r--r-- | usr/src/uts/common/sys/attr.h | 7 | ||||
-rw-r--r-- | usr/src/uts/common/sys/vfs.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/sys/vnode.h | 8 |
18 files changed, 384 insertions, 16 deletions
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index 2c0777fc54..7d8ed8dac1 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -162,6 +162,7 @@ GENUNIX_OBJS += \ fork.o \ vpm.o \ fsat.o \ + fs_reparse.o \ fs_subr.o \ fsflush.o \ ftrace.o \ diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules index 75354e4c62..01a28db0be 100644 --- a/usr/src/uts/common/Makefile.rules +++ b/usr/src/uts/common/Makefile.rules @@ -340,6 +340,10 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/io/scsi/adapters/pmcs/%.bin $(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/vr/%.c $(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/yge/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(COMMONBASE)/fsreparse/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) diff --git a/usr/src/uts/common/fs/Makefile b/usr/src/uts/common/fs/Makefile index 28ad019955..53660e655d 100644 --- a/usr/src/uts/common/fs/Makefile +++ b/usr/src/uts/common/fs/Makefile @@ -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 diff --git a/usr/src/uts/common/fs/fs_reparse.h b/usr/src/uts/common/fs/fs_reparse.h new file mode 100644 index 0000000000..ec44484117 --- /dev/null +++ b/usr/src/uts/common/fs/fs_reparse.h @@ -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 */ diff --git a/usr/src/uts/common/fs/fs_subr.c b/usr/src/uts/common/fs/fs_subr.c index 5187ecf327..a465a97043 100644 --- a/usr/src/uts/common/fs/fs_subr.c +++ b/usr/src/uts/common/fs/fs_subr.c @@ -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 @@ static callb_cpr_t *frlock_serialize_blocked(flk_cb_when_t, void *); 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 @@ fs_vscan(vnode_t *vp, cred_t *cr, int async) 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); +} diff --git a/usr/src/uts/common/fs/vfs.c b/usr/src/uts/common/fs/vfs.c index bf9d325048..0d750e00ed 100644 --- a/usr/src/uts/common/fs/vfs.c +++ b/usr/src/uts/common/fs/vfs.c @@ -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 @@ vfsinit(void) } xattr_init(); + + reparse_point_init(); } vfs_t * diff --git a/usr/src/uts/common/fs/vnode.c b/usr/src/uts/common/fs/vnode.c index 09a011fc87..a42259df93 100644 --- a/usr/src/uts/common/fs/vnode.c +++ b/usr/src/uts/common/fs/vnode.c @@ -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 @@ int vopstats_enabled = 1; 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 @@ fop_symlink( int flags) { int err; + xvattr_t xvattr; /* * If this file system doesn't support case-insensitive access @@ -3616,6 +3623,14 @@ fop_symlink( 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 @@ vsd_realloc(void *old, size_t osize, size_t nsize) } 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); +} diff --git a/usr/src/uts/common/fs/xattr.c b/usr/src/uts/common/fs/xattr.c index 274c57869c..137379ecc3 100644 --- a/usr/src/uts/common/fs/xattr.c +++ b/usr/src/uts/common/fs/xattr.c @@ -212,6 +212,9 @@ xattr_fill_nvlist(vnode_t *vp, xattr_view_t xattr_view, nvlist_t *nvlp, 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 @@ xattr_fill_nvlist(vnode_t *vp, xattr_view_t xattr_view, nvlist_t *nvlp, 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 @@ xattr_file_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, return (EINVAL); } break; + case F_REPARSE: + XVA_SET_REQ(&xvattr, XAT_REPARSE); + xoap->xoa_reparse = value; + break; default: break; } @@ -807,6 +819,7 @@ xattr_copy(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, 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); diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h index 5db5b8d518..ca826abbac 100644 --- a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h +++ b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h @@ -57,6 +57,7 @@ extern "C" { #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) \ { \ diff --git a/usr/src/uts/common/fs/zfs/zfs_log.c b/usr/src/uts/common/fs/zfs/zfs_log.c index 4df7115f58..f0a713ed94 100644 --- a/usr/src/uts/common/fs/zfs/zfs_log.c +++ b/usr/src/uts/common/fs/zfs/zfs_log.c @@ -175,6 +175,9 @@ zfs_log_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) 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 * diff --git a/usr/src/uts/common/fs/zfs/zfs_replay.c b/usr/src/uts/common/fs/zfs/zfs_replay.c index 85b79703a7..232422b0f8 100644 --- a/usr/src/uts/common/fs/zfs/zfs_replay.c +++ b/usr/src/uts/common/fs/zfs/zfs_replay.c @@ -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_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) 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 diff --git a/usr/src/uts/common/fs/zfs/zfs_vfsops.c b/usr/src/uts/common/fs/zfs/zfs_vfsops.c index 8f51a0dbf2..7a6b850d1c 100644 --- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c +++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c @@ -1049,6 +1049,7 @@ zfs_set_fuid_feature(zfsvfs_t *zfsvfs) 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); } } diff --git a/usr/src/uts/common/fs/zfs/zfs_vnops.c b/usr/src/uts/common/fs/zfs/zfs_vnops.c index 644b2dba9a..6513640437 100644 --- a/usr/src/uts/common/fs/zfs/zfs_vnops.c +++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c @@ -2370,6 +2370,12 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, 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 @@ top: } } + 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))) { diff --git a/usr/src/uts/common/fs/zfs/zfs_znode.c b/usr/src/uts/common/fs/zfs/zfs_znode.c index 62156fb4f6..c861bd9936 100644 --- a/usr/src/uts/common/fs/zfs/zfs_znode.c +++ b/usr/src/uts/common/fs/zfs/zfs_znode.c @@ -909,6 +909,10 @@ zfs_xvattr_set(znode_t *zp, xvattr_t *xvap) 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 diff --git a/usr/src/uts/common/fs/zut/zut.c b/usr/src/uts/common/fs/zut/zut.c index 9381b69aea..c655585968 100644 --- a/usr/src/uts/common/fs/zut/zut.c +++ b/usr/src/uts/common/fs/zut/zut.c @@ -217,6 +217,7 @@ zut_stat64(vnode_t *vp, struct stat64 *sb, uint64_t *xvs, int flag, cred_t *cr) 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 @@ zut_stat64(vnode_t *vp, struct stat64 *sb, uint64_t *xvs, int flag, cred_t *cr) *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); } diff --git a/usr/src/uts/common/sys/attr.h b/usr/src/uts/common/sys/attr.h index 86c4cd5d6c..b312b5a429 100644 --- a/usr/src/uts/common/sys/attr.h +++ b/usr/src/uts/common/sys/attr.h @@ -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 @@ extern "C" { #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 @@ extern "C" { #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 @@ typedef enum { F_OWNERSID, F_GROUPSID, F_FSID, + F_REPARSE, F_ATTR_ALL } f_attr_t; diff --git a/usr/src/uts/common/sys/vfs.h b/usr/src/uts/common/sys/vfs.h index 17ee536024..4d0d6d1257 100644 --- a/usr/src/uts/common/sys/vfs.h +++ b/usr/src/uts/common/sys/vfs.h @@ -297,6 +297,7 @@ typedef uint64_t vfs_feature_t; #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). diff --git a/usr/src/uts/common/sys/vnode.h b/usr/src/uts/common/sys/vnode.h index f3e3fe6879..a060c30434 100644 --- a/usr/src/uts/common/sys/vnode.h +++ b/usr/src/uts/common/sys/vnode.h @@ -387,6 +387,7 @@ typedef struct xoptattr { 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 @@ typedef vattr_t vattr32_t; #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 @@ typedef vattr_t vattr32_t; #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 @@ void xattr_init(void); /* Initialize vnodeops for xattrs */ /* 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(); |