summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/zfs/zfs_vnops.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs/zfs/zfs_vnops.c')
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vnops.c141
1 files changed, 69 insertions, 72 deletions
diff --git a/usr/src/uts/common/fs/zfs/zfs_vnops.c b/usr/src/uts/common/fs/zfs/zfs_vnops.c
index 20b8a6d658..cd7033934c 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c
@@ -667,6 +667,13 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
/*
* Start a transaction.
*/
+ if (zfs_usergroup_overquota(zfsvfs,
+ B_FALSE, zp->z_phys->zp_uid) ||
+ zfs_usergroup_overquota(zfsvfs,
+ B_TRUE, zp->z_phys->zp_gid)) {
+ error = EDQUOT;
+ break;
+ }
woff = uio->uio_loffset;
tx = dmu_tx_create(zfsvfs->z_os);
dmu_tx_hold_bonus(tx, zp->z_id);
@@ -1183,23 +1190,16 @@ top:
if ((error = zfs_acl_ids_create(dzp, 0, vap, cr, vsecp,
&acl_ids)) != 0)
goto out;
+ if (zfs_acl_ids_overquota(zfsvfs, &acl_ids)) {
+ error = EDQUOT;
+ goto out;
+ }
tx = dmu_tx_create(os);
dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
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,
- FUID_SIZE_ESTIMATE(zfsvfs));
- dmu_tx_hold_zap(tx, MASTER_NODE_OBJ,
- FALSE, NULL);
- } else {
- dmu_tx_hold_bonus(tx, zfsvfs->z_fuid_obj);
- dmu_tx_hold_write(tx, zfsvfs->z_fuid_obj, 0,
- FUID_SIZE_ESTIMATE(zfsvfs));
- }
- }
+ if (fuid_dirtied)
+ zfs_fuid_txhold(zfsvfs, tx);
dmu_tx_hold_bonus(tx, dzp->z_id);
dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
if (acl_ids.z_aclp->z_acl_bytes > ZFS_ACE_SPACE) {
@@ -1608,6 +1608,11 @@ top:
ZFS_EXIT(zfsvfs);
return (error);
}
+ if (zfs_acl_ids_overquota(zfsvfs, &acl_ids)) {
+ zfs_dirent_unlock(dl);
+ ZFS_EXIT(zfsvfs);
+ return (EDQUOT);
+ }
/*
* Add a new entry to the directory.
@@ -1616,18 +1621,8 @@ top:
dmu_tx_hold_zap(tx, dzp->z_id, TRUE, dirname);
dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL);
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,
- FUID_SIZE_ESTIMATE(zfsvfs));
- dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, FALSE, NULL);
- } else {
- dmu_tx_hold_bonus(tx, zfsvfs->z_fuid_obj);
- dmu_tx_hold_write(tx, zfsvfs->z_fuid_obj, 0,
- FUID_SIZE_ESTIMATE(zfsvfs));
- }
- }
+ if (fuid_dirtied)
+ zfs_fuid_txhold(zfsvfs, tx);
if (acl_ids.z_aclp->z_acl_bytes > ZFS_ACE_SPACE)
dmu_tx_hold_write(tx, DMU_NEW_OBJECT,
0, SPA_MAXBLOCKSIZE);
@@ -2623,11 +2618,8 @@ top:
new_mode = (pmode & S_IFMT) | (vap->va_mode & ~S_IFMT);
- if (err = zfs_acl_chmod_setattr(zp, &aclp, new_mode)) {
- dmu_tx_abort(tx);
- ZFS_EXIT(zfsvfs);
- return (err);
- }
+ if (err = zfs_acl_chmod_setattr(zp, &aclp, new_mode))
+ goto out;
if (pzp->zp_acl.z_acl_extern_obj) {
/* Are we upgrading ACL from old V0 format to new V1 */
if (zfsvfs->z_version <= ZPL_VERSION_FUID &&
@@ -2652,22 +2644,28 @@ top:
if (mask & (AT_UID | AT_GID)) {
if (pzp->zp_xattr) {
err = zfs_zget(zp->z_zfsvfs, pzp->zp_xattr, &attrzp);
- if (err) {
- dmu_tx_abort(tx);
- ZFS_EXIT(zfsvfs);
- if (aclp)
- zfs_acl_free(aclp);
- return (err);
- }
+ if (err)
+ goto out;
dmu_tx_hold_bonus(tx, attrzp->z_id);
}
if (mask & AT_UID) {
new_uid = zfs_fuid_create(zfsvfs,
(uint64_t)vap->va_uid, cr, ZFS_OWNER, &fuidp);
+ if (new_uid != pzp->zp_uid &&
+ zfs_usergroup_overquota(zfsvfs, B_FALSE, new_uid)) {
+ err = EDQUOT;
+ goto out;
+ }
}
+
if (mask & AT_GID) {
new_gid = zfs_fuid_create(zfsvfs, (uint64_t)vap->va_gid,
cr, ZFS_GROUP, &fuidp);
+ if (new_gid != pzp->zp_gid &&
+ zfs_usergroup_overquota(zfsvfs, B_TRUE, new_gid)) {
+ err = EDQUOT;
+ goto out;
+ }
}
fuid_dirtied = zfsvfs->z_fuid_dirty;
if (fuid_dirtied) {
@@ -2687,22 +2685,9 @@ top:
err = dmu_tx_assign(tx, TXG_NOWAIT);
if (err) {
- if (attrzp)
- VN_RELE(ZTOV(attrzp));
-
- if (aclp) {
- zfs_acl_free(aclp);
- aclp = NULL;
- }
-
- if (err == ERESTART) {
+ if (err == ERESTART)
dmu_tx_wait(tx);
- dmu_tx_abort(tx);
- goto top;
- }
- dmu_tx_abort(tx);
- ZFS_EXIT(zfsvfs);
- return (err);
+ goto out;
}
dmu_buf_will_dirty(zp->z_dbuf, tx);
@@ -2740,9 +2725,6 @@ top:
attrzp->z_phys->zp_gid = new_gid;
}
- if (aclp)
- zfs_acl_free(aclp);
-
if (attrzp)
mutex_exit(&attrzp->z_lock);
@@ -2810,15 +2792,29 @@ top:
if (mask != 0)
zfs_log_setattr(zilog, tx, TX_SETATTR, zp, vap, mask, fuidp);
- if (fuidp)
- zfs_fuid_info_free(fuidp);
mutex_exit(&zp->z_lock);
- dmu_tx_commit(tx);
-
+out:
if (attrzp)
VN_RELE(ZTOV(attrzp));
+ if (aclp) {
+ zfs_acl_free(aclp);
+ aclp = NULL;
+ }
+
+ if (fuidp) {
+ zfs_fuid_info_free(fuidp);
+ fuidp = NULL;
+ }
+
+ if (err)
+ dmu_tx_abort(tx);
+ else
+ dmu_tx_commit(tx);
+
+ if (err == ERESTART)
+ goto top;
ZFS_EXIT(zfsvfs);
return (err);
@@ -3286,6 +3282,12 @@ top:
}
VERIFY(0 == zfs_acl_ids_create(dzp, 0, vap, cr, NULL, &acl_ids));
+ if (zfs_acl_ids_overquota(zfsvfs, &acl_ids)) {
+ zfs_acl_ids_free(&acl_ids);
+ zfs_dirent_unlock(dl);
+ ZFS_EXIT(zfsvfs);
+ return (EDQUOT);
+ }
tx = dmu_tx_create(zfsvfs->z_os);
fuid_dirtied = zfsvfs->z_fuid_dirty;
dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, MAX(1, len));
@@ -3293,18 +3295,8 @@ top:
dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
if (acl_ids.z_aclp->z_acl_bytes > ZFS_ACE_SPACE)
dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, SPA_MAXBLOCKSIZE);
- 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,
- FUID_SIZE_ESTIMATE(zfsvfs));
- dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, FALSE, NULL);
- } else {
- dmu_tx_hold_bonus(tx, zfsvfs->z_fuid_obj);
- dmu_tx_hold_write(tx, zfsvfs->z_fuid_obj, 0,
- FUID_SIZE_ESTIMATE(zfsvfs));
- }
- }
+ if (fuid_dirtied)
+ zfs_fuid_txhold(zfsvfs, tx);
error = dmu_tx_assign(tx, TXG_NOWAIT);
if (error) {
zfs_acl_ids_free(&acl_ids);
@@ -3357,7 +3349,6 @@ top:
* Insert the new object into the directory.
*/
(void) zfs_link_create(dl, zp, tx, ZNEW);
-out:
if (error == 0) {
uint64_t txtype = TX_SYMLINK;
if (flags & FIGNORECASE)
@@ -3642,6 +3633,12 @@ zfs_putapage(vnode_t *vp, page_t *pp, u_offset_t *offp,
pvn_write_done(trunc, flags);
len = filesz - off;
}
+
+ if (zfs_usergroup_overquota(zfsvfs, B_FALSE, zp->z_phys->zp_uid) ||
+ zfs_usergroup_overquota(zfsvfs, B_TRUE, zp->z_phys->zp_gid)) {
+ err = EDQUOT;
+ goto out;
+ }
top:
tx = dmu_tx_create(zfsvfs->z_os);
dmu_tx_hold_write(tx, zp->z_id, off, len);