Skip to content

Commit b979547

Browse files
adam900710kdave
authored andcommitted
btrfs: scrub: introduce helper to find and fill sector info for a scrub_stripe
The new helper will search the extent tree to find the first extent of a logical range, then fill the sectors array by two loops: - Loop 1 to fill common bits and metadata generation - Loop 2 to fill csum data (only for data bgs) This loop will use the new btrfs_lookup_csums_bitmap() to fill the full csum buffer, and set scrub_sector_verification::csum. With all the needed info filled by this function, later we only need to submit and verify the stripe. Here we temporarily export the helper to avoid warning on unused static function. Signed-off-by: Qu Wenruo <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 2af2aaf commit b979547

File tree

5 files changed

+158
-3
lines changed

5 files changed

+158
-3
lines changed

fs/btrfs/file-item.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,8 @@ int btrfs_lookup_csums_list(struct btrfs_root *root, u64 start, u64 end,
597597
* in is large enough to contain all csums.
598598
*/
599599
int btrfs_lookup_csums_bitmap(struct btrfs_root *root, u64 start, u64 end,
600-
u8 *csum_buf, unsigned long *csum_bitmap)
600+
u8 *csum_buf, unsigned long *csum_bitmap,
601+
bool search_commit)
601602
{
602603
struct btrfs_fs_info *fs_info = root->fs_info;
603604
struct btrfs_key key;
@@ -614,6 +615,12 @@ int btrfs_lookup_csums_bitmap(struct btrfs_root *root, u64 start, u64 end,
614615
if (!path)
615616
return -ENOMEM;
616617

618+
if (search_commit) {
619+
path->skip_locking = 1;
620+
path->reada = READA_FORWARD;
621+
path->search_commit_root = 1;
622+
}
623+
617624
key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
618625
key.type = BTRFS_EXTENT_CSUM_KEY;
619626
key.offset = start;

fs/btrfs/file-item.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ int btrfs_lookup_csums_list(struct btrfs_root *root, u64 start, u64 end,
5757
struct list_head *list, int search_commit,
5858
bool nowait);
5959
int btrfs_lookup_csums_bitmap(struct btrfs_root *root, u64 start, u64 end,
60-
u8 *csum_buf, unsigned long *csum_bitmap);
60+
u8 *csum_buf, unsigned long *csum_bitmap,
61+
bool search_commit);
6162
void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode,
6263
const struct btrfs_path *path,
6364
struct btrfs_file_extent_item *fi,

fs/btrfs/raid56.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2113,7 +2113,7 @@ static void fill_data_csums(struct btrfs_raid_bio *rbio)
21132113
}
21142114

21152115
ret = btrfs_lookup_csums_bitmap(csum_root, start, start + len - 1,
2116-
rbio->csum_buf, rbio->csum_bitmap);
2116+
rbio->csum_buf, rbio->csum_bitmap, false);
21172117
if (ret < 0)
21182118
goto error;
21192119
if (bitmap_empty(rbio->csum_bitmap, len >> fs_info->sectorsize_bits))

fs/btrfs/scrub.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3642,6 +3642,149 @@ static int sync_write_pointer_for_zoned(struct scrub_ctx *sctx, u64 logical,
36423642
return ret;
36433643
}
36443644

