@@ -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 }
13441346out :
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) */
23822544static 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
26562818static 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
0 commit comments