mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
xfs: create quota preallocation watermarks for realtime quota
Refactor the quota preallocation watermarking code so that it'll work for realtime quota too. Convert the do_div calls into div_u64 for compactness. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
9a17ebfea9
commit
5dd70852b0
@ -277,6 +277,25 @@ xfs_qm_init_dquot_blk(
|
||||
xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1);
|
||||
}
|
||||
|
||||
static void
|
||||
xfs_dquot_set_prealloc(
|
||||
struct xfs_dquot_pre *pre,
|
||||
const struct xfs_dquot_res *res)
|
||||
{
|
||||
xfs_qcnt_t space;
|
||||
|
||||
pre->q_prealloc_hi_wmark = res->hardlimit;
|
||||
pre->q_prealloc_lo_wmark = res->softlimit;
|
||||
|
||||
space = div_u64(pre->q_prealloc_hi_wmark, 100);
|
||||
if (!pre->q_prealloc_lo_wmark)
|
||||
pre->q_prealloc_lo_wmark = space * 95;
|
||||
|
||||
pre->q_low_space[XFS_QLOWSP_1_PCNT] = space;
|
||||
pre->q_low_space[XFS_QLOWSP_3_PCNT] = space * 3;
|
||||
pre->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the dynamic speculative preallocation thresholds. The lo/hi
|
||||
* watermarks correspond to the soft and hard limits by default. If a soft limit
|
||||
@ -285,22 +304,8 @@ xfs_qm_init_dquot_blk(
|
||||
void
|
||||
xfs_dquot_set_prealloc_limits(struct xfs_dquot *dqp)
|
||||
{
|
||||
uint64_t space;
|
||||
|
||||
dqp->q_prealloc_hi_wmark = dqp->q_blk.hardlimit;
|
||||
dqp->q_prealloc_lo_wmark = dqp->q_blk.softlimit;
|
||||
if (!dqp->q_prealloc_lo_wmark) {
|
||||
dqp->q_prealloc_lo_wmark = dqp->q_prealloc_hi_wmark;
|
||||
do_div(dqp->q_prealloc_lo_wmark, 100);
|
||||
dqp->q_prealloc_lo_wmark *= 95;
|
||||
}
|
||||
|
||||
space = dqp->q_prealloc_hi_wmark;
|
||||
|
||||
do_div(space, 100);
|
||||
dqp->q_low_space[XFS_QLOWSP_1_PCNT] = space;
|
||||
dqp->q_low_space[XFS_QLOWSP_3_PCNT] = space * 3;
|
||||
dqp->q_low_space[XFS_QLOWSP_5_PCNT] = space * 5;
|
||||
xfs_dquot_set_prealloc(&dqp->q_blk_prealloc, &dqp->q_blk);
|
||||
xfs_dquot_set_prealloc(&dqp->q_rtb_prealloc, &dqp->q_rtb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -56,6 +56,12 @@ xfs_dquot_res_over_limits(
|
||||
return false;
|
||||
}
|
||||
|
||||
struct xfs_dquot_pre {
|
||||
xfs_qcnt_t q_prealloc_lo_wmark;
|
||||
xfs_qcnt_t q_prealloc_hi_wmark;
|
||||
int64_t q_low_space[XFS_QLOWSP_MAX];
|
||||
};
|
||||
|
||||
/*
|
||||
* The incore dquot structure
|
||||
*/
|
||||
@ -76,9 +82,9 @@ struct xfs_dquot {
|
||||
|
||||
struct xfs_dq_logitem q_logitem;
|
||||
|
||||
xfs_qcnt_t q_prealloc_lo_wmark;
|
||||
xfs_qcnt_t q_prealloc_hi_wmark;
|
||||
int64_t q_low_space[XFS_QLOWSP_MAX];
|
||||
struct xfs_dquot_pre q_blk_prealloc;
|
||||
struct xfs_dquot_pre q_rtb_prealloc;
|
||||
|
||||
struct mutex q_qlock;
|
||||
struct completion q_flush;
|
||||
atomic_t q_pincount;
|
||||
@ -192,7 +198,11 @@ static inline bool xfs_dquot_lowsp(struct xfs_dquot *dqp)
|
||||
int64_t freesp;
|
||||
|
||||
freesp = dqp->q_blk.hardlimit - dqp->q_blk.reserved;
|
||||
if (freesp < dqp->q_low_space[XFS_QLOWSP_1_PCNT])
|
||||
if (freesp < dqp->q_blk_prealloc.q_low_space[XFS_QLOWSP_1_PCNT])
|
||||
return true;
|
||||
|
||||
freesp = dqp->q_rtb.hardlimit - dqp->q_rtb.reserved;
|
||||
if (freesp < dqp->q_rtb_prealloc.q_low_space[XFS_QLOWSP_1_PCNT])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -353,16 +353,26 @@ xfs_quota_need_throttle(
|
||||
xfs_fsblock_t alloc_blocks)
|
||||
{
|
||||
struct xfs_dquot *dq = xfs_inode_dquot(ip, type);
|
||||
struct xfs_dquot_res *res;
|
||||
struct xfs_dquot_pre *pre;
|
||||
|
||||
if (!dq || !xfs_this_quota_on(ip->i_mount, type))
|
||||
return false;
|
||||
|
||||
if (XFS_IS_REALTIME_INODE(ip)) {
|
||||
res = &dq->q_rtb;
|
||||
pre = &dq->q_rtb_prealloc;
|
||||
} else {
|
||||
res = &dq->q_blk;
|
||||
pre = &dq->q_blk_prealloc;
|
||||
}
|
||||
|
||||
/* no hi watermark, no throttle */
|
||||
if (!dq->q_prealloc_hi_wmark)
|
||||
if (!pre->q_prealloc_hi_wmark)
|
||||
return false;
|
||||
|
||||
/* under the lo watermark, no throttle */
|
||||
if (dq->q_blk.reserved + alloc_blocks < dq->q_prealloc_lo_wmark)
|
||||
if (res->reserved + alloc_blocks < pre->q_prealloc_lo_wmark)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -377,22 +387,35 @@ xfs_quota_calc_throttle(
|
||||
int64_t *qfreesp)
|
||||
{
|
||||
struct xfs_dquot *dq = xfs_inode_dquot(ip, type);
|
||||
struct xfs_dquot_res *res;
|
||||
struct xfs_dquot_pre *pre;
|
||||
int64_t freesp;
|
||||
int shift = 0;
|
||||
|
||||
if (!dq) {
|
||||
res = NULL;
|
||||
pre = NULL;
|
||||
} else if (XFS_IS_REALTIME_INODE(ip)) {
|
||||
res = &dq->q_rtb;
|
||||
pre = &dq->q_rtb_prealloc;
|
||||
} else {
|
||||
res = &dq->q_blk;
|
||||
pre = &dq->q_blk_prealloc;
|
||||
}
|
||||
|
||||
/* no dq, or over hi wmark, squash the prealloc completely */
|
||||
if (!dq || dq->q_blk.reserved >= dq->q_prealloc_hi_wmark) {
|
||||
if (!res || res->reserved >= pre->q_prealloc_hi_wmark) {
|
||||
*qblocks = 0;
|
||||
*qfreesp = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
freesp = dq->q_prealloc_hi_wmark - dq->q_blk.reserved;
|
||||
if (freesp < dq->q_low_space[XFS_QLOWSP_5_PCNT]) {
|
||||
freesp = pre->q_prealloc_hi_wmark - res->reserved;
|
||||
if (freesp < pre->q_low_space[XFS_QLOWSP_5_PCNT]) {
|
||||
shift = 2;
|
||||
if (freesp < dq->q_low_space[XFS_QLOWSP_3_PCNT])
|
||||
if (freesp < pre->q_low_space[XFS_QLOWSP_3_PCNT])
|
||||
shift += 2;
|
||||
if (freesp < dq->q_low_space[XFS_QLOWSP_1_PCNT])
|
||||
if (freesp < pre->q_low_space[XFS_QLOWSP_1_PCNT])
|
||||
shift += 2;
|
||||
}
|
||||
|
||||
|
@ -2178,6 +2178,8 @@ xfs_inode_near_dquot_enforcement(
|
||||
xfs_dqtype_t type)
|
||||
{
|
||||
struct xfs_dquot *dqp;
|
||||
struct xfs_dquot_res *res;
|
||||
struct xfs_dquot_pre *pre;
|
||||
int64_t freesp;
|
||||
|
||||
/* We only care for quotas that are enabled and enforced. */
|
||||
@ -2186,21 +2188,30 @@ xfs_inode_near_dquot_enforcement(
|
||||
return false;
|
||||
|
||||
if (xfs_dquot_res_over_limits(&dqp->q_ino) ||
|
||||
xfs_dquot_res_over_limits(&dqp->q_blk) ||
|
||||
xfs_dquot_res_over_limits(&dqp->q_rtb))
|
||||
return true;
|
||||
|
||||
if (XFS_IS_REALTIME_INODE(ip)) {
|
||||
res = &dqp->q_rtb;
|
||||
pre = &dqp->q_rtb_prealloc;
|
||||
} else {
|
||||
res = &dqp->q_blk;
|
||||
pre = &dqp->q_blk_prealloc;
|
||||
}
|
||||
|
||||
/* For space on the data device, check the various thresholds. */
|
||||
if (!dqp->q_prealloc_hi_wmark)
|
||||
if (!pre->q_prealloc_hi_wmark)
|
||||
return false;
|
||||
|
||||
if (dqp->q_blk.reserved < dqp->q_prealloc_lo_wmark)
|
||||
if (res->reserved < pre->q_prealloc_lo_wmark)
|
||||
return false;
|
||||
|
||||
if (dqp->q_blk.reserved >= dqp->q_prealloc_hi_wmark)
|
||||
if (res->reserved >= pre->q_prealloc_hi_wmark)
|
||||
return true;
|
||||
|
||||
freesp = dqp->q_prealloc_hi_wmark - dqp->q_blk.reserved;
|
||||
if (freesp < dqp->q_low_space[XFS_QLOWSP_5_PCNT])
|
||||
freesp = pre->q_prealloc_hi_wmark - res->reserved;
|
||||
if (freesp < pre->q_low_space[XFS_QLOWSP_5_PCNT])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user