3645+
static void fill_one_extent_info(struct btrfs_fs_info *fs_info,
3646+
struct scrub_stripe *stripe,
3647+
u64 extent_start, u64 extent_len,
3648+
u64 extent_flags, u64 extent_gen)
3649+
{
3650+
for (u64 cur_logical = max(stripe->logical, extent_start);
3651+
cur_logical < min(stripe->logical + BTRFS_STRIPE_LEN,
3652+
extent_start + extent_len);
3653+
cur_logical += fs_info->sectorsize) {
3654+
const int nr_sector = (cur_logical - stripe->logical) >>
3655+
fs_info->sectorsize_bits;
3656+
struct scrub_sector_verification *sector =
3657+
&stripe->sectors[nr_sector];
3658+
3659+
set_bit(nr_sector, &stripe->extent_sector_bitmap);
3660+
if (extent_flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
3661+
sector->is_metadata = true;
3662+
sector->generation = extent_gen;
3663+
}
3664+
}
3665+
}
3666+
3667+
static void scrub_stripe_reset_bitmaps(struct scrub_stripe *stripe)
3668+
{
3669+
stripe->extent_sector_bitmap = 0;
3670+
stripe->init_error_bitmap = 0;
3671+
stripe->error_bitmap = 0;
3672+
stripe->io_error_bitmap = 0;
3673+
stripe->csum_error_bitmap = 0;
3674+
stripe->meta_error_bitmap = 0;
3675+
}
3676+
3677+
/*
3678+
* Locate one stripe which has at least one extent in its range.
3679+
*
3680+
* Return 0 if found such stripe, and store its info into @stripe.
3681+
* Return >0 if there is no such stripe in the specified range.
3682+
* Return <0 for error.
3683+
*/
3684+
int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
3685+
struct btrfs_device *dev, u64 physical,
3686+
int mirror_num, u64 logical_start,
3687+
u32 logical_len, struct scrub_stripe *stripe)
3688+
{
3689+
struct btrfs_fs_info *fs_info = bg->fs_info;
3690+
struct btrfs_root *extent_root = btrfs_extent_root(fs_info, bg->start);
3691+
struct btrfs_root *csum_root = btrfs_csum_root(fs_info, bg->start);
3692+
const u64 logical_end = logical_start + logical_len;
3693+
struct btrfs_path path = { 0 };
3694+
u64 cur_logical = logical_start;
3695+
u64 stripe_end;
3696+
u64 extent_start;
3697+
u64 extent_len;
3698+
u64 extent_flags;
3699+
u64 extent_gen;
3700+
int ret;
3701+
3702+
memset(stripe->sectors, 0, sizeof(struct scrub_sector_verification) *
3703+
stripe->nr_sectors);
3704+
scrub_stripe_reset_bitmaps(stripe);
3705+
3706+
/* The range must be inside the bg. */
3707+
ASSERT(logical_start >= bg->start && logical_end <= bg->start + bg->length);
3708+
3709+
path.search_commit_root = 1;
3710+
path.skip_locking = 1;
3711+
3712+
ret = find_first_extent_item(extent_root, &path, logical_start, logical_len);
3713+
/* Either error or not found. */
3714+
if (ret)
3715+
goto out;
3716+
get_extent_info(&path, &extent_start, &extent_len, &extent_flags, &extent_gen);
3717+
cur_logical = max(extent_start, cur_logical);
3718+
3719+
/*
3720+
* Round down to stripe boundary.
3721+
*
3722+
* The extra calculation against bg->start is to handle block groups
3723+
* whose logical bytenr is not BTRFS_STRIPE_LEN aligned.
3724+
*/
3725+
stripe->logical = round_down(cur_logical - bg->start, BTRFS_STRIPE_LEN) +
3726+
bg->start;
3727+
stripe->physical = physical + stripe->logical - logical_start;
3728+
stripe->dev = dev;
3729+
stripe->bg = bg;
3730+
stripe->mirror_num = mirror_num;
3731+
stripe_end = stripe->logical + BTRFS_STRIPE_LEN - 1;
3732+
3733+
/* Fill the first extent info into stripe->sectors[] array. */
3734+
fill_one_extent_info(fs_info, stripe, extent_start, extent_len,
3735+
extent_flags, extent_gen);
3736+
cur_logical = extent_start + extent_len;
3737+
3738+
/* Fill the extent info for the remaining sectors. */
3739+
while (cur_logical <= stripe_end) {
3740+
ret = find_first_extent_item(extent_root, &path, cur_logical,
3741+
stripe_end - cur_logical + 1);
3742+
if (ret < 0)
3743+
goto out;
3744+
if (ret > 0) {
3745+
ret = 0;
3746+
break;
3747+
}
3748+
get_extent_info(&path, &extent_start, &extent_len,
3749+
&extent_flags, &extent_gen);
3750+
fill_one_extent_info(fs_info, stripe, extent_start, extent_len,
3751+
extent_flags, extent_gen);
3752+
cur_logical = extent_start + extent_len;
3753+
}
3754+
3755+
/* Now fill the data csum. */
3756+
if (bg->flags & BTRFS_BLOCK_GROUP_DATA) {
3757+
int sector_nr;
3758+
unsigned long csum_bitmap = 0;
3759+
3760+
/* Csum space should have already been allocated. */
3761+
ASSERT(stripe->csums);
3762+
3763+
/*
3764+
* Our csum bitmap should be large enough, as BTRFS_STRIPE_LEN
3765+
* should contain at most 16 sectors.
3766+
*/
3767+
ASSERT(BITS_PER_LONG >= BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits);
3768+
3769+
ret = btrfs_lookup_csums_bitmap(csum_root, stripe->logical,
3770+
stripe_end, stripe->csums,
3771+
&csum_bitmap, true);
3772+
if (ret < 0)
3773+
goto out;
3774+
if (ret > 0)
3775+
ret = 0;
3776+
3777+
for_each_set_bit(sector_nr, &csum_bitmap, stripe->nr_sectors) {
3778+
stripe->sectors[sector_nr].csum = stripe->csums +
3779+
sector_nr * fs_info->csum_size;
3780+
}
3781+
}
3782+
set_bit(SCRUB_STRIPE_FLAG_INITIALIZED, &stripe->state);
3783+
out:
3784+
btrfs_release_path(&path);
3785+
return ret;
3786+
}
3787+
36453788
/*
36463789
* Scrub one range which can only has simple mirror based profile.
36473790
* (Including all range in SINGLE/DUP/RAID1/RAID1C*, and each stripe in

fs/btrfs/scrub.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,9 @@ int btrfs_scrub_progress(struct btrfs_fs_info *fs_info, u64 devid,
2020
struct scrub_stripe;
2121
int init_scrub_stripe(struct btrfs_fs_info *fs_info, struct scrub_stripe *stripe);
2222
void wait_scrub_stripe_io(struct scrub_stripe *stripe);
23+
int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
24+
struct btrfs_device *dev, u64 physical,
25+
int mirror_num, u64 logical_start,
26+
u32 logical_len, struct scrub_stripe *stripe);
2327

2428
#endif

0 commit comments

Comments
 (0)