diff -r 76b07e8f675d -r d8fbd96b79b3 usr/src/uts/common/fs/zfs/zfs_acl.c --- a/usr/src/uts/common/fs/zfs/zfs_acl.c Thu Mar 26 11:48:34 2009 -0600 +++ b/usr/src/uts/common/fs/zfs/zfs_acl.c Thu Mar 26 13:13:24 2009 -0600 @@ -539,8 +539,9 @@ * ACE FUIDs will be created later. */ int -zfs_copy_ace_2_fuid(vtype_t obj_type, zfs_acl_t *aclp, void *datap, - zfs_ace_t *z_acl, int aclcnt, size_t *size) +zfs_copy_ace_2_fuid(zfsvfs_t *zfsvfs, vtype_t obj_type, zfs_acl_t *aclp, + void *datap, zfs_ace_t *z_acl, int aclcnt, size_t *size, + zfs_fuid_info_t **fuidp, cred_t *cr) { int i; uint16_t entry_type; @@ -556,9 +557,9 @@ entry_type = aceptr->z_hdr.z_flags & ACE_TYPE_FLAGS; if (entry_type != ACE_OWNER && entry_type != OWNING_GROUP && entry_type != ACE_EVERYONE) { - if (!aclp->z_has_fuids) - aclp->z_has_fuids = IS_EPHEMERAL(acep->a_who); - aceptr->z_fuid = (uint64_t)acep->a_who; + aceptr->z_fuid = zfs_fuid_create(zfsvfs, acep->a_who, + cr, (entry_type == 0) ? + ZFS_ACE_USER : ZFS_ACE_GROUP, fuidp); } /* @@ -683,7 +684,7 @@ * convert old ACL format to new */ void -zfs_acl_xform(znode_t *zp, zfs_acl_t *aclp) +zfs_acl_xform(znode_t *zp, zfs_acl_t *aclp, cred_t *cr) { zfs_oldace_t *oldaclp; int i; @@ -715,9 +716,9 @@ newaclnode = zfs_acl_node_alloc(aclp->z_acl_count * sizeof (zfs_object_ace_t)); aclp->z_ops = zfs_acl_fuid_ops; - VERIFY(zfs_copy_ace_2_fuid(ZTOV(zp)->v_type, aclp, oldaclp, - newaclnode->z_acldata, aclp->z_acl_count, - &newaclnode->z_size) == 0); + VERIFY(zfs_copy_ace_2_fuid(zp->z_zfsvfs, ZTOV(zp)->v_type, aclp, + oldaclp, newaclnode->z_acldata, aclp->z_acl_count, + &newaclnode->z_size, NULL, cr) == 0); newaclnode->z_ace_count = aclp->z_acl_count; aclp->z_version = ZFS_ACL_VERSION; kmem_free(oldaclp, aclp->z_acl_count * sizeof (zfs_oldace_t)); @@ -771,8 +772,7 @@ * Also, create FUIDs for any User/Group ACEs */ static uint64_t -zfs_mode_fuid_compute(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, - zfs_fuid_info_t **fuidp, dmu_tx_t *tx) +zfs_mode_compute(znode_t *zp, zfs_acl_t *aclp) { int entry_type; mode_t mode; @@ -906,15 +906,6 @@ } } } - /* - * Now handle FUID create for user/group ACEs - */ - if (entry_type == 0 || entry_type == ACE_IDENTIFIER_GROUP) { - aclp->z_ops.ace_who_set(acep, - zfs_fuid_create(zp->z_zfsvfs, who, cr, - (entry_type == 0) ? ZFS_ACE_USER : ZFS_ACE_GROUP, - tx, fuidp)); - } } return (mode); } @@ -1015,8 +1006,7 @@ * already checked the acl and knows whether to inherit. */ int -zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, - zfs_fuid_info_t **fuidp, dmu_tx_t *tx) +zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx) { int error; znode_phys_t *zphys = zp->z_phys; @@ -1027,12 +1017,9 @@ dmu_object_type_t otype; zfs_acl_node_t *aclnode; - ASSERT(MUTEX_HELD(&zp->z_lock)); - ASSERT(MUTEX_HELD(&zp->z_acl_lock)); - dmu_buf_will_dirty(zp->z_dbuf, tx); - zphys->zp_mode = zfs_mode_fuid_compute(zp, aclp, cr, fuidp, tx); + zphys->zp_mode = zfs_mode_compute(zp, aclp); /* * Decide which opbject type to use. If we are forced to @@ -1044,7 +1031,7 @@ } else { if ((aclp->z_version == ZFS_ACL_VERSION_INITIAL) && (zfsvfs->z_version >= ZPL_VERSION_FUID)) - zfs_acl_xform(zp, aclp); + zfs_acl_xform(zp, aclp, cr); ASSERT(aclp->z_version >= ZFS_ACL_VERSION_FUID); otype = DMU_OT_ACL; } @@ -1126,7 +1113,6 @@ if (ace_trivial_common(aclp, 0, zfs_ace_walk) == 0) zp->z_phys->zp_flags |= ZFS_ACL_TRIVIAL; - zfs_time_stamper_locked(zp, STATE_CHANGED, tx); return (0); } @@ -1337,7 +1323,7 @@ * Prepend deny ACE */ static void * -zfs_acl_prepend_deny(znode_t *zp, zfs_acl_t *aclp, void *acep, +zfs_acl_prepend_deny(uint64_t uid, zfs_acl_t *aclp, void *acep, mode_t mode) { zfs_acl_node_t *aclnode; @@ -1350,7 +1336,7 @@ fuid = aclp->z_ops.ace_who_get(acep); flags = aclp->z_ops.ace_flags_get(acep); zfs_set_ace(aclp, newacep, 0, DENY, fuid, (flags & ACE_TYPE_FLAGS)); - zfs_acl_prepend_fixup(aclp, newacep, acep, mode, zp->z_phys->zp_uid); + zfs_acl_prepend_fixup(aclp, newacep, acep, mode, uid); return (newacep); } @@ -1474,9 +1460,9 @@ * in PSARC/2002/240 */ static void -zfs_acl_chmod(znode_t *zp, uint64_t mode, zfs_acl_t *aclp) +zfs_acl_chmod(zfsvfs_t *zfsvfs, uint64_t uid, + uint64_t mode, zfs_acl_t *aclp) { - zfsvfs_t *zfsvfs = zp->z_zfsvfs; void *acep = NULL, *prevacep = NULL; uint64_t who; int i; @@ -1486,11 +1472,6 @@ uint16_t iflags, type; uint32_t access_mask; - ASSERT(MUTEX_HELD(&zp->z_acl_lock)); - ASSERT(MUTEX_HELD(&zp->z_lock)); - - aclp->z_hints = (zp->z_phys->zp_flags & V4_ACL_WIDE_FLAGS); - /* * If discard then just discard all ACL nodes which * represent the ACEs. @@ -1555,17 +1536,15 @@ if (!reuse_deny) { prevacep = - zfs_acl_prepend_deny(zp, + zfs_acl_prepend_deny(uid, aclp, acep, mode); } else { zfs_acl_prepend_fixup( aclp, prevacep, - acep, mode, - zp->z_phys->zp_uid); + acep, mode, uid); } zfs_fixup_group_entries(aclp, acep, prevacep, mode); - } } } @@ -1624,8 +1603,10 @@ mutex_enter(&zp->z_acl_lock); *aclp = NULL; error = zfs_acl_node_read(zp, aclp, B_TRUE); - if (error == 0) - zfs_acl_chmod(zp, mode, *aclp); + if (error == 0) { + (*aclp)->z_hints = zp->z_phys->zp_flags & V4_ACL_WIDE_FLAGS; + zfs_acl_chmod(zp->z_zfsvfs, zp->z_phys->zp_uid, mode, *aclp); + } mutex_exit(&zp->z_acl_lock); mutex_exit(&zp->z_lock); return (error); @@ -1650,9 +1631,8 @@ * Should ACE be inherited? */ static int -zfs_ace_can_use(znode_t *zp, uint16_t acep_flags) +zfs_ace_can_use(vtype_t vtype, uint16_t acep_flags) { - int vtype = ZTOV(zp)->v_type; int iflags = (acep_flags & 0xf); if ((vtype == VDIR) && (iflags & ACE_DIRECTORY_INHERIT_ACE)) @@ -1667,10 +1647,9 @@ * inherit inheritable ACEs from parent */ static zfs_acl_t * -zfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp, uint64_t mode, - boolean_t *need_chmod) +zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp, + uint64_t mode, boolean_t *need_chmod) { - zfsvfs_t *zfsvfs = zp->z_zfsvfs; void *pacep; void *acep, *acep2; zfs_acl_node_t *aclnode, *aclnode2; @@ -1681,8 +1660,8 @@ size_t ace_size; void *data1, *data2; size_t data1sz, data2sz; - boolean_t vdir = ZTOV(zp)->v_type == VDIR; - boolean_t vreg = ZTOV(zp)->v_type == VREG; + boolean_t vdir = vtype == VDIR; + boolean_t vreg = vtype == VREG; boolean_t passthrough, passthrough_x, noallow; passthrough_x = @@ -1711,7 +1690,7 @@ ace_size = aclp->z_ops.ace_size(pacep); - if (!zfs_ace_can_use(zp, iflags)) + if (!zfs_ace_can_use(vtype, iflags)) continue; /* @@ -1807,55 +1786,58 @@ * Create file system object initial permissions * including inheritable ACEs. */ -void -zfs_perm_init(znode_t *zp, znode_t *parent, int flag, - vattr_t *vap, dmu_tx_t *tx, cred_t *cr, - zfs_acl_t *setaclp, zfs_fuid_info_t **fuidp) +int +zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr, + vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids) { - uint64_t mode, fuid, fgid; int error; - zfsvfs_t *zfsvfs = zp->z_zfsvfs; - zfs_acl_t *aclp = NULL; + zfsvfs_t *zfsvfs = dzp->z_zfsvfs; zfs_acl_t *paclp; - xvattr_t *xvap = (xvattr_t *)vap; gid_t gid; boolean_t need_chmod = B_TRUE; - if (setaclp) - aclp = setaclp; + bzero(acl_ids, sizeof (zfs_acl_ids_t)); + acl_ids->z_mode = MAKEIMODE(vap->va_type, vap->va_mode); - mode = MAKEIMODE(vap->va_type, vap->va_mode); + if (vsecp) + if ((error = zfs_vsec_2_aclp(zfsvfs, vap->va_type, vsecp, cr, + &acl_ids->z_fuidp, &acl_ids->z_aclp)) != 0) + return (error); /* * Determine uid and gid. */ if ((flag & (IS_ROOT_NODE | IS_REPLAY)) || ((flag & IS_XATTR) && (vap->va_type == VDIR))) { - fuid = zfs_fuid_create(zfsvfs, vap->va_uid, cr, - ZFS_OWNER, tx, fuidp); - fgid = zfs_fuid_create(zfsvfs, vap->va_gid, cr, - ZFS_GROUP, tx, fuidp); + acl_ids->z_fuid = zfs_fuid_create(zfsvfs, + (uint64_t)vap->va_uid, cr, + ZFS_OWNER, &acl_ids->z_fuidp); + acl_ids->z_fgid = zfs_fuid_create(zfsvfs, + (uint64_t)vap->va_gid, cr, + ZFS_GROUP, &acl_ids->z_fuidp); gid = vap->va_gid; } else { - fuid = zfs_fuid_create_cred(zfsvfs, ZFS_OWNER, tx, cr, fuidp); - fgid = 0; + acl_ids->z_fuid = zfs_fuid_create_cred(zfsvfs, ZFS_OWNER, + cr, &acl_ids->z_fuidp); + acl_ids->z_fgid = 0; if (vap->va_mask & AT_GID) { - fgid = zfs_fuid_create(zfsvfs, vap->va_gid, cr, - ZFS_GROUP, tx, fuidp); + acl_ids->z_fgid = zfs_fuid_create(zfsvfs, + (uint64_t)vap->va_gid, + cr, ZFS_GROUP, &acl_ids->z_fuidp); gid = vap->va_gid; - if (fgid != parent->z_phys->zp_gid && + if (acl_ids->z_fgid != dzp->z_phys->zp_gid && !groupmember(vap->va_gid, cr) && secpolicy_vnode_create_gid(cr) != 0) - fgid = 0; + acl_ids->z_fgid = 0; } - if (fgid == 0) { - if (parent->z_phys->zp_mode & S_ISGID) { - fgid = parent->z_phys->zp_gid; - gid = zfs_fuid_map_id(zfsvfs, fgid, + if (acl_ids->z_fgid == 0) { + if (dzp->z_phys->zp_mode & S_ISGID) { + acl_ids->z_fgid = dzp->z_phys->zp_gid; + gid = zfs_fuid_map_id(zfsvfs, acl_ids->z_fgid, cr, ZFS_GROUP); } else { - fgid = zfs_fuid_create_cred(zfsvfs, - ZFS_GROUP, tx, cr, fuidp); + acl_ids->z_fgid = zfs_fuid_create_cred(zfsvfs, + ZFS_GROUP, cr, &acl_ids->z_fuidp); gid = crgetgid(cr); } } @@ -1868,58 +1850,56 @@ * file's new group, clear the file's set-GID bit. */ - if ((parent->z_phys->zp_mode & S_ISGID) && (vap->va_type == VDIR)) { - mode |= S_ISGID; + if (!(flag & IS_ROOT_NODE) && (dzp->z_phys->zp_mode & S_ISGID) && + (vap->va_type == VDIR)) { + acl_ids->z_mode |= S_ISGID; } else { - if ((mode & S_ISGID) && + if ((acl_ids->z_mode & S_ISGID) && secpolicy_vnode_setids_setgids(cr, gid) != 0) - mode &= ~S_ISGID; + acl_ids->z_mode &= ~S_ISGID; } - zp->z_phys->zp_uid = fuid; - zp->z_phys->zp_gid = fgid; - zp->z_phys->zp_mode = mode; - - if (aclp == NULL) { - mutex_enter(&parent->z_lock); - if ((ZTOV(parent)->v_type == VDIR && - (parent->z_phys->zp_flags & ZFS_INHERIT_ACE)) && - !(zp->z_phys->zp_flags & ZFS_XATTR)) { - mutex_enter(&parent->z_acl_lock); - VERIFY(0 == zfs_acl_node_read(parent, &paclp, B_FALSE)); - mutex_exit(&parent->z_acl_lock); - aclp = zfs_acl_inherit(zp, paclp, mode, &need_chmod); + if (acl_ids->z_aclp == NULL) { + mutex_enter(&dzp->z_lock); + if (!(flag & IS_ROOT_NODE) && (ZTOV(dzp)->v_type == VDIR && + (dzp->z_phys->zp_flags & ZFS_INHERIT_ACE)) && + !(dzp->z_phys->zp_flags & ZFS_XATTR)) { + mutex_enter(&dzp->z_acl_lock); + VERIFY(0 == zfs_acl_node_read(dzp, &paclp, B_FALSE)); + mutex_exit(&dzp->z_acl_lock); + acl_ids->z_aclp = zfs_acl_inherit(zfsvfs, + vap->va_type, paclp, acl_ids->z_mode, &need_chmod); zfs_acl_free(paclp); } else { - aclp = zfs_acl_alloc(zfs_acl_version_zp(zp)); + acl_ids->z_aclp = + zfs_acl_alloc(zfs_acl_version_zp(dzp)); } - mutex_exit(&parent->z_lock); - mutex_enter(&zp->z_lock); - mutex_enter(&zp->z_acl_lock); - if (need_chmod) - zfs_acl_chmod(zp, mode, aclp); - } else { - mutex_enter(&zp->z_lock); - mutex_enter(&zp->z_acl_lock); + mutex_exit(&dzp->z_lock); + if (need_chmod) { + acl_ids->z_aclp->z_hints = (vap->va_type == VDIR) ? + ZFS_ACL_AUTO_INHERIT : 0; + zfs_acl_chmod(zfsvfs, acl_ids->z_fuid, + acl_ids->z_mode, acl_ids->z_aclp); + } } - /* Force auto_inherit on all new directory objects */ - if (vap->va_type == VDIR) - aclp->z_hints |= ZFS_ACL_AUTO_INHERIT; - - error = zfs_aclset_common(zp, aclp, cr, fuidp, tx); + return (0); +} - /* Set optional attributes if any */ - if (vap->va_mask & AT_XVATTR) - zfs_xvattr_set(zp, xvap); +/* + * Free ACL and fuid_infop, but not the acl_ids structure + */ +void +zfs_acl_ids_free(zfs_acl_ids_t *acl_ids) +{ + if (acl_ids->z_aclp) + zfs_acl_free(acl_ids->z_aclp); + if (acl_ids->z_fuidp) + zfs_fuid_info_free(acl_ids->z_fuidp); + acl_ids->z_aclp = NULL; + acl_ids->z_fuidp = NULL; +} - mutex_exit(&zp->z_lock); - mutex_exit(&zp->z_acl_lock); - ASSERT3U(error, ==, 0); - - if (aclp != setaclp) - zfs_acl_free(aclp); -} /* * Retrieve a files ACL @@ -2019,7 +1999,7 @@ int zfs_vsec_2_aclp(zfsvfs_t *zfsvfs, vtype_t obj_type, - vsecattr_t *vsecp, zfs_acl_t **zaclp) + vsecattr_t *vsecp, cred_t *cr, zfs_fuid_info_t **fuidp, zfs_acl_t **zaclp) { zfs_acl_t *aclp; zfs_acl_node_t *aclnode; @@ -2042,9 +2022,9 @@ return (error); } } else { - if ((error = zfs_copy_ace_2_fuid(obj_type, aclp, + if ((error = zfs_copy_ace_2_fuid(zfsvfs, obj_type, aclp, vsecp->vsa_aclentp, aclnode->z_acldata, aclcnt, - &aclnode->z_size)) != 0) { + &aclnode->z_size, fuidp, cr)) != 0) { zfs_acl_free(aclp); zfs_acl_node_free(aclnode); return (error); @@ -2085,6 +2065,7 @@ int error; zfs_acl_t *aclp; zfs_fuid_info_t *fuidp = NULL; + boolean_t fuid_dirtied; if (mask == 0) return (ENOSYS); @@ -2095,7 +2076,8 @@ if (error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr)) return (error); - error = zfs_vsec_2_aclp(zfsvfs, ZTOV(zp)->v_type, vsecp, &aclp); + error = zfs_vsec_2_aclp(zfsvfs, ZTOV(zp)->v_type, vsecp, cr, &fuidp, + &aclp); if (error) return (error); @@ -2136,7 +2118,8 @@ } else if (aclp->z_acl_bytes > ZFS_ACE_SPACE) { dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, aclp->z_acl_bytes); } - if (aclp->z_has_fuids) { + fuid_dirtied = zfsvfs->z_fuid_dirty; + if (fuid_dirtied) { if (zfsvfs->z_fuid_obj == 0) { dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, @@ -2164,9 +2147,13 @@ return (error); } - error = zfs_aclset_common(zp, aclp, cr, &fuidp, tx); + error = zfs_aclset_common(zp, aclp, cr, tx); ASSERT(error == 0); + if (fuid_dirtied) + zfs_fuid_sync(zfsvfs, tx); + + zfs_time_stamper_locked(zp, STATE_CHANGED, tx); zfs_log_acl(zilog, tx, zp, vsecp, fuidp); if (fuidp)