Skip to content

Commit 2a2dc22

Browse files
adam900710kdave
authored andcommitted
btrfs: scrub: use dedicated super block verification function to scrub one super block
There is really no need to go through the super complex scrub_sectors() to just handle super blocks. Introduce a dedicated function to handle super block scrubbing. This new function will introduce a behavior change, instead of using the complex but concurrent scrub_bio system, here we just go submit-and-wait. There is really not much sense to care the performance of super block scrubbing. It only has 3 super blocks at most, and they are all scattered around the devices already. Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Anand Jain <anand.jain@oracle.com> 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 f0bb547 commit 2a2dc22

1 file changed

Lines changed: 52 additions & 8 deletions

File tree

fs/btrfs/scrub.c

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4243,18 +4243,62 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
42434243
return ret;
42444244
}
42454245

4246+
static int scrub_one_super(struct scrub_ctx *sctx, struct btrfs_device *dev,
4247+
struct page *page, u64 physical, u64 generation)
4248+
{
4249+
struct btrfs_fs_info *fs_info = sctx->fs_info;
4250+
struct bio_vec bvec;
4251+
struct bio bio;
4252+
struct btrfs_super_block *sb = page_address(page);
4253+
int ret;
4254+
4255+
bio_init(&bio, dev->bdev, &bvec, 1, REQ_OP_READ);
4256+
bio.bi_iter.bi_sector = physical >> SECTOR_SHIFT;
4257+
__bio_add_page(&bio, page, BTRFS_SUPER_INFO_SIZE, 0);
4258+
ret = submit_bio_wait(&bio);
4259+
bio_uninit(&bio);
4260+
4261+
if (ret < 0)
4262+
return ret;
4263+
ret = btrfs_check_super_csum(fs_info, sb);
4264+
if (ret != 0) {
4265+
btrfs_err_rl(fs_info,
4266+
"super block at physical %llu devid %llu has bad csum",
4267+
physical, dev->devid);
4268+
return -EIO;
4269+
}
4270+
if (btrfs_super_generation(sb) != generation) {
4271+
btrfs_err_rl(fs_info,
4272+
"super block at physical %llu devid %llu has bad generation %llu expect %llu",
4273+
physical, dev->devid,
4274+
btrfs_super_generation(sb), generation);
4275+
return -EUCLEAN;
4276+
}
4277+
4278+
return btrfs_validate_super(fs_info, sb, -1);
4279+
}
4280+
42464281
static noinline_for_stack int scrub_supers(struct scrub_ctx *sctx,
42474282
struct btrfs_device *scrub_dev)
42484283
{
42494284
int i;
42504285
u64 bytenr;
42514286
u64 gen;
4252-
int ret;
4287+
int ret = 0;
4288+
struct page *page;
42534289
struct btrfs_fs_info *fs_info = sctx->fs_info;
42544290

42554291
if (BTRFS_FS_ERROR(fs_info))
42564292
return -EROFS;
42574293

4294+
page = alloc_page(GFP_KERNEL);
4295+
if (!page) {
4296+
spin_lock(&sctx->stat_lock);
4297+
sctx->stat.malloc_errors++;
4298+
spin_unlock(&sctx->stat_lock);
4299+
return -ENOMEM;
4300+
}
4301+
42584302
/* Seed devices of a new filesystem has their own generation. */
42594303
if (scrub_dev->fs_devices != fs_info->fs_devices)
42604304
gen = scrub_dev->generation;
@@ -4269,14 +4313,14 @@ static noinline_for_stack int scrub_supers(struct scrub_ctx *sctx,
42694313
if (!btrfs_check_super_location(scrub_dev, bytenr))
42704314
continue;
42714315

4272-
ret = scrub_sectors(sctx, bytenr, BTRFS_SUPER_INFO_SIZE, bytenr,
4273-
scrub_dev, BTRFS_EXTENT_FLAG_SUPER, gen, i,
4274-
NULL, bytenr);
4275-
if (ret)
4276-
return ret;
4316+
ret = scrub_one_super(sctx, scrub_dev, page, bytenr, gen);
4317+
if (ret) {
4318+
spin_lock(&sctx->stat_lock);
4319+
sctx->stat.super_errors++;
4320+
spin_unlock(&sctx->stat_lock);
4321+
}
42774322
}
4278-
wait_event(sctx->list_wait, atomic_read(&sctx->bios_in_flight) == 0);
4279-
4323+
__free_page(page);
42804324
return 0;
42814325
}
42824326

0 commit comments

Comments
 (0)