diff options
| -rw-r--r-- | fs/btrfs/disk-io.c | 12 | ||||
| -rw-r--r-- | fs/btrfs/fs.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/super.c | 28 |
3 files changed, 36 insertions, 5 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index d3d3d67ced3e..66b054eb98c6 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2715,10 +2715,14 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info) int ret = 0; if (use_backup) { - ret = read_backup_root(fs_info, 1); + ASSERT(fs_info->use_backup_slot >= 0 && + fs_info->use_backup_slot < BTRFS_NUM_BACKUP_ROOTS); + + ret = read_backup_root(fs_info, fs_info->use_backup_slot); if (ret < 0) { btrfs_err(fs_info, - "failed to load backup roots at slot %d", 1); + "failed to load backup roots at slot %d", + fs_info->use_backup_slot); return ret; } /* @@ -2727,7 +2731,8 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info) */ btrfs_set_super_log_root(sb, 0); backup_index = ret; - btrfs_warn(fs_info, "loaded backup roots at slot %d", 1); + btrfs_warn(fs_info, "loaded backup roots at slot %d", + fs_info->use_backup_slot); } ret = load_important_roots(fs_info); @@ -2898,6 +2903,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info) init_waitqueue_head(&fs_info->async_submit_wait); init_waitqueue_head(&fs_info->delayed_iputs_wait); + fs_info->use_backup_slot = -1; /* Usable values until the real ones are cached from the superblock */ fs_info->nodesize = 4096; fs_info->sectorsize = 4096; diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h index 3eba8438593c..649623c603e8 100644 --- a/fs/btrfs/fs.h +++ b/fs/btrfs/fs.h @@ -857,6 +857,7 @@ struct btrfs_fs_info { /* Next backup root to be overwritten */ int backup_root_index; + int use_backup_slot; /* Device replace state */ struct btrfs_dev_replace dev_replace; diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index ddb620ac241b..8d01409ed382 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -87,6 +87,7 @@ struct btrfs_fs_context { unsigned long long mount_opt; unsigned long compress_type:4; int compress_level; + int use_backup_slot; refcount_t refs; }; @@ -175,6 +176,10 @@ static const struct constant_table btrfs_parameter_space_cache[] = { enum { Opt_rescue_usebackuproot, + Opt_rescue_usebackup_slot_0, + Opt_rescue_usebackup_slot_1, + Opt_rescue_usebackup_slot_2, + Opt_rescue_usebackup_slot_3, Opt_rescue_nologreplay, Opt_rescue_ignorebadroots, Opt_rescue_ignoredatacsums, @@ -185,6 +190,10 @@ enum { static const struct constant_table btrfs_parameter_rescue[] = { { "usebackuproot", Opt_rescue_usebackuproot }, + { "usebackuproot_0", Opt_rescue_usebackup_slot_0}, + { "usebackuproot_1", Opt_rescue_usebackup_slot_1}, + { "usebackuproot_2", Opt_rescue_usebackup_slot_2}, + { "usebackuproot_3", Opt_rescue_usebackup_slot_3}, { "nologreplay", Opt_rescue_nologreplay }, { "ignorebadroots", Opt_rescue_ignorebadroots }, { "ibadroots", Opt_rescue_ignorebadroots }, @@ -588,6 +597,14 @@ static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param) switch (result.uint_32) { case Opt_rescue_usebackuproot: btrfs_set_opt(ctx->mount_opt, USEBACKUPROOT); + ctx->use_backup_slot = 1; + break; + case Opt_rescue_usebackup_slot_0: + case Opt_rescue_usebackup_slot_1: + case Opt_rescue_usebackup_slot_2: + case Opt_rescue_usebackup_slot_3: + btrfs_set_opt(ctx->mount_opt, USEBACKUPROOT); + ctx->use_backup_slot = result.uint_32 - Opt_rescue_usebackup_slot_0; break; case Opt_rescue_nologreplay: btrfs_set_opt(ctx->mount_opt, NOLOGREPLAY); @@ -611,6 +628,7 @@ static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param) btrfs_set_opt(ctx->mount_opt, IGNOREBADROOTS); btrfs_set_opt(ctx->mount_opt, NOLOGREPLAY); btrfs_set_opt(ctx->mount_opt, USEBACKUPROOT); + ctx->use_backup_slot = 1; break; default: btrfs_info(NULL, "unrecognized rescue option '%s'", @@ -1089,8 +1107,11 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry) seq_puts(seq, ",notreelog"); if (btrfs_test_opt(info, NOLOGREPLAY)) print_rescue_option(seq, "nologreplay", &printed); - if (btrfs_test_opt(info, USEBACKUPROOT)) - print_rescue_option(seq, "usebackuproot", &printed); + if (btrfs_test_opt(info, USEBACKUPROOT)) { + seq_printf(seq, "%susebackuproot_%d", printed ? ":" : ",rescue=", + info->use_backup_slot); + printed = true; + } if (btrfs_test_opt(info, IGNOREBADROOTS)) print_rescue_option(seq, "ignorebadroots", &printed); if (btrfs_test_opt(info, IGNOREDATACSUMS)) @@ -1406,6 +1427,7 @@ static void btrfs_ctx_to_info(struct btrfs_fs_info *fs_info, struct btrfs_fs_con fs_info->mount_opt = ctx->mount_opt; fs_info->compress_type = ctx->compress_type; fs_info->compress_level = ctx->compress_level; + fs_info->use_backup_slot = ctx->use_backup_slot; } static void btrfs_info_to_ctx(struct btrfs_fs_info *fs_info, struct btrfs_fs_context *ctx) @@ -1417,6 +1439,7 @@ static void btrfs_info_to_ctx(struct btrfs_fs_info *fs_info, struct btrfs_fs_con ctx->mount_opt = fs_info->mount_opt; ctx->compress_type = fs_info->compress_type; ctx->compress_level = fs_info->compress_level; + ctx->use_backup_slot = fs_info->use_backup_slot; } #define btrfs_info_if_set(fs_info, old_ctx, opt, fmt, args...) \ @@ -2209,6 +2232,7 @@ static int btrfs_init_fs_context(struct fs_context *fc) if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) { btrfs_info_to_ctx(btrfs_sb(fc->root->d_sb), ctx); } else { + ctx->use_backup_slot = -1; ctx->thread_pool_size = min_t(unsigned long, num_online_cpus() + 2, 8); ctx->max_inline = BTRFS_DEFAULT_MAX_INLINE; |
