xfs: squash prealloc while over quota free space as well
authorBrian Foster <bfoster@redhat.com>
Thu, 24 Jul 2014 09:56:08 +0000 (19:56 +1000)
committerDave Chinner <david@fromorbit.com>
Thu, 24 Jul 2014 09:56:08 +0000 (19:56 +1000)
From: Brian Foster <bfoster@redhat.com>

Commit 4d559a3b introduced heavy prealloc. squashing to catch the case
of requesting too large a prealloc on smaller filesystems, leading to
repeated flush and retry cycles that occur on ENOSPC. Now that we issue
eofblocks scans on EDQUOT/ENOSPC, squash the prealloc against the
minimum available free space across all applicable quotas as well to
avoid a similar problem of repeated eofblocks scans.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
fs/xfs/xfs_iomap.c

index 923c044bd26f04efbbcde012c1d89e58cd40b697..783b3b1b0684ae83f4a2a6b5a08749387bebe9a8 100644 (file)
@@ -397,7 +397,8 @@ xfs_quota_calc_throttle(
        struct xfs_inode *ip,
        int type,
        xfs_fsblock_t *qblocks,
-       int *qshift)
+       int *qshift,
+       int64_t *qfreesp)
 {
        int64_t freesp;
        int shift = 0;
@@ -406,6 +407,7 @@ xfs_quota_calc_throttle(
        /* over hi wmark, squash the prealloc completely */
        if (dq->q_res_bcount >= dq->q_prealloc_hi_wmark) {
                *qblocks = 0;
+               *qfreesp = 0;
                return;
        }
 
@@ -418,6 +420,9 @@ xfs_quota_calc_throttle(
                        shift += 2;
        }
 
+       if (freesp < *qfreesp)
+               *qfreesp = freesp;
+
        /* only overwrite the throttle values if we are more aggressive */
        if ((freesp >> shift) < (*qblocks >> *qshift)) {
                *qblocks = freesp;
@@ -476,15 +481,18 @@ xfs_iomap_prealloc_size(
        }
 
        /*
-        * Check each quota to cap the prealloc size and provide a shift
-        * value to throttle with.
+        * Check each quota to cap the prealloc size, provide a shift value to
+        * throttle with and adjust amount of available space.
         */
        if (xfs_quota_need_throttle(ip, XFS_DQ_USER, alloc_blocks))
-               xfs_quota_calc_throttle(ip, XFS_DQ_USER, &qblocks, &qshift);
+               xfs_quota_calc_throttle(ip, XFS_DQ_USER, &qblocks, &qshift,
+                                       &freesp);
        if (xfs_quota_need_throttle(ip, XFS_DQ_GROUP, alloc_blocks))
-               xfs_quota_calc_throttle(ip, XFS_DQ_GROUP, &qblocks, &qshift);
+               xfs_quota_calc_throttle(ip, XFS_DQ_GROUP, &qblocks, &qshift,
+                                       &freesp);
        if (xfs_quota_need_throttle(ip, XFS_DQ_PROJ, alloc_blocks))
-               xfs_quota_calc_throttle(ip, XFS_DQ_PROJ, &qblocks, &qshift);
+               xfs_quota_calc_throttle(ip, XFS_DQ_PROJ, &qblocks, &qshift,
+                                       &freesp);
 
        /*
         * The final prealloc size is set to the minimum of free space available