OSDN Git Service

xfs: clean up weird while loop in xfs_alloc_ag_vextent_near
authorDarrick J. Wong <darrick.wong@oracle.com>
Thu, 7 Nov 2019 20:29:00 +0000 (12:29 -0800)
committerDarrick J. Wong <darrick.wong@oracle.com>
Sun, 10 Nov 2019 18:21:58 +0000 (10:21 -0800)
Refactor the weird while loop out of existence.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_alloc.c

index b39bd81..675613c 100644 (file)
@@ -1464,6 +1464,64 @@ xfs_alloc_ag_vextent_locality(
        return 0;
 }
 
+/* Check the last block of the cnt btree for allocations. */
+static int
+xfs_alloc_ag_vextent_lastblock(
+       struct xfs_alloc_arg    *args,
+       struct xfs_alloc_cur    *acur,
+       xfs_agblock_t           *bno,
+       xfs_extlen_t            *len,
+       bool                    *allocated)
+{
+       int                     error;
+       int                     i;
+
+#ifdef DEBUG
+       /* Randomly don't execute the first algorithm. */
+       if (prandom_u32() & 1)
+               return 0;
+#endif
+
+       /*
+        * Start from the entry that lookup found, sequence through all larger
+        * free blocks.  If we're actually pointing at a record smaller than
+        * maxlen, go to the start of this block, and skip all those smaller
+        * than minlen.
+        */
+       if (len || args->alignment > 1) {
+               acur->cnt->bc_ptrs[0] = 1;
+               do {
+                       error = xfs_alloc_get_rec(acur->cnt, bno, len, &i);
+                       if (error)
+                               return error;
+                       XFS_WANT_CORRUPTED_RETURN(args->mp, i == 1);
+                       if (*len >= args->minlen)
+                               break;
+                       error = xfs_btree_increment(acur->cnt, 0, &i);
+                       if (error)
+                               return error;
+               } while (i);
+               ASSERT(*len >= args->minlen);
+               if (!i)
+                       return 0;
+       }
+
+       error = xfs_alloc_walk_iter(args, acur, acur->cnt, true, false, -1, &i);
+       if (error)
+               return error;
+
+       /*
+        * It didn't work.  We COULD be in a case where there's a good record
+        * somewhere, so try again.
+        */
+       if (acur->len == 0)
+               return 0;
+
+       trace_xfs_alloc_near_first(args);
+       *allocated = true;
+       return 0;
+}
+
 /*
  * Allocate a variable extent near bno in the allocation group agno.
  * Extent's length (returned in len) will be between minlen and maxlen,
@@ -1479,14 +1537,6 @@ xfs_alloc_ag_vextent_near(
        int                     i;              /* result code, temporary */
        xfs_agblock_t           bno;
        xfs_extlen_t            len;
-#ifdef DEBUG
-       /*
-        * Randomly don't execute the first algorithm.
-        */
-       int             dofirst;        /* set to do first algorithm */
-
-       dofirst = prandom_u32() & 1;
-#endif
 
        /* handle uninitialized agbno range so caller doesn't have to */
        if (!args->min_agbno && !args->max_agbno)
@@ -1529,53 +1579,16 @@ restart:
         * near the right edge of the tree.  If it's in the last btree leaf
         * block, then we just examine all the entries in that block
         * that are big enough, and pick the best one.
-        * This is written as a while loop so we can break out of it,
-        * but we never loop back to the top.
         */
-       while (xfs_btree_islastblock(acur.cnt, 0)) {
-#ifdef DEBUG
-               if (dofirst)
-                       break;
-#endif
-               /*
-                * Start from the entry that lookup found, sequence through
-                * all larger free blocks.  If we're actually pointing at a
-                * record smaller than maxlen, go to the start of this block,
-                * and skip all those smaller than minlen.
-                */
-               if (len || args->alignment > 1) {
-                       acur.cnt->bc_ptrs[0] = 1;
-                       do {
-                               error = xfs_alloc_get_rec(acur.cnt, &bno, &len,
-                                               &i);
-                               if (error)
-                                       goto out;
-                               XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, out);
-                               if (len >= args->minlen)
-                                       break;
-                               error = xfs_btree_increment(acur.cnt, 0, &i);
-                               if (error)
-                                       goto out;
-                       } while (i);
-                       ASSERT(len >= args->minlen);
-                       if (!i)
-                               break;
-               }
+       if (xfs_btree_islastblock(acur.cnt, 0)) {
+               bool            allocated = false;
 
-               error = xfs_alloc_walk_iter(args, &acur, acur.cnt, true, false,
-                                           -1, &i);
+               error = xfs_alloc_ag_vextent_lastblock(args, &acur, &bno, &len,
+                               &allocated);
                if (error)
                        goto out;
-
-               /*
-                * It didn't work.  We COULD be in a case where
-                * there's a good record somewhere, so try again.
-                */
-               if (acur.len == 0)
-                       break;
-
-               trace_xfs_alloc_near_first(args);
-               goto alloc;
+               if (allocated)
+                       goto alloc_finish;
        }
 
        /*
@@ -1601,7 +1614,7 @@ restart:
                goto out;
        }
 
-alloc:
+alloc_finish:
        /* fix up btrees on a successful allocation */
        error = xfs_alloc_cur_finish(args, &acur);