@@ -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;
}
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(-)