Skip to content

Commit e9389a3

Browse files
rmacklembehlendorf
authored andcommitted
Add support for FreeBSD's Solaris style extended attribute interface
FreeBSD commit 2ec2ba7e232d added the Solaris style syscall interface for extended attributes. This patch wires this interface into the FreeBSD ZFS port, since this style of extended attributes is supported by OpenZFS internally when the "xattr" property is set to "dir". Some specific changes: LOOKUP_NAMED_ATTR is defined to indicate the need to set V_NAMEDATTR for calls to zfs_zaccess(). V_NAMEDATTR indicates that the access checking does need to be done for FreeBSD. The access checking code for extended attributes was copy/pasted from the Linux port into zfs_zaccess() in the FreeBSD port. Most of the changes are in zfs_freebsd_lookup() and zfs_freebsd_create(). The semantics of these functions should remain unchanged unless named attributes are being manipulated. All the code changes are enabled for __FreeBSD_version 1500040 and newer. Signed-off-by: Rick Macklem <[email protected]>
1 parent 10a78e2 commit e9389a3

File tree

5 files changed

+348
-13
lines changed

5 files changed

+348
-13
lines changed

include/os/freebsd/spl/sys/vnode_impl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ struct taskq;
227227
#define LOOKUP_XATTR 0x02 /* lookup up extended attr dir */
228228
#define CREATE_XATTR_DIR 0x04 /* Create extended attr dir */
229229
#define LOOKUP_HAVE_SYSATTR_DIR 0x08 /* Already created virtual GFS dir */
230+
#define LOOKUP_NAMED_ATTR 0x10 /* Lookup a named attribute */
230231

231232
/*
232233
* Public vnode manipulation functions.

include/sys/xvattr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ xva_getxoptattr(xvattr_t *xvap)
311311
*/
312312
#define V_ACE_MASK 0x1 /* mask represents NFSv4 ACE permissions */
313313
#define V_APPEND 0x2 /* want to do append only check */
314+
#define V_NAMEDATTR 0x4 /* is a named attribute check */
314315

315316
/*
316317
* Structure used on VOP_GETSECATTR and VOP_SETSECATTR operations

module/os/freebsd/zfs/zfs_acl.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2357,10 +2357,42 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr,
23572357
* In FreeBSD, we don't care about permissions of individual ADS.
23582358
* Note that not checking them is not just an optimization - without
23592359
* this shortcut, EA operations may bogusly fail with EACCES.
2360+
*
2361+
* If this is a named attribute lookup, do the checks.
23602362
*/
2363+
#if __FreeBSD_version >= 1500040
2364+
if ((zp->z_pflags & ZFS_XATTR) && (flags & V_NAMEDATTR) == 0)
2365+
#else
23612366
if (zp->z_pflags & ZFS_XATTR)
2367+
#endif
23622368
return (0);
23632369

2370+
/*
2371+
* If a named attribute directory then validate against base file
2372+
*/
2373+
if (is_attr) {
2374+
if ((error = zfs_zget(ZTOZSB(zp),
2375+
zp->z_xattr_parent, &xzp)) != 0) {
2376+
return (error);
2377+
}
2378+
2379+
check_zp = xzp;
2380+
2381+
/*
2382+
* fixup mode to map to xattr perms
2383+
*/
2384+
2385+
if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) {
2386+
mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA);
2387+
mode |= ACE_WRITE_NAMED_ATTRS;
2388+
}
2389+
2390+
if (mode & (ACE_READ_DATA|ACE_EXECUTE)) {
2391+
mode &= ~(ACE_READ_DATA|ACE_EXECUTE);
2392+
mode |= ACE_READ_NAMED_ATTRS;
2393+
}
2394+
}
2395+
23642396
owner = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_uid, cr, ZFS_OWNER);
23652397

23662398
/*

module/os/freebsd/zfs/zfs_vfsops.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,8 @@ zfs_set_fuid_feature(zfsvfs_t *zfsvfs)
12091209
zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os);
12101210
}
12111211

1212+
extern int zfs_xattr_compat;
1213+
12121214
static int
12131215
zfs_domount(vfs_t *vfsp, char *osname)
12141216
{
@@ -1289,6 +1291,16 @@ zfs_domount(vfs_t *vfsp, char *osname)
12891291
goto out;
12901292
}
12911293

1294+
#if __FreeBSD_version >= 1500040
1295+
/*
1296+
* Named attributes can only work if the xattr property is set to
1297+
* on/dir and not sa. Also, zfs_xattr_compat must be set.
1298+
*/
1299+
if ((zfsvfs->z_flags & ZSB_XATTR) != 0 && !zfsvfs->z_xattr_sa &&
1300+
zfs_xattr_compat)
1301+
vfsp->mnt_flag |= MNT_NAMEDATTR;
1302+
#endif
1303+
12921304
vfs_mountedfrom(vfsp, osname);
12931305

12941306
if (!zfsvfs->z_issnap)
@@ -1812,6 +1824,14 @@ zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp)
18121824
err = vn_lock(*vpp, flags);
18131825
if (err != 0)
18141826
vrele(*vpp);
1827+
#if __FreeBSD_version >= 1500040
1828+
else if ((zp->z_pflags & ZFS_XATTR) != 0) {
1829+
if ((*vpp)->v_type == VDIR)
1830+
vn_irflag_set_cond(*vpp, VIRF_NAMEDDIR);
1831+
else
1832+
vn_irflag_set_cond(*vpp, VIRF_NAMEDATTR);
1833+
}
1834+
#endif
18151835
}
18161836
if (err != 0)
18171837
*vpp = NULL;
@@ -1964,9 +1984,17 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp)
19641984
*vpp = ZTOV(zp);
19651985
zfs_exit(zfsvfs, FTAG);
19661986
err = vn_lock(*vpp, flags);
1967-
if (err == 0)
1987+
if (err == 0) {
19681988
vnode_create_vobject(*vpp, zp->z_size, curthread);
1969-
else
1989+
#if __FreeBSD_version >= 1500040
1990+
if ((zp->z_pflags & ZFS_XATTR) != 0) {
1991+
if ((*vpp)->v_type == VDIR)
1992+
vn_irflag_set_cond(*vpp, VIRF_NAMEDDIR);
1993+
else
1994+
vn_irflag_set_cond(*vpp, VIRF_NAMEDATTR);
1995+
}
1996+
#endif
1997+
} else
19701998
*vpp = NULL;
19711999
return (err);
19722000
}

0 commit comments

Comments
 (0)