Message ID | eb752c34ca23d5d55ce7df9b43cdcb5f52b97490.1680225140.git.wqu@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | btrfs: scrub: use a more reader friendly code to implement scrub_simple_mirror() | expand |
On Fri, Mar 31, 2023 at 09:20:09AM +0800, Qu Wenruo wrote: > +void scrub_verify_one_metadata(struct scrub_stripe *stripe, int sector_nr) > +{ > + struct btrfs_fs_info *fs_info = stripe->bg->fs_info; > + const unsigned int sectors_per_tree = fs_info->nodesize >> > + fs_info->sectorsize_bits; > + const u64 logical = stripe->logical + (sector_nr << fs_info->sectorsize_bits); > + const struct page *first_page = scrub_stripe_get_page(stripe, sector_nr); > + const unsigned int first_off = scrub_stripe_get_page_offset(stripe, sector_nr); > + SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); > + u8 on_disk_csum[BTRFS_CSUM_SIZE]; > + u8 calculated_csum[BTRFS_CSUM_SIZE]; > + struct btrfs_header *header; > + > + /* > + * Here we don't have a good way to attach the pages (and subpages) > + * to a dummy extent buffer, thus we have to directly grab the members > + * from pages. > + */ > + header = (struct btrfs_header *)(page_address(first_page) + first_off); > + memcpy(on_disk_csum, header->csum, fs_info->csum_size); > + > + if (logical != btrfs_stack_header_bytenr(header)) { > + bitmap_set(&stripe->csum_error_bitmap, sector_nr, > + sectors_per_tree); > + bitmap_set(&stripe->error_bitmap, sector_nr, > + sectors_per_tree); > + btrfs_warn_rl(fs_info, > + "tree block %llu mirror %u has bad bytenr, has %llu want %llu", > + logical, stripe->mirror_num, > + btrfs_stack_header_bytenr(header), logical); > + return; > + } > + if (memcmp(header->fsid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE) != 0) { > + bitmap_set(&stripe->meta_error_bitmap, sector_nr, > + sectors_per_tree); > + bitmap_set(&stripe->error_bitmap, sector_nr, > + sectors_per_tree); > + btrfs_warn_rl(fs_info, > + "tree block %llu mirror %u has bad fsid, has %pU want %pU", > + logical, stripe->mirror_num, > + header->fsid, fs_info->fs_devices->fsid); > + return; > + } > + if (memcmp(header->chunk_tree_uuid, fs_info->chunk_tree_uuid, > + BTRFS_UUID_SIZE) != 0) { > + bitmap_set(&stripe->meta_error_bitmap, sector_nr, > + sectors_per_tree); > + bitmap_set(&stripe->error_bitmap, sector_nr, > + sectors_per_tree); > + btrfs_warn_rl(fs_info, > + "tree block %llu mirror %u has bad chunk tree uuid, has %pU want %pU", > + logical, stripe->mirror_num, > + header->chunk_tree_uuid, fs_info->chunk_tree_uuid); > + return; > + } > + > + /* Now check tree block csum. */ > + shash->tfm = fs_info->csum_shash; > + crypto_shash_init(shash); > + crypto_shash_update(shash, page_address(first_page) + first_off + > + BTRFS_CSUM_SIZE, fs_info->sectorsize - BTRFS_CSUM_SIZE); > + > + for (int i = sector_nr + 1; i < sector_nr + sectors_per_tree; i++) { > + struct page *page = scrub_stripe_get_page(stripe, i); > + unsigned int page_off = scrub_stripe_get_page_offset(stripe, i); > + > + crypto_shash_update(shash, page_address(page) + page_off, > + fs_info->sectorsize); > + } > + crypto_shash_final(shash, calculated_csum); > + if (memcmp(calculated_csum, on_disk_csum, fs_info->csum_size) != 0) { > + bitmap_set(&stripe->meta_error_bitmap, sector_nr, > + sectors_per_tree); > + bitmap_set(&stripe->error_bitmap, sector_nr, > + sectors_per_tree); > + btrfs_warn_rl(fs_info, > + "tree block %llu mirror %u has bad csum, has " CSUM_FMT " want " CSUM_FMT, > + logical, stripe->mirror_num, > + CSUM_FMT_VALUE(fs_info->csum_size, on_disk_csum), > + CSUM_FMT_VALUE(fs_info->csum_size, calculated_csum)); > + return; > + } > + if (stripe->sectors[sector_nr].generation != > + btrfs_stack_header_generation(header)) { > + bitmap_set(&stripe->meta_error_bitmap, sector_nr, > + sectors_per_tree); > + bitmap_set(&stripe->error_bitmap, sector_nr, > + sectors_per_tree); > + btrfs_warn_rl(fs_info, > + "tree block %llu mirror %u has bad geneartion, has %llu want %llu", > + logical, stripe->mirror_num, > + btrfs_stack_header_generation(header), > + stripe->sectors[sector_nr].generation); Is return; missing here? > + } > + bitmap_clear(&stripe->error_bitmap, sector_nr, sectors_per_tree); > + bitmap_clear(&stripe->csum_error_bitmap, sector_nr, sectors_per_tree); > + bitmap_clear(&stripe->meta_error_bitmap, sector_nr, sectors_per_tree); > +}
On 2023/4/5 23:28, David Sterba wrote: > On Fri, Mar 31, 2023 at 09:20:09AM +0800, Qu Wenruo wrote: >> +void scrub_verify_one_metadata(struct scrub_stripe *stripe, int sector_nr) >> +{ >> + struct btrfs_fs_info *fs_info = stripe->bg->fs_info; >> + const unsigned int sectors_per_tree = fs_info->nodesize >> >> + fs_info->sectorsize_bits; >> + const u64 logical = stripe->logical + (sector_nr << fs_info->sectorsize_bits); >> + const struct page *first_page = scrub_stripe_get_page(stripe, sector_nr); >> + const unsigned int first_off = scrub_stripe_get_page_offset(stripe, sector_nr); >> + SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); >> + u8 on_disk_csum[BTRFS_CSUM_SIZE]; >> + u8 calculated_csum[BTRFS_CSUM_SIZE]; >> + struct btrfs_header *header; >> + >> + /* >> + * Here we don't have a good way to attach the pages (and subpages) >> + * to a dummy extent buffer, thus we have to directly grab the members >> + * from pages. >> + */ >> + header = (struct btrfs_header *)(page_address(first_page) + first_off); >> + memcpy(on_disk_csum, header->csum, fs_info->csum_size); >> + >> + if (logical != btrfs_stack_header_bytenr(header)) { >> + bitmap_set(&stripe->csum_error_bitmap, sector_nr, >> + sectors_per_tree); >> + bitmap_set(&stripe->error_bitmap, sector_nr, >> + sectors_per_tree); >> + btrfs_warn_rl(fs_info, >> + "tree block %llu mirror %u has bad bytenr, has %llu want %llu", >> + logical, stripe->mirror_num, >> + btrfs_stack_header_bytenr(header), logical); >> + return; >> + } >> + if (memcmp(header->fsid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE) != 0) { >> + bitmap_set(&stripe->meta_error_bitmap, sector_nr, >> + sectors_per_tree); >> + bitmap_set(&stripe->error_bitmap, sector_nr, >> + sectors_per_tree); >> + btrfs_warn_rl(fs_info, >> + "tree block %llu mirror %u has bad fsid, has %pU want %pU", >> + logical, stripe->mirror_num, >> + header->fsid, fs_info->fs_devices->fsid); >> + return; >> + } >> + if (memcmp(header->chunk_tree_uuid, fs_info->chunk_tree_uuid, >> + BTRFS_UUID_SIZE) != 0) { >> + bitmap_set(&stripe->meta_error_bitmap, sector_nr, >> + sectors_per_tree); >> + bitmap_set(&stripe->error_bitmap, sector_nr, >> + sectors_per_tree); >> + btrfs_warn_rl(fs_info, >> + "tree block %llu mirror %u has bad chunk tree uuid, has %pU want %pU", >> + logical, stripe->mirror_num, >> + header->chunk_tree_uuid, fs_info->chunk_tree_uuid); >> + return; >> + } >> + >> + /* Now check tree block csum. */ >> + shash->tfm = fs_info->csum_shash; >> + crypto_shash_init(shash); >> + crypto_shash_update(shash, page_address(first_page) + first_off + >> + BTRFS_CSUM_SIZE, fs_info->sectorsize - BTRFS_CSUM_SIZE); >> + >> + for (int i = sector_nr + 1; i < sector_nr + sectors_per_tree; i++) { >> + struct page *page = scrub_stripe_get_page(stripe, i); >> + unsigned int page_off = scrub_stripe_get_page_offset(stripe, i); >> + >> + crypto_shash_update(shash, page_address(page) + page_off, >> + fs_info->sectorsize); >> + } >> + crypto_shash_final(shash, calculated_csum); >> + if (memcmp(calculated_csum, on_disk_csum, fs_info->csum_size) != 0) { >> + bitmap_set(&stripe->meta_error_bitmap, sector_nr, >> + sectors_per_tree); >> + bitmap_set(&stripe->error_bitmap, sector_nr, >> + sectors_per_tree); >> + btrfs_warn_rl(fs_info, >> + "tree block %llu mirror %u has bad csum, has " CSUM_FMT " want " CSUM_FMT, >> + logical, stripe->mirror_num, >> + CSUM_FMT_VALUE(fs_info->csum_size, on_disk_csum), >> + CSUM_FMT_VALUE(fs_info->csum_size, calculated_csum)); >> + return; >> + } >> + if (stripe->sectors[sector_nr].generation != >> + btrfs_stack_header_generation(header)) { >> + bitmap_set(&stripe->meta_error_bitmap, sector_nr, >> + sectors_per_tree); >> + bitmap_set(&stripe->error_bitmap, sector_nr, >> + sectors_per_tree); >> + btrfs_warn_rl(fs_info, >> + "tree block %llu mirror %u has bad geneartion, has %llu want %llu", >> + logical, stripe->mirror_num, >> + btrfs_stack_header_generation(header), >> + stripe->sectors[sector_nr].generation); > > Is return; missing here? Oh, right we should return or we clear the error bitmap. Thanks, Qu > >> + } >> + bitmap_clear(&stripe->error_bitmap, sector_nr, sectors_per_tree); >> + bitmap_clear(&stripe->csum_error_bitmap, sector_nr, sectors_per_tree); >> + bitmap_clear(&stripe->meta_error_bitmap, sector_nr, sectors_per_tree); >> +}
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 00f43e3a2471..33ff0dc6a785 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -2159,6 +2159,122 @@ static int scrub_checksum_data(struct scrub_block *sblock) return sblock->checksum_error; } +static struct page *scrub_stripe_get_page(struct scrub_stripe *stripe, + int sector_nr) +{ + struct btrfs_fs_info *fs_info = stripe->bg->fs_info; + int page_index = (sector_nr << fs_info->sectorsize_bits) >> PAGE_SHIFT; + + return stripe->pages[page_index]; +} + +static unsigned int scrub_stripe_get_page_offset(struct scrub_stripe *stripe, + int sector_nr) +{ + struct btrfs_fs_info *fs_info = stripe->bg->fs_info; + + return offset_in_page(sector_nr << fs_info->sectorsize_bits); +} + +void scrub_verify_one_metadata(struct scrub_stripe *stripe, int sector_nr) +{ + struct btrfs_fs_info *fs_info = stripe->bg->fs_info; + const unsigned int sectors_per_tree = fs_info->nodesize >> + fs_info->sectorsize_bits; + const u64 logical = stripe->logical + (sector_nr << fs_info->sectorsize_bits); + const struct page *first_page = scrub_stripe_get_page(stripe, sector_nr); + const unsigned int first_off = scrub_stripe_get_page_offset(stripe, sector_nr); + SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); + u8 on_disk_csum[BTRFS_CSUM_SIZE]; + u8 calculated_csum[BTRFS_CSUM_SIZE]; + struct btrfs_header *header; + + /* + * Here we don't have a good way to attach the pages (and subpages) + * to a dummy extent buffer, thus we have to directly grab the members + * from pages. + */ + header = (struct btrfs_header *)(page_address(first_page) + first_off); + memcpy(on_disk_csum, header->csum, fs_info->csum_size); + + if (logical != btrfs_stack_header_bytenr(header)) { + bitmap_set(&stripe->csum_error_bitmap, sector_nr, + sectors_per_tree); + bitmap_set(&stripe->error_bitmap, sector_nr, + sectors_per_tree); + btrfs_warn_rl(fs_info, + "tree block %llu mirror %u has bad bytenr, has %llu want %llu", + logical, stripe->mirror_num, + btrfs_stack_header_bytenr(header), logical); + return; + } + if (memcmp(header->fsid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE) != 0) { + bitmap_set(&stripe->meta_error_bitmap, sector_nr, + sectors_per_tree); + bitmap_set(&stripe->error_bitmap, sector_nr, + sectors_per_tree); + btrfs_warn_rl(fs_info, + "tree block %llu mirror %u has bad fsid, has %pU want %pU", + logical, stripe->mirror_num, + header->fsid, fs_info->fs_devices->fsid); + return; + } + if (memcmp(header->chunk_tree_uuid, fs_info->chunk_tree_uuid, + BTRFS_UUID_SIZE) != 0) { + bitmap_set(&stripe->meta_error_bitmap, sector_nr, + sectors_per_tree); + bitmap_set(&stripe->error_bitmap, sector_nr, + sectors_per_tree); + btrfs_warn_rl(fs_info, + "tree block %llu mirror %u has bad chunk tree uuid, has %pU want %pU", + logical, stripe->mirror_num, + header->chunk_tree_uuid, fs_info->chunk_tree_uuid); + return; + } + + /* Now check tree block csum. */ + shash->tfm = fs_info->csum_shash; + crypto_shash_init(shash); + crypto_shash_update(shash, page_address(first_page) + first_off + + BTRFS_CSUM_SIZE, fs_info->sectorsize - BTRFS_CSUM_SIZE); + + for (int i = sector_nr + 1; i < sector_nr + sectors_per_tree; i++) { + struct page *page = scrub_stripe_get_page(stripe, i); + unsigned int page_off = scrub_stripe_get_page_offset(stripe, i); + + crypto_shash_update(shash, page_address(page) + page_off, + fs_info->sectorsize); + } + crypto_shash_final(shash, calculated_csum); + if (memcmp(calculated_csum, on_disk_csum, fs_info->csum_size) != 0) { + bitmap_set(&stripe->meta_error_bitmap, sector_nr, + sectors_per_tree); + bitmap_set(&stripe->error_bitmap, sector_nr, + sectors_per_tree); + btrfs_warn_rl(fs_info, + "tree block %llu mirror %u has bad csum, has " CSUM_FMT " want " CSUM_FMT, + logical, stripe->mirror_num, + CSUM_FMT_VALUE(fs_info->csum_size, on_disk_csum), + CSUM_FMT_VALUE(fs_info->csum_size, calculated_csum)); + return; + } + if (stripe->sectors[sector_nr].generation != + btrfs_stack_header_generation(header)) { + bitmap_set(&stripe->meta_error_bitmap, sector_nr, + sectors_per_tree); + bitmap_set(&stripe->error_bitmap, sector_nr, + sectors_per_tree); + btrfs_warn_rl(fs_info, + "tree block %llu mirror %u has bad geneartion, has %llu want %llu", + logical, stripe->mirror_num, + btrfs_stack_header_generation(header), + stripe->sectors[sector_nr].generation); + } + bitmap_clear(&stripe->error_bitmap, sector_nr, sectors_per_tree); + bitmap_clear(&stripe->csum_error_bitmap, sector_nr, sectors_per_tree); + bitmap_clear(&stripe->meta_error_bitmap, sector_nr, sectors_per_tree); +} + static int scrub_checksum_tree_block(struct scrub_block *sblock) { struct scrub_ctx *sctx = sblock->sctx; diff --git a/fs/btrfs/scrub.h b/fs/btrfs/scrub.h index 27019d86b539..0d8bdc7df89c 100644 --- a/fs/btrfs/scrub.h +++ b/fs/btrfs/scrub.h @@ -24,5 +24,6 @@ int scrub_find_fill_first_stripe(struct btrfs_block_group *bg, struct btrfs_device *dev, u64 physical, int mirror_num, u64 logical_start, u32 logical_len, struct scrub_stripe *stripe); +void scrub_verify_one_metadata(struct scrub_stripe *stripe, int sector_nr); #endif