Skip to content

Commit eddb1a4

Browse files
josefbacikkdave
authored andcommitted
btrfs: add reconfigure callback for fs_context
This is what is used to remount the file system with the new mount API. Because the mount options are parsed separately and one at a time I've added a helper to emit the mount options after the fact once the mount is configured, this matches the dmesg output for what happens with the old mount API. Reviewed-by: Johannes Thumshirn <[email protected]> Acked-by: Christian Brauner <[email protected]> Signed-off-by: Josef Bacik <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 0f85e24 commit eddb1a4

File tree

3 files changed

+197
-29
lines changed

3 files changed

+197
-29
lines changed

fs/btrfs/super.c

Lines changed: 185 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -725,46 +725,48 @@ static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
725725
return 0;
726726
}
727727

728-
static bool check_ro_option(struct btrfs_fs_info *fs_info, unsigned long opt,
728+
static bool check_ro_option(struct btrfs_fs_info *fs_info,
729+
unsigned long mount_opt, unsigned long opt,
729730
const char *opt_name)
730731
{
731-
if (fs_info->mount_opt & opt) {
732+
if (mount_opt & opt) {
732733
btrfs_err(fs_info, "%s must be used with ro mount option",
733734
opt_name);
734735
return true;
735736
}
736737
return false;
737738
}
738739

739-
static bool check_options(struct btrfs_fs_info *info, unsigned long flags)
740+
static bool check_options(struct btrfs_fs_info *info, unsigned long *mount_opt,
741+
unsigned long flags)
740742
{
741743
bool ret = true;
742744

743745
if (!(flags & SB_RDONLY) &&
744-
(check_ro_option(info, BTRFS_MOUNT_NOLOGREPLAY, "nologreplay") ||
745-
check_ro_option(info, BTRFS_MOUNT_IGNOREBADROOTS, "ignorebadroots") ||
746-
check_ro_option(info, BTRFS_MOUNT_IGNOREDATACSUMS, "ignoredatacsums")))
746+
(check_ro_option(info, *mount_opt, BTRFS_MOUNT_NOLOGREPLAY, "nologreplay") ||
747+
check_ro_option(info, *mount_opt, BTRFS_MOUNT_IGNOREBADROOTS, "ignorebadroots") ||
748+
check_ro_option(info, *mount_opt, BTRFS_MOUNT_IGNOREDATACSUMS, "ignoredatacsums")))
747749
ret = false;
748750

749751
if (btrfs_fs_compat_ro(info, FREE_SPACE_TREE) &&
750-
!btrfs_test_opt(info, FREE_SPACE_TREE) &&
751-
!btrfs_test_opt(info, CLEAR_CACHE)) {
752+
!btrfs_raw_test_opt(*mount_opt, FREE_SPACE_TREE) &&
753+
!btrfs_raw_test_opt(*mount_opt, CLEAR_CACHE)) {
752754
btrfs_err(info, "cannot disable free-space-tree");
753755
ret = false;
754756
}
755757
if (btrfs_fs_compat_ro(info, BLOCK_GROUP_TREE) &&
756-
!btrfs_test_opt(info, FREE_SPACE_TREE)) {
758+
!btrfs_raw_test_opt(*mount_opt, FREE_SPACE_TREE)) {
757759
btrfs_err(info, "cannot disable free-space-tree with block-group-tree feature");
758760
ret = false;
759761
}
760762

761-
if (btrfs_check_mountopts_zoned(info))
763+
if (btrfs_check_mountopts_zoned(info, mount_opt))
762764
ret = false;
763765

764766
if (!test_bit(BTRFS_FS_STATE_REMOUNTING, &info->fs_state)) {
765-
if (btrfs_test_opt(info, SPACE_CACHE))
767+
if (btrfs_raw_test_opt(*mount_opt, SPACE_CACHE))
766768
btrfs_info(info, "disk space caching is enabled");
767-
if (btrfs_test_opt(info, FREE_SPACE_TREE))
769+
if (btrfs_raw_test_opt(*mount_opt, FREE_SPACE_TREE))
768770
btrfs_info(info, "using free-space-tree");
769771
}
770772

@@ -1342,7 +1344,7 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
13421344
}
13431345
}
13441346
out:
1345-
if (!ret && !check_options(info, new_flags))
1347+
if (!ret && !check_options(info, &info->mount_opt, new_flags))
13461348
ret = -EINVAL;
13471349
return ret;
13481350
}
@@ -2378,6 +2380,166 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
23782380
return ret;
23792381
}
23802382

