Skip to content

Commit 3c771c1

Browse files
adam900710kdave
authored andcommitted
btrfs: scrub: avoid unnecessary csum tree search preparing stripes
One of the bottleneck of the new scrub code is the extra csum tree search. The old code would only do the csum tree search for each scrub bio, which can be as large as 512KiB, thus they can afford to allocate a new path each time. But the new scrub code is doing csum tree search for each stripe, which is only 64KiB, this means we'd better re-use the same csum path during each search. This patch would introduce a per-sctx path for csum tree search, as we don't need to re-allocate the path every time we need to do a csum tree search. With this change we can further improve the queue depth and improve the scrub read performance: Before (with regression and cached extent tree path): Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz aqu-sz %util nvme0n1p3 15875.00 1013328.00 12.00 0.08 0.08 63.83 1.35 100.00 After (with both cached extent/csum tree path): nvme0n1p3 17759.00 1133280.00 10.00 0.06 0.08 63.81 1.50 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 1dc4888 commit 3c771c1

File tree

4 files changed

+46
-27
lines changed

4 files changed

+46
-27
lines changed

fs/btrfs/file-item.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -597,29 +597,37 @@ int btrfs_lookup_csums_list(struct btrfs_root *root, u64 start, u64 end,
597597
* Each bit represents a sector. Thus caller should ensure @csum_buf passed
598598
* in is large enough to contain all csums.
599599
*/
600-
int btrfs_lookup_csums_bitmap(struct btrfs_root *root, u64 start, u64 end,
601-
u8 *csum_buf, unsigned long *csum_bitmap,
602-
bool search_commit)
600+
int btrfs_lookup_csums_bitmap(struct btrfs_root *root, struct btrfs_path *path,
601+
u64 start, u64 end, u8 *csum_buf,
602+
unsigned long *csum_bitmap)
603603
{
604604
struct btrfs_fs_info *fs_info = root->fs_info;
605605
struct btrfs_key key;
606-
struct btrfs_path *path;
607606
struct extent_buffer *leaf;
608607
struct btrfs_csum_item *item;
609608
const u64 orig_start = start;
609+
bool free_path = false;
610610
int ret;
611611

612612
ASSERT(IS_ALIGNED(start, fs_info->sectorsize) &&
613613
IS_ALIGNED(end + 1, fs_info->sectorsize));
614614

615-
path = btrfs_alloc_path();
616-
if (!path)
617-
return -ENOMEM;
615+
if (!path) {
616+
path = btrfs_alloc_path();
617+
if (!path)
618+
return -ENOMEM;
619+
free_path = true;
620+
}
618621

619-
if (search_commit) {
620-
path->skip_locking = 1;
621-
path->reada = READA_FORWARD;
622-
path->search_commit_root = 1;
622+
/* Check if we can reuse the previous path. */
623+
if (path->nodes[0]) {
624+
btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
625+
626+
if (key.objectid == BTRFS_EXTENT_CSUM_OBJECTID &&
627+
key.type == BTRFS_EXTENT_CSUM_KEY &&
628+
key.offset <= start)
629+
goto search_forward;
630+
btrfs_release_path(path);
623631
}
624632

625633
key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
@@ -656,6 +664,7 @@ int btrfs_lookup_csums_bitmap(struct btrfs_root *root, u64 start, u64 end,
656664
}
657665
}
658666

667+
search_forward:
659668
while (start <= end) {
660669
u64 csum_end;
661670

@@ -712,7 +721,8 @@ int btrfs_lookup_csums_bitmap(struct btrfs_root *root, u64 start, u64 end,
712721
}
713722
ret = 0;
714723
fail:
715-
btrfs_free_path(path);
724+
if (free_path)
725+
btrfs_free_path(path);
716726
return ret;
717727
}
718728

fs/btrfs/file-item.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
5757
int btrfs_lookup_csums_list(struct btrfs_root *root, u64 start, u64 end,
5858
struct list_head *list, int search_commit,
5959
bool nowait);
60-
int btrfs_lookup_csums_bitmap(struct btrfs_root *root, u64 start, u64 end,
61-
u8 *csum_buf, unsigned long *csum_bitmap,
62-
bool search_commit);
60+
int btrfs_lookup_csums_bitmap(struct btrfs_root *root, struct btrfs_path *path,
61+
u64 start, u64 end, u8 *csum_buf,
62+
unsigned long *csum_bitmap);
6363
void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode,
6464
const struct btrfs_path *path,
6565
struct btrfs_file_extent_item *fi,

fs/btrfs/raid56.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,8 +2105,8 @@ static void fill_data_csums(struct btrfs_raid_bio *rbio)
21052105
goto error;
21062106
}
21072107

2108-
ret = btrfs_lookup_csums_bitmap(csum_root, start, start + len - 1,
2109-
rbio->csum_buf, rbio->csum_bitmap, false);
2108+
ret = btrfs_lookup_csums_bitmap(csum_root, NULL, start, start + len - 1,
2109+
rbio->csum_buf, rbio->csum_bitmap);
21102110
if (ret < 0)
21112111
goto error;
21122112
if (bitmap_empty(rbio->csum_bitmap, len >> fs_info->sectorsize_bits))

fs/btrfs/scrub.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ struct scrub_ctx {
176176
struct scrub_stripe *raid56_data_stripes;
177177
struct btrfs_fs_info *fs_info;
178178
struct btrfs_path extent_path;
179+
struct btrfs_path csum_path;
179180
int first_free;
180181
int cur_stripe;
181182
atomic_t cancel_req;
@@ -342,6 +343,8 @@ static noinline_for_stack struct scrub_ctx *scrub_setup_ctx(
342343
sctx->fs_info = fs_info;
343344
sctx->extent_path.search_commit_root = 1;
344345
sctx->extent_path.skip_locking = 1;
346+
sctx->csum_path.search_commit_root = 1;
347+
sctx->csum_path.skip_locking = 1;
345348
for (i = 0; i < SCRUB_STRIPES_PER_SCTX; i++) {
346349
int ret;
347350

@@ -1471,6 +1474,7 @@ static void scrub_stripe_reset_bitmaps(struct scrub_stripe *stripe)
14711474
*/
14721475
static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
14731476
struct btrfs_path *extent_path,
1477+
struct btrfs_path *csum_path,
14741478
struct btrfs_device *dev, u64 physical,
14751479
int mirror_num, u64 logical_start,
14761480
u32 logical_len,
@@ -1562,9 +1566,9 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
15621566
*/
15631567
ASSERT(BITS_PER_LONG >= BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits);
15641568

1565-
ret = btrfs_lookup_csums_bitmap(csum_root, stripe->logical,
1566-
stripe_end, stripe->csums,
1567-
&csum_bitmap, true);
1569+
ret = btrfs_lookup_csums_bitmap(csum_root, csum_path,
1570+
stripe->logical, stripe_end,
1571+
stripe->csums, &csum_bitmap);
15681572
if (ret < 0)
15691573
goto out;
15701574
if (ret > 0)
@@ -1766,9 +1770,9 @@ static int queue_scrub_stripe(struct scrub_ctx *sctx, struct btrfs_block_group *
17661770

17671771
/* We can queue one stripe using the remaining slot. */
17681772
scrub_reset_stripe(stripe);
1769-
ret = scrub_find_fill_first_stripe(bg, &sctx->extent_path, dev,
1770-
physical, mirror_num, logical,
1771-
length, stripe);
1773+
ret = scrub_find_fill_first_stripe(bg, &sctx->extent_path,
1774+
&sctx->csum_path, dev, physical,
1775+
mirror_num, logical, length, stripe);
17721776
/* Either >0 as no more extents or <0 for error. */
17731777
if (ret)
17741778
return ret;
@@ -1787,6 +1791,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
17871791
struct btrfs_raid_bio *rbio;
17881792
struct btrfs_io_context *bioc = NULL;
17891793
struct btrfs_path extent_path = { 0 };
1794+
struct btrfs_path csum_path = { 0 };
17901795
struct bio *bio;
17911796
struct scrub_stripe *stripe;
17921797
bool all_empty = true;
@@ -1798,12 +1803,14 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
17981803
ASSERT(sctx->raid56_data_stripes);
17991804

18001805
/*
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.
1806+
* For data stripe search, we cannot re-use the same extent/csum paths,
1807+
* as the data stripe bytenr may be smaller than previous extent. Thus
1808+
* we have to use our own extent/csum paths.
18041809
*/
18051810
extent_path.search_commit_root = 1;
18061811
extent_path.skip_locking = 1;
1812+
csum_path.search_commit_root = 1;
1813+
csum_path.skip_locking = 1;
18071814

18081815
for (int i = 0; i < data_stripes; i++) {
18091816
int stripe_index;
@@ -1819,7 +1826,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
18191826

18201827
scrub_reset_stripe(stripe);
18211828
set_bit(SCRUB_STRIPE_FLAG_NO_REPORT, &stripe->state);
1822-
ret = scrub_find_fill_first_stripe(bg, &extent_path,
1829+
ret = scrub_find_fill_first_stripe(bg, &extent_path, &csum_path,
18231830
map->stripes[stripe_index].dev, physical, 1,
18241831
full_stripe_start + btrfs_stripe_nr_to_offset(i),
18251832
BTRFS_STRIPE_LEN, stripe);
@@ -1948,6 +1955,7 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
19481955
btrfs_bio_counter_dec(fs_info);
19491956

19501957
btrfs_release_path(&extent_path);
1958+
btrfs_release_path(&csum_path);
19511959
out:
19521960
return ret;
19531961
}
@@ -2237,6 +2245,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
22372245
if (!ret)
22382246
ret = ret2;
22392247
btrfs_release_path(&sctx->extent_path);
2248+
btrfs_release_path(&sctx->csum_path);
22402249

22412250
if (sctx->raid56_data_stripes) {
22422251
for (int i = 0; i < nr_data_stripes(map); i++)

0 commit comments

Comments
 (0)