summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2019-11-07 12:29:00 -0800
committerDarrick J. Wong <darrick.wong@oracle.com>2019-11-10 10:21:58 -0800
commit5113f8ec3753ed4d68a5d54d3345fee33a914bfe (patch)
treeeefc2a2d66b0db25d70e2bde5252285533904d08
parentf755979355d46ef088f9c9fdb5d11c4a425e738e (diff)
downloadlinux-stable-5113f8ec3753ed4d68a5d54d3345fee33a914bfe.tar.gz
linux-stable-5113f8ec3753ed4d68a5d54d3345fee33a914bfe.tar.bz2
linux-stable-5113f8ec3753ed4d68a5d54d3345fee33a914bfe.zip
xfs: clean up weird while loop in xfs_alloc_ag_vextent_near
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>
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c117
1 files changed, 65 insertions, 52 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index b39bd81d78bd..675613c7bacb 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -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);