Commit 292b47b4 authored by Darrick J. Wong's avatar Darrick J. Wong

xfs: refactor xfs_trans_dqresv

Now that we've refactored the resource usage and limits into
per-resource structures, we can refactor some of the open-coded
reservation limit checking in xfs_trans_dqresv.
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarChandan Babu R <chandanrlinux@gmail.com>
Reviewed-by: default avatarAllison Collins <allison.henderson@oracle.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent d1520dea
...@@ -554,6 +554,58 @@ xfs_quota_warn( ...@@ -554,6 +554,58 @@ xfs_quota_warn(
mp->m_super->s_dev, type); mp->m_super->s_dev, type);
} }
/*
* Decide if we can make an additional reservation against a quota resource.
* Returns an inode QUOTA_NL_ warning code and whether or not it's fatal.
*
* Note that we assume that the numeric difference between the inode and block
* warning codes will always be 3 since it's userspace ABI now, and will never
* decrease the quota reservation, so the *BELOW messages are irrelevant.
*/
static inline int
xfs_dqresv_check(
struct xfs_dquot_res *res,
struct xfs_quota_limits *qlim,
int64_t delta,
bool *fatal)
{
xfs_qcnt_t hardlimit = res->hardlimit;
xfs_qcnt_t softlimit = res->softlimit;
xfs_qcnt_t total_count = res->reserved + delta;
BUILD_BUG_ON(QUOTA_NL_BHARDWARN != QUOTA_NL_IHARDWARN + 3);
BUILD_BUG_ON(QUOTA_NL_BSOFTLONGWARN != QUOTA_NL_ISOFTLONGWARN + 3);
BUILD_BUG_ON(QUOTA_NL_BSOFTWARN != QUOTA_NL_ISOFTWARN + 3);
*fatal = false;
if (delta <= 0)
return QUOTA_NL_NOWARN;
if (!hardlimit)
hardlimit = qlim->hard;
if (!softlimit)
softlimit = qlim->soft;
if (hardlimit && total_count > hardlimit) {
*fatal = true;
return QUOTA_NL_IHARDWARN;
}
if (softlimit && total_count > softlimit) {
time64_t now = ktime_get_real_seconds();
if ((res->timer != 0 && now > res->timer) ||
(res->warnings != 0 && res->warnings >= qlim->warn)) {
*fatal = true;
return QUOTA_NL_ISOFTLONGWARN;
}
return QUOTA_NL_ISOFTWARN;
}
return QUOTA_NL_NOWARN;
}
/* /*
* This reserves disk blocks and inodes against a dquot. * This reserves disk blocks and inodes against a dquot.
* Flags indicate if the dquot is to be locked here and also * Flags indicate if the dquot is to be locked here and also
...@@ -569,108 +621,59 @@ xfs_trans_dqresv( ...@@ -569,108 +621,59 @@ xfs_trans_dqresv(
long ninos, long ninos,
uint flags) uint flags)
{ {
xfs_qcnt_t hardlimit;
xfs_qcnt_t softlimit;
time64_t timer;
xfs_qwarncnt_t warns;
xfs_qwarncnt_t warnlimit;
xfs_qcnt_t total_count;
xfs_qcnt_t *resbcountp;
struct xfs_quotainfo *q = mp->m_quotainfo; struct xfs_quotainfo *q = mp->m_quotainfo;
struct xfs_def_quota *defq; struct xfs_def_quota *defq;
struct xfs_dquot_res *blkres;
struct xfs_quota_limits *qlim;
xfs_dqlock(dqp); xfs_dqlock(dqp);
defq = xfs_get_defquota(q, xfs_dquot_type(dqp)); defq = xfs_get_defquota(q, xfs_dquot_type(dqp));
if (flags & XFS_TRANS_DQ_RES_BLKS) { if (flags & XFS_TRANS_DQ_RES_BLKS) {
hardlimit = dqp->q_blk.hardlimit; blkres = &dqp->q_blk;
if (!hardlimit) qlim = &defq->blk;
hardlimit = defq->blk.hard;
softlimit = dqp->q_blk.softlimit;
if (!softlimit)
softlimit = defq->blk.soft;
timer = dqp->q_blk.timer;
warns = dqp->q_blk.warnings;
warnlimit = defq->blk.warn;
resbcountp = &dqp->q_blk.reserved;
} else { } else {
ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS); blkres = &dqp->q_rtb;
hardlimit = dqp->q_rtb.hardlimit; qlim = &defq->rtb;
if (!hardlimit)
hardlimit = defq->rtb.hard;
softlimit = dqp->q_rtb.softlimit;
if (!softlimit)
softlimit = defq->rtb.soft;
timer = dqp->q_rtb.timer;
warns = dqp->q_rtb.warnings;
warnlimit = defq->rtb.warn;
resbcountp = &dqp->q_rtb.reserved;
} }
if ((flags & XFS_QMOPT_FORCE_RES) == 0 && dqp->q_id && if ((flags & XFS_QMOPT_FORCE_RES) == 0 && dqp->q_id &&
((XFS_IS_UQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISUDQ(dqp)) || ((XFS_IS_UQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISUDQ(dqp)) ||
(XFS_IS_GQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISGDQ(dqp)) || (XFS_IS_GQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISGDQ(dqp)) ||
(XFS_IS_PQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISPDQ(dqp)))) { (XFS_IS_PQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISPDQ(dqp)))) {
if (nblks > 0) { int quota_nl;
bool fatal;
/* /*
* dquot is locked already. See if we'd go over the * dquot is locked already. See if we'd go over the hardlimit
* hardlimit or exceed the timelimit if we allocate * or exceed the timelimit if we'd reserve resources.
* nblks.
*/ */
total_count = *resbcountp + nblks; quota_nl = xfs_dqresv_check(blkres, qlim, nblks, &fatal);
if (hardlimit && total_count > hardlimit) { if (quota_nl != QUOTA_NL_NOWARN) {
xfs_quota_warn(mp, dqp, QUOTA_NL_BHARDWARN); /*
goto error_return; * Quota block warning codes are 3 more than the inode
} * codes, which we check above.
if (softlimit && total_count > softlimit) { */
if ((timer != 0 && xfs_quota_warn(mp, dqp, quota_nl + 3);
ktime_get_real_seconds() > timer) || if (fatal)
(warns != 0 && warns >= warnlimit)) {
xfs_quota_warn(mp, dqp,
QUOTA_NL_BSOFTLONGWARN);
goto error_return; goto error_return;
} }
xfs_quota_warn(mp, dqp, QUOTA_NL_BSOFTWARN); quota_nl = xfs_dqresv_check(&dqp->q_ino, &defq->ino, ninos,
} &fatal);
} if (quota_nl != QUOTA_NL_NOWARN) {
if (ninos > 0) { xfs_quota_warn(mp, dqp, quota_nl);
total_count = dqp->q_ino.reserved + ninos; if (fatal)
timer = dqp->q_ino.timer;
warns = dqp->q_ino.warnings;
warnlimit = defq->ino.warn;
hardlimit = dqp->q_ino.hardlimit;
if (!hardlimit)
hardlimit = defq->ino.hard;
softlimit = dqp->q_ino.softlimit;
if (!softlimit)
softlimit = defq->ino.soft;
if (hardlimit && total_count > hardlimit) {
xfs_quota_warn(mp, dqp, QUOTA_NL_IHARDWARN);
goto error_return; goto error_return;
} }
if (softlimit && total_count > softlimit) {
if ((timer != 0 &&
ktime_get_real_seconds() > timer) ||
(warns != 0 && warns >= warnlimit)) {
xfs_quota_warn(mp, dqp,
QUOTA_NL_ISOFTLONGWARN);
goto error_return;
}
xfs_quota_warn(mp, dqp, QUOTA_NL_ISOFTWARN);
}
}
} }
/* /*
* Change the reservation, but not the actual usage. * Change the reservation, but not the actual usage.
* Note that q_blk.reserved = q_blk.count + resv * Note that q_blk.reserved = q_blk.count + resv
*/ */
(*resbcountp) += (xfs_qcnt_t)nblks; blkres->reserved += (xfs_qcnt_t)nblks;
if (ninos != 0)
dqp->q_ino.reserved += (xfs_qcnt_t)ninos; dqp->q_ino.reserved += (xfs_qcnt_t)ninos;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment