aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOmar Sandoval <osandov@fb.com>2015-09-29 23:50:38 -0400
committerChris Mason <clm@fb.com>2015-12-17 15:16:47 -0500
commit70f6d82ec73c3ae2d3adc6853c5bebcd73610097 (patch)
treec9f062c00713267ecd5e2e62fc1dd41063fa1426
parent1e144fb8f4a4d6d6d88c58f87e4366e3cd02ab72 (diff)
Btrfs: add free space tree mount option
Now we can finally hook up everything so we can actually use free space tree. The free space tree is enabled by passing the space_cache=v2 mount option. On the first mount with the this option set, the free space tree will be created and the FREE_SPACE_TREE read-only compat bit will be set. Any time the filesystem is mounted from then on, we must use the free space tree. The clear_cache option will also clear the free space tree. Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r--fs/btrfs/ctree.h7
-rw-r--r--fs/btrfs/disk-io.c38
-rw-r--r--fs/btrfs/super.c53
3 files changed, 88 insertions, 10 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 0888c3e2cc7d..ed610f9c04b2 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -531,7 +531,10 @@ struct btrfs_super_block {
531#define BTRFS_FEATURE_COMPAT_SUPP 0ULL 531#define BTRFS_FEATURE_COMPAT_SUPP 0ULL
532#define BTRFS_FEATURE_COMPAT_SAFE_SET 0ULL 532#define BTRFS_FEATURE_COMPAT_SAFE_SET 0ULL
533#define BTRFS_FEATURE_COMPAT_SAFE_CLEAR 0ULL 533#define BTRFS_FEATURE_COMPAT_SAFE_CLEAR 0ULL
534#define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL 534
535#define BTRFS_FEATURE_COMPAT_RO_SUPP \
536 (BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE)
537
535#define BTRFS_FEATURE_COMPAT_RO_SAFE_SET 0ULL 538#define BTRFS_FEATURE_COMPAT_RO_SAFE_SET 0ULL
536#define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR 0ULL 539#define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR 0ULL
537 540
@@ -2203,6 +2206,7 @@ struct btrfs_ioctl_defrag_range_args {
2203#define BTRFS_MOUNT_CHECK_INTEGRITY_INCLUDING_EXTENT_DATA (1 << 21) 2206#define BTRFS_MOUNT_CHECK_INTEGRITY_INCLUDING_EXTENT_DATA (1 << 21)
2204#define BTRFS_MOUNT_PANIC_ON_FATAL_ERROR (1 << 22) 2207#define BTRFS_MOUNT_PANIC_ON_FATAL_ERROR (1 << 22)
2205#define BTRFS_MOUNT_RESCAN_UUID_TREE (1 << 23) 2208#define BTRFS_MOUNT_RESCAN_UUID_TREE (1 << 23)
2209#define BTRFS_MOUNT_FREE_SPACE_TREE (1 << 24)
2206 2210
2207#define BTRFS_DEFAULT_COMMIT_INTERVAL (30) 2211#define BTRFS_DEFAULT_COMMIT_INTERVAL (30)
2208#define BTRFS_DEFAULT_MAX_INLINE (8192) 2212#define BTRFS_DEFAULT_MAX_INLINE (8192)
@@ -3744,6 +3748,7 @@ static inline void free_fs_info(struct btrfs_fs_info *fs_info)
3744 kfree(fs_info->csum_root); 3748 kfree(fs_info->csum_root);
3745 kfree(fs_info->quota_root); 3749 kfree(fs_info->quota_root);
3746 kfree(fs_info->uuid_root); 3750 kfree(fs_info->uuid_root);
3751 kfree(fs_info->free_space_root);
3747 kfree(fs_info->super_copy); 3752 kfree(fs_info->super_copy);
3748 kfree(fs_info->super_for_commit); 3753 kfree(fs_info->super_for_commit);
3749 security_free_mnt_opts(&fs_info->security_opts); 3754 security_free_mnt_opts(&fs_info->security_opts);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 1e60d00d4ea7..af7ac28380c2 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -42,6 +42,7 @@
42#include "locking.h" 42#include "locking.h"
43#include "tree-log.h" 43#include "tree-log.h"
44#include "free-space-cache.h" 44#include "free-space-cache.h"
45#include "free-space-tree.h"
45#include "inode-map.h" 46#include "inode-map.h"
46#include "check-integrity.h" 47#include "check-integrity.h"
47#include "rcu-string.h" 48#include "rcu-string.h"
@@ -1647,6 +1648,9 @@ struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
1647 if (location->objectid == BTRFS_UUID_TREE_OBJECTID) 1648 if (location->objectid == BTRFS_UUID_TREE_OBJECTID)
1648 return fs_info->uuid_root ? fs_info->uuid_root : 1649 return fs_info->uuid_root ? fs_info->uuid_root :
1649 ERR_PTR(-ENOENT); 1650 ERR_PTR(-ENOENT);
1651 if (location->objectid == BTRFS_FREE_SPACE_TREE_OBJECTID)
1652 return fs_info->free_space_root ? fs_info->free_space_root :
1653 ERR_PTR(-ENOENT);
1650again: 1654again:
1651 root = btrfs_lookup_fs_root(fs_info, location->objectid); 1655 root = btrfs_lookup_fs_root(fs_info, location->objectid);
1652 if (root) { 1656 if (root) {
@@ -2144,6 +2148,7 @@ static void free_root_pointers(struct btrfs_fs_info *info, int chunk_root)
2144 free_root_extent_buffers(info->uuid_root); 2148 free_root_extent_buffers(info->uuid_root);
2145 if (chunk_root) 2149 if (chunk_root)
2146 free_root_extent_buffers(info->chunk_root); 2150 free_root_extent_buffers(info->chunk_root);
2151 free_root_extent_buffers(info->free_space_root);
2147} 2152}
2148 2153
2149void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info) 2154void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info)
@@ -2445,6 +2450,15 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info,
2445 fs_info->uuid_root = root; 2450 fs_info->uuid_root = root;
2446 } 2451 }
2447 2452
2453 if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
2454 location.objectid = BTRFS_FREE_SPACE_TREE_OBJECTID;
2455 root = btrfs_read_tree_root(tree_root, &location);
2456 if (IS_ERR(root))
2457 return PTR_ERR(root);
2458 set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
2459 fs_info->free_space_root = root;
2460 }
2461
2448 return 0; 2462 return 0;
2449} 2463}
2450 2464
@@ -3073,6 +3087,30 @@ retry_root_backup:
3073 3087
3074 btrfs_qgroup_rescan_resume(fs_info); 3088 btrfs_qgroup_rescan_resume(fs_info);
3075 3089
3090 if (btrfs_test_opt(tree_root, CLEAR_CACHE) &&
3091 btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
3092 pr_info("BTRFS: clearing free space tree\n");
3093 ret = btrfs_clear_free_space_tree(fs_info);
3094 if (ret) {
3095 pr_warn("BTRFS: failed to clear free space tree %d\n",
3096 ret);
3097 close_ctree(tree_root);
3098 return ret;
3099 }
3100 }
3101
3102 if (btrfs_test_opt(tree_root, FREE_SPACE_TREE) &&
3103 !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
3104 pr_info("BTRFS: creating free space tree\n");
3105 ret = btrfs_create_free_space_tree(fs_info);
3106 if (ret) {
3107 pr_warn("BTRFS: failed to create free space tree %d\n",
3108 ret);
3109 close_ctree(tree_root);
3110 return ret;
3111 }
3112 }
3113
3076 if (!fs_info->uuid_root) { 3114 if (!fs_info->uuid_root) {
3077 pr_info("BTRFS: creating UUID tree\n"); 3115 pr_info("BTRFS: creating UUID tree\n");
3078 ret = btrfs_create_uuid_tree(fs_info); 3116 ret = btrfs_create_uuid_tree(fs_info);
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 442bf434b783..bfdaf123f4e9 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -312,10 +312,11 @@ enum {
312 Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, Opt_compress, 312 Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, Opt_compress,
313 Opt_compress_type, Opt_compress_force, Opt_compress_force_type, 313 Opt_compress_type, Opt_compress_force, Opt_compress_force_type,
314 Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard, 314 Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard,
315 Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed, 315 Opt_space_cache, Opt_space_cache_version, Opt_clear_cache,
316 Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_inode_cache, 316 Opt_user_subvol_rm_allowed, Opt_enospc_debug, Opt_subvolrootid,
317 Opt_no_space_cache, Opt_recovery, Opt_skip_balance, 317 Opt_defrag, Opt_inode_cache, Opt_no_space_cache, Opt_recovery,
318 Opt_check_integrity, Opt_check_integrity_including_extent_data, 318 Opt_skip_balance, Opt_check_integrity,
319 Opt_check_integrity_including_extent_data,
319 Opt_check_integrity_print_mask, Opt_fatal_errors, Opt_rescan_uuid_tree, 320 Opt_check_integrity_print_mask, Opt_fatal_errors, Opt_rescan_uuid_tree,
320 Opt_commit_interval, Opt_barrier, Opt_nodefrag, Opt_nodiscard, 321 Opt_commit_interval, Opt_barrier, Opt_nodefrag, Opt_nodiscard,
321 Opt_noenospc_debug, Opt_noflushoncommit, Opt_acl, Opt_datacow, 322 Opt_noenospc_debug, Opt_noflushoncommit, Opt_acl, Opt_datacow,
@@ -354,6 +355,7 @@ static match_table_t tokens = {
354 {Opt_discard, "discard"}, 355 {Opt_discard, "discard"},
355 {Opt_nodiscard, "nodiscard"}, 356 {Opt_nodiscard, "nodiscard"},
356 {Opt_space_cache, "space_cache"}, 357 {Opt_space_cache, "space_cache"},
358 {Opt_space_cache_version, "space_cache=%s"},
357 {Opt_clear_cache, "clear_cache"}, 359 {Opt_clear_cache, "clear_cache"},
358 {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"}, 360 {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"},
359 {Opt_enospc_debug, "enospc_debug"}, 361 {Opt_enospc_debug, "enospc_debug"},
@@ -392,7 +394,9 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
392 bool compress_force = false; 394 bool compress_force = false;
393 395
394 cache_gen = btrfs_super_cache_generation(root->fs_info->super_copy); 396 cache_gen = btrfs_super_cache_generation(root->fs_info->super_copy);
395 if (cache_gen) 397 if (btrfs_fs_compat_ro(root->fs_info, FREE_SPACE_TREE))
398 btrfs_set_opt(info->mount_opt, FREE_SPACE_TREE);
399 else if (cache_gen)
396 btrfs_set_opt(info->mount_opt, SPACE_CACHE); 400 btrfs_set_opt(info->mount_opt, SPACE_CACHE);
397 401
398 if (!options) 402 if (!options)
@@ -626,15 +630,35 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
626 "turning off discard"); 630 "turning off discard");
627 break; 631 break;
628 case Opt_space_cache: 632 case Opt_space_cache:
629 btrfs_set_and_info(root, SPACE_CACHE, 633 case Opt_space_cache_version:
630 "enabling disk space caching"); 634 if (token == Opt_space_cache ||
635 strcmp(args[0].from, "v1") == 0) {
636 btrfs_clear_opt(root->fs_info->mount_opt,
637 FREE_SPACE_TREE);
638 btrfs_set_and_info(root, SPACE_CACHE,
639 "enabling disk space caching");
640 } else if (strcmp(args[0].from, "v2") == 0) {
641 btrfs_clear_opt(root->fs_info->mount_opt,
642 SPACE_CACHE);
643 btrfs_set_and_info(root, FREE_SPACE_TREE,
644 "enabling free space tree");
645 } else {
646 ret = -EINVAL;
647 goto out;
648 }
631 break; 649 break;
632 case Opt_rescan_uuid_tree: 650 case Opt_rescan_uuid_tree:
633 btrfs_set_opt(info->mount_opt, RESCAN_UUID_TREE); 651 btrfs_set_opt(info->mount_opt, RESCAN_UUID_TREE);
634 break; 652 break;
635 case Opt_no_space_cache: 653 case Opt_no_space_cache:
636 btrfs_clear_and_info(root, SPACE_CACHE, 654 if (btrfs_test_opt(root, SPACE_CACHE)) {
637 "disabling disk space caching"); 655 btrfs_clear_and_info(root, SPACE_CACHE,
656 "disabling disk space caching");
657 }
658 if (btrfs_test_opt(root, FREE_SPACE_TREE)) {
659 btrfs_clear_and_info(root, FREE_SPACE_TREE,
660 "disabling free space tree");
661 }
638 break; 662 break;
639 case Opt_inode_cache: 663 case Opt_inode_cache:
640 btrfs_set_pending_and_info(info, INODE_MAP_CACHE, 664 btrfs_set_pending_and_info(info, INODE_MAP_CACHE,
@@ -747,8 +771,17 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
747 } 771 }
748 } 772 }
749out: 773out:
774 if (btrfs_fs_compat_ro(root->fs_info, FREE_SPACE_TREE) &&
775 !btrfs_test_opt(root, FREE_SPACE_TREE) &&
776 !btrfs_test_opt(root, CLEAR_CACHE)) {
777 btrfs_err(root->fs_info, "cannot disable free space tree");
778 ret = -EINVAL;
779
780 }
750 if (!ret && btrfs_test_opt(root, SPACE_CACHE)) 781 if (!ret && btrfs_test_opt(root, SPACE_CACHE))
751 btrfs_info(root->fs_info, "disk space caching is enabled"); 782 btrfs_info(root->fs_info, "disk space caching is enabled");
783 if (!ret && btrfs_test_opt(root, FREE_SPACE_TREE))
784 btrfs_info(root->fs_info, "using free space tree");
752 kfree(orig); 785 kfree(orig);
753 return ret; 786 return ret;
754} 787}
@@ -1155,6 +1188,8 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
1155 seq_puts(seq, ",noacl"); 1188 seq_puts(seq, ",noacl");
1156 if (btrfs_test_opt(root, SPACE_CACHE)) 1189 if (btrfs_test_opt(root, SPACE_CACHE))
1157 seq_puts(seq, ",space_cache"); 1190 seq_puts(seq, ",space_cache");
1191 else if (btrfs_test_opt(root, FREE_SPACE_TREE))
1192 seq_puts(seq, ",space_cache=v2");
1158 else 1193 else
1159 seq_puts(seq, ",nospace_cache"); 1194 seq_puts(seq, ",nospace_cache");
1160 if (btrfs_test_opt(root, RESCAN_UUID_TREE)) 1195 if (btrfs_test_opt(root, RESCAN_UUID_TREE))