Messages in this thread | | | From | Dāvis Mosāns <> | Date | Wed, 21 Apr 2021 19:00:51 +0300 | Subject | Re: [PATCH] btrfs: Allow read-only mount with corrupted extent tree |
| |
svētd., 2021. g. 21. marts, plkst. 23:46 — lietotājs Dāvis Mosāns (<davispuh@gmail.com>) rakstīja: > > Currently if there's any corruption at all in extent tree > (eg. even single bit) then mounting will fail with: > "failed to read block groups: -5" (-EIO) > It happens because we immediately abort on first error when > searching in extent tree for block groups. > > Now with this patch if `ignorebadroots` option is specified > then we handle such case and continue by removing already > created block groups and creating dummy block groups. > > Signed-off-by: Dāvis Mosāns <davispuh@gmail.com> > --- > fs/btrfs/block-group.c | 20 ++++++++++++++++++++ > fs/btrfs/disk-io.c | 4 ++-- > fs/btrfs/disk-io.h | 2 ++ > 3 files changed, 24 insertions(+), 2 deletions(-) > > diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c > index 48ebc106a606..f485cf14c2f8 100644 > --- a/fs/btrfs/block-group.c > +++ b/fs/btrfs/block-group.c > @@ -2048,6 +2048,26 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info) > ret = check_chunk_block_group_mappings(info); > error: > btrfs_free_path(path); > + > + if (ret == -EIO && btrfs_test_opt(info, IGNOREBADROOTS)) { > + > + if (btrfs_super_log_root(info->super_copy) != 0) { > + btrfs_warn(info, "Ignoring tree-log replay due to extent tree corruption!"); > + btrfs_set_super_log_root(info->super_copy, 0); > + } > + > + btrfs_put_block_group_cache(info); > + btrfs_stop_all_workers(info); > + btrfs_free_block_groups(info); > + ret = btrfs_init_workqueues(info, NULL); > + if (ret) > + return ret; > + ret = btrfs_init_space_info(info); > + if (ret) > + return ret; > + return fill_dummy_bgs(info); > + } > + > return ret; > } > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index 07a2b4f69b10..dc744f76d075 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -1955,7 +1955,7 @@ static int read_backup_root(struct btrfs_fs_info *fs_info, u8 priority) > } > > /* helper to cleanup workers */ > -static void btrfs_stop_all_workers(struct btrfs_fs_info *fs_info) > +void btrfs_stop_all_workers(struct btrfs_fs_info *fs_info) > { > btrfs_destroy_workqueue(fs_info->fixup_workers); > btrfs_destroy_workqueue(fs_info->delalloc_workers); > @@ -2122,7 +2122,7 @@ static void btrfs_init_qgroup(struct btrfs_fs_info *fs_info) > mutex_init(&fs_info->qgroup_rescan_lock); > } > > -static int btrfs_init_workqueues(struct btrfs_fs_info *fs_info, > +int btrfs_init_workqueues(struct btrfs_fs_info *fs_info, > struct btrfs_fs_devices *fs_devices) > { > u32 max_active = fs_info->thread_pool_size; > diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h > index e45057c0c016..f9bfcba86a04 100644 > --- a/fs/btrfs/disk-io.h > +++ b/fs/btrfs/disk-io.h > @@ -137,6 +137,8 @@ int btrfs_find_free_objectid(struct btrfs_root *root, u64 *objectid); > int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid); > int __init btrfs_end_io_wq_init(void); > void __cold btrfs_end_io_wq_exit(void); > +void btrfs_stop_all_workers(struct btrfs_fs_info *fs_info); > +int btrfs_init_workqueues(struct btrfs_fs_info *fs_info, struct btrfs_fs_devices *fs_devices); > > #ifdef CONFIG_DEBUG_LOCK_ALLOC > void btrfs_set_buffer_lockdep_class(u64 objectid, > -- > 2.30.2 >
Ping? Could anyone take a look?
| |