2383+
static void btrfs_ctx_to_info(struct btrfs_fs_info *fs_info, struct btrfs_fs_context *ctx)
2384+
{
2385+
fs_info->max_inline = ctx->max_inline;
2386+
fs_info->commit_interval = ctx->commit_interval;
2387+
fs_info->metadata_ratio = ctx->metadata_ratio;
2388+
fs_info->thread_pool_size = ctx->thread_pool_size;
2389+
fs_info->mount_opt = ctx->mount_opt;
2390+
fs_info->compress_type = ctx->compress_type;
2391+
fs_info->compress_level = ctx->compress_level;
2392+
}
2393+
2394+
static void btrfs_info_to_ctx(struct btrfs_fs_info *fs_info, struct btrfs_fs_context *ctx)
2395+
{
2396+
ctx->max_inline = fs_info->max_inline;
2397+
ctx->commit_interval = fs_info->commit_interval;
2398+
ctx->metadata_ratio = fs_info->metadata_ratio;
2399+
ctx->thread_pool_size = fs_info->thread_pool_size;
2400+
ctx->mount_opt = fs_info->mount_opt;
2401+
ctx->compress_type = fs_info->compress_type;
2402+
ctx->compress_level = fs_info->compress_level;
2403+
}
2404+
2405+
#define btrfs_info_if_set(fs_info, old_ctx, opt, fmt, args...) \
2406+
do { \
2407+
if ((!old_ctx || !btrfs_raw_test_opt(old_ctx->mount_opt, opt)) && \
2408+
btrfs_raw_test_opt(fs_info->mount_opt, opt)) \
2409+
btrfs_info(fs_info, fmt, ##args); \
2410+
} while (0)
2411+
2412+
#define btrfs_info_if_unset(fs_info, old_ctx, opt, fmt, args...) \
2413+
do { \
2414+
if ((old_ctx && btrfs_raw_test_opt(old_ctx->mount_opt, opt)) && \
2415+
!btrfs_raw_test_opt(fs_info->mount_opt, opt)) \
2416+
btrfs_info(fs_info, fmt, ##args); \
2417+
} while (0)
2418+
2419+
static void btrfs_emit_options(struct btrfs_fs_info *info,
2420+
struct btrfs_fs_context *old)
2421+
{
2422+
btrfs_info_if_set(info, old, NODATASUM, "setting nodatasum");
2423+
btrfs_info_if_set(info, old, DEGRADED, "allowing degraded mounts");
2424+
btrfs_info_if_set(info, old, NODATASUM, "setting nodatasum");
2425+
btrfs_info_if_set(info, old, SSD, "enabling ssd optimizations");
2426+
btrfs_info_if_set(info, old, SSD_SPREAD, "using spread ssd allocation scheme");
2427+
btrfs_info_if_set(info, old, NOBARRIER, "turning off barriers");
2428+
btrfs_info_if_set(info, old, NOTREELOG, "disabling tree log");
2429+
btrfs_info_if_set(info, old, NOLOGREPLAY, "disabling log replay at mount time");
2430+
btrfs_info_if_set(info, old, FLUSHONCOMMIT, "turning on flush-on-commit");
2431+
btrfs_info_if_set(info, old, DISCARD_SYNC, "turning on sync discard");
2432+
btrfs_info_if_set(info, old, DISCARD_ASYNC, "turning on async discard");
2433+
btrfs_info_if_set(info, old, FREE_SPACE_TREE, "enabling free space tree");
2434+
btrfs_info_if_set(info, old, SPACE_CACHE, "enabling disk space caching");
2435+
btrfs_info_if_set(info, old, CLEAR_CACHE, "force clearing of disk cache");
2436+
btrfs_info_if_set(info, old, AUTO_DEFRAG, "enabling auto defrag");
2437+
btrfs_info_if_set(info, old, FRAGMENT_DATA, "fragmenting data");
2438+
btrfs_info_if_set(info, old, FRAGMENT_METADATA, "fragmenting metadata");
2439+
btrfs_info_if_set(info, old, REF_VERIFY, "doing ref verification");
2440+
btrfs_info_if_set(info, old, USEBACKUPROOT, "trying to use backup root at mount time");
2441+
btrfs_info_if_set(info, old, IGNOREBADROOTS, "ignoring bad roots");
2442+
btrfs_info_if_set(info, old, IGNOREDATACSUMS, "ignoring data csums");
2443+
2444+
btrfs_info_if_unset(info, old, NODATACOW, "setting datacow");
2445+
btrfs_info_if_unset(info, old, SSD, "not using ssd optimizations");
2446+
btrfs_info_if_unset(info, old, SSD_SPREAD, "not using spread ssd allocation scheme");
2447+
btrfs_info_if_unset(info, old, NOBARRIER, "turning off barriers");
2448+
btrfs_info_if_unset(info, old, NOTREELOG, "enabling tree log");
2449+
btrfs_info_if_unset(info, old, SPACE_CACHE, "disabling disk space caching");
2450+
btrfs_info_if_unset(info, old, FREE_SPACE_TREE, "disabling free space tree");
2451+
btrfs_info_if_unset(info, old, AUTO_DEFRAG, "disabling auto defrag");
2452+
btrfs_info_if_unset(info, old, COMPRESS, "use no compression");
2453+
2454+
/* Did the compression settings change? */
2455+
if (btrfs_test_opt(info, COMPRESS) &&
2456+
(!old ||
2457+
old->compress_type != info->compress_type ||
2458+
old->compress_level != info->compress_level ||
2459+
(!btrfs_raw_test_opt(old->mount_opt, FORCE_COMPRESS) &&
2460+
btrfs_raw_test_opt(info->mount_opt, FORCE_COMPRESS)))) {
2461+
const char *compress_type = btrfs_compress_type2str(info->compress_type);
2462+
2463+
btrfs_info(info, "%s %s compression, level %d",
2464+
btrfs_test_opt(info, FORCE_COMPRESS) ? "force" : "use",
2465+
compress_type, info->compress_level);
2466+
}
2467+
2468+
if (info->max_inline != BTRFS_DEFAULT_MAX_INLINE)
2469+
btrfs_info(info, "max_inline set to %llu", info->max_inline);
2470+
}
2471+
2472+
static int btrfs_reconfigure(struct fs_context *fc)
2473+
{
2474+
struct super_block *sb = fc->root->d_sb;
2475+
struct btrfs_fs_info *fs_info = btrfs_sb(sb);
2476+
struct btrfs_fs_context *ctx = fc->fs_private;
2477+
struct btrfs_fs_context old_ctx;
2478+
int ret = 0;
2479+
2480+
btrfs_info_to_ctx(fs_info, &old_ctx);
2481+
2482+
sync_filesystem(sb);
2483+
set_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state);
2484+
2485+
if (!check_options(fs_info, &ctx->mount_opt, fc->sb_flags))
2486+
return -EINVAL;
2487+
2488+
ret = btrfs_check_features(fs_info, !(fc->sb_flags & SB_RDONLY));
2489+
if (ret < 0)
2490+
return ret;
2491+
2492+
btrfs_ctx_to_info(fs_info, ctx);
2493+
btrfs_remount_begin(fs_info, old_ctx.mount_opt, fc->sb_flags);
2494+
btrfs_resize_thread_pool(fs_info, fs_info->thread_pool_size,
2495+
old_ctx.thread_pool_size);
2496+
2497+
if ((bool)btrfs_test_opt(fs_info, FREE_SPACE_TREE) !=
2498+
(bool)btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
2499+
(!sb_rdonly(sb) || (fc->sb_flags & SB_RDONLY))) {
2500+
btrfs_warn(fs_info,
2501+
"remount supports changing free space tree only from RO to RW");
2502+
/* Make sure free space cache options match the state on disk. */
2503+
if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
2504+
btrfs_set_opt(fs_info->mount_opt, FREE_SPACE_TREE);
2505+
btrfs_clear_opt(fs_info->mount_opt, SPACE_CACHE);
2506+
}
2507+
if (btrfs_free_space_cache_v1_active(fs_info)) {
2508+
btrfs_clear_opt(fs_info->mount_opt, FREE_SPACE_TREE);
2509+
btrfs_set_opt(fs_info->mount_opt, SPACE_CACHE);
2510+
}
2511+
}
2512+
2513+
ret = 0;
2514+
if (!sb_rdonly(sb) && (fc->sb_flags & SB_RDONLY))
2515+
ret = btrfs_remount_ro(fs_info);
2516+
else if (sb_rdonly(sb) && !(fc->sb_flags & SB_RDONLY))
2517+
ret = btrfs_remount_rw(fs_info);
2518+
if (ret)
2519+
goto restore;
2520+
2521+
/*
2522+
* If we set the mask during the parameter parsing VFS would reject the
2523+
* remount. Here we can set the mask and the value will be updated
2524+
* appropriately.
2525+
*/
2526+
if ((fc->sb_flags & SB_POSIXACL) != (sb->s_flags & SB_POSIXACL))
2527+
fc->sb_flags_mask |= SB_POSIXACL;
2528+
2529+
btrfs_emit_options(fs_info, &old_ctx);
2530+
wake_up_process(fs_info->transaction_kthread);
2531+
btrfs_remount_cleanup(fs_info, old_ctx.mount_opt);
2532+
btrfs_clear_oneshot_options(fs_info);
2533+
clear_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state);
2534+
2535+
return 0;
2536+
restore:
2537+
btrfs_ctx_to_info(fs_info, &old_ctx);
2538+
btrfs_remount_cleanup(fs_info, old_ctx.mount_opt);
2539+
clear_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state);
2540+
return ret;
2541+
}
2542+
23812543
/* Used to sort the devices by max_avail(descending sort) */
23822544
static int btrfs_cmp_device_free_bytes(const void *a, const void *b)
23832545
{
@@ -2655,6 +2817,7 @@ static void btrfs_free_fs_context(struct fs_context *fc)
26552817

26562818
static const struct fs_context_operations btrfs_fs_context_ops = {
26572819
.parse_param = btrfs_parse_param,
2820+
.reconfigure = btrfs_reconfigure,
26582821
.free = btrfs_free_fs_context,
26592822
};
26602823

@@ -2666,17 +2829,18 @@ static int __maybe_unused btrfs_init_fs_context(struct fs_context *fc)
26662829
if (!ctx)
26672830
return -ENOMEM;
26682831

2669-
ctx->thread_pool_size = min_t(unsigned long, num_online_cpus() + 2, 8);
2670-
ctx->max_inline = BTRFS_DEFAULT_MAX_INLINE;
2671-
ctx->commit_interval = BTRFS_DEFAULT_COMMIT_INTERVAL;
2672-
ctx->subvol_objectid = BTRFS_FS_TREE_OBJECTID;
2673-
#ifndef CONFIG_BTRFS_FS_POSIX_ACL
2674-
ctx->noacl = true;
2675-
#endif
2676-
26772832
fc->fs_private = ctx;
26782833
fc->ops = &btrfs_fs_context_ops;
26792834

2835+
if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) {
2836+
btrfs_info_to_ctx(btrfs_sb(fc->root->d_sb), ctx);
2837+
} else {
2838+
ctx->thread_pool_size =
2839+
min_t(unsigned long, num_online_cpus() + 2, 8);
2840+
ctx->max_inline = BTRFS_DEFAULT_MAX_INLINE;
2841+
ctx->commit_interval = BTRFS_DEFAULT_COMMIT_INTERVAL;
2842+
}
2843+
26802844
return 0;
26812845
}
26822846

