@@ -725,46 +725,48 @@ static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
725
725
return 0 ;
726
726
}
727
727
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 ,
729
730
const char * opt_name )
730
731
{
731
- if (fs_info -> mount_opt & opt ) {
732
+ if (mount_opt & opt ) {
732
733
btrfs_err (fs_info , "%s must be used with ro mount option" ,
733
734
opt_name );
734
735
return true;
735
736
}
736
737
return false;
737
738
}
738
739
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 )
740
742
{
741
743
bool ret = true;
742
744
743
745
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" )))
747
749
ret = false;
748
750
749
751
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 )) {
752
754
btrfs_err (info , "cannot disable free-space-tree" );
753
755
ret = false;
754
756
}
755
757
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 )) {
757
759
btrfs_err (info , "cannot disable free-space-tree with block-group-tree feature" );
758
760
ret = false;
759
761
}
760
762
761
- if (btrfs_check_mountopts_zoned (info ))
763
+ if (btrfs_check_mountopts_zoned (info , mount_opt ))
762
764
ret = false;
763
765
764
766
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 ))
766
768
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 ))
768
770
btrfs_info (info , "using free-space-tree" );
769
771
}
770
772
@@ -1342,7 +1344,7 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
1342
1344
}
1343
1345
}
1344
1346
out :
1345
- if (!ret && !check_options (info , new_flags ))
1347
+ if (!ret && !check_options (info , & info -> mount_opt , new_flags ))
1346
1348
ret = - EINVAL ;
1347
1349
return ret ;
1348
1350
}
@@ -2378,6 +2380,166 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
2378
2380
return ret ;
2379
2381
}
2380
2382
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
+
2381
2543
/* Used to sort the devices by max_avail(descending sort) */
2382
2544
static int btrfs_cmp_device_free_bytes (const void * a , const void * b )
2383
2545
{
@@ -2655,6 +2817,7 @@ static void btrfs_free_fs_context(struct fs_context *fc)
2655
2817
2656
2818
static const struct fs_context_operations btrfs_fs_context_ops = {
2657
2819
.parse_param = btrfs_parse_param ,
2820
+ .reconfigure = btrfs_reconfigure ,
2658
2821
.free = btrfs_free_fs_context ,
2659
2822
};
2660
2823
@@ -2666,17 +2829,18 @@ static int __maybe_unused btrfs_init_fs_context(struct fs_context *fc)
2666
2829
if (!ctx )
2667
2830
return - ENOMEM ;
2668
2831
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
-
2677
2832
fc -> fs_private = ctx ;
2678
2833
fc -> ops = & btrfs_fs_context_ops ;
2679
2834
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
+
2680
2844
return 0 ;
2681
2845
}
2682
2846
0 commit comments