Changeset View
Changeset View
Standalone View
Standalone View
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c
Show First 20 Lines • Show All 1,049 Lines • ▼ Show 20 Lines | zfs_mode_compute(uint64_t fmode, zfs_acl_t *aclp, | ||||
return (mode); | return (mode); | ||||
} | } | ||||
/* | /* | ||||
* Read an external acl object. If the intent is to modify, always | * Read an external acl object. If the intent is to modify, always | ||||
* create a new acl and leave any cached acl in place. | * create a new acl and leave any cached acl in place. | ||||
*/ | */ | ||||
static int | static int | ||||
zfs_acl_node_read(znode_t *zp, boolean_t have_lock, zfs_acl_t **aclpp, | zfs_acl_node_read(znode_t *zp, zfs_acl_t **aclpp, boolean_t will_modify) | ||||
boolean_t will_modify) | |||||
{ | { | ||||
zfs_acl_t *aclp; | zfs_acl_t *aclp; | ||||
int aclsize; | int aclsize; | ||||
int acl_count; | int acl_count; | ||||
zfs_acl_node_t *aclnode; | zfs_acl_node_t *aclnode; | ||||
zfs_acl_phys_t znode_acl; | zfs_acl_phys_t znode_acl; | ||||
int version; | int version; | ||||
int error; | int error; | ||||
boolean_t drop_lock = B_FALSE; | |||||
ASSERT(MUTEX_HELD(&zp->z_acl_lock)); | ASSERT(MUTEX_HELD(&zp->z_acl_lock)); | ||||
ASSERT_VOP_LOCKED(ZTOV(zp), "zfs_acl_node_read"); | |||||
mahrens: Looks like the 2nd arg to this macro is always the function name. You could use __func__… | |||||
emasteUnsubmitted Not Done Inline ActionsGood point, at least passing __func__ in new callers will simplify any future effort to update the macro (by avoiding the need to verify the arg matches the function name). emaste: Good point, at least passing `__func__` in new callers will simplify any future effort to… | |||||
avgAuthorUnsubmitted Not Done Inline ActionsThe second argument does not have tobe just a function name, it can include a more detailed explanation of an assertion. But you are absolutely correct that in this case we can use __func__ in all instances. Thank you for the suggestion, I will make sure to implement it. avg: The second argument does not have tobe just a function name, it can include a more detailed… | |||||
if (zp->z_acl_cached && !will_modify) { | if (zp->z_acl_cached && !will_modify) { | ||||
*aclpp = zp->z_acl_cached; | *aclpp = zp->z_acl_cached; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | |||||
* 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); | version = zfs_znode_acl_version(zp); | ||||
if ((error = zfs_acl_znode_info(zp, &aclsize, | if ((error = zfs_acl_znode_info(zp, &aclsize, | ||||
&acl_count, &znode_acl)) != 0) { | &acl_count, &znode_acl)) != 0) { | ||||
goto done; | goto done; | ||||
} | } | ||||
aclp = zfs_acl_alloc(version); | aclp = zfs_acl_alloc(version); | ||||
Show All 29 Lines | zfs_acl_node_read(znode_t *zp, zfs_acl_t **aclpp, boolean_t will_modify) | ||||
} | } | ||||
list_insert_head(&aclp->z_acl, aclnode); | list_insert_head(&aclp->z_acl, aclnode); | ||||
*aclpp = aclp; | *aclpp = aclp; | ||||
if (!will_modify) | if (!will_modify) | ||||
zp->z_acl_cached = aclp; | zp->z_acl_cached = aclp; | ||||
done: | done: | ||||
if (drop_lock) | |||||
mutex_exit(&zp->z_lock); | |||||
return (error); | return (error); | ||||
} | } | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
void | void | ||||
zfs_acl_data_locator(void **dataptr, uint32_t *length, uint32_t buflen, | zfs_acl_data_locator(void **dataptr, uint32_t *length, uint32_t buflen, | ||||
boolean_t start, void *userdata) | boolean_t start, void *userdata) | ||||
{ | { | ||||
Show All 10 Lines | |||||
} | } | ||||
int | int | ||||
zfs_acl_chown_setattr(znode_t *zp) | zfs_acl_chown_setattr(znode_t *zp) | ||||
{ | { | ||||
int error; | int error; | ||||
zfs_acl_t *aclp; | zfs_acl_t *aclp; | ||||
ASSERT(MUTEX_HELD(&zp->z_lock)); | ASSERT_VOP_ELOCKED(ZTOV(zp), "zfs_acl_chown_setattr"); | ||||
ASSERT(MUTEX_HELD(&zp->z_acl_lock)); | ASSERT(MUTEX_HELD(&zp->z_acl_lock)); | ||||
if ((error = zfs_acl_node_read(zp, B_TRUE, &aclp, B_FALSE)) == 0) | if ((error = zfs_acl_node_read(zp, &aclp, B_FALSE)) == 0) | ||||
zp->z_mode = zfs_mode_compute(zp->z_mode, aclp, | zp->z_mode = zfs_mode_compute(zp->z_mode, aclp, | ||||
&zp->z_pflags, zp->z_uid, zp->z_gid); | &zp->z_pflags, zp->z_uid, zp->z_gid); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* common code for setting ACLs. | * common code for setting ACLs. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 275 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
int | int | ||||
zfs_acl_chmod_setattr(znode_t *zp, zfs_acl_t **aclp, uint64_t mode) | zfs_acl_chmod_setattr(znode_t *zp, zfs_acl_t **aclp, uint64_t mode) | ||||
{ | { | ||||
int error = 0; | int error = 0; | ||||
mutex_enter(&zp->z_acl_lock); | mutex_enter(&zp->z_acl_lock); | ||||
mutex_enter(&zp->z_lock); | ASSERT_VOP_ELOCKED(ZTOV(zp), "zfs_acl_chmod_setattr"); | ||||
if (zp->z_zfsvfs->z_acl_mode == ZFS_ACL_DISCARD) | if (zp->z_zfsvfs->z_acl_mode == ZFS_ACL_DISCARD) | ||||
*aclp = zfs_acl_alloc(zfs_acl_version_zp(zp)); | *aclp = zfs_acl_alloc(zfs_acl_version_zp(zp)); | ||||
else | else | ||||
error = zfs_acl_node_read(zp, B_TRUE, aclp, B_TRUE); | error = zfs_acl_node_read(zp, aclp, B_TRUE); | ||||
if (error == 0) { | if (error == 0) { | ||||
(*aclp)->z_hints = zp->z_pflags & V4_ACL_WIDE_FLAGS; | (*aclp)->z_hints = zp->z_pflags & V4_ACL_WIDE_FLAGS; | ||||
zfs_acl_chmod(ZTOV(zp)->v_type, mode, B_TRUE, | zfs_acl_chmod(ZTOV(zp)->v_type, mode, B_TRUE, | ||||
(zp->z_zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK), *aclp); | (zp->z_zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK), *aclp); | ||||
} | } | ||||
mutex_exit(&zp->z_lock); | |||||
mutex_exit(&zp->z_acl_lock); | mutex_exit(&zp->z_acl_lock); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Should ACE be inherited? | * Should ACE be inherited? | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 136 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
int error; | int error; | ||||
zfsvfs_t *zfsvfs = dzp->z_zfsvfs; | zfsvfs_t *zfsvfs = dzp->z_zfsvfs; | ||||
zfs_acl_t *paclp; | zfs_acl_t *paclp; | ||||
gid_t gid; | gid_t gid; | ||||
boolean_t trim = B_FALSE; | boolean_t trim = B_FALSE; | ||||
boolean_t inherited = B_FALSE; | boolean_t inherited = B_FALSE; | ||||
ASSERT_VOP_ELOCKED(ZTOV(dzp), "zfs_acl_chmod_setattr"); | |||||
bzero(acl_ids, sizeof (zfs_acl_ids_t)); | bzero(acl_ids, sizeof (zfs_acl_ids_t)); | ||||
acl_ids->z_mode = MAKEIMODE(vap->va_type, vap->va_mode); | acl_ids->z_mode = MAKEIMODE(vap->va_type, vap->va_mode); | ||||
if (vsecp) | if (vsecp) | ||||
if ((error = zfs_vsec_2_aclp(zfsvfs, vap->va_type, vsecp, cr, | if ((error = zfs_vsec_2_aclp(zfsvfs, vap->va_type, vsecp, cr, | ||||
&acl_ids->z_fuidp, &acl_ids->z_aclp)) != 0) | &acl_ids->z_fuidp, &acl_ids->z_aclp)) != 0) | ||||
return (error); | return (error); | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | #endif | ||||
} else { | } else { | ||||
if ((acl_ids->z_mode & S_ISGID) && | if ((acl_ids->z_mode & S_ISGID) && | ||||
secpolicy_vnode_setids_setgids(ZTOV(dzp), cr, gid) != 0) | secpolicy_vnode_setids_setgids(ZTOV(dzp), cr, gid) != 0) | ||||
acl_ids->z_mode &= ~S_ISGID; | acl_ids->z_mode &= ~S_ISGID; | ||||
} | } | ||||
if (acl_ids->z_aclp == NULL) { | if (acl_ids->z_aclp == NULL) { | ||||
mutex_enter(&dzp->z_acl_lock); | mutex_enter(&dzp->z_acl_lock); | ||||
mutex_enter(&dzp->z_lock); | |||||
if (!(flag & IS_ROOT_NODE) && | if (!(flag & IS_ROOT_NODE) && | ||||
(dzp->z_pflags & ZFS_INHERIT_ACE) && | (dzp->z_pflags & ZFS_INHERIT_ACE) && | ||||
!(dzp->z_pflags & ZFS_XATTR)) { | !(dzp->z_pflags & ZFS_XATTR)) { | ||||
VERIFY(0 == zfs_acl_node_read(dzp, B_TRUE, | VERIFY(0 == zfs_acl_node_read(dzp, &paclp, B_FALSE)); | ||||
&paclp, B_FALSE)); | |||||
acl_ids->z_aclp = zfs_acl_inherit(zfsvfs, | acl_ids->z_aclp = zfs_acl_inherit(zfsvfs, | ||||
vap->va_type, paclp, acl_ids->z_mode); | vap->va_type, paclp, acl_ids->z_mode); | ||||
inherited = B_TRUE; | inherited = B_TRUE; | ||||
} else { | } else { | ||||
acl_ids->z_aclp = | acl_ids->z_aclp = | ||||
zfs_acl_alloc(zfs_acl_version_zp(dzp)); | zfs_acl_alloc(zfs_acl_version_zp(dzp)); | ||||
acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL; | acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL; | ||||
} | } | ||||
mutex_exit(&dzp->z_lock); | |||||
mutex_exit(&dzp->z_acl_lock); | mutex_exit(&dzp->z_acl_lock); | ||||
if (vap->va_type == VDIR) | if (vap->va_type == VDIR) | ||||
acl_ids->z_aclp->z_hints |= ZFS_ACL_AUTO_INHERIT; | acl_ids->z_aclp->z_hints |= ZFS_ACL_AUTO_INHERIT; | ||||
if (zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK && | if (zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK && | ||||
zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH && | zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH && | ||||
zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH_X) | zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH_X) | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) | ||||
if (mask == 0) | if (mask == 0) | ||||
return (SET_ERROR(ENOSYS)); | return (SET_ERROR(ENOSYS)); | ||||
if (error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr)) | if (error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr)) | ||||
return (error); | return (error); | ||||
mutex_enter(&zp->z_acl_lock); | mutex_enter(&zp->z_acl_lock); | ||||
error = zfs_acl_node_read(zp, B_FALSE, &aclp, B_FALSE); | ASSERT_VOP_LOCKED(ZTOV(zp), "zfs_getacl"); | ||||
error = zfs_acl_node_read(zp, &aclp, B_FALSE); | |||||
if (error != 0) { | if (error != 0) { | ||||
mutex_exit(&zp->z_acl_lock); | mutex_exit(&zp->z_acl_lock); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Scan ACL to determine number of ACEs | * Scan ACL to determine number of ACEs | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 131 Lines • ▼ Show 20 Lines | zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) | ||||
ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT); | ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT); | ||||
dmu_tx_t *tx; | dmu_tx_t *tx; | ||||
int error; | int error; | ||||
zfs_acl_t *aclp; | zfs_acl_t *aclp; | ||||
zfs_fuid_info_t *fuidp = NULL; | zfs_fuid_info_t *fuidp = NULL; | ||||
boolean_t fuid_dirtied; | boolean_t fuid_dirtied; | ||||
uint64_t acl_obj; | uint64_t acl_obj; | ||||
ASSERT_VOP_ELOCKED(ZTOV(zp), "zfs_setacl"); | |||||
if (mask == 0) | if (mask == 0) | ||||
return (SET_ERROR(ENOSYS)); | return (SET_ERROR(ENOSYS)); | ||||
if (zp->z_pflags & ZFS_IMMUTABLE) | if (zp->z_pflags & ZFS_IMMUTABLE) | ||||
return (SET_ERROR(EPERM)); | return (SET_ERROR(EPERM)); | ||||
if (error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr)) | if (error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr)) | ||||
return (error); | return (error); | ||||
error = zfs_vsec_2_aclp(zfsvfs, ZTOV(zp)->v_type, vsecp, cr, &fuidp, | error = zfs_vsec_2_aclp(zfsvfs, ZTOV(zp)->v_type, vsecp, cr, &fuidp, | ||||
&aclp); | &aclp); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
/* | /* | ||||
* If ACL wide flags aren't being set then preserve any | * If ACL wide flags aren't being set then preserve any | ||||
* existing flags. | * existing flags. | ||||
*/ | */ | ||||
if (!(vsecp->vsa_mask & VSA_ACE_ACLFLAGS)) { | if (!(vsecp->vsa_mask & VSA_ACE_ACLFLAGS)) { | ||||
aclp->z_hints |= | aclp->z_hints |= | ||||
(zp->z_pflags & V4_ACL_WIDE_FLAGS); | (zp->z_pflags & V4_ACL_WIDE_FLAGS); | ||||
} | } | ||||
top: | top: | ||||
mutex_enter(&zp->z_acl_lock); | mutex_enter(&zp->z_acl_lock); | ||||
mutex_enter(&zp->z_lock); | |||||
tx = dmu_tx_create(zfsvfs->z_os); | tx = dmu_tx_create(zfsvfs->z_os); | ||||
dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); | dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); | ||||
fuid_dirtied = zfsvfs->z_fuid_dirty; | fuid_dirtied = zfsvfs->z_fuid_dirty; | ||||
if (fuid_dirtied) | if (fuid_dirtied) | ||||
zfs_fuid_txhold(zfsvfs, tx); | zfs_fuid_txhold(zfsvfs, tx); | ||||
Show All 15 Lines | if ((acl_obj = zfs_external_acl(zp)) != 0) { | ||||
} | } | ||||
} else if (!zp->z_is_sa && aclp->z_acl_bytes > ZFS_ACE_SPACE) { | } 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); | dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, aclp->z_acl_bytes); | ||||
} | } | ||||
zfs_sa_upgrade_txholds(tx, zp); | zfs_sa_upgrade_txholds(tx, zp); | ||||
error = dmu_tx_assign(tx, TXG_NOWAIT); | error = dmu_tx_assign(tx, TXG_NOWAIT); | ||||
if (error) { | if (error) { | ||||
mutex_exit(&zp->z_lock); | |||||
mutex_exit(&zp->z_acl_lock); | mutex_exit(&zp->z_acl_lock); | ||||
if (error == ERESTART) { | if (error == ERESTART) { | ||||
dmu_tx_wait(tx); | dmu_tx_wait(tx); | ||||
dmu_tx_abort(tx); | dmu_tx_abort(tx); | ||||
goto top; | goto top; | ||||
} | } | ||||
dmu_tx_abort(tx); | dmu_tx_abort(tx); | ||||
Show All 9 Lines | top: | ||||
if (fuid_dirtied) | if (fuid_dirtied) | ||||
zfs_fuid_sync(zfsvfs, tx); | zfs_fuid_sync(zfsvfs, tx); | ||||
zfs_log_acl(zilog, tx, zp, vsecp, fuidp); | zfs_log_acl(zilog, tx, zp, vsecp, fuidp); | ||||
if (fuidp) | if (fuidp) | ||||
zfs_fuid_info_free(fuidp); | zfs_fuid_info_free(fuidp); | ||||
dmu_tx_commit(tx); | dmu_tx_commit(tx); | ||||
mutex_exit(&zp->z_lock); | |||||
mutex_exit(&zp->z_acl_lock); | mutex_exit(&zp->z_acl_lock); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Check accesses of interest (AoI) against attributes of the dataset | * Check accesses of interest (AoI) against attributes of the dataset | ||||
* such as read-only. Returns zero if no AoI conflict with dataset | * such as read-only. Returns zero if no AoI conflict with dataset | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode, | ||||
boolean_t checkit; | boolean_t checkit; | ||||
uid_t gowner; | uid_t gowner; | ||||
uid_t fowner; | uid_t fowner; | ||||
zfs_fuid_map_ids(zp, cr, &fowner, &gowner); | zfs_fuid_map_ids(zp, cr, &fowner, &gowner); | ||||
mutex_enter(&zp->z_acl_lock); | mutex_enter(&zp->z_acl_lock); | ||||
error = zfs_acl_node_read(zp, B_FALSE, &aclp, B_FALSE); | ASSERT_VOP_LOCKED(ZTOV(zp), "zfs_zaccess_aces_check"); | ||||
error = zfs_acl_node_read(zp, &aclp, B_FALSE); | |||||
if (error != 0) { | if (error != 0) { | ||||
mutex_exit(&zp->z_acl_lock); | mutex_exit(&zp->z_acl_lock); | ||||
return (error); | return (error); | ||||
} | } | ||||
ASSERT(zp->z_acl_cached); | ASSERT(zp->z_acl_cached); | ||||
while (acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask, | while (acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask, | ||||
▲ Show 20 Lines • Show All 658 Lines • Show Last 20 Lines |
Looks like the 2nd arg to this macro is always the function name. You could use func inside the macro instead. (like dprintf() in zfs_debug.h) Or if you don't want to change the macro, you could pass func to it from these new callers.