From 58e586c894fbde5117a1c2540cfe8a5bcde2efd5 Mon Sep 17 00:00:00 2001 From: Ryan Moeller Date: Thu, 29 Apr 2021 03:00:16 +0000 Subject: [PATCH] FreeBSD: Implement zfs_deleteextattr_sa Signed-off-by: Ryan Moeller --- module/os/freebsd/zfs/zfs_vnops_os.c | 114 +++++++++++++++++++-------- 1 file changed, 82 insertions(+), 32 deletions(-) diff --git a/module/os/freebsd/zfs/zfs_vnops_os.c b/module/os/freebsd/zfs/zfs_vnops_os.c index 58a3b8f9f9ee..efeecc4e62ff 100644 --- a/module/os/freebsd/zfs/zfs_vnops_os.c +++ b/module/os/freebsd/zfs/zfs_vnops_os.c @@ -5451,54 +5451,25 @@ struct vop_deleteextattr { }; #endif -/* - * Vnode operation to remove a named attribute. - */ static int -zfs_deleteextattr(struct vop_deleteextattr_args *ap) +zfs_deleteextattr_dir(struct vop_deleteextattr_args *ap, const char *attrname) { - zfsvfs_t *zfsvfs = VTOZ(ap->a_vp)->z_zfsvfs; struct thread *td = ap->a_td; struct nameidata nd; - char attrname[255]; vnode_t *xvp = NULL, *vp; int error; - /* - * If the xattr property is off, refuse the request. - */ - if (!(zfsvfs->z_flags & ZSB_XATTR)) { - return (SET_ERROR(EOPNOTSUPP)); - } - - error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, - ap->a_cred, ap->a_td, VWRITE); - if (error != 0) - return (error); - - error = zfs_create_attrname(ap->a_attrnamespace, ap->a_name, attrname, - sizeof (attrname)); - if (error != 0) - return (error); - - ZFS_ENTER(zfsvfs); - error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred, td, LOOKUP_XATTR, B_FALSE); - if (error != 0) { - ZFS_EXIT(zfsvfs); + if (error != 0) return (error); - } NDINIT_ATVP(&nd, DELETE, NOFOLLOW | LOCKPARENT | LOCKLEAF, UIO_SYSSPACE, attrname, xvp, td); error = namei(&nd); vp = nd.ni_vp; if (error != 0) { - ZFS_EXIT(zfsvfs); NDFREE(&nd, NDF_ONLY_PNBUF); - if (error == ENOENT) - error = ENOATTR; return (error); } @@ -5510,11 +5481,90 @@ zfs_deleteextattr(struct vop_deleteextattr_args *ap) vrele(vp); else vput(vp); - ZFS_EXIT(zfsvfs); return (error); } +static int +zfs_deleteextattr_sa(struct vop_deleteextattr_args *ap, const char *attrname) +{ + znode_t *zp = VTOZ(ap->a_vp); + nvlist_t *nvl; + int error; + + error = zfs_ensure_xattr_cached(zp); + if (error != 0) + return (error); + + ASSERT(RW_WRITE_HELD(&zp->z_xattr_lock)); + ASSERT3P(zp->z_xattr_cached, !=, NULL); + + nvl = zp->z_xattr_cached; + error = nvlist_remove(nvl, attrname, DATA_TYPE_BYTE_ARRAY); + if (error == 0) + error = zfs_sa_set_xattr(zp); + if (error != 0) { + zp->z_xattr_cached = NULL; + nvlist_free(nvl); + } + return (error); +} + +/* + * Vnode operation to remove a named attribute. + */ +static int +zfs_deleteextattr(struct vop_deleteextattr_args *ap) +{ + znode_t *zp = VTOZ(ap->a_vp); + zfsvfs_t *zfsvfs = ZTOZSB(zp); + char attrname[EXTATTR_MAXNAMELEN+1]; + int error; + + /* + * If the xattr property is off, refuse the request. + */ + if (!(zfsvfs->z_flags & ZSB_XATTR)) + return (SET_ERROR(EOPNOTSUPP)); + + error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, + ap->a_cred, ap->a_td, VWRITE); + if (error != 0) + return (error); + + error = zfs_create_attrname(ap->a_attrnamespace, ap->a_name, attrname, + sizeof (attrname)); + if (error != 0) + return (error); + + size_t size = 0; + struct vop_getextattr_args vga = { + .a_vp = ap->a_vp, + .a_size = &size, + .a_cred = ap->a_cred, + .a_td = ap->a_td, + }; + error = ENOENT; + ZFS_ENTER(zfsvfs); + ZFS_VERIFY_ZP(zp); + rw_enter(&zp->z_xattr_lock, RW_WRITER); + if (zfsvfs->z_use_sa && zp->z_is_sa) { + error = zfs_getextattr_sa(&vga, attrname); + if (error == 0) + error = zfs_deleteextattr_sa(ap, attrname); + } + if (error == ENOENT) { + error = zfs_getextattr_dir(&vga, attrname); + if (error == 0) + error = zfs_deleteextattr_dir(ap, attrname); + } + rw_exit(&zp->z_xattr_lock); + ZFS_EXIT(zfsvfs); + if (error == ENOENT) + error = SET_ERROR(ENOATTR); + return (error); +} + #ifndef _SYS_SYSPROTO_H_ struct vop_setextattr { IN struct vnode *a_vp;