mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
xfs: simplify xfs_qm_dqusage_adjust
There is no need to have the users and group/project quota locked at the same time. Get rid of xfs_qm_dqget_noattach and just do a xfs_qm_dqget inside xfs_qm_quotacheck_dqadjust for the quota we are operating on right now. The new version of xfs_qm_quotacheck_dqadjust holds the inode lock over it's operations, which is not a problem as it simply increments counters and there is no concern about log contention during mount time. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
This commit is contained in:
parent
4472235205
commit
52fda11424
@ -1199,87 +1199,6 @@ xfs_qm_list_destroy(
|
||||
mutex_destroy(&(list->qh_lock));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Stripped down version of dqattach. This doesn't attach, or even look at the
|
||||
* dquots attached to the inode. The rationale is that there won't be any
|
||||
* attached at the time this is called from quotacheck.
|
||||
*/
|
||||
STATIC int
|
||||
xfs_qm_dqget_noattach(
|
||||
xfs_inode_t *ip,
|
||||
xfs_dquot_t **O_udqpp,
|
||||
xfs_dquot_t **O_gdqpp)
|
||||
{
|
||||
int error;
|
||||
xfs_mount_t *mp;
|
||||
xfs_dquot_t *udqp, *gdqp;
|
||||
|
||||
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
|
||||
mp = ip->i_mount;
|
||||
udqp = NULL;
|
||||
gdqp = NULL;
|
||||
|
||||
if (XFS_IS_UQUOTA_ON(mp)) {
|
||||
ASSERT(ip->i_udquot == NULL);
|
||||
/*
|
||||
* We want the dquot allocated if it doesn't exist.
|
||||
*/
|
||||
if ((error = xfs_qm_dqget(mp, ip, ip->i_d.di_uid, XFS_DQ_USER,
|
||||
XFS_QMOPT_DQALLOC | XFS_QMOPT_DOWARN,
|
||||
&udqp))) {
|
||||
/*
|
||||
* Shouldn't be able to turn off quotas here.
|
||||
*/
|
||||
ASSERT(error != ESRCH);
|
||||
ASSERT(error != ENOENT);
|
||||
return error;
|
||||
}
|
||||
ASSERT(udqp);
|
||||
}
|
||||
|
||||
if (XFS_IS_OQUOTA_ON(mp)) {
|
||||
ASSERT(ip->i_gdquot == NULL);
|
||||
if (udqp)
|
||||
xfs_dqunlock(udqp);
|
||||
error = XFS_IS_GQUOTA_ON(mp) ?
|
||||
xfs_qm_dqget(mp, ip,
|
||||
ip->i_d.di_gid, XFS_DQ_GROUP,
|
||||
XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
|
||||
&gdqp) :
|
||||
xfs_qm_dqget(mp, ip,
|
||||
ip->i_d.di_projid, XFS_DQ_PROJ,
|
||||
XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
|
||||
&gdqp);
|
||||
if (error) {
|
||||
if (udqp)
|
||||
xfs_qm_dqrele(udqp);
|
||||
ASSERT(error != ESRCH);
|
||||
ASSERT(error != ENOENT);
|
||||
return error;
|
||||
}
|
||||
ASSERT(gdqp);
|
||||
|
||||
/* Reacquire the locks in the right order */
|
||||
if (udqp) {
|
||||
if (! xfs_qm_dqlock_nowait(udqp)) {
|
||||
xfs_dqunlock(gdqp);
|
||||
xfs_dqlock(udqp);
|
||||
xfs_dqlock(gdqp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*O_udqpp = udqp;
|
||||
*O_gdqpp = gdqp;
|
||||
|
||||
#ifdef QUOTADEBUG
|
||||
if (udqp) ASSERT(XFS_DQ_IS_LOCKED(udqp));
|
||||
if (gdqp) ASSERT(XFS_DQ_IS_LOCKED(gdqp));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create an inode and return with a reference already taken, but unlocked
|
||||
* This is how we create quota inodes
|
||||
@ -1546,18 +1465,34 @@ xfs_qm_dqiterate(
|
||||
|
||||
/*
|
||||
* Called by dqusage_adjust in doing a quotacheck.
|
||||
* Given the inode, and a dquot (either USR or GRP, doesn't matter),
|
||||
* this updates its incore copy as well as the buffer copy. This is
|
||||
* so that once the quotacheck is done, we can just log all the buffers,
|
||||
* as opposed to logging numerous updates to individual dquots.
|
||||
*
|
||||
* Given the inode, and a dquot id this updates both the incore dqout as well
|
||||
* as the buffer copy. This is so that once the quotacheck is done, we can
|
||||
* just log all the buffers, as opposed to logging numerous updates to
|
||||
* individual dquots.
|
||||
*/
|
||||
STATIC void
|
||||
STATIC int
|
||||
xfs_qm_quotacheck_dqadjust(
|
||||
xfs_dquot_t *dqp,
|
||||
struct xfs_inode *ip,
|
||||
xfs_dqid_t id,
|
||||
uint type,
|
||||
xfs_qcnt_t nblks,
|
||||
xfs_qcnt_t rtblks)
|
||||
{
|
||||
ASSERT(XFS_DQ_IS_LOCKED(dqp));
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
struct xfs_dquot *dqp;
|
||||
int error;
|
||||
|
||||
error = xfs_qm_dqget(mp, ip, id, type,
|
||||
XFS_QMOPT_DQALLOC | XFS_QMOPT_DOWARN, &dqp);
|
||||
if (error) {
|
||||
/*
|
||||
* Shouldn't be able to turn off quotas here.
|
||||
*/
|
||||
ASSERT(error != ESRCH);
|
||||
ASSERT(error != ENOENT);
|
||||
return error;
|
||||
}
|
||||
|
||||
trace_xfs_dqadjust(dqp);
|
||||
|
||||
@ -1582,11 +1517,13 @@ xfs_qm_quotacheck_dqadjust(
|
||||
* There are no timers for the default values set in the root dquot.
|
||||
*/
|
||||
if (dqp->q_core.d_id) {
|
||||
xfs_qm_adjust_dqlimits(dqp->q_mount, &dqp->q_core);
|
||||
xfs_qm_adjust_dqtimers(dqp->q_mount, &dqp->q_core);
|
||||
xfs_qm_adjust_dqlimits(mp, &dqp->q_core);
|
||||
xfs_qm_adjust_dqtimers(mp, &dqp->q_core);
|
||||
}
|
||||
|
||||
dqp->dq_flags |= XFS_DQ_DIRTY;
|
||||
xfs_qm_dqput(dqp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
@ -1629,8 +1566,7 @@ xfs_qm_dqusage_adjust(
|
||||
int *res) /* result code value */
|
||||
{
|
||||
xfs_inode_t *ip;
|
||||
xfs_dquot_t *udqp, *gdqp;
|
||||
xfs_qcnt_t nblks, rtblks;
|
||||
xfs_qcnt_t nblks, rtblks = 0;
|
||||
int error;
|
||||
|
||||
ASSERT(XFS_IS_QUOTA_RUNNING(mp));
|
||||
@ -1650,51 +1586,24 @@ xfs_qm_dqusage_adjust(
|
||||
* the case in all other instances. It's OK that we do this because
|
||||
* quotacheck is done only at mount time.
|
||||
*/
|
||||
if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip))) {
|
||||
error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip);
|
||||
if (error) {
|
||||
*res = BULKSTAT_RV_NOTHING;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain the locked dquots. In case of an error (eg. allocation
|
||||
* fails for ENOSPC), we return the negative of the error number
|
||||
* to bulkstat, so that it can get propagated to quotacheck() and
|
||||
* making us disable quotas for the file system.
|
||||
*/
|
||||
if ((error = xfs_qm_dqget_noattach(ip, &udqp, &gdqp))) {
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
IRELE(ip);
|
||||
*res = BULKSTAT_RV_GIVEUP;
|
||||
return error;
|
||||
}
|
||||
ASSERT(ip->i_delayed_blks == 0);
|
||||
|
||||
rtblks = 0;
|
||||
if (! XFS_IS_REALTIME_INODE(ip)) {
|
||||
nblks = (xfs_qcnt_t)ip->i_d.di_nblocks;
|
||||
} else {
|
||||
if (XFS_IS_REALTIME_INODE(ip)) {
|
||||
/*
|
||||
* Walk thru the extent list and count the realtime blocks.
|
||||
*/
|
||||
if ((error = xfs_qm_get_rtblks(ip, &rtblks))) {
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
IRELE(ip);
|
||||
if (udqp)
|
||||
xfs_qm_dqput(udqp);
|
||||
if (gdqp)
|
||||
xfs_qm_dqput(gdqp);
|
||||
*res = BULKSTAT_RV_GIVEUP;
|
||||
return error;
|
||||
}
|
||||
nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks;
|
||||
error = xfs_qm_get_rtblks(ip, &rtblks);
|
||||
if (error)
|
||||
goto error0;
|
||||
}
|
||||
ASSERT(ip->i_delayed_blks == 0);
|
||||
|
||||
/*
|
||||
* We can't release the inode while holding its dquot locks.
|
||||
* The inode can go into inactive and might try to acquire the dquotlocks.
|
||||
* So, just unlock here and do a vn_rele at the end.
|
||||
*/
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks;
|
||||
|
||||
/*
|
||||
* Add the (disk blocks and inode) resources occupied by this
|
||||
@ -1709,26 +1618,36 @@ xfs_qm_dqusage_adjust(
|
||||
* and quotaoffs don't race. (Quotachecks happen at mount time only).
|
||||
*/
|
||||
if (XFS_IS_UQUOTA_ON(mp)) {
|
||||
ASSERT(udqp);
|
||||
xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks);
|
||||
xfs_qm_dqput(udqp);
|
||||
error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_uid,
|
||||
XFS_DQ_USER, nblks, rtblks);
|
||||
if (error)
|
||||
goto error0;
|
||||
}
|
||||
if (XFS_IS_OQUOTA_ON(mp)) {
|
||||
ASSERT(gdqp);
|
||||
xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks);
|
||||
xfs_qm_dqput(gdqp);
|
||||
}
|
||||
/*
|
||||
* Now release the inode. This will send it to 'inactive', and
|
||||
* possibly even free blocks.
|
||||
*/
|
||||
IRELE(ip);
|
||||
|
||||
/*
|
||||
* Goto next inode.
|
||||
*/
|
||||
if (XFS_IS_GQUOTA_ON(mp)) {
|
||||
error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_gid,
|
||||
XFS_DQ_GROUP, nblks, rtblks);
|
||||
if (error)
|
||||
goto error0;
|
||||
}
|
||||
|
||||
if (XFS_IS_PQUOTA_ON(mp)) {
|
||||
error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_projid,
|
||||
XFS_DQ_PROJ, nblks, rtblks);
|
||||
if (error)
|
||||
goto error0;
|
||||
}
|
||||
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
IRELE(ip);
|
||||
*res = BULKSTAT_RV_DIDONE;
|
||||
return 0;
|
||||
|
||||
error0:
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
IRELE(ip);
|
||||
*res = BULKSTAT_RV_GIVEUP;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user