xfs: create quota preallocation watermarks for realtime quota
authorDarrick J. Wong <djwong@kernel.org>
Mon, 4 Nov 2024 04:19:41 +0000 (20:19 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 5 Nov 2024 21:38:46 +0000 (13:38 -0800)
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>
fs/xfs/xfs_dquot.c
fs/xfs/xfs_dquot.h
fs/xfs/xfs_iomap.c
fs/xfs/xfs_qm.c

index 3bf4745..ff982d9 100644 (file)
@@ -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);
 }
 
 /*
index 677bb2d..d73d179 100644 (file)
@@ -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;
index 17e5c27..a6fc5ac 100644 (file)
@@ -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;
        }
 
index 1c7d861..90d45aa 100644 (file)
@@ -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;