Skip to content

Commit

Permalink
btrfs: scrub: avoid unnecessary extent tree search preparing stripes
Browse files Browse the repository at this point in the history
commit 1dc4888 upstream.

Since commit e02ee89 ("btrfs: scrub: switch scrub_simple_mirror()
to scrub_stripe infrastructure"), scrub no longer re-use the same path
for extent tree search.

This can lead to unnecessary extent tree search, especially for the new
stripe based scrub, as we have way more stripes to prepare.

This patch would re-introduce a shared path for extent tree search, and
properly release it when the block group is scrubbed.

This change alone can improve scrub performance slightly by reducing the
time spend preparing the stripe thus improving the queue depth.

Before (with regression):

 Device         r/s      rkB/s   rrqm/s  %rrqm r_await rareq-sz aqu-sz  %util
 nvme0n1p3 15578.00  993616.00     5.00   0.03    0.09    63.78   1.32 100.00

After (with this patch):

 nvme0n1p3 15875.00 1013328.00    12.00   0.08    0.08    63.83   1.35 100.00

Fixes: e02ee89 ("btrfs: scrub: switch scrub_simple_mirror() to scrub_stripe infrastructure")
CC: stable@vger.kernel.org # 6.4+
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
adam900710 authored and gregkh committed Sep 19, 2023
1 parent 06a03d7 commit 5a5b4a2
Showing 1 changed file with 29 additions and 12 deletions.
41 changes: 29 additions & 12 deletions fs/btrfs/scrub.c
Expand Up @@ -175,6 +175,7 @@ struct scrub_ctx {
struct scrub_stripe stripes[SCRUB_STRIPES_PER_SCTX];
struct scrub_stripe *raid56_data_stripes;
struct btrfs_fs_info *fs_info;
struct btrfs_path extent_path;
int first_free;
int cur_stripe;
atomic_t cancel_req;
Expand Down Expand Up @@ -339,6 +340,8 @@ static noinline_for_stack struct scrub_ctx *scrub_setup_ctx(
refcount_set(&sctx->refs, 1);
sctx->is_dev_replace = is_dev_replace;
sctx->fs_info = fs_info;
sctx->extent_path.search_commit_root = 1;
sctx->extent_path.skip_locking = 1;
for (i = 0; i < SCRUB_STRIPES_PER_SCTX; i++) {
int ret;

Expand Down Expand Up @@ -1468,6 +1471,7 @@ static void scrub_stripe_reset_bitmaps(struct scrub_stripe *stripe)
* Return <0 for error.
*/
static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
struct btrfs_path *extent_path,
struct btrfs_device *dev, u64 physical,
int mirror_num, u64 logical_start,
u32 logical_len,
Expand All @@ -1477,7 +1481,6 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
struct btrfs_root *extent_root = btrfs_extent_root(fs_info, bg->start);
struct btrfs_root *csum_root = btrfs_csum_root(fs_info, bg->start);
const u64 logical_end = logical_start + logical_len;
struct btrfs_path path = { 0 };
u64 cur_logical = logical_start;
u64 stripe_end;
u64 extent_start;
Expand All @@ -1493,14 +1496,13 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
/* The range must be inside the bg. */
ASSERT(logical_start >= bg->start && logical_end <= bg->start + bg->length);

path.search_commit_root = 1;
path.skip_locking = 1;

ret = find_first_extent_item(extent_root, &path, logical_start, logical_len);
ret = find_first_extent_item(extent_root, extent_path, logical_start,
logical_len);
/* Either error or not found. */
if (ret)
goto out;
get_extent_info(&path, &extent_start, &extent_len, &extent_flags, &extent_gen);
get_extent_info(extent_path, &extent_start, &extent_len, &extent_flags,
&extent_gen);
if (extent_flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)
stripe->nr_meta_extents++;
if (extent_flags & BTRFS_EXTENT_FLAG_DATA)
Expand Down Expand Up @@ -1528,15 +1530,15 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,

/* Fill the extent info for the remaining sectors. */
while (cur_logical <= stripe_end) {
ret = find_first_extent_item(extent_root, &path, cur_logical,
ret = find_first_extent_item(extent_root, extent_path, cur_logical,
stripe_end - cur_logical + 1);
if (ret < 0)
goto out;
if (ret > 0) {
ret = 0;
break;
}
get_extent_info(&path, &extent_start, &extent_len,
get_extent_info(extent_path, &extent_start, &extent_len,
&extent_flags, &extent_gen);
if (extent_flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)
stripe->nr_meta_extents++;
Expand Down Expand Up @@ -1576,7 +1578,6 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
}
set_bit(SCRUB_STRIPE_FLAG_INITIALIZED, &stripe->state);
out:
btrfs_release_path(&path);
return ret;
}

Expand Down Expand Up @@ -1766,8 +1767,9 @@ static int queue_scrub_stripe(struct scrub_ctx *sctx, struct btrfs_block_group *

/* We can queue one stripe using the remaining slot. */
scrub_reset_stripe(stripe);
ret = scrub_find_fill_first_stripe(bg, dev, physical, mirror_num,
logical, length, stripe);
ret = scrub_find_fill_first_stripe(bg, &sctx->extent_path, dev,
physical, mirror_num, logical,
length, stripe);
/* Either >0 as no more extents or <0 for error. */
if (ret)
return ret;
Expand All @@ -1785,6 +1787,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
struct btrfs_fs_info *fs_info = sctx->fs_info;
struct btrfs_raid_bio *rbio;
struct btrfs_io_context *bioc = NULL;
struct btrfs_path extent_path = { 0 };
struct bio *bio;
struct scrub_stripe *stripe;
bool all_empty = true;
Expand All @@ -1795,6 +1798,14 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,

ASSERT(sctx->raid56_data_stripes);

/*
* For data stripe search, we cannot re-use the same extent path, as
* the data stripe bytenr may be smaller than previous extent. Thus we
* have to use our own extent path.
*/
extent_path.search_commit_root = 1;
extent_path.skip_locking = 1;

for (int i = 0; i < data_stripes; i++) {
int stripe_index;
int rot;
Expand All @@ -1809,7 +1820,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,

scrub_reset_stripe(stripe);
set_bit(SCRUB_STRIPE_FLAG_NO_REPORT, &stripe->state);
ret = scrub_find_fill_first_stripe(bg,
ret = scrub_find_fill_first_stripe(bg, &extent_path,
map->stripes[stripe_index].dev, physical, 1,
full_stripe_start + btrfs_stripe_nr_to_offset(i),
BTRFS_STRIPE_LEN, stripe);
Expand Down Expand Up @@ -1937,6 +1948,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
bio_put(bio);
btrfs_bio_counter_dec(fs_info);

btrfs_release_path(&extent_path);
out:
return ret;
}
Expand Down Expand Up @@ -2109,6 +2121,9 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
u64 stripe_logical;
int stop_loop = 0;

/* Extent_path should be released by now. */
ASSERT(sctx->extent_path.nodes[0] == NULL);

scrub_blocked_if_needed(fs_info);

if (sctx->is_dev_replace &&
Expand Down Expand Up @@ -2227,6 +2242,8 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
ret2 = flush_scrub_stripes(sctx);
if (!ret)
ret = ret2;
btrfs_release_path(&sctx->extent_path);

if (sctx->raid56_data_stripes) {
for (int i = 0; i < nr_data_stripes(map); i++)
release_scrub_stripe(&sctx->raid56_data_stripes[i]);
Expand Down

0 comments on commit 5a5b4a2

Please sign in to comment.