xfs: refactor xfs_trans_dqresv
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 14 Jul 2020 17:37:34 +0000 (10:37 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Wed, 29 Jul 2020 03:24:14 +0000 (20:24 -0700)
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: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/xfs_trans_dquot.c

index 6f0bfd5221161e08b2051b874755a7a92b396bb6..9dc8dd9f852cc9106dd0d17f003532bfde5c7db4 100644 (file)
@@ -554,6 +554,58 @@ xfs_quota_warn(
                           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.
  * Flags indicate if the dquot is to be locked here and also
@@ -569,99 +621,51 @@ xfs_trans_dqresv(
        long                    ninos,
        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_def_quota    *defq;
-
+       struct xfs_dquot_res    *blkres;
+       struct xfs_quota_limits *qlim;
 
        xfs_dqlock(dqp);
 
        defq = xfs_get_defquota(q, xfs_dquot_type(dqp));
 
        if (flags & XFS_TRANS_DQ_RES_BLKS) {
-               hardlimit = dqp->q_blk.hardlimit;
-               if (!hardlimit)
-                       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;
+               blkres = &dqp->q_blk;
+               qlim = &defq->blk;
        } else {
-               ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS);
-               hardlimit = dqp->q_rtb.hardlimit;
-               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;
+               blkres = &dqp->q_rtb;
+               qlim = &defq->rtb;
        }
 
        if ((flags & XFS_QMOPT_FORCE_RES) == 0 && dqp->q_id &&
            ((XFS_IS_UQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISUDQ(dqp)) ||
             (XFS_IS_GQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISGDQ(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 hardlimit
+                * or exceed the timelimit if we'd reserve resources.
+                */
+               quota_nl = xfs_dqresv_check(blkres, qlim, nblks, &fatal);
+               if (quota_nl != QUOTA_NL_NOWARN) {
                        /*
-                        * dquot is locked already. See if we'd go over the
-                        * hardlimit or exceed the timelimit if we allocate
-                        * nblks.
+                        * Quota block warning codes are 3 more than the inode
+                        * codes, which we check above.
                         */
-                       total_count = *resbcountp + nblks;
-                       if (hardlimit && total_count > hardlimit) {
-                               xfs_quota_warn(mp, dqp, QUOTA_NL_BHARDWARN);
+                       xfs_quota_warn(mp, dqp, quota_nl + 3);
+                       if (fatal)
                                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_BSOFTLONGWARN);
-                                       goto error_return;
-                               }
-
-                               xfs_quota_warn(mp, dqp, QUOTA_NL_BSOFTWARN);
-                       }
                }
-               if (ninos > 0) {
-                       total_count = dqp->q_ino.reserved + ninos;
-                       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);
+
+               quota_nl = xfs_dqresv_check(&dqp->q_ino, &defq->ino, ninos,
+                               &fatal);
+               if (quota_nl != QUOTA_NL_NOWARN) {
+                       xfs_quota_warn(mp, dqp, quota_nl);
+                       if (fatal)
                                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);
-                       }
                }
        }
 
@@ -669,9 +673,8 @@ xfs_trans_dqresv(
         * Change the reservation, but not the actual usage.
         * Note that q_blk.reserved = q_blk.count + resv
         */
-       (*resbcountp) += (xfs_qcnt_t)nblks;
-       if (ninos != 0)
-               dqp->q_ino.reserved += (xfs_qcnt_t)ninos;
+       blkres->reserved += (xfs_qcnt_t)nblks;
+       dqp->q_ino.reserved += (xfs_qcnt_t)ninos;
 
        /*
         * note the reservation amt in the trans struct too,