Mercurial > illumos > illumos-gate
changeset 12620:12fcd99a642d
6957974 assertion failed: 0 == sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zp->z_zfsvfs)
6960907 zfs_rezget() has uninitialized z_mode variable
author | Mark Shellenbaum <Mark.Shellenbaum@Oracle.COM> |
---|---|
date | Mon, 14 Jun 2010 10:04:10 -0600 |
parents | 60877912fc2d |
children | 67c30502d363 |
files | usr/src/uts/common/fs/zfs/sa.c usr/src/uts/common/fs/zfs/sys/zfs_acl.h usr/src/uts/common/fs/zfs/zfs_acl.c usr/src/uts/common/fs/zfs/zfs_dir.c usr/src/uts/common/fs/zfs/zfs_ioctl.c usr/src/uts/common/fs/zfs/zfs_sa.c usr/src/uts/common/fs/zfs/zfs_vnops.c usr/src/uts/common/fs/zfs/zfs_znode.c |
diffstat | 8 files changed, 173 insertions(+), 70 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/sa.c Mon Jun 14 07:12:23 2010 -0700 +++ b/usr/src/uts/common/fs/zfs/sa.c Mon Jun 14 10:04:10 2010 -0600 @@ -713,7 +713,7 @@ length = attr_desc[i].sa_length; if (buf_space < length) { /* switch to spill buffer */ - ASSERT(bonustype != DMU_OT_ZNODE); + VERIFY(bonustype == DMU_OT_SA); if (buftype == SA_BONUS && !sa->sa_force_spill) { sa_find_layout(hdl->sa_os, hash, attrs_start, lot_count, tx, &lot); @@ -747,6 +747,14 @@ } sa_find_layout(hdl->sa_os, hash, attrs_start, lot_count, tx, &lot); + + /* + * Verify that old znodes always have layout number 0. + * Must be DMU_OT_SA for arbitrary layouts + */ + VERIFY((bonustype == DMU_OT_ZNODE && lot->lot_num == 0) || + (bonustype == DMU_OT_SA && lot->lot_num > 1)); + if (bonustype == DMU_OT_SA) { SA_SET_HDR(sahdr, lot->lot_num, buftype == SA_BONUS ? hdrsize : spillhdrsize);
--- a/usr/src/uts/common/fs/zfs/sys/zfs_acl.h Mon Jun 14 07:12:23 2010 -0700 +++ b/usr/src/uts/common/fs/zfs/sys/zfs_acl.h Mon Jun 14 10:04:10 2010 -0600 @@ -185,10 +185,6 @@ struct zfs_fuid_info *z_fuidp; /* for tracking fuids for log */ } zfs_acl_ids_t; -#define ZFS_EXTERNAL_ACL(zp) \ - (zp->z_is_sa ? 0 : zfs_external_acl(zp)) -#define ZNODE_ACL_VERSION(zp) \ - (zp->z_is_sa ? ZFS_ACL_VERSION_FUID : zfs_znode_acl_version(zp)) /* * Property values for acl_mode and acl_inherit. *
--- a/usr/src/uts/common/fs/zfs/zfs_acl.c Mon Jun 14 07:12:23 2010 -0700 +++ b/usr/src/uts/common/fs/zfs/zfs_acl.c Mon Jun 14 10:04:10 2010 -0600 @@ -327,19 +327,35 @@ * an external ACL and what version of ACL previously existed on the * file. Would really be nice to not need this, sigh. */ - uint64_t zfs_external_acl(znode_t *zp) { zfs_acl_phys_t acl_phys; + int error; if (zp->z_is_sa) return (0); - VERIFY(0 == sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zp->z_zfsvfs), - &acl_phys, sizeof (acl_phys))); - - return (acl_phys.z_acl_extern_obj); + /* + * Need to deal with a potential + * race where zfs_sa_upgrade could cause + * z_isa_sa to change. + * + * If the lookup fails then the state of z_is_sa should have + * changed. + */ + + if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zp->z_zfsvfs), + &acl_phys, sizeof (acl_phys))) == 0) + return (acl_phys.z_acl_extern_obj); + else { + /* + * after upgrade the SA_ZPL_ZNODE_ACL should have been + * removed + */ + VERIFY(zp->z_is_sa && error == ENOENT); + return (0); + } } /* @@ -357,6 +373,7 @@ int size; int error; + ASSERT(MUTEX_HELD(&zp->z_acl_lock)); if (zp->z_is_sa) { if ((error = sa_size(zp->z_sa_hdl, SA_ZPL_DACL_ACES(zfsvfs), &size)) != 0) @@ -387,13 +404,31 @@ { zfs_acl_phys_t acl_phys; - if (zp->z_is_sa) { + if (zp->z_is_sa) return (ZFS_ACL_VERSION_FUID); - } else { - VERIFY(0 == sa_lookup(zp->z_sa_hdl, + else { + int error; + + /* + * Need to deal with a potential + * race where zfs_sa_upgrade could cause + * z_isa_sa to change. + * + * If the lookup fails then the state of z_is_sa should have + * changed. + */ + if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zp->z_zfsvfs), - &acl_phys, sizeof (acl_phys))); - return (acl_phys.z_acl_version); + &acl_phys, sizeof (acl_phys))) == 0) + return (acl_phys.z_acl_version); + else { + /* + * After upgrade SA_ZPL_ZNODE_ACL should have + * been removed. + */ + VERIFY(zp->z_is_sa && error == ENOENT); + return (ZFS_ACL_VERSION_FUID); + } } } @@ -1024,7 +1059,8 @@ * create a new acl and leave any cached acl in place. */ static int -zfs_acl_node_read(znode_t *zp, zfs_acl_t **aclpp, boolean_t will_modify) +zfs_acl_node_read(znode_t *zp, boolean_t have_lock, zfs_acl_t **aclpp, + boolean_t will_modify) { zfs_acl_t *aclp; int aclsize; @@ -1033,6 +1069,7 @@ zfs_acl_phys_t znode_acl; int version; int error; + boolean_t drop_lock = B_FALSE; ASSERT(MUTEX_HELD(&zp->z_acl_lock)); @@ -1041,11 +1078,23 @@ return (0); } - version = ZNODE_ACL_VERSION(zp); + /* + * close race where znode could be upgrade while trying to + * read the znode attributes. + * + * But this could only happen if the file isn't already an SA + * znode + */ + if (!zp->z_is_sa && !have_lock) { + mutex_enter(&zp->z_lock); + drop_lock = B_TRUE; + } + version = zfs_znode_acl_version(zp); if ((error = zfs_acl_znode_info(zp, &aclsize, - &acl_count, &znode_acl)) != 0) - return (error); + &acl_count, &znode_acl)) != 0) { + goto done; + } aclp = zfs_acl_alloc(version); @@ -1076,7 +1125,7 @@ /* convert checksum errors into IO errors */ if (error == ECKSUM) error = EIO; - return (error); + goto done; } list_insert_head(&aclp->z_acl, aclnode); @@ -1084,7 +1133,10 @@ *aclpp = aclp; if (!will_modify) zp->z_acl_cached = aclp; - return (0); +done: + if (drop_lock) + mutex_exit(&zp->z_lock); + return (error); } /*ARGSUSED*/ @@ -1134,14 +1186,14 @@ zfs_acl_t *aclp; uint64_t fuid, fgid; + ASSERT(MUTEX_HELD(&zp->z_lock)); + ASSERT(MUTEX_HELD(&zp->z_acl_lock)); if ((error = zfs_acl_get_owner_fuids(zp, &fuid, &fgid)) != 0) return (error); - mutex_enter(&zp->z_acl_lock); - if ((error = zfs_acl_node_read(zp, &aclp, B_FALSE)) == 0) + if ((error = zfs_acl_node_read(zp, B_TRUE, &aclp, B_FALSE)) == 0) zp->z_mode = zfs_mode_compute(zp->z_mode, aclp, &zp->z_pflags, fuid, fgid); - mutex_exit(&zp->z_acl_lock); return (error); } @@ -1485,13 +1537,13 @@ int zfs_acl_chmod_setattr(znode_t *zp, zfs_acl_t **aclp, uint64_t mode) { + mutex_enter(&zp->z_acl_lock); mutex_enter(&zp->z_lock); - mutex_enter(&zp->z_acl_lock); *aclp = zfs_acl_alloc(zfs_acl_version_zp(zp)); (*aclp)->z_hints = zp->z_pflags & V4_ACL_WIDE_FLAGS; zfs_acl_chmod(zp->z_zfsvfs, mode, *aclp); + mutex_exit(&zp->z_lock); mutex_exit(&zp->z_acl_lock); - mutex_exit(&zp->z_lock); ASSERT(*aclp); return (0); } @@ -1746,15 +1798,15 @@ } if (acl_ids->z_aclp == NULL) { + mutex_enter(&dzp->z_acl_lock); mutex_enter(&dzp->z_lock); if (!(flag & IS_ROOT_NODE) && (ZTOV(dzp)->v_type == VDIR && (dzp->z_pflags & ZFS_INHERIT_ACE)) && !(dzp->z_pflags & ZFS_XATTR)) { - mutex_enter(&dzp->z_acl_lock); - VERIFY(0 == zfs_acl_node_read(dzp, &paclp, B_FALSE)); + VERIFY(0 == zfs_acl_node_read(dzp, B_TRUE, + &paclp, B_FALSE)); acl_ids->z_aclp = zfs_acl_inherit(zfsvfs, vap->va_type, paclp, acl_ids->z_mode, &need_chmod); - mutex_exit(&dzp->z_acl_lock); inherited = B_TRUE; } else { acl_ids->z_aclp = @@ -1762,6 +1814,7 @@ acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL; } mutex_exit(&dzp->z_lock); + mutex_exit(&dzp->z_acl_lock); if (need_chmod) { acl_ids->z_aclp->z_hints |= (vap->va_type == VDIR) ? ZFS_ACL_AUTO_INHERIT : 0; @@ -1824,7 +1877,7 @@ mutex_enter(&zp->z_acl_lock); - error = zfs_acl_node_read(zp, &aclp, B_FALSE); + error = zfs_acl_node_read(zp, B_FALSE, &aclp, B_FALSE); if (error != 0) { mutex_exit(&zp->z_acl_lock); return (error); @@ -1970,6 +2023,7 @@ zfs_acl_t *aclp; zfs_fuid_info_t *fuidp = NULL; boolean_t fuid_dirtied; + uint64_t acl_obj; if (mask == 0) return (ENOSYS); @@ -1994,8 +2048,8 @@ (zp->z_pflags & V4_ACL_WIDE_FLAGS); } top: + mutex_enter(&zp->z_acl_lock); mutex_enter(&zp->z_lock); - mutex_enter(&zp->z_acl_lock); tx = dmu_tx_create(zfsvfs->z_os); @@ -2010,14 +2064,13 @@ * upgrading then take out necessary DMU holds */ - if (ZFS_EXTERNAL_ACL(zp)) { + if ((acl_obj = zfs_external_acl(zp)) != 0) { if (zfsvfs->z_version <= ZPL_VERSION_SA && - ZNODE_ACL_VERSION(zp) <= ZFS_ACL_VERSION_INITIAL) { - dmu_tx_hold_free(tx, ZFS_EXTERNAL_ACL(zp), 0, + zfs_znode_acl_version(zp) <= ZFS_ACL_VERSION_INITIAL) { + dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END); } else { - dmu_tx_hold_write(tx, ZFS_EXTERNAL_ACL(zp), - 0, aclp->z_acl_bytes); + dmu_tx_hold_write(tx, acl_obj, 0, aclp->z_acl_bytes); } } else if (!zp->z_is_sa && aclp->z_acl_bytes > ZFS_ACE_SPACE) { dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, aclp->z_acl_bytes); @@ -2052,8 +2105,8 @@ zfs_fuid_info_free(fuidp); dmu_tx_commit(tx); done: + mutex_exit(&zp->z_lock); mutex_exit(&zp->z_acl_lock); - mutex_exit(&zp->z_lock); return (error); } @@ -2141,7 +2194,7 @@ mutex_enter(&zp->z_acl_lock); - error = zfs_acl_node_read(zp, &aclp, B_FALSE); + error = zfs_acl_node_read(zp, B_FALSE, &aclp, B_FALSE); if (error != 0) { mutex_exit(&zp->z_acl_lock); return (error);
--- a/usr/src/uts/common/fs/zfs/zfs_dir.c Mon Jun 14 07:12:23 2010 -0700 +++ b/usr/src/uts/common/fs/zfs/zfs_dir.c Mon Jun 14 10:04:10 2010 -0600 @@ -630,7 +630,7 @@ ASSERT(error == 0); } - acl_obj = ZFS_EXTERNAL_ACL(zp); + acl_obj = zfs_external_acl(zp); /* * Set up the final transaction.
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c Mon Jun 14 07:12:23 2010 -0700 +++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c Mon Jun 14 10:04:10 2010 -0600 @@ -1002,14 +1002,15 @@ * case its z_vfs will be NULL, and it will be opened as the owner. */ static int -zfsvfs_hold(const char *name, void *tag, zfsvfs_t **zfvp) +zfsvfs_hold(const char *name, void *tag, zfsvfs_t **zfvp, boolean_t writer) { int error = 0; if (getzfsvfs(name, zfvp) != 0) error = zfsvfs_create(name, zfvp); if (error == 0) { - rrw_enter(&(*zfvp)->z_teardown_lock, RW_READER, tag); + rrw_enter(&(*zfvp)->z_teardown_lock, (writer) ? RW_WRITER : + RW_READER, tag); if ((*zfvp)->z_unmounted) { /* * XXX we could probably try again, since the unmounting @@ -1906,7 +1907,7 @@ rid = valary[1]; quota = valary[2]; - err = zfsvfs_hold(dsname, FTAG, &zfsvfs); + err = zfsvfs_hold(dsname, FTAG, &zfsvfs, B_FALSE); if (err == 0) { err = zfs_set_userquota(zfsvfs, type, domain, rid, quota); zfsvfs_rele(zfsvfs, FTAG); @@ -1971,7 +1972,7 @@ { zfsvfs_t *zfsvfs; - if ((err = zfsvfs_hold(dsname, FTAG, &zfsvfs)) != 0) + if ((err = zfsvfs_hold(dsname, FTAG, &zfsvfs, B_TRUE)) != 0) break; err = zfs_set_version(zfsvfs, intval); @@ -3806,7 +3807,7 @@ if (zc->zc_objset_type >= ZFS_NUM_USERQUOTA_PROPS) return (EINVAL); - error = zfsvfs_hold(zc->zc_name, FTAG, &zfsvfs); + error = zfsvfs_hold(zc->zc_name, FTAG, &zfsvfs, B_FALSE); if (error) return (error); @@ -3837,7 +3838,7 @@ if (bufsize <= 0) return (ENOMEM); - int error = zfsvfs_hold(zc->zc_name, FTAG, &zfsvfs); + int error = zfsvfs_hold(zc->zc_name, FTAG, &zfsvfs, B_FALSE); if (error) return (error);
--- a/usr/src/uts/common/fs/zfs/zfs_sa.c Mon Jun 14 07:12:23 2010 -0700 +++ b/usr/src/uts/common/fs/zfs/zfs_sa.c Mon Jun 14 10:04:10 2010 -0600 @@ -125,6 +125,7 @@ zfsvfs_t *zfsvfs = zp->z_zfsvfs; xoptattr_t *xoap; + ASSERT(MUTEX_HELD(&zp->z_lock)); VERIFY((xoap = xva_getxoptattr(xvap)) != NULL); if (zp->z_is_sa) { if (sa_lookup(zp->z_sa_hdl, SA_ZPL_SCANSTAMP(zfsvfs), @@ -158,6 +159,7 @@ zfsvfs_t *zfsvfs = zp->z_zfsvfs; xoptattr_t *xoap; + ASSERT(MUTEX_HELD(&zp->z_lock)); VERIFY((xoap = xva_getxoptattr(xvap)) != NULL); if (zp->z_is_sa) VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_SCANSTAMP(zfsvfs), @@ -204,6 +206,7 @@ uint64_t crtime[2], mtime[2], ctime[2]; zfs_acl_phys_t znode_acl; char scanstamp[AV_SCANSTAMP_SZ]; + boolean_t drop_lock = B_FALSE; /* * No upgrade if ACL isn't cached @@ -214,6 +217,22 @@ if (zp->z_acl_cached == NULL || ZTOV(zp)->v_type == VLNK) return; + /* + * If the z_lock is held and we aren't the owner + * the just return since we don't want to deadlock + * trying to update the status of z_is_sa. This + * file can then be upgraded at a later time. + * + * Otherwise, we know we are doing the + * sa_update() that caused us to enter this function. + */ + if (mutex_owner(&zp->z_lock) != curthread) { + if (mutex_tryenter(&zp->z_lock) == 0) + return; + else + drop_lock = B_TRUE; + } + /* First do a bulk query of the attributes that aren't cached */ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, &mtime, 16); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16); @@ -228,7 +247,7 @@ &znode_acl, 88); if (sa_bulk_lookup_locked(hdl, bulk, count) != 0) - return; + goto done; /* @@ -269,9 +288,10 @@ locate.cb_aclp = zp->z_acl_cached; SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_DACL_ACES(zfsvfs), zfs_acl_data_locator, &locate, zp->z_acl_cached->z_acl_bytes); + if (xattr) - SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_RDEV(zfsvfs), - NULL, &rdev, 8); + SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_XATTR(zfsvfs), + NULL, &xattr, 8); /* if scanstamp then add scanstamp */ @@ -291,6 +311,9 @@ znode_acl.z_acl_extern_obj, tx)); zp->z_is_sa = B_TRUE; +done: + if (drop_lock) + mutex_exit(&zp->z_lock); } void @@ -299,12 +322,11 @@ if (!zp->z_zfsvfs->z_use_sa || zp->z_is_sa) return; - ASSERT(!zp->z_is_sa); dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); - if (ZFS_EXTERNAL_ACL(zp)) { - dmu_tx_hold_free(tx, ZFS_EXTERNAL_ACL(zp), 0, + if (zfs_external_acl(zp)) { + dmu_tx_hold_free(tx, zfs_external_acl(zp), 0, DMU_OBJECT_END); } }
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c Mon Jun 14 07:12:23 2010 -0700 +++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c Mon Jun 14 10:04:10 2010 -0600 @@ -1619,9 +1619,10 @@ dmu_tx_hold_sa(tx, xzp->z_sa_hdl, B_FALSE); } - /* are there any additional acls */ - if ((acl_obj = ZFS_EXTERNAL_ACL(zp)) != 0 && may_delete_now) + mutex_enter(&zp->z_lock); + if ((acl_obj = zfs_external_acl(zp)) != 0 && may_delete_now) dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END); + mutex_exit(&zp->z_lock); /* charge as an update -- would be nice not to charge at all */ dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL); @@ -1654,13 +1655,18 @@ if (unlinked) { + /* + * Hold z_lock so that we can make sure that the ACL obj + * hasn't changed. Could have been deleted due to + * zfs_sa_upgrade(). + */ + mutex_enter(&zp->z_lock); mutex_enter(&vp->v_lock); - (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs), &xattr_obj_unlinked, sizeof (xattr_obj_unlinked)); delete_now = may_delete_now && !toobig && vp->v_count == 1 && !vn_has_cached_data(vp) && - xattr_obj == xattr_obj_unlinked && ZFS_EXTERNAL_ACL(zp) == + xattr_obj == xattr_obj_unlinked && zfs_external_acl(zp) == acl_obj; mutex_exit(&vp->v_lock); } @@ -1676,6 +1682,7 @@ ASSERT3U(error, ==, 0); mutex_exit(&xzp->z_lock); zfs_unlinked_add(xzp, tx); + if (zp->z_is_sa) error = sa_remove(zp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs), tx); @@ -1685,7 +1692,6 @@ sizeof (uint64_t), tx); ASSERT3U(error, ==, 0); } - mutex_enter(&zp->z_lock); mutex_enter(&vp->v_lock); vp->v_count--; ASSERT3U(vp->v_count, ==, 0); @@ -1693,6 +1699,7 @@ mutex_exit(&zp->z_lock); zfs_znode_delete(zp, tx); } else if (unlinked) { + mutex_exit(&zp->z_lock); zfs_unlinked_add(zp, tx); } @@ -2912,32 +2919,34 @@ if (mask & AT_MODE) { uint64_t pmode = zp->z_mode; + uint64_t acl_obj; new_mode = (pmode & S_IFMT) | (vap->va_mode & ~S_IFMT); if (err = zfs_acl_chmod_setattr(zp, &aclp, new_mode)) goto out; - if (!zp->z_is_sa && ZFS_EXTERNAL_ACL(zp)) { + mutex_enter(&zp->z_lock); + if (!zp->z_is_sa && ((acl_obj = zfs_external_acl(zp)) != 0)) { /* * Are we upgrading ACL from old V0 format * to V1 format? */ if (zfsvfs->z_version <= ZPL_VERSION_FUID && - ZNODE_ACL_VERSION(zp) == + zfs_znode_acl_version(zp) == ZFS_ACL_VERSION_INITIAL) { - dmu_tx_hold_free(tx, - ZFS_EXTERNAL_ACL(zp), 0, + dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END); dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, aclp->z_acl_bytes); } else { - dmu_tx_hold_write(tx, ZFS_EXTERNAL_ACL(zp), 0, + dmu_tx_hold_write(tx, acl_obj, 0, aclp->z_acl_bytes); } } else if (!zp->z_is_sa && aclp->z_acl_bytes > ZFS_ACE_SPACE) { dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, aclp->z_acl_bytes); } + mutex_exit(&zp->z_lock); dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); } else { if ((mask & AT_XVATTR) && @@ -2973,12 +2982,17 @@ * updated as a side-effect of calling this function. */ + + if (mask & (AT_UID|AT_GID|AT_MODE)) + mutex_enter(&zp->z_acl_lock); mutex_enter(&zp->z_lock); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL, &zp->z_pflags, sizeof (zp->z_pflags)); if (attrzp) { + if (mask & (AT_UID|AT_GID|AT_MODE)) + mutex_enter(&attrzp->z_acl_lock); mutex_enter(&attrzp->z_lock); SA_ADD_BULK_ATTR(xattr_bulk, xattr_count, SA_ZPL_FLAGS(zfsvfs), NULL, &attrzp->z_pflags, @@ -3026,7 +3040,6 @@ } if (mask & AT_MODE) { - mutex_enter(&zp->z_acl_lock); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &new_mode, sizeof (new_mode)); zp->z_mode = new_mode; @@ -3035,11 +3048,8 @@ ASSERT3U(err, ==, 0); zp->z_acl_cached = aclp; aclp = NULL; - mutex_exit(&zp->z_acl_lock); } - if (attrzp) - mutex_exit(&attrzp->z_lock); if (mask & AT_ATIME) { ZFS_TIME_ENCODE(&vap->va_atime, zp->z_atime); @@ -3118,7 +3128,14 @@ zfs_log_setattr(zilog, tx, TX_SETATTR, zp, vap, mask, fuidp); mutex_exit(&zp->z_lock); - + if (mask & (AT_UID|AT_GID|AT_MODE)) + mutex_exit(&zp->z_acl_lock); + + if (attrzp) { + if (mask & (AT_UID|AT_GID|AT_MODE)) + mutex_exit(&attrzp->z_acl_lock); + mutex_exit(&attrzp->z_lock); + } out: if (err == 0 && attrzp) { err2 = sa_bulk_update(attrzp->z_sa_hdl, xattr_bulk, @@ -3724,11 +3741,13 @@ if (fuid_dirtied) zfs_fuid_sync(zfsvfs, tx); + mutex_enter(&zp->z_lock); if (zp->z_is_sa) error = sa_update(zp->z_sa_hdl, SA_ZPL_SYMLINK(zfsvfs), link, len, tx); else zfs_sa_symlink(zp, link, len, tx); + mutex_exit(&zp->z_lock); zp->z_size = len; (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zfsvfs), @@ -3785,11 +3804,13 @@ ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); + mutex_enter(&zp->z_lock); if (zp->z_is_sa) error = sa_lookup_uio(zp->z_sa_hdl, SA_ZPL_SYMLINK(zfsvfs), uio); else error = zfs_sa_readlink(zp, uio); + mutex_exit(&zp->z_lock); ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
--- a/usr/src/uts/common/fs/zfs/zfs_znode.c Mon Jun 14 07:12:23 2010 -0700 +++ b/usr/src/uts/common/fs/zfs/zfs_znode.c Mon Jun 14 10:04:10 2010 -0600 @@ -1226,14 +1226,14 @@ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &mode, sizeof (mode)); - zp->z_mode = mode; - if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count)) { zfs_znode_dmu_fini(zp); ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); return (EIO); } + zp->z_mode = mode; + if (gen != zp->z_gen) { zfs_znode_dmu_fini(zp); ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); @@ -1256,11 +1256,13 @@ zfsvfs_t *zfsvfs = zp->z_zfsvfs; objset_t *os = zfsvfs->z_os; uint64_t obj = zp->z_id; - uint64_t acl_obj = ZFS_EXTERNAL_ACL(zp); + uint64_t acl_obj = zfs_external_acl(zp); ZFS_OBJ_HOLD_ENTER(zfsvfs, obj); - if (acl_obj) + if (acl_obj) { + VERIFY(!zp->z_is_sa); VERIFY(0 == dmu_object_free(os, acl_obj, tx)); + } VERIFY(0 == dmu_object_free(os, obj, tx)); zfs_znode_dmu_fini(zp); ZFS_OBJ_HOLD_EXIT(zfsvfs, obj);