Skip to content

Add support for FreeBSD's Solaris style extended attribute interface #17540

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/os/freebsd/spl/sys/vnode_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ struct taskq;
#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.
Expand Down
1 change: 1 addition & 0 deletions include/sys/xvattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ xva_getxoptattr(xvattr_t *xvap)
*/
#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
Expand Down
32 changes: 32 additions & 0 deletions module/os/freebsd/zfs/zfs_acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2357,10 +2357,42 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr,
* 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 __FreeBSD_version >= 1500040
if ((zp->z_pflags & ZFS_XATTR) && (flags & V_NAMEDATTR) == 0)
#else
if (zp->z_pflags & ZFS_XATTR)
#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);

/*
Expand Down
32 changes: 30 additions & 2 deletions module/os/freebsd/zfs/zfs_vfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,8 @@ zfs_set_fuid_feature(zfsvfs_t *zfsvfs)
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)
{
Expand Down Expand Up @@ -1289,6 +1291,16 @@ zfs_domount(vfs_t *vfsp, char *osname)
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)
Expand Down Expand Up @@ -1812,6 +1824,14 @@ zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp)
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;
Expand Down Expand Up @@ -1964,9 +1984,17 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp)
*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);
}
Expand Down
Loading
Loading