btrfs-progs: mkfs: support free space tree as -R option

Add a runtime feature (-R) flag for the free space tree. A filesystem
that is mkfs'd with -R free-space-tree then mounted with no options has
the same contents as one mkfs'd without the option, then mounted with
'-o space_cache=v2'.

The only tricky thing is in exactly how to call the tree creation code.
Using btrfs_create_free_space_tree as is did not quite work, because an
extra reference to the eb (root->commit_root) is leaked, which mkfs
complains about with a warning. I opted to follow how the uuid tree is
created by adding it to the dirty roots list for cleanup by
commit_tree_roots in commit_transaction. As a result,
btrfs_create_free_space_tree no longer exactly matches the version in
the kernel sources.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Boris Burkov <boris@bur.io>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Boris Burkov 2020-09-02 11:50:49 -07:00 committed by David Sterba
parent 5011ef94ac
commit 92d92e99b7
7 changed files with 45 additions and 1 deletions

View file

@ -257,6 +257,12 @@ permanent, this does not replace mount options.
Enable quota support (qgroups). The qgroup accounting will be consistent,
can be used together with '--rootdir'. See also `btrfs-quota`(8).
*free-space-tree*::
(kernel support since 4.5)
+
Enable the free space tree (mount option space_cache=v2) for persisting the
free space cache.
BLOCK GROUPS, CHUNKS, RAID
--------------------------

View file

@ -107,6 +107,12 @@ static const struct btrfs_feature runtime_features[] = {
{ "quota", BTRFS_RUNTIME_FEATURE_QUOTA, NULL,
VERSION_TO_STRING2(3, 4), NULL, 0, NULL, 0,
"quota support (qgroups)" },
{ "free-space-tree", BTRFS_RUNTIME_FEATURE_FREE_SPACE_TREE,
"free_space_tree",
VERSION_TO_STRING2(4, 5),
VERSION_TO_STRING2(4, 9),
NULL, 0,
"free space tree (space_cache=v2)" },
/* Keep this one last */
{ "list-all", BTRFS_FEATURE_LIST_ALL, NULL }
};

View file

@ -39,7 +39,8 @@
#define BTRFS_FEATURE_LIST_ALL (1ULL << 63)
#define BTRFS_RUNTIME_FEATURE_QUOTA (1ULL << 0)
#define BTRFS_RUNTIME_FEATURE_QUOTA (1ULL << 0)
#define BTRFS_RUNTIME_FEATURE_FREE_SPACE_TREE (1ULL << 1)
void btrfs_list_all_fs_features(u64 mask_disallowed);
void btrfs_list_all_runtime_features(u64 mask_disallowed);

View file

@ -1003,10 +1003,15 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
ret = find_and_setup_root(root, fs_info, BTRFS_FREE_SPACE_TREE_OBJECTID,
fs_info->free_space_root);
if (ret) {
free(fs_info->free_space_root);
fs_info->free_space_root = NULL;
printk("Couldn't read free space tree\n");
return -EIO;
}
fs_info->free_space_root->track_dirty = 1;
} else {
free(fs_info->free_space_root);
fs_info->free_space_root = NULL;
}
ret = find_and_setup_log_root(root, fs_info, sb);

View file

@ -1433,6 +1433,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
goto abort;
}
fs_info->free_space_root = free_space_root;
add_root_to_dirty_list(free_space_root);
do {
block_group = btrfs_lookup_first_block_group(fs_info, start);

View file

@ -34,6 +34,7 @@
#include <blkid/blkid.h>
#include "kernel-shared/ctree.h"
#include "kernel-shared/disk-io.h"
#include "kernel-shared/free-space-tree.h"
#include "kernel-shared/volumes.h"
#include "kernel-shared/transaction.h"
#include "common/utils.h"
@ -1495,6 +1496,13 @@ raid_groups:
goto out;
}
}
if (runtime_features & BTRFS_RUNTIME_FEATURE_FREE_SPACE_TREE) {
ret = btrfs_create_free_space_tree(fs_info);
if (ret < 0) {
error("failed to create free space tree: %d (%m)", ret);
goto out;
}
}
if (verbose) {
char features_buf[64];

View file

@ -0,0 +1,17 @@
#!/bin/bash
# Basic check if mkfs supports the runtime feature free-space-tree
source "$TEST_TOP/common"
check_prereq mkfs.btrfs
check_prereq btrfs
setup_root_helper
prepare_test_dev
run_check_mkfs_test_dev -R free-space-tree
run_check_stdout $SUDO_HELPER "$TOP/btrfs" inspect-internal dump-super "$TEST_DEV" | \
grep -q FREE_SPACE_TREE || _fail "free space tree not created"
run_check_stdout $SUDO_HELPER "$TOP/btrfs" inspect-internal dump-super "$TEST_DEV" | \
grep -q FREE_SPACE_TREE_VALID || _fail "free space tree not valid"