Skip to content

Commit 97cf8f3

Browse files
adam900710kdave
authored andcommitted
btrfs: scrub: introduce a helper to verify one scrub_stripe
The new helper, scrub_verify_stripe(), shares the same main workflow of the old scrub code. The major differences are: - How pages/page_offset is grabbed Everything can be grabbed from scrub_stripe easily. - When error report happens Currently the helper only verifies the sectors, not really doing any error reporting. The error reporting would be done after we have done the repair. Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent a3ddbae commit 97cf8f3

2 files changed

Lines changed: 77 additions & 2 deletions

File tree

fs/btrfs/scrub.c

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2175,7 +2175,7 @@ static unsigned int scrub_stripe_get_page_offset(struct scrub_stripe *stripe,
21752175
return offset_in_page(sector_nr << fs_info->sectorsize_bits);
21762176
}
21772177

2178-
void scrub_verify_one_metadata(struct scrub_stripe *stripe, int sector_nr)
2178+
static void scrub_verify_one_metadata(struct scrub_stripe *stripe, int sector_nr)
21792179
{
21802180
struct btrfs_fs_info *fs_info = stripe->bg->fs_info;
21812181
const u32 sectors_per_tree = fs_info->nodesize >> fs_info->sectorsize_bits;
@@ -2265,6 +2265,81 @@ void scrub_verify_one_metadata(struct scrub_stripe *stripe, int sector_nr)
22652265
bitmap_clear(&stripe->meta_error_bitmap, sector_nr, sectors_per_tree);
22662266
}
22672267

2268+
static void scrub_verify_one_sector(struct scrub_stripe *stripe, int sector_nr)
2269+
{
2270+
struct btrfs_fs_info *fs_info = stripe->bg->fs_info;
2271+
struct scrub_sector_verification *sector = &stripe->sectors[sector_nr];
2272+
const u32 sectors_per_tree = fs_info->nodesize >> fs_info->sectorsize_bits;
2273+
struct page *page = scrub_stripe_get_page(stripe, sector_nr);
2274+
unsigned int pgoff = scrub_stripe_get_page_offset(stripe, sector_nr);
2275+
u8 csum_buf[BTRFS_CSUM_SIZE];
2276+
int ret;
2277+
2278+
ASSERT(sector_nr >= 0 && sector_nr < stripe->nr_sectors);
2279+
2280+
/* Sector not utilized, skip it. */
2281+
if (!test_bit(sector_nr, &stripe->extent_sector_bitmap))
2282+
return;
2283+
2284+
/* IO error, no need to check. */
2285+
if (test_bit(sector_nr, &stripe->io_error_bitmap))
2286+
return;
2287+
2288+
/* Metadata, verify the full tree block. */
2289+
if (sector->is_metadata) {
2290+
/*
2291+
* Check if the tree block crosses the stripe boudary. If
2292+
* crossed the boundary, we cannot verify it but only give a
2293+
* warning.
2294+
*
2295+
* This can only happen on a very old filesystem where chunks
2296+
* are not ensured to be stripe aligned.
2297+
*/
2298+
if (unlikely(sector_nr + sectors_per_tree > stripe->nr_sectors)) {
2299+
btrfs_warn_rl(fs_info,
2300+
"tree block at %llu crosses stripe boundary %llu",
2301+
stripe->logical +
2302+
(sector_nr << fs_info->sectorsize_bits),
2303+
stripe->logical);
2304+
return;
2305+
}
2306+
scrub_verify_one_metadata(stripe, sector_nr);
2307+
return;
2308+
}
2309+
2310+
/*
2311+
* Data is easier, we just verify the data csum (if we have it). For
2312+
* cases without csum, we have no other choice but to trust it.
2313+
*/
2314+
if (!sector->csum) {
2315+
clear_bit(sector_nr, &stripe->error_bitmap);
2316+
return;
2317+
}
2318+
2319+
ret = btrfs_check_sector_csum(fs_info, page, pgoff, csum_buf, sector->csum);
2320+
if (ret < 0) {
2321+
set_bit(sector_nr, &stripe->csum_error_bitmap);
2322+
set_bit(sector_nr, &stripe->error_bitmap);
2323+
} else {
2324+
clear_bit(sector_nr, &stripe->csum_error_bitmap);
2325+
clear_bit(sector_nr, &stripe->error_bitmap);
2326+
}
2327+
}
2328+
2329+
/* Verify specified sectors of a stripe. */
2330+
void scrub_verify_one_stripe(struct scrub_stripe *stripe, unsigned long bitmap)
2331+
{
2332+
struct btrfs_fs_info *fs_info = stripe->bg->fs_info;
2333+
const u32 sectors_per_tree = fs_info->nodesize >> fs_info->sectorsize_bits;
2334+
int sector_nr;
2335+
2336+
for_each_set_bit(sector_nr, &bitmap, stripe->nr_sectors) {
2337+
scrub_verify_one_sector(stripe, sector_nr);
2338+
if (stripe->sectors[sector_nr].is_metadata)
2339+
sector_nr += sectors_per_tree - 1;
2340+
}
2341+
}
2342+
22682343
static int scrub_checksum_tree_block(struct scrub_block *sblock)
22692344
{
22702345
struct scrub_ctx *sctx = sblock->sctx;

fs/btrfs/scrub.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
2424
struct btrfs_device *dev, u64 physical,
2525
int mirror_num, u64 logical_start,
2626
u32 logical_len, struct scrub_stripe *stripe);
27-
void scrub_verify_one_metadata(struct scrub_stripe *stripe, int sector_nr);
27+
void scrub_verify_one_stripe(struct scrub_stripe *stripe, unsigned long bitmap);
2828

2929
#endif

0 commit comments

Comments
 (0)