diff mbox series

[5/5] btrfs: scrub: extract the stripe group submission into a helper

Message ID c326029c9c515e2ac293810f0492a41a8196e4a2.1689849582.git.wqu@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs: scrub: fix the scrub performance regression caused by unnecessary extent/csum tree searchs | expand

Commit Message

Qu Wenruo July 20, 2023, 10:48 a.m. UTC
Introduce a new helper, submit_initial_stripes_read(), to submit
multiple stripes in one go.

This function can be utilized to submit one group, or the remaining ones
which doesn't fill a full group (during flush_scrub_stripes()).

This helper has extra ASSERT()s to make sure the stripes are properly
initialized and not yet submitted.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/scrub.c | 67 +++++++++++++++++++++++++++++-------------------
 1 file changed, 41 insertions(+), 26 deletions(-)
diff mbox series

Patch

diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 6d08836c0056..d6dfffb4efc9 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -1695,12 +1695,36 @@  static bool stripe_has_metadata_error(struct scrub_stripe *stripe)
 	return false;
 }
 
+static void submit_initial_stripes_read(struct scrub_ctx *sctx, int first_slot,
+					int nr_stripes)
+{
+	struct blk_plug plug;
+
+	ASSERT(first_slot >= 0);
+	ASSERT(first_slot + nr_stripes <= SCRUB_STRIPES_PER_SCTX);
+
+	scrub_throttle_dev_io(sctx, sctx->stripes[0].dev,
+			      btrfs_stripe_nr_to_offset(nr_stripes));
+
+	blk_start_plug(&plug);
+	for (int i = 0; i < nr_stripes; i++) {
+		struct scrub_stripe *stripe = &sctx->stripes[first_slot + i];
+
+		/* Those stripes should be initialized and not yet submitted. */
+		ASSERT(test_bit(SCRUB_STRIPE_FLAG_INITIALIZED, &stripe->state));
+		ASSERT(!test_bit(SCRUB_STRIPE_FLAG_READ_SUBMITTED, &stripe->state));
+
+		scrub_submit_initial_read(sctx, stripe);
+	}
+	blk_finish_plug(&plug);
+
+}
+
 static int flush_scrub_stripes(struct scrub_ctx *sctx)
 {
 	struct btrfs_fs_info *fs_info = sctx->fs_info;
 	struct scrub_stripe *stripe;
 	const int nr_stripes = sctx->cur_stripe;
-	struct blk_plug plug;
 	int ret = 0;
 
 	if (!nr_stripes)
@@ -1708,17 +1732,14 @@  static int flush_scrub_stripes(struct scrub_ctx *sctx)
 
 	ASSERT(test_bit(SCRUB_STRIPE_FLAG_INITIALIZED, &sctx->stripes[0].state));
 
-	/* We should only have at most one group to submit. */
-	scrub_throttle_dev_io(sctx, sctx->stripes[0].dev,
-			      btrfs_stripe_nr_to_offset(
-				      nr_stripes % SCRUB_STRIPES_PER_GROUP ?:
-				      SCRUB_STRIPES_PER_GROUP));
-	blk_start_plug(&plug);
-	for (int i = 0; i < nr_stripes; i++) {
-		stripe = &sctx->stripes[i];
-		scrub_submit_initial_read(sctx, stripe);
+	/* Submit the stripes which are populated but not submitted. */
+	if (nr_stripes % SCRUB_STRIPES_PER_GROUP) {
+		const int first_slot = round_down(nr_stripes,
+						  SCRUB_STRIPES_PER_GROUP);
+
+		submit_initial_stripes_read(sctx, first_slot,
+					    nr_stripes - first_slot);
 	}
-	blk_finish_plug(&plug);
 
 	for (int i = 0; i < nr_stripes; i++) {
 		stripe = &sctx->stripes[i];
@@ -1820,25 +1841,19 @@  static int queue_scrub_stripe(struct scrub_ctx *sctx, struct btrfs_block_group *
 
 	sctx->cur_stripe++;
 
+	/* We have filled one group, submit them now. */
+	if (sctx->cur_stripe % SCRUB_STRIPES_PER_GROUP == 0) {
+		const int first_slot = sctx->cur_stripe -
+				       SCRUB_STRIPES_PER_GROUP;
+
+		submit_initial_stripes_read(sctx, first_slot,
+					    SCRUB_STRIPES_PER_GROUP);
+	}
+
 	/* Last slot used, flush them all. */
 	if (sctx->cur_stripe == SCRUB_STRIPES_PER_SCTX)
 		return flush_scrub_stripes(sctx);
 
-	/* We have filled one group, submit them now. */
-	if (sctx->cur_stripe % SCRUB_STRIPES_PER_GROUP == 0) {
-		struct blk_plug plug;
-
-		scrub_throttle_dev_io(sctx, sctx->stripes[0].dev,
-			      btrfs_stripe_nr_to_offset(SCRUB_STRIPES_PER_GROUP));
-
-		blk_start_plug(&plug);
-		for (int i = sctx->cur_stripe - SCRUB_STRIPES_PER_GROUP;
-		     i < sctx->cur_stripe; i++) {
-			stripe = &sctx->stripes[i];
-			scrub_submit_initial_read(sctx, stripe);
-		}
-		blk_finish_plug(&plug);
-	}
 	return 0;
 }