fs/btrfs/zoned.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -781,15 +781,15 @@ int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info)
781781
* Check mount options here, because we might change fs_info->zoned
782782
* from fs_info->zone_size.
783783
*/
784-
ret = btrfs_check_mountopts_zoned(fs_info);
784+
ret = btrfs_check_mountopts_zoned(fs_info, &fs_info->mount_opt);
785785
if (ret)
786786
return ret;
787787

788788
btrfs_info(fs_info, "zoned mode enabled with zone size %llu", zone_size);
789789
return 0;
790790
}
791791

792-
int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info)
792+
int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info, unsigned long *mount_opt)
793793
{
794794
if (!btrfs_is_zoned(info))
795795
return 0;
@@ -798,18 +798,21 @@ int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info)
798798
* Space cache writing is not COWed. Disable that to avoid write errors
799799
* in sequential zones.
800800
*/
801-
if (btrfs_test_opt(info, SPACE_CACHE)) {
801+
if (btrfs_raw_test_opt(*mount_opt, SPACE_CACHE)) {
802802
btrfs_err(info, "zoned: space cache v1 is not supported");
803803
return -EINVAL;
804804
}
805805

806-
if (btrfs_test_opt(info, NODATACOW)) {
806+
if (btrfs_raw_test_opt(*mount_opt, NODATACOW)) {
807807
btrfs_err(info, "zoned: NODATACOW not supported");
808808
return -EINVAL;
809809
}
810810

811-
btrfs_clear_and_info(info, DISCARD_ASYNC,
812-
"zoned: async discard ignored and disabled for zoned mode");
811+
if (btrfs_raw_test_opt(*mount_opt, DISCARD_ASYNC)) {
812+
btrfs_info(info,
813+
"zoned: async discard ignored and disabled for zoned mode");
814+
btrfs_clear_opt(*mount_opt, DISCARD_ASYNC);
815+
}
813816

814817
return 0;
815818
}

fs/btrfs/zoned.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache);
4545
void btrfs_destroy_dev_zone_info(struct btrfs_device *device);
4646
struct btrfs_zoned_device_info *btrfs_clone_dev_zone_info(struct btrfs_device *orig_dev);
4747
int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info);
48-
int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info);
48+
int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info, unsigned long *mount_opt);
4949
int btrfs_sb_log_location_bdev(struct block_device *bdev, int mirror, int rw,
5050
u64 *bytenr_ret);
5151
int btrfs_sb_log_location(struct btrfs_device *device, int mirror, int rw,
@@ -121,7 +121,8 @@ static inline int btrfs_check_zoned_mode(const struct btrfs_fs_info *fs_info)
121121
return -EOPNOTSUPP;
122122
}
123123

124-
static inline int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info)
124+
static inline int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info,
125+
unsigned long *mount_opt)
125126
{
126127
return 0;
127128
}

0 commit comments

Comments
 (0)