diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-01-29 11:32:09 -0800 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-02-03 09:18:49 -0800 |
commit | 7317a03df703f7cdae3ae9e9635a0ef45849fe09 (patch) | |
tree | ac751913a2d3a2fe2376ce8459ec814097f7dfa3 /fs/xfs/xfs_iops.c | |
parent | f2f7b9ff62a28928f6fe2bd55cdb4d4b02ab7477 (diff) | |
download | lwn-7317a03df703f7cdae3ae9e9635a0ef45849fe09.tar.gz lwn-7317a03df703f7cdae3ae9e9635a0ef45849fe09.zip |
xfs: refactor inode ownership change transaction/inode/quota allocation idiom
For file ownership (uid, gid, prid) changes, create a new helper
xfs_trans_alloc_ichange that allocates a transaction and reserves the
appropriate amount of quota against that transction in preparation for a
change of user, group, or project id. Replace all the open-coded idioms
with a single call to this helper so that we can contain the retry loops
in the next patchset.
This changes the locking behavior for ichange transactions slightly.
Since tr_ichange does not have a permanent reservation and cannot roll,
we pass XFS_ILOCK_EXCL to ijoin so that the inode will be unlocked
automatically at commit time.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Diffstat (limited to 'fs/xfs/xfs_iops.c')
-rw-r--r-- | fs/xfs/xfs_iops.c | 26 |
1 files changed, 2 insertions, 24 deletions
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index f1e21b6cfa48..00369502fe25 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -700,13 +700,11 @@ xfs_setattr_nonsize( return error; } - error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); + error = xfs_trans_alloc_ichange(ip, udqp, gdqp, NULL, + capable(CAP_FOWNER), &tp); if (error) goto out_dqrele; - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, ip, 0); - /* * Change file ownership. Must be the owner or privileged. */ @@ -723,21 +721,6 @@ xfs_setattr_nonsize( uid = (mask & ATTR_UID) ? iattr->ia_uid : iuid; /* - * Do a quota reservation only if uid/gid is actually - * going to change. - */ - if (XFS_IS_QUOTA_RUNNING(mp) && - ((XFS_IS_UQUOTA_ON(mp) && !uid_eq(iuid, uid)) || - (XFS_IS_GQUOTA_ON(mp) && !gid_eq(igid, gid)))) { - ASSERT(tp); - error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, - NULL, capable(CAP_FOWNER) ? - XFS_QMOPT_FORCE_RES : 0); - if (error) /* out of quota */ - goto out_cancel; - } - - /* * CAP_FSETID overrides the following restrictions: * * The set-user-ID and set-group-ID bits of a file will be @@ -786,8 +769,6 @@ xfs_setattr_nonsize( xfs_trans_set_sync(tp); error = xfs_trans_commit(tp); - xfs_iunlock(ip, XFS_ILOCK_EXCL); - /* * Release any dquot(s) the inode had kept before chown. */ @@ -814,9 +795,6 @@ xfs_setattr_nonsize( return 0; -out_cancel: - xfs_trans_cancel(tp); - xfs_iunlock(ip, XFS_ILOCK_EXCL); out_dqrele: xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); |