From 6dc46c7d549b22864f9cfc06a2567b174cf6ddd4 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 27 Mar 2022 07:01:11 -0500 Subject: [PATCH] NAS-115465 / 22.12 / expose ZFS_ACL_TRIVIAL to users (#52) Add ACL_IS_TRIVIAL and ACL_IS_DIR flags as ACL-wide flags in the system.nfs4_acl_xdr generated on getxattr requests. This are non-RFC flags that are useful for userspace applications (especially the ACL_IS_TRIVIAL flag as it can be used to avoid relatively expensive ACL-related operations). Also add system.nfs4_acl_xdr to xattr results if ACL is not trivial. This duplicates POSIX ACL behavior where whether an ACL is set on a path can be determined via listxattr(). Since the ACL is not actually removed, we check whether the ZFS_ACL_TRIVIAL is set. If the flag is not set, then we omit the xattr name from the list. This allows users to determine whether ACL is trivial from listxattr(). Signed-off-by: Andrew Walker --- include/os/linux/spl/sys/acl.h | 2 ++ module/os/linux/zfs/zfs_acl.c | 4 ++++ module/os/linux/zfs/zpl_xattr.c | 10 +++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/os/linux/spl/sys/acl.h b/include/os/linux/spl/sys/acl.h index 5cd7a56b86ec..d66b523b985e 100644 --- a/include/os/linux/spl/sys/acl.h +++ b/include/os/linux/spl/sys/acl.h @@ -83,6 +83,8 @@ typedef struct ace_object { #define ACL_PROTECTED 0x0002 #define ACL_DEFAULTED 0x0004 #define ACL_FLAGS_ALL (ACL_AUTO_INHERIT|ACL_PROTECTED|ACL_DEFAULTED) +#define ACL_IS_TRIVIAL 0x10000 +#define ACL_IS_DIR 0x20000 #define ACE_ACCESS_ALLOWED_COMPOUND_ACE_TYPE 0x04 #define ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05 diff --git a/module/os/linux/zfs/zfs_acl.c b/module/os/linux/zfs/zfs_acl.c index a1fd3c9856cc..1c28dae2ab46 100644 --- a/module/os/linux/zfs/zfs_acl.c +++ b/module/os/linux/zfs/zfs_acl.c @@ -2054,6 +2054,10 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) vsecp->vsa_aclflags |= ACL_PROTECTED; if (zp->z_pflags & ZFS_ACL_AUTO_INHERIT) vsecp->vsa_aclflags |= ACL_AUTO_INHERIT; + if (zp->z_pflags & ZFS_ACL_TRIVIAL) + vsecp->vsa_aclflags |= ACL_IS_TRIVIAL; + if (S_ISDIR(ZTOI(zp)->i_mode)) + vsecp->vsa_aclflags |= ACL_IS_DIR; } mutex_exit(&zp->z_acl_lock); diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c index 30de314d8073..4e97c32bdce0 100644 --- a/module/os/linux/zfs/zpl_xattr.c +++ b/module/os/linux/zfs/zpl_xattr.c @@ -275,6 +275,14 @@ zpl_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size) goto out1; rw_enter(&zp->z_xattr_lock, RW_READER); + if ((zfsvfs->z_acl_type == ZFS_ACLTYPE_NFSV4) && + ((zp->z_pflags & ZFS_ACL_TRIVIAL) == 0)) { + error = zpl_xattr_filldir(&xf, NFS41ACL_XATTR, + sizeof (NFS41ACL_XATTR) - 1); + if (error) + goto out; + } + if (zfsvfs->z_use_sa && zp->z_is_sa) { error = zpl_xattr_list_sa(&xf); if (error) @@ -1737,7 +1745,7 @@ nfsacl41i_to_zfsacl(const nfsacl41i *nacl, vsecattr_t *_vsecp) vsecattr_t vsecp; vsecp.vsa_aclcnt = nacl->na41_aces.na41_aces_len; - vsecp.vsa_aclflags = nacl->na41_flag; + vsecp.vsa_aclflags = nacl->na41_flag & ACL_FLAGS_ALL; vsecp.vsa_aclentsz = vsecp.vsa_aclcnt * sizeof (ace_t); vsecp.vsa_mask = (VSA_ACE | VSA_ACE_ACLFLAGS); vsecp.vsa_aclentp = kmem_alloc(vsecp.vsa_aclentsz, KM_SLEEP);