Skip to content

Commit 1dc4888

Browse files
adam900710kdave
authored andcommitted
btrfs: scrub: avoid unnecessary extent tree search preparing stripes
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: [email protected] # 6.4+ Signed-off-by: Qu Wenruo <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 94628ad commit 1dc4888

File tree

1 file changed

+29
-12
lines changed

1 file changed

+29
-12
lines changed

fs/btrfs/scrub.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ struct scrub_ctx {
175175
struct scrub_stripe stripes[SCRUB_STRIPES_PER_SCTX];
176176
struct scrub_stripe *raid56_data_stripes;
177177
struct btrfs_fs_info *fs_info;
178+
struct btrfs_path extent_path;
178179
int first_free;
179180
int cur_stripe;
180181
atomic_t cancel_req;
@@ -339,6 +340,8 @@ static noinline_for_stack struct scrub_ctx *scrub_setup_ctx(
339340
refcount_set(&sctx->refs, 1);
340341
sctx->is_dev_replace = is_dev_replace;
341342
sctx->fs_info = fs_info;
343+
sctx->extent_path.search_commit_root = 1;
344+
sctx->extent_path.skip_locking = 1;
342345
for (i = 0; i < SCRUB_STRIPES_PER_SCTX; i++) {
343346
int ret;
344347

@@ -1467,6 +1470,7 @@ static void scrub_stripe_reset_bitmaps(struct scrub_stripe *stripe)
14671470
* Return <0 for error.
14681471
*/
14691472
static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
1473+
struct btrfs_path *extent_path,
14701474
struct btrfs_device *dev, u64 physical,
14711475
int mirror_num, u64 logical_start,
14721476
u32 logical_len,
@@ -1476,7 +1480,6 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
14761480
struct btrfs_root *extent_root = btrfs_extent_root(fs_info, bg->start);
14771481
struct btrfs_root *csum_root = btrfs_csum_root(fs_info, bg->start);
14781482
const u64 logical_end = logical_start + logical_len;
1479-
struct btrfs_path path = { 0 };
14801483
u64 cur_logical = logical_start;
14811484
u64 stripe_end;
14821485
u64 extent_start;
@@ -1492,14 +1495,13 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
14921495
/* The range must be inside the bg. */
14931496
ASSERT(logical_start >= bg->start && logical_end <= bg->start + bg->length);
14941497

1495-
path.search_commit_root = 1;
1496-
path.skip_locking = 1;
1497-
1498-
ret = find_first_extent_item(extent_root, &path, logical_start, logical_len);
1498+
ret = find_first_extent_item(extent_root, extent_path, logical_start,
1499+
logical_len);
14991500
/* Either error or not found. */
15001501
if (ret)
15011502
goto out;
1502-
get_extent_info(&path, &extent_start, &extent_len, &extent_flags, &extent_gen);
1503+
get_extent_info(extent_path, &extent_start, &extent_len, &extent_flags,
1504+
&extent_gen);
15031505
if (extent_flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)
15041506
stripe->nr_meta_extents++;
15051507
if (extent_flags & BTRFS_EXTENT_FLAG_DATA)
@@ -1527,15 +1529,15 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
15271529

15281530
/* Fill the extent info for the remaining sectors. */
15291531
while (cur_logical <= stripe_end) {
1530-
ret = find_first_extent_item(extent_root, &path, cur_logical,
1532+
ret = find_first_extent_item(extent_root, extent_path, cur_logical,
15311533
stripe_end - cur_logical + 1);
15321534
if (ret < 0)
15331535
goto out;
15341536
if (ret > 0) {
15351537
ret = 0;
15361538
break;
15371539
}
1538-
get_extent_info(&path, &extent_start, &extent_len,
1540+
get_extent_info(extent_path, &extent_start, &extent_len,
15391541
&extent_flags, &extent_gen);
15401542
if (extent_flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)
15411543
stripe->nr_meta_extents++;
@@ -1575,7 +1577,6 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
15751577
}
15761578
set_bit(SCRUB_STRIPE_FLAG_INITIALIZED, &stripe->state);
15771579
out:
1578-
btrfs_release_path(&path);
15791580
return ret;
15801581
}
15811582

@@ -1765,8 +1766,9 @@ static int queue_scrub_stripe(struct scrub_ctx *sctx, struct btrfs_block_group *
17651766

17661767
/* We can queue one stripe using the remaining slot. */
17671768
scrub_reset_stripe(stripe);
1768-
ret = scrub_find_fill_first_stripe(bg, dev, physical, mirror_num,
1769-
logical, length, stripe);
1769+
ret = scrub_find_fill_first_stripe(bg, &sctx->extent_path, dev,
1770+
physical, mirror_num, logical,
1771+
length, stripe);
17701772
/* Either >0 as no more extents or <0 for error. */
17711773
if (ret)
17721774
return ret;
@@ -1784,6 +1786,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
17841786
struct btrfs_fs_info *fs_info = sctx->fs_info;
17851787
struct btrfs_raid_bio *rbio;
17861788
struct btrfs_io_context *bioc = NULL;
1789+
struct btrfs_path extent_path = { 0 };
17871790
struct bio *bio;
17881791
struct scrub_stripe *stripe;
17891792
bool all_empty = true;
@@ -1794,6 +1797,14 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
17941797

17951798
ASSERT(sctx->raid56_data_stripes);
17961799

1800+
/*
1801+
* For data stripe search, we cannot re-use the same extent path, as
1802+
* the data stripe bytenr may be smaller than previous extent. Thus we
1803+
* have to use our own extent path.
1804+
*/
1805+
extent_path.search_commit_root = 1;
1806+
extent_path.skip_locking = 1;
1807+
17971808
for (int i = 0; i < data_stripes; i++) {
17981809
int stripe_index;
17991810
int rot;
@@ -1808,7 +1819,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
18081819

18091820
scrub_reset_stripe(stripe);
18101821
set_bit(SCRUB_STRIPE_FLAG_NO_REPORT, &stripe->state);
1811-
ret = scrub_find_fill_first_stripe(bg,
1822+
ret = scrub_find_fill_first_stripe(bg, &extent_path,
18121823
map->stripes[stripe_index].dev, physical, 1,
18131824
full_stripe_start + btrfs_stripe_nr_to_offset(i),
18141825
BTRFS_STRIPE_LEN, stripe);
@@ -1936,6 +1947,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
19361947
bio_put(bio);
19371948
btrfs_bio_counter_dec(fs_info);
19381949

1950+
btrfs_release_path(&extent_path);
19391951
out:
19401952
return ret;
19411953
}
@@ -2103,6 +2115,9 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
21032115
u64 stripe_logical;
21042116
int stop_loop = 0;
21052117

2118+
/* Extent_path should be released by now. */
2119+
ASSERT(sctx->extent_path.nodes[0] == NULL);
2120+
21062121
scrub_blocked_if_needed(fs_info);
21072122

21082123
if (sctx->is_dev_replace &&
@@ -2221,6 +2236,8 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
22212236
ret2 = flush_scrub_stripes(sctx);
22222237
if (!ret)
22232238
ret = ret2;
2239+
btrfs_release_path(&sctx->extent_path);
2240+
22242241
if (sctx->raid56_data_stripes) {
22252242
for (int i = 0; i < nr_data_stripes(map); i++)
22262243
release_scrub_stripe(&sctx->raid56_data_stripes[i]);

0 commit comments

Comments
 (0)