Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142019188
D49654.id156021.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
18 KB
Referenced Files
None
Subscribers
None
D49654.id156021.diff
View Options
diff --git a/sys/contrib/openzfs/include/os/freebsd/spl/sys/vnode_impl.h.xattr b/sys/contrib/openzfs/include/os/freebsd/spl/sys/vnode_impl.h
--- a/sys/contrib/openzfs/include/os/freebsd/spl/sys/vnode_impl.h.xattr
+++ b/sys/contrib/openzfs/include/os/freebsd/spl/sys/vnode_impl.h
@@ -227,6 +227,7 @@
#define LOOKUP_XATTR 0x02 /* lookup up extended attr dir */
#define CREATE_XATTR_DIR 0x04 /* Create extended attr dir */
#define LOOKUP_HAVE_SYSATTR_DIR 0x08 /* Already created virtual GFS dir */
+#define LOOKUP_NAMED_ATTR 0x10 /* Lookup a named attribute */
/*
* Public vnode manipulation functions.
diff --git a/sys/contrib/openzfs/include/sys/xvattr.h.xattr b/sys/contrib/openzfs/include/sys/xvattr.h
--- a/sys/contrib/openzfs/include/sys/xvattr.h.xattr
+++ b/sys/contrib/openzfs/include/sys/xvattr.h
@@ -311,6 +311,7 @@
*/
#define V_ACE_MASK 0x1 /* mask represents NFSv4 ACE permissions */
#define V_APPEND 0x2 /* want to do append only check */
+#define V_NAMEDATTR 0x4 /* is a named attribute check */
/*
* Structure used on VOP_GETSECATTR and VOP_SETSECATTR operations
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c.xattr b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c.xattr
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c
@@ -2357,10 +2357,42 @@
* In FreeBSD, we don't care about permissions of individual ADS.
* Note that not checking them is not just an optimization - without
* this shortcut, EA operations may bogusly fail with EACCES.
+ *
+ * If this is a named attribute lookup, do the checks.
*/
- if (zp->z_pflags & ZFS_XATTR)
+ if ((zp->z_pflags & ZFS_XATTR)
+#if __FreeBSD_version >= 1500040
+ && (flags & V_NAMEDATTR) == 0
+#endif
+ )
return (0);
+
+ /*
+ * If a named attribute directory then validate against base file
+ */
+ if (is_attr) {
+ if ((error = zfs_zget(ZTOZSB(zp),
+ zp->z_xattr_parent, &xzp)) != 0) {
+ return (error);
+ }
+
+ check_zp = xzp;
+
+ /*
+ * fixup mode to map to xattr perms
+ */
+
+ if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) {
+ mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA);
+ mode |= ACE_WRITE_NAMED_ATTRS;
+ }
+ if (mode & (ACE_READ_DATA|ACE_EXECUTE)) {
+ mode &= ~(ACE_READ_DATA|ACE_EXECUTE);
+ mode |= ACE_READ_NAMED_ATTRS;
+ }
+ }
+
owner = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_uid, cr, ZFS_OWNER);
/*
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c.xattr b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c.xattr
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c
@@ -1174,6 +1174,8 @@
zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os);
zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os);
}
+
+extern int zfs_xattr_compat;
static int
zfs_domount(vfs_t *vfsp, char *osname)
@@ -1255,6 +1257,16 @@
goto out;
}
+#if __FreeBSD_version >= 1500040
+ /*
+ * Named attributes can only work if the xattr property is set to
+ * on/dir and not sa. Also, zfs_xattr_compat must be set.
+ */
+ if ((zfsvfs->z_flags & ZSB_XATTR) != 0 && !zfsvfs->z_xattr_sa &&
+ zfs_xattr_compat)
+ vfsp->mnt_flag |= MNT_NAMEDATTR;
+#endif
+
vfs_mountedfrom(vfsp, osname);
if (!zfsvfs->z_issnap)
@@ -1778,6 +1790,14 @@
err = vn_lock(*vpp, flags);
if (err != 0)
vrele(*vpp);
+#if __FreeBSD_version >= 1500040
+ else if ((zp->z_pflags & ZFS_XATTR) != 0) {
+ if ((*vpp)->v_type == VDIR)
+ vn_irflag_set_cond(*vpp, VIRF_NAMEDDIR);
+ else
+ vn_irflag_set_cond(*vpp, VIRF_NAMEDATTR);
+ }
+#endif
}
if (err != 0)
*vpp = NULL;
@@ -1930,9 +1950,17 @@
*vpp = ZTOV(zp);
zfs_exit(zfsvfs, FTAG);
err = vn_lock(*vpp, flags);
- if (err == 0)
+ if (err == 0) {
vnode_create_vobject(*vpp, zp->z_size, curthread);
- else
+#if __FreeBSD_version >= 1500040
+ if ((zp->z_pflags & ZFS_XATTR) != 0) {
+ if ((*vpp)->v_type == VDIR)
+ vn_irflag_set_cond(*vpp, VIRF_NAMEDDIR);
+ else
+ vn_irflag_set_cond(*vpp, VIRF_NAMEDATTR);
+ }
+#endif
+ } else
*vpp = NULL;
return (err);
}
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c.xattr b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c.xattr
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
@@ -717,7 +717,12 @@
/*
* Do we have permission to get into attribute directory?
*/
- error = zfs_zaccess(zp, ACE_EXECUTE, 0, B_FALSE, cr, NULL);
+ if (flags & LOOKUP_NAMED_ATTR)
+ error = zfs_zaccess(zp, ACE_EXECUTE, V_NAMEDATTR,
+ B_FALSE, cr, NULL);
+ else
+ error = zfs_zaccess(zp, ACE_EXECUTE, 0, B_FALSE, cr,
+ NULL);
if (error) {
vrele(ZTOV(zp));
}
@@ -1583,7 +1588,7 @@
*/
static int
zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
- int *ncookies, cookie_t **cookies)
+ bool nameddir, int *ncookies, cookie_t **cookies)
{
znode_t *zp = VTOZ(vp);
iovec_t *iovp;
@@ -1692,7 +1697,9 @@
ino64_t objnum;
ushort_t reclen;
off64_t *next = NULL;
+ bool skipit, is_dot_or_dotdot;
+ is_dot_or_dotdot = false;
/*
* Special case `.', `..', and `.zfs'.
*/
@@ -1701,11 +1708,13 @@
zap->za_normalization_conflict = 0;
objnum = zp->z_id;
type = DT_DIR;
+ is_dot_or_dotdot = true;
} else if (offset == 1) {
(void) strcpy(zap->za_name, "..");
zap->za_normalization_conflict = 0;
objnum = parent;
type = DT_DIR;
+ is_dot_or_dotdot = true;
} else if (offset == 2 && zfs_show_ctldir(zp)) {
(void) strcpy(zap->za_name, ZFS_CTLDIR_NAME);
zap->za_normalization_conflict = 0;
@@ -1755,23 +1764,33 @@
}
break;
}
- /*
- * Add normal entry:
- */
- odp->d_ino = objnum;
- odp->d_reclen = reclen;
- odp->d_namlen = strlen(zap->za_name);
- /* NOTE: d_off is the offset for the *next* entry. */
- next = &odp->d_off;
- strlcpy(odp->d_name, zap->za_name, odp->d_namlen + 1);
- odp->d_type = type;
- dirent_terminate(odp);
- odp = (dirent64_t *)((intptr_t)odp + reclen);
- outcount += reclen;
+ /* Skip prohibited entries for a named attribute dir. */
+ skipit = false;
+ if (nameddir && !is_dot_or_dotdot &&
+ ((type != DT_REG && type != DT_UNKNOWN) ||
+ ZFS_XA_NS_PREFIX_FORBIDDEN(zap->za_name)))
+ skipit = true;
- ASSERT3S(outcount, <=, bufsize);
+ if (!skipit) {
+ /*
+ * Add normal entry:
+ */
+ odp->d_ino = objnum;
+ odp->d_reclen = reclen;
+ odp->d_namlen = strlen(zap->za_name);
+ /* NOTE: d_off is the offset for the *next* entry. */
+ next = &odp->d_off;
+ strlcpy(odp->d_name, zap->za_name, odp->d_namlen + 1);
+ odp->d_type = type;
+ dirent_terminate(odp);
+ odp = (dirent64_t *)((intptr_t)odp + reclen);
+
+ outcount += reclen;
+ ASSERT3S(outcount, <=, bufsize);
+ }
+
if (prefetch)
dmu_prefetch_dnode(os, objnum, ZIO_PRIORITY_SYNC_READ);
@@ -1785,13 +1804,15 @@
offset += 1;
}
- /* Fill the offset right after advancing the cursor. */
- if (next != NULL)
- *next = offset;
- if (cooks != NULL) {
- *cooks++ = offset;
- ncooks--;
- KASSERT(ncooks >= 0, ("ncookies=%d", ncooks));
+ if (!skipit) {
+ /* Fill the offset right after advancing the cursor. */
+ if (next != NULL)
+ *next = offset;
+ if (cooks != NULL) {
+ *cooks++ = offset;
+ ncooks--;
+ KASSERT(ncooks >= 0, ("ncookies=%d", ncooks));
+ }
}
}
zp->z_zn_prefetch = B_FALSE; /* a lookup will re-enable pre-fetching */
@@ -4480,8 +4501,16 @@
* ZFS itself only knowns about VREAD, VWRITE, VEXEC and VAPPEND,
*/
accmode = ap->a_accmode & (VREAD|VWRITE|VEXEC|VAPPEND);
- if (accmode != 0)
- error = zfs_access(zp, accmode, 0, ap->a_cred);
+ if (accmode != 0) {
+#if __FreeBSD_version >= 1500040
+ /* For named attributes, do the checks. */
+ if ((vn_irflag_read(vp) & VIRF_NAMEDATTR) != 0)
+ error = zfs_access(zp, accmode, V_NAMEDATTR,
+ ap->a_cred);
+ else
+#endif
+ error = zfs_access(zp, accmode, 0, ap->a_cred);
+ }
/*
* VADMIN has to be handled by vaccess().
@@ -4513,7 +4542,179 @@
struct componentname *a_cnp;
};
#endif
+
+#if __FreeBSD_version >= 1500040
+static int
+zfs_lookup_nameddir(struct vnode *dvp, struct componentname *cnp,
+ struct vnode **vpp)
+{
+ struct vnode *xvp;
+ int error, flags;
+
+ *vpp = NULL;
+ flags = LOOKUP_XATTR | LOOKUP_NAMED_ATTR;
+ if ((cnp->cn_flags & CREATENAMED) != 0)
+ flags |= CREATE_XATTR_DIR;
+ error = zfs_lookup(dvp, NULL, &xvp, NULL, 0, cnp->cn_cred, flags,
+ B_FALSE);
+ if (error == 0) {
+ if ((cnp->cn_flags & LOCKLEAF) != 0)
+ error = vn_lock(xvp, cnp->cn_lkflags);
+ if (error == 0) {
+ vn_irflag_set_cond(xvp, VIRF_NAMEDDIR);
+ *vpp = xvp;
+ } else {
+ vrele(xvp);
+ }
+ }
+ return (error);
+}
+
+static ssize_t
+zfs_readdir_named(struct vnode *vp, char *buf, ssize_t blen, off_t *offp,
+ int *eofflagp, struct ucred *cred, struct thread *td)
+{
+ struct uio io;
+ struct iovec iv;
+ zfs_uio_t uio;
+ int error;
+
+ io.uio_offset = *offp;
+ io.uio_segflg = UIO_SYSSPACE;
+ io.uio_rw = UIO_READ;
+ io.uio_td = td;
+ iv.iov_base = buf;
+ iv.iov_len = blen;
+ io.uio_iov = &iv;
+ io.uio_iovcnt = 1;
+ io.uio_resid = blen;
+ zfs_uio_init(&uio, &io);
+ error = zfs_readdir(vp, &uio, cred, eofflagp, true, NULL, NULL);
+ if (error != 0)
+ return (-1);
+ *offp = io.uio_offset;
+ return (blen - io.uio_resid);
+}
+
+static bool
+zfs_has_namedattr(struct vnode *vp, struct ucred *cred)
+{
+ struct componentname cn;
+ struct vnode *xvp;
+ struct dirent *dp;
+ off_t offs;
+ ssize_t rsize;
+ char *buf, *cp, *endcp;
+ int eofflag, error;
+ bool ret;
+
+ if ((vp->v_mount->mnt_flag & MNT_NAMEDATTR) == 0)
+ return (false);
+
+ /* Now see if a named attribute directory exists. */
+ cn.cn_flags = LOCKLEAF;
+ cn.cn_lkflags = LK_SHARED;
+ cn.cn_cred = cred;
+ error = zfs_lookup_nameddir(vp, &cn, &xvp);
+ if (error != 0)
+ return (false);
+
+ /* It exists, so see if there is any entry other than "." and "..". */
+ buf = malloc(DEV_BSIZE, M_TEMP, M_WAITOK);
+ ret = false;
+ offs = 0;
+ do {
+ rsize = zfs_readdir_named(xvp, buf, DEV_BSIZE, &offs, &eofflag,
+ cred, curthread);
+ if (rsize <= 0)
+ break;
+ cp = buf;
+ endcp = &buf[rsize];
+ while (cp < endcp) {
+ dp = (struct dirent *)cp;
+ if ((dp->d_namlen == 1 && dp->d_name[0] != '.') ||
+ (dp->d_namlen == 2 && (dp->d_name[0] != '.' ||
+ dp->d_name[1] != '.')) || dp->d_namlen > 2) {
+ ret = true;
+ break;
+ }
+ cp += dp->d_reclen;
+ }
+ } while (!ret && rsize > 0 && eofflag == 0);
+ vput(xvp);
+ free(buf, M_TEMP);
+ return (ret);
+}
+
+static int
+zfs_freebsd_lookup(struct vop_lookup_args *ap, boolean_t cached)
+{
+ struct componentname *cnp = ap->a_cnp;
+ char nm[NAME_MAX + 1];
+ int error;
+ struct vnode **vpp = ap->a_vpp, *dvp = ap->a_dvp, *xvp;
+ bool is_nameddir, needs_nameddir, opennamed = false;
+ /*
+ * These variables are used to handle the named attribute cases:
+ * opennamed - Is true when this is a call from open with O_NAMEDATTR
+ * specified and it is the last component.
+ * is_nameddir - Is true when the directory is a named attribute dir.
+ * needs_nameddir - Is set when the lookup needs to look for/create
+ * a named attribute directory. It is only set when is_nameddir
+ * is false and opennamed is true.
+ * xvp - Is the directory that the lookup needs to be done in.
+ * Usually dvp, unless needs_nameddir is true where it is the
+ * result of the first non-named directory lookup.
+ * Note that name caching must be disabled for named attribute
+ * handling.
+ */
+ needs_nameddir = false;
+ xvp = dvp;
+ opennamed = (cnp->cn_flags & (OPENNAMED | ISLASTCN)) ==
+ (OPENNAMED | ISLASTCN);
+ is_nameddir = (vn_irflag_read(dvp) & VIRF_NAMEDDIR) != 0;
+ if (is_nameddir && (cnp->cn_flags & ISLASTCN) == 0)
+ return (ENOATTR);
+ if (opennamed && !is_nameddir && (cnp->cn_flags & ISDOTDOT) != 0)
+ return (ENOATTR);
+ if (opennamed || is_nameddir)
+ cnp->cn_flags &= ~MAKEENTRY;
+ if (opennamed && !is_nameddir)
+ needs_nameddir = true;
+ ASSERT3U(cnp->cn_namelen, <, sizeof (nm));
+ error = 0;
+ *vpp = NULL;
+ if (needs_nameddir) {
+ error = zfs_lookup_nameddir(dvp, cnp, &xvp);
+ if (error == 0)
+ is_nameddir = true;
+ }
+ if (error == 0) {
+ if (!needs_nameddir || cnp->cn_namelen != 1 ||
+ *cnp->cn_nameptr != '.') {
+ strlcpy(nm, cnp->cn_nameptr, MIN(cnp->cn_namelen + 1,
+ sizeof (nm)));
+ error = zfs_lookup(xvp, nm, vpp, cnp, cnp->cn_nameiop,
+ cnp->cn_cred, 0, cached);
+ if (is_nameddir && error == 0 &&
+ (cnp->cn_namelen != 1 || *cnp->cn_nameptr != '.') &&
+ (cnp->cn_flags & ISDOTDOT) == 0) {
+ if ((*vpp)->v_type == VDIR)
+ vn_irflag_set_cond(*vpp, VIRF_NAMEDDIR);
+ else
+ vn_irflag_set_cond(*vpp, VIRF_NAMEDATTR);
+ }
+ if (needs_nameddir && xvp != *vpp)
+ vput(xvp);
+ } else {
+ /* Lookup of "." when a named attribute dir is needed. */
+ *vpp = xvp;
+ }
+ }
+ return (error);
+}
+#else
static int
zfs_freebsd_lookup(struct vop_lookup_args *ap, boolean_t cached)
{
@@ -4526,6 +4727,7 @@
return (zfs_lookup(ap->a_dvp, nm, ap->a_vpp, cnp, cnp->cn_nameiop,
cnp->cn_cred, 0, cached));
}
+#endif
static int
zfs_freebsd_cachedlookup(struct vop_cachedlookup_args *ap)
@@ -4548,12 +4750,28 @@
zfsvfs_t *zfsvfs;
zfsvfs = ap->a_dvp->v_mount->mnt_data;
- if (zfsvfs->z_use_namecache)
+ if (zfsvfs->z_use_namecache
+#if __FreeBSD_version >= 1500040
+ && (ap->a_cnp->cn_flags & OPENNAMED) == 0
+#endif
+ )
return (vfs_cache_lookup(ap));
else
return (zfs_freebsd_lookup(ap, B_FALSE));
}
+static int
+zfs_check_attrname(const char *name)
+{
+ /* We don't allow '/' character in attribute name. */
+ if (strchr(name, '/') != NULL)
+ return (SET_ERROR(EINVAL));
+ /* We don't allow attribute names that start with a namespace prefix. */
+ if (ZFS_XA_NS_PREFIX_FORBIDDEN(name))
+ return (SET_ERROR(EINVAL));
+ return (0);
+}
+
#ifndef _SYS_SYSPROTO_H_
struct vop_create_args {
struct vnode *a_dvp;
@@ -4571,6 +4789,11 @@
vattr_t *vap = ap->a_vap;
znode_t *zp = NULL;
int rc, mode;
+ struct vnode *dvp = ap->a_dvp;
+#if __FreeBSD_version >= 1500040
+ struct vnode *xvp;
+ bool is_nameddir;
+#endif
#if __FreeBSD_version < 1400068
ASSERT(cnp->cn_flags & SAVENAME);
@@ -4581,10 +4804,36 @@
zfsvfs = ap->a_dvp->v_mount->mnt_data;
*ap->a_vpp = NULL;
- rc = zfs_create(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap, 0, mode,
- &zp, cnp->cn_cred, 0 /* flag */, NULL /* vsecattr */, NULL);
+ rc = 0;
+#if __FreeBSD_version >= 1500040
+ xvp = NULL;
+ is_nameddir = (vn_irflag_read(dvp) & VIRF_NAMEDDIR) != 0;
+ if (!is_nameddir && (cnp->cn_flags & OPENNAMED) != 0) {
+ /* Needs a named attribute directory. */
+ rc = zfs_lookup_nameddir(dvp, cnp, &xvp);
+ if (rc == 0) {
+ dvp = xvp;
+ is_nameddir = true;
+ }
+ }
+ if (is_nameddir && rc == 0 && (cnp->cn_flags & OPENNAMED) != 0)
+ rc = zfs_check_attrname(cnp->cn_nameptr);
+#endif
+
if (rc == 0)
+ rc = zfs_create(VTOZ(dvp), cnp->cn_nameptr, vap, 0, mode,
+ &zp, cnp->cn_cred, 0 /* flag */, NULL /* vsecattr */, NULL);
+#if __FreeBSD_version >= 1500040
+ if (xvp != NULL)
+ vput(xvp);
+#endif
+ if (rc == 0) {
*ap->a_vpp = ZTOV(zp);
+#if __FreeBSD_version >= 1500040
+ if (is_nameddir)
+ vn_irflag_set_cond(*ap->a_vpp, VIRF_NAMEDATTR);
+#endif
+ }
if (zfsvfs->z_use_namecache &&
rc == 0 && (cnp->cn_flags & MAKEENTRY) != 0)
cache_enter(ap->a_dvp, *ap->a_vpp, cnp);
@@ -4603,13 +4852,21 @@
static int
zfs_freebsd_remove(struct vop_remove_args *ap)
{
+ int error = 0;
#if __FreeBSD_version < 1400068
ASSERT(ap->a_cnp->cn_flags & SAVENAME);
#endif
- return (zfs_remove_(ap->a_dvp, ap->a_vp, ap->a_cnp->cn_nameptr,
- ap->a_cnp->cn_cred));
+#if __FreeBSD_version >= 1500040
+ if ((vn_irflag_read(ap->a_dvp) & VIRF_NAMEDDIR) != 0)
+ error = zfs_check_attrname(ap->a_cnp->cn_nameptr);
+#endif
+
+ if (error == 0)
+ error = zfs_remove_(ap->a_dvp, ap->a_vp, ap->a_cnp->cn_nameptr,
+ ap->a_cnp->cn_cred);
+ return (error);
}
#ifndef _SYS_SYSPROTO_H_
@@ -4678,8 +4935,15 @@
zfs_freebsd_readdir(struct vop_readdir_args *ap)
{
zfs_uio_t uio;
+ bool nameddir;
+
+ nameddir = false;
+#if __FreeBSD_version >= 1500040
+ if ((vn_irflag_read(ap->a_vp) & VIRF_NAMEDDIR) != 0)
+ nameddir = true;
+#endif
zfs_uio_init(&uio, ap->a_uio);
- return (zfs_readdir(ap->a_vp, &uio, ap->a_cred, ap->a_eofflag,
+ return (zfs_readdir(ap->a_vp, &uio, ap->a_cred, ap->a_eofflag, nameddir,
ap->a_ncookies, ap->a_cookies));
}
@@ -4767,6 +5031,11 @@
#undef FLAG_CHECK
*vap = xvap.xva_vattr;
vap->va_flags = fflags;
+
+#if __FreeBSD_version >= 1500040
+ if ((vn_irflag_read(ap->a_vp) & (VIRF_NAMEDDIR | VIRF_NAMEDATTR)) != 0)
+ vap->va_bsdflags |= SFBSD_NAMEDATTR;
+#endif
return (0);
}
@@ -4909,16 +5178,25 @@
vnode_t *fvp = ap->a_fvp;
vnode_t *tdvp = ap->a_tdvp;
vnode_t *tvp = ap->a_tvp;
- int error;
+ int error = 0;
#if __FreeBSD_version < 1400068
ASSERT(ap->a_fcnp->cn_flags & (SAVENAME|SAVESTART));
ASSERT(ap->a_tcnp->cn_flags & (SAVENAME|SAVESTART));
#endif
- error = zfs_do_rename(fdvp, &fvp, ap->a_fcnp, tdvp, &tvp,
- ap->a_tcnp, ap->a_fcnp->cn_cred);
+#if __FreeBSD_version >= 1500040
+ if ((vn_irflag_read(fdvp) & VIRF_NAMEDDIR) != 0) {
+ error = zfs_check_attrname(ap->a_fcnp->cn_nameptr);
+ if (error == 0)
+ error = zfs_check_attrname(ap->a_tcnp->cn_nameptr);
+ }
+#endif
+ if (error == 0)
+ error = zfs_do_rename(fdvp, &fvp, ap->a_fcnp, tdvp, &tvp,
+ ap->a_tcnp, ap->a_fcnp->cn_cred);
+
vrele(fdvp);
vrele(fvp);
vrele(tdvp);
@@ -5171,24 +5449,28 @@
return (0);
}
return (EINVAL);
+#if __FreeBSD_version >= 1500040
+ case _PC_NAMEDATTR_ENABLED:
+ MNT_ILOCK(ap->a_vp->v_mount);
+ if ((ap->a_vp->v_mount->mnt_flag & MNT_NAMEDATTR) != 0)
+ *ap->a_retval = 1;
+ else
+ *ap->a_retval = 0;
+ MNT_IUNLOCK(ap->a_vp->v_mount);
+ return (0);
+ case _PC_HAS_NAMEDATTR:
+ if (zfs_has_namedattr(ap->a_vp, curthread->td_ucred))
+ *ap->a_retval = 1;
+ else
+ *ap->a_retval = 0;
+ return (0);
+#endif
default:
return (vop_stdpathconf(ap));
}
}
-static int zfs_xattr_compat = 1;
-
-static int
-zfs_check_attrname(const char *name)
-{
- /* We don't allow '/' character in attribute name. */
- if (strchr(name, '/') != NULL)
- return (SET_ERROR(EINVAL));
- /* We don't allow attribute names that start with a namespace prefix. */
- if (ZFS_XA_NS_PREFIX_FORBIDDEN(name))
- return (SET_ERROR(EINVAL));
- return (0);
-}
+int zfs_xattr_compat = 1;
/*
* FreeBSD's extended attributes namespace defines file name prefix for ZFS'
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jan 16, 12:24 AM (18 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27656308
Default Alt Text
D49654.id156021.diff (18 KB)
Attached To
Mode
D49654: openzfs: Add support for Solaris style extended attributes
Attached
Detach File
Event Timeline
Log In to Comment