* [PATCH v3 1/7] btrfs-progs: Refactor excluded extent functions to use fs_info
2019-10-10 6:41 [PATCH v3 0/7] btrfs-progs: Support for BG_TREE feature Qu Wenruo
@ 2019-10-10 6:41 ` Qu Wenruo
2019-10-10 6:41 ` [PATCH v3 2/7] btrfs-progs: Refactor btrfs_read_block_groups() Qu Wenruo
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2019-10-10 6:41 UTC (permalink / raw)
To: linux-btrfs; +Cc: Johannes Thumshirn
The following functions are just using @root to reach fs_info:
- exclude_super_stripes
- free_excluded_extents
- add_excluded_extent
Refactor them to use fs_info directly.
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
---
check/main.c | 4 ++--
ctree.h | 4 ++--
extent-tree.c | 20 ++++++++++----------
3 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/check/main.c b/check/main.c
index c2d0f3949c5e..94ffab46cb70 100644
--- a/check/main.c
+++ b/check/main.c
@@ -5552,7 +5552,7 @@ static int check_space_cache(struct btrfs_root *root)
}
if (btrfs_fs_compat_ro(root->fs_info, FREE_SPACE_TREE)) {
- ret = exclude_super_stripes(root, cache);
+ ret = exclude_super_stripes(root->fs_info, cache);
if (ret) {
errno = -ret;
fprintf(stderr,
@@ -5561,7 +5561,7 @@ static int check_space_cache(struct btrfs_root *root)
continue;
}
ret = load_free_space_tree(root->fs_info, cache);
- free_excluded_extents(root, cache);
+ free_excluded_extents(root->fs_info, cache);
if (ret < 0) {
errno = -ret;
fprintf(stderr,
diff --git a/ctree.h b/ctree.h
index 0d12563b7261..8c7b3cb40151 100644
--- a/ctree.h
+++ b/ctree.h
@@ -2568,9 +2568,9 @@ int btrfs_record_file_extent(struct btrfs_trans_handle *trans,
u64 num_bytes);
int btrfs_free_block_group(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info, u64 bytenr, u64 len);
-void free_excluded_extents(struct btrfs_root *root,
+void free_excluded_extents(struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache);
-int exclude_super_stripes(struct btrfs_root *root,
+int exclude_super_stripes(struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache);
u64 add_new_free_space(struct btrfs_block_group_cache *block_group,
struct btrfs_fs_info *info, u64 start, u64 end);
diff --git a/extent-tree.c b/extent-tree.c
index 932af2c644bd..19d1ea0df570 100644
--- a/extent-tree.c
+++ b/extent-tree.c
@@ -2716,7 +2716,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
if (btrfs_chunk_readonly(info, cache->key.objectid))
cache->ro = 1;
- exclude_super_stripes(root, cache);
+ exclude_super_stripes(info, cache);
ret = update_space_info(info, cache->flags, found_key.offset,
btrfs_block_group_used(&cache->item),
@@ -2760,7 +2760,7 @@ btrfs_add_block_group(struct btrfs_fs_info *fs_info, u64 bytes_used, u64 type,
cache->flags = type;
btrfs_set_block_group_flags(&cache->item, type);
- exclude_super_stripes(fs_info->extent_root, cache);
+ exclude_super_stripes(fs_info, cache);
ret = update_space_info(fs_info, cache->flags, size, bytes_used,
&cache->space_info);
BUG_ON(ret);
@@ -3551,16 +3551,16 @@ int btrfs_record_file_extent(struct btrfs_trans_handle *trans,
}
-static int add_excluded_extent(struct btrfs_root *root,
+static int add_excluded_extent(struct btrfs_fs_info *fs_info,
u64 start, u64 num_bytes)
{
u64 end = start + num_bytes - 1;
- set_extent_bits(&root->fs_info->pinned_extents,
+ set_extent_bits(&fs_info->pinned_extents,
start, end, EXTENT_UPTODATE);
return 0;
}
-void free_excluded_extents(struct btrfs_root *root,
+void free_excluded_extents(struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache)
{
u64 start, end;
@@ -3568,11 +3568,11 @@ void free_excluded_extents(struct btrfs_root *root,
start = cache->key.objectid;
end = start + cache->key.offset - 1;
- clear_extent_bits(&root->fs_info->pinned_extents,
+ clear_extent_bits(&fs_info->pinned_extents,
start, end, EXTENT_UPTODATE);
}
-int exclude_super_stripes(struct btrfs_root *root,
+int exclude_super_stripes(struct btrfs_fs_info *fs_info,
struct btrfs_block_group_cache *cache)
{
u64 bytenr;
@@ -3583,7 +3583,7 @@ int exclude_super_stripes(struct btrfs_root *root,
if (cache->key.objectid < BTRFS_SUPER_INFO_OFFSET) {
stripe_len = BTRFS_SUPER_INFO_OFFSET - cache->key.objectid;
cache->bytes_super += stripe_len;
- ret = add_excluded_extent(root, cache->key.objectid,
+ ret = add_excluded_extent(fs_info, cache->key.objectid,
stripe_len);
if (ret)
return ret;
@@ -3591,7 +3591,7 @@ int exclude_super_stripes(struct btrfs_root *root,
for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
bytenr = btrfs_sb_offset(i);
- ret = btrfs_rmap_block(root->fs_info,
+ ret = btrfs_rmap_block(fs_info,
cache->key.objectid, bytenr,
&logical, &nr, &stripe_len);
if (ret)
@@ -3618,7 +3618,7 @@ int exclude_super_stripes(struct btrfs_root *root,
}
cache->bytes_super += len;
- ret = add_excluded_extent(root, start, len);
+ ret = add_excluded_extent(fs_info, start, len);
if (ret) {
kfree(logical);
return ret;
--
2.23.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 2/7] btrfs-progs: Refactor btrfs_read_block_groups()
2019-10-10 6:41 [PATCH v3 0/7] btrfs-progs: Support for BG_TREE feature Qu Wenruo
2019-10-10 6:41 ` [PATCH v3 1/7] btrfs-progs: Refactor excluded extent functions to use fs_info Qu Wenruo
@ 2019-10-10 6:41 ` Qu Wenruo
2019-10-10 6:41 ` [PATCH v3 3/7] btrfs-progs: Enable read-write ability for 'bg_tree' feature Qu Wenruo
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2019-10-10 6:41 UTC (permalink / raw)
To: linux-btrfs
This patch does the following refactor:
- Refactor parameter from @root to @fs_info
- Refactor the large loop body into another function
Now we have a helper function, read_one_block_group(), to handle
block group cache and space info related routine.
- Refactor the return value
Even we have the code handling ret > 0 from find_first_block_group(),
it never works, as when there is no more block group,
find_first_block_group() just return -ENOENT other than 1.
This is super confusing, it's almost a mircle it even works.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
ctree.h | 2 +-
disk-io.c | 9 ++-
extent-tree.c | 160 ++++++++++++++++++++++++++++----------------------
3 files changed, 97 insertions(+), 74 deletions(-)
diff --git a/ctree.h b/ctree.h
index 8c7b3cb40151..2899de358613 100644
--- a/ctree.h
+++ b/ctree.h
@@ -2550,7 +2550,7 @@ int update_space_info(struct btrfs_fs_info *info, u64 flags,
u64 total_bytes, u64 bytes_used,
struct btrfs_space_info **space_info);
int btrfs_free_block_groups(struct btrfs_fs_info *info);
-int btrfs_read_block_groups(struct btrfs_root *root);
+int btrfs_read_block_groups(struct btrfs_fs_info *info);
struct btrfs_block_group_cache *
btrfs_add_block_group(struct btrfs_fs_info *fs_info, u64 bytes_used, u64 type,
u64 chunk_offset, u64 size);
diff --git a/disk-io.c b/disk-io.c
index be44eead5cef..8978f0cb60c7 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -983,14 +983,17 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
fs_info->last_trans_committed = generation;
if (extent_buffer_uptodate(fs_info->extent_root->node) &&
!(flags & OPEN_CTREE_NO_BLOCK_GROUPS)) {
- ret = btrfs_read_block_groups(fs_info->tree_root);
+ ret = btrfs_read_block_groups(fs_info);
/*
* If we don't find any blockgroups (ENOENT) we're either
* restoring or creating the filesystem, where it's expected,
* anything else is error
*/
- if (ret != -ENOENT)
- return -EIO;
+ if (ret < 0 && ret != -ENOENT) {
+ errno = -ret;
+ error("failed to read block groups: %m");
+ return ret;
+ }
}
key.objectid = BTRFS_FS_TREE_OBJECTID;
diff --git a/extent-tree.c b/extent-tree.c
index 19d1ea0df570..9713d627764c 100644
--- a/extent-tree.c
+++ b/extent-tree.c
@@ -2607,6 +2607,13 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
return 0;
}
+/*
+ * Find a block group which starts >= @key->objectid in extent tree.
+ *
+ * Return 0 for found
+ * Retrun >0 for not found
+ * Return <0 for error
+ */
static int find_first_block_group(struct btrfs_root *root,
struct btrfs_path *path, struct btrfs_key *key)
{
@@ -2636,36 +2643,95 @@ static int find_first_block_group(struct btrfs_root *root,
return 0;
path->slots[0]++;
}
- ret = -ENOENT;
+ ret = 1;
error:
return ret;
}
-int btrfs_read_block_groups(struct btrfs_root *root)
+/*
+ * Helper function to read out one BLOCK_GROUP_ITEM and insert it into
+ * block group cache.
+ *
+ * Return 0 if nothing wrong (either insert the bg cache or skip 0 sized bg)
+ * Return <0 for error.
+ */
+static int read_one_block_group(struct btrfs_fs_info *fs_info,
+ struct btrfs_path *path)
{
- struct btrfs_path *path;
- int ret;
- int bit;
- struct btrfs_block_group_cache *cache;
- struct btrfs_fs_info *info = root->fs_info;
+ struct extent_io_tree *block_group_cache = &fs_info->block_group_cache;
+ struct extent_buffer *leaf = path->nodes[0];
struct btrfs_space_info *space_info;
- struct extent_io_tree *block_group_cache;
+ struct btrfs_block_group_cache *cache;
struct btrfs_key key;
- struct btrfs_key found_key;
- struct extent_buffer *leaf;
+ int slot = path->slots[0];
+ int bit = 0;
+ int ret;
- block_group_cache = &info->block_group_cache;
+ btrfs_item_key_to_cpu(leaf, &key, slot);
+ ASSERT(key.type == BTRFS_BLOCK_GROUP_ITEM_KEY);
+
+ /*
+ * Skip 0 sized block group, don't insert them into block
+ * group cache tree, as its length is 0, it won't get
+ * freed at close_ctree() time.
+ */
+ if (key.offset == 0)
+ return 0;
+
+ cache = kzalloc(sizeof(*cache), GFP_NOFS);
+ if (!cache)
+ return -ENOMEM;
+ read_extent_buffer(leaf, &cache->item,
+ btrfs_item_ptr_offset(leaf, slot),
+ sizeof(cache->item));
+ memcpy(&cache->key, &key, sizeof(key));
+ cache->cached = 0;
+ cache->pinned = 0;
+ cache->flags = btrfs_block_group_flags(&cache->item);
+ if (cache->flags & BTRFS_BLOCK_GROUP_DATA) {
+ bit = BLOCK_GROUP_DATA;
+ } else if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) {
+ bit = BLOCK_GROUP_SYSTEM;
+ } else if (cache->flags & BTRFS_BLOCK_GROUP_METADATA) {
+ bit = BLOCK_GROUP_METADATA;
+ }
+ set_avail_alloc_bits(fs_info, cache->flags);
+ if (btrfs_chunk_readonly(fs_info, cache->key.objectid))
+ cache->ro = 1;
+ exclude_super_stripes(fs_info, cache);
+
+ ret = update_space_info(fs_info, cache->flags, cache->key.offset,
+ btrfs_block_group_used(&cache->item),
+ &space_info);
+ if (ret < 0) {
+ free(cache);
+ return ret;
+ }
+ cache->space_info = space_info;
+
+ set_extent_bits(block_group_cache, cache->key.objectid,
+ cache->key.objectid + cache->key.offset - 1,
+ bit | EXTENT_LOCKED);
+ set_state_private(block_group_cache, cache->key.objectid,
+ (unsigned long)cache);
+ return 0;
+}
- root = info->extent_root;
+int btrfs_read_block_groups(struct btrfs_fs_info *fs_info)
+{
+ struct btrfs_path path;
+ struct btrfs_root *root;
+ int ret;
+ struct btrfs_key key;
+
+ root = fs_info->extent_root;
key.objectid = 0;
key.offset = 0;
key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
- path = btrfs_alloc_path();
- if (!path)
- return -ENOMEM;
+ btrfs_init_path(&path);
while(1) {
- ret = find_first_block_group(root, path, &key);
+ ret = find_first_block_group(root, &path, &key);
if (ret > 0) {
ret = 0;
goto error;
@@ -2673,67 +2739,21 @@ int btrfs_read_block_groups(struct btrfs_root *root)
if (ret != 0) {
goto error;
}
- leaf = path->nodes[0];
- btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
+ btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
- cache = kzalloc(sizeof(*cache), GFP_NOFS);
- if (!cache) {
- ret = -ENOMEM;
+ ret = read_one_block_group(fs_info, &path);
+ if (ret < 0)
goto error;
- }
- read_extent_buffer(leaf, &cache->item,
- btrfs_item_ptr_offset(leaf, path->slots[0]),
- sizeof(cache->item));
- memcpy(&cache->key, &found_key, sizeof(found_key));
- cache->cached = 0;
- cache->pinned = 0;
- key.objectid = found_key.objectid + found_key.offset;
- if (found_key.offset == 0)
+ if (key.offset == 0)
key.objectid++;
- btrfs_release_path(path);
-
- /*
- * Skip 0 sized block group, don't insert them into block
- * group cache tree, as its length is 0, it won't get
- * freed at close_ctree() time.
- */
- if (found_key.offset == 0) {
- free(cache);
- continue;
- }
-
- cache->flags = btrfs_block_group_flags(&cache->item);
- bit = 0;
- if (cache->flags & BTRFS_BLOCK_GROUP_DATA) {
- bit = BLOCK_GROUP_DATA;
- } else if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) {
- bit = BLOCK_GROUP_SYSTEM;
- } else if (cache->flags & BTRFS_BLOCK_GROUP_METADATA) {
- bit = BLOCK_GROUP_METADATA;
- }
- set_avail_alloc_bits(info, cache->flags);
- if (btrfs_chunk_readonly(info, cache->key.objectid))
- cache->ro = 1;
-
- exclude_super_stripes(info, cache);
-
- ret = update_space_info(info, cache->flags, found_key.offset,
- btrfs_block_group_used(&cache->item),
- &space_info);
- BUG_ON(ret);
- cache->space_info = space_info;
-
- /* use EXTENT_LOCKED to prevent merging */
- set_extent_bits(block_group_cache, found_key.objectid,
- found_key.objectid + found_key.offset - 1,
- bit | EXTENT_LOCKED);
- set_state_private(block_group_cache, found_key.objectid,
- (unsigned long)cache);
+ else
+ key.objectid = key.objectid + key.offset;
+ btrfs_release_path(&path);
}
ret = 0;
error:
- btrfs_free_path(path);
+ btrfs_release_path(&path);
return ret;
}
--
2.23.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 3/7] btrfs-progs: Enable read-write ability for 'bg_tree' feature
2019-10-10 6:41 [PATCH v3 0/7] btrfs-progs: Support for BG_TREE feature Qu Wenruo
2019-10-10 6:41 ` [PATCH v3 1/7] btrfs-progs: Refactor excluded extent functions to use fs_info Qu Wenruo
2019-10-10 6:41 ` [PATCH v3 2/7] btrfs-progs: Refactor btrfs_read_block_groups() Qu Wenruo
@ 2019-10-10 6:41 ` Qu Wenruo
2019-10-10 6:41 ` [PATCH v3 4/7] btrfs-progs: mkfs: Introduce -O bg-tree Qu Wenruo
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2019-10-10 6:41 UTC (permalink / raw)
To: linux-btrfs
Allow btrfs-progs to open, read and write 'bg_tree' enabled fs.
The modification itself is not large, as block groups items are only
used at 4 timing:
1) open_ctree()
We only need to populate fs_info->bg_root and read block group items
from fs_info->bg_root.
The obvious change is, we don't need to do btrfs_search_slot() for
each block group item, but btrfs_next_item() is enough.
This should hugely reduce open_ctree() execution duration.
2) btrfs_commit_transaction()
We need to write back dirty block group items back to bg_root.
The modification here is to insert new block group item if we can't
find one existing in bg_root, and delete the old one in extent tree
if we're converting to bg_tree feature.
3) btrfs_make_block_group()
Just change @root for btrfs_insert_item() from @extent_root to
@bg_root for fs with that feature.
This modification needs extra handling for converting case, where
block group items can be either in extent tree or bg tree.
4) free_block_group_item()
Just delete the block group item in extent tree.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
ctree.h | 11 +++-
disk-io.c | 20 +++++++
extent-tree.c | 152 +++++++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 168 insertions(+), 15 deletions(-)
diff --git a/ctree.h b/ctree.h
index 2899de358613..c2a18c8ab72f 100644
--- a/ctree.h
+++ b/ctree.h
@@ -89,6 +89,9 @@ struct btrfs_free_space_ctl;
/* tracks free space in block groups. */
#define BTRFS_FREE_SPACE_TREE_OBJECTID 10ULL
+/* store BLOCK_GROUP_ITEMS in a seperate tree */
+#define BTRFS_BLOCK_GROUP_TREE_OBJECTID 11ULL
+
/* device stats in the device tree */
#define BTRFS_DEV_STATS_OBJECTID 0ULL
@@ -490,6 +493,7 @@ struct btrfs_super_block {
#define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8)
#define BTRFS_FEATURE_INCOMPAT_NO_HOLES (1ULL << 9)
#define BTRFS_FEATURE_INCOMPAT_METADATA_UUID (1ULL << 10)
+#define BTRFS_FEATURE_INCOMPAT_BG_TREE (1ULL << 11)
#define BTRFS_FEATURE_COMPAT_SUPP 0ULL
@@ -513,7 +517,8 @@ struct btrfs_super_block {
BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS | \
BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA | \
BTRFS_FEATURE_INCOMPAT_NO_HOLES | \
- BTRFS_FEATURE_INCOMPAT_METADATA_UUID)
+ BTRFS_FEATURE_INCOMPAT_METADATA_UUID | \
+ BTRFS_FEATURE_INCOMPAT_BG_TREE)
/*
* A leaf is full of items. offset and size tell us where to find
@@ -1123,6 +1128,7 @@ struct btrfs_fs_info {
struct btrfs_root *quota_root;
struct btrfs_root *free_space_root;
struct btrfs_root *uuid_root;
+ struct btrfs_root *bg_root;
struct rb_root fs_root_tree;
@@ -1175,6 +1181,9 @@ struct btrfs_fs_info {
unsigned int avoid_sys_chunk_alloc:1;
unsigned int finalize_on_close:1;
+ /* Converting from bg in extent tree to bg tree */
+ unsigned int convert_to_bg_tree:1;
+
int transaction_aborted;
int (*free_extent_hook)(struct btrfs_fs_info *fs_info,
diff --git a/disk-io.c b/disk-io.c
index 8978f0cb60c7..38248aa895b8 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -716,6 +716,8 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
if (location->objectid == BTRFS_FREE_SPACE_TREE_OBJECTID)
return fs_info->free_space_root ? fs_info->free_space_root :
ERR_PTR(-ENOENT);
+ if (location->objectid == BTRFS_BLOCK_GROUP_TREE_OBJECTID)
+ return fs_info->bg_root ? fs_info->bg_root : ERR_PTR(-ENOENT);
BUG_ON(location->objectid == BTRFS_TREE_RELOC_OBJECTID ||
location->offset != (u64)-1);
@@ -768,6 +770,7 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
fs_info->quota_root = calloc(1, sizeof(struct btrfs_root));
fs_info->free_space_root = calloc(1, sizeof(struct btrfs_root));
fs_info->uuid_root = calloc(1, sizeof(struct btrfs_root));
+ fs_info->bg_root = calloc(1, sizeof(struct btrfs_root));
fs_info->super_copy = calloc(1, BTRFS_SUPER_INFO_SIZE);
if (!fs_info->tree_root || !fs_info->extent_root ||
@@ -930,6 +933,21 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
return ret;
fs_info->extent_root->track_dirty = 1;
+ if (btrfs_fs_incompat(fs_info, BG_TREE)) {
+ ret = setup_root_or_create_block(fs_info, flags,
+ fs_info->bg_root,
+ BTRFS_BLOCK_GROUP_TREE_OBJECTID, "bg");
+ if (ret < 0) {
+ error("Couldn't setup bg tree");
+ return ret;
+ }
+ fs_info->bg_root->track_dirty = 1;
+ fs_info->bg_root->ref_cows = 0;
+ } else {
+ free(fs_info->bg_root);
+ fs_info->bg_root = NULL;
+ }
+
ret = find_and_setup_root(root, fs_info, BTRFS_DEV_TREE_OBJECTID,
fs_info->dev_root);
if (ret) {
@@ -1012,6 +1030,8 @@ void btrfs_release_all_roots(struct btrfs_fs_info *fs_info)
free_extent_buffer(fs_info->free_space_root->node);
if (fs_info->quota_root)
free_extent_buffer(fs_info->quota_root->node);
+ if (fs_info->bg_root)
+ free_extent_buffer(fs_info->bg_root->node);
if (fs_info->csum_root)
free_extent_buffer(fs_info->csum_root->node);
if (fs_info->dev_root)
diff --git a/extent-tree.c b/extent-tree.c
index 9713d627764c..cb3d7a1add0f 100644
--- a/extent-tree.c
+++ b/extent-tree.c
@@ -1528,22 +1528,68 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
struct btrfs_path *path,
struct btrfs_block_group_cache *cache)
{
+ bool is_bg_tree = btrfs_fs_incompat(trans->fs_info, BG_TREE);
int ret;
- struct btrfs_root *extent_root = trans->fs_info->extent_root;
+ struct btrfs_fs_info *fs_info = trans->fs_info;
+ struct btrfs_root *root;
unsigned long bi;
struct extent_buffer *leaf;
- ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1);
+ if (is_bg_tree)
+ root = fs_info->bg_root;
+ else
+ root = fs_info->extent_root;
+
+ ret = btrfs_search_slot(trans, root, &cache->key, path, 0, 1);
if (ret < 0)
- goto fail;
- BUG_ON(ret);
+ goto out;
- leaf = path->nodes[0];
- bi = btrfs_item_ptr_offset(leaf, path->slots[0]);
- write_extent_buffer(leaf, &cache->item, bi, sizeof(cache->item));
- btrfs_mark_buffer_dirty(leaf);
- btrfs_release_path(path);
-fail:
+ if (ret == 0) {
+ /* Update existing bg */
+ leaf = path->nodes[0];
+ bi = btrfs_item_ptr_offset(leaf, path->slots[0]);
+ write_extent_buffer(leaf, &cache->item, bi, sizeof(cache->item));
+ btrfs_mark_buffer_dirty(leaf);
+ btrfs_release_path(path);
+ } else {
+ btrfs_release_path(path);
+
+ /*
+ * Insert new bg item
+ *
+ * This only happens for bg_tree feature
+ */
+ if (!is_bg_tree) {
+ error("can't find block group item for bytenr %llu",
+ cache->key.objectid);
+ ret = -ENOENT;
+ goto out;
+ }
+ ret = btrfs_insert_item(trans, root, &cache->key, &cache->item,
+ sizeof(cache->item));
+ if (ret < 0)
+ goto out;
+
+ /* Also delete the existing one in next tree if needed */
+ if (fs_info->convert_to_bg_tree) {
+ ret = btrfs_search_slot(trans, fs_info->extent_root,
+ &cache->key, path, -1, 1);
+ if (ret < 0) {
+ btrfs_release_path(path);
+ goto out;
+ }
+ /* Good, already converted */
+ if (ret > 0) {
+ ret = 0;
+ btrfs_release_path(path);
+ goto out;
+ }
+ /* Delete old block group item in extent tree */
+ ret = btrfs_del_item(trans, fs_info->extent_root, path);
+ btrfs_release_path(path);
+ }
+ }
+out:
if (ret)
return ret;
return 0;
@@ -2717,14 +2763,66 @@ static int read_one_block_group(struct btrfs_fs_info *fs_info,
return 0;
}
+static int read_block_group_tree(struct btrfs_fs_info *fs_info)
+{
+ struct btrfs_root *root = fs_info->bg_root;
+ struct btrfs_key key = { 0 };
+ struct btrfs_path path;
+ int ret;
+
+ btrfs_init_path(&path);
+ ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
+ if (ret < 0) {
+ errno = -ret;
+ error("failed to search block group tree: %m");
+ return ret;
+ }
+ if (ret == 0)
+ goto invalid_key;
+
+ while (1) {
+ btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
+ if (key.type != BTRFS_BLOCK_GROUP_ITEM_KEY)
+ goto invalid_key;
+
+ ret = read_one_block_group(fs_info, &path);
+ if (ret < 0) {
+ errno = -ret;
+ error("failed to read one block group: %m");
+ goto out;
+ }
+ ret = btrfs_next_item(root, &path);
+ if (ret < 0) {
+ errno = -ret;
+ error("failed to search block group tree: %m");
+ goto out;
+ }
+ if (ret > 0) {
+ ret = 0;
+ break;
+ }
+ }
+out:
+ btrfs_release_path(&path);
+ return ret;
+
+invalid_key:
+ error("invalid key (%llu, %u, %llu) found in block group tree",
+ key.objectid, key.type, key.offset);
+ btrfs_release_path(&path);
+ return -EUCLEAN;
+}
+
int btrfs_read_block_groups(struct btrfs_fs_info *fs_info)
{
struct btrfs_path path;
- struct btrfs_root *root;
+ struct btrfs_root *root = fs_info->extent_root;
int ret;
struct btrfs_key key;
- root = fs_info->extent_root;
+ if (btrfs_fs_incompat(fs_info, BG_TREE))
+ return read_block_group_tree(fs_info);
+
key.objectid = 0;
key.offset = 0;
key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
@@ -2804,12 +2902,17 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
u64 type, u64 chunk_offset, u64 size)
{
int ret;
- struct btrfs_root *extent_root = fs_info->extent_root;
+ struct btrfs_root *root;
struct btrfs_block_group_cache *cache;
+ if (btrfs_fs_incompat(fs_info, BG_TREE))
+ root = fs_info->bg_root;
+ else
+ root = fs_info->extent_root;
+
cache = btrfs_add_block_group(fs_info, bytes_used, type, chunk_offset,
size);
- ret = btrfs_insert_item(trans, extent_root, &cache->key, &cache->item,
+ ret = btrfs_insert_item(trans, root, &cache->key, &cache->item,
sizeof(cache->item));
BUG_ON(ret);
@@ -2943,8 +3046,16 @@ static int free_block_group_item(struct btrfs_trans_handle *trans,
if (!path)
return -ENOMEM;
+ /* Using bg tree only */
+ if (btrfs_fs_incompat(fs_info, BG_TREE) && !fs_info->convert_to_bg_tree)
+ goto bg_tree;
+
ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
if (ret > 0) {
+ if (btrfs_fs_incompat(fs_info, BG_TREE)) {
+ btrfs_release_path(path);
+ goto bg_tree;
+ }
ret = -ENOENT;
goto out;
}
@@ -2952,6 +3063,19 @@ static int free_block_group_item(struct btrfs_trans_handle *trans,
goto out;
ret = btrfs_del_item(trans, root, path);
+ goto out;
+
+bg_tree:
+ root = fs_info->bg_root;
+ ret = btrfs_search_slot(trans, fs_info->bg_root, &key, path, -1, 1);
+ if (ret < 0)
+ goto out;
+ if (ret > 0) {
+ ret = -ENOENT;
+ goto out;
+ }
+ ret = btrfs_del_item(trans, root, path);
+
out:
btrfs_free_path(path);
return ret;
--
2.23.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 4/7] btrfs-progs: mkfs: Introduce -O bg-tree
2019-10-10 6:41 [PATCH v3 0/7] btrfs-progs: Support for BG_TREE feature Qu Wenruo
` (2 preceding siblings ...)
2019-10-10 6:41 ` [PATCH v3 3/7] btrfs-progs: Enable read-write ability for 'bg_tree' feature Qu Wenruo
@ 2019-10-10 6:41 ` Qu Wenruo
2019-10-10 6:41 ` [PATCH v3 5/7] btrfs-progs: dump-tree/dump-super: Introduce support for bg tree Qu Wenruo
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2019-10-10 6:41 UTC (permalink / raw)
To: linux-btrfs
This allow mkfs.btrfs to create a btrfs with bg-tree feature.
This patch introduce a global function, btrfs_convert_to_bg_tree() in
extent-tree.c, to do the work.
The workflow is pretty simple:
- Create a new tree block for bg tree
- Set the BG_TREE feature for superblock
- Set the fs_info->convert_to_bg_tree flag
- Mark all block group items as dirty
- Commit transaction
* With fs_info->convert_to_bg_tree set, we will try to delete the
BLOCK_GROUP_ITEM in extent tree first, then write the new
BLOCK_GROUP_ITEM into bg tree.
This btrfs_convert_to_bg_tree() will be used in mkfs after the basic fs
is created.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
common/fsfeatures.c | 6 ++++++
ctree.h | 1 +
extent-tree.c | 39 +++++++++++++++++++++++++++++++++++++++
mkfs/common.c | 6 ++++--
mkfs/main.c | 25 +++++++++++++++++++++++++
transaction.c | 1 +
6 files changed, 76 insertions(+), 2 deletions(-)
diff --git a/common/fsfeatures.c b/common/fsfeatures.c
index 50934bd161b0..b9bd70a4b3b6 100644
--- a/common/fsfeatures.c
+++ b/common/fsfeatures.c
@@ -86,6 +86,12 @@ static const struct btrfs_fs_feature {
VERSION_TO_STRING2(4,0),
NULL, 0,
"no explicit hole extents for files" },
+ { "bg-tree", BTRFS_FEATURE_INCOMPAT_BG_TREE,
+ "bg_tree",
+ VERSION_TO_STRING2(5, 0),
+ NULL, 0,
+ NULL, 0,
+ "store block group items in dedicated tree" },
/* Keep this one last */
{ "list-all", BTRFS_FEATURE_LIST_ALL, NULL }
};
diff --git a/ctree.h b/ctree.h
index c2a18c8ab72f..3d3992487a53 100644
--- a/ctree.h
+++ b/ctree.h
@@ -2856,5 +2856,6 @@ int btrfs_read_file(struct btrfs_root *root, u64 ino, u64 start, int len,
/* extent-tree.c */
int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, unsigned long nr);
+int btrfs_convert_to_bg_tree(struct btrfs_trans_handle *trans);
#endif
diff --git a/extent-tree.c b/extent-tree.c
index cb3d7a1add0f..7dda933956ce 100644
--- a/extent-tree.c
+++ b/extent-tree.c
@@ -1524,6 +1524,45 @@ int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
return __btrfs_mod_ref(trans, root, buf, record_parent, 0);
}
+int btrfs_convert_to_bg_tree(struct btrfs_trans_handle *trans)
+{
+ struct btrfs_fs_info *fs_info = trans->fs_info;
+ struct btrfs_block_group_cache *bg;
+ struct btrfs_root *bg_root;
+ u64 features = btrfs_super_incompat_flags(fs_info->super_copy);
+ int ret;
+
+ /* create bg tree first */
+ bg_root = btrfs_create_tree(trans, fs_info, BTRFS_BLOCK_GROUP_TREE_OBJECTID);
+ if (IS_ERR(bg_root)) {
+ ret = PTR_ERR(bg_root);
+ errno = -ret;
+ error("failed to create bg tree: %m");
+ return ret;
+ }
+ fs_info->bg_root = bg_root;
+ fs_info->bg_root->track_dirty = 1;
+ fs_info->bg_root->ref_cows = 0;
+ add_root_to_dirty_list(bg_root);
+
+ /* set BG_TREE feature and mark the fs into bg_tree convert status */
+ btrfs_set_super_incompat_flags(fs_info->super_copy,
+ features | BTRFS_FEATURE_INCOMPAT_BG_TREE);
+ fs_info->convert_to_bg_tree = 1;
+
+ /*
+ * Mark all block groups dirty so they will get converted to bg tree at
+ * commit transaction time
+ */
+ for (bg = btrfs_lookup_first_block_group(fs_info, 0); bg;
+ bg = btrfs_lookup_first_block_group(fs_info,
+ bg->key.objectid + bg->key.offset))
+ set_extent_bits(&fs_info->block_group_cache, bg->key.objectid,
+ bg->key.objectid + bg->key.offset - 1,
+ BLOCK_GROUP_DIRTY);
+ return 0;
+}
+
static int write_one_cache_group(struct btrfs_trans_handle *trans,
struct btrfs_path *path,
struct btrfs_block_group_cache *cache)
diff --git a/mkfs/common.c b/mkfs/common.c
index caca5e707233..876193838612 100644
--- a/mkfs/common.c
+++ b/mkfs/common.c
@@ -111,6 +111,9 @@ static int btrfs_create_tree_root(int fd, struct btrfs_mkfs_config *cfg,
return ret;
}
+/* These features will not be set in the temporary fs */
+#define MASKED_FEATURES (~(BTRFS_FEATURE_INCOMPAT_BG_TREE))
+
/*
* @fs_uuid - if NULL, generates a UUID, returns back the new filesystem UUID
*
@@ -204,7 +207,7 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
btrfs_set_super_csum_type(&super, BTRFS_CSUM_TYPE_CRC32);
btrfs_set_super_chunk_root_generation(&super, 1);
btrfs_set_super_cache_generation(&super, -1);
- btrfs_set_super_incompat_flags(&super, cfg->features);
+ btrfs_set_super_incompat_flags(&super, cfg->features & MASKED_FEATURES);
if (cfg->label)
__strncpy_null(super.label, cfg->label, BTRFS_LABEL_SIZE - 1);
@@ -824,4 +827,3 @@ int test_minimum_size(const char *file, u64 min_dev_size)
return 0;
}
-
diff --git a/mkfs/main.c b/mkfs/main.c
index b752da13aba9..55bc4288dc08 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -1312,6 +1312,31 @@ raid_groups:
goto out;
}
+ /*
+ * Bg tree are converted after temp chunks cleaned up, or we can
+ * populate temp chunks.
+ */
+ if (mkfs_cfg.features & BTRFS_FEATURE_INCOMPAT_BG_TREE) {
+ trans = btrfs_start_transaction(fs_info->tree_root, 1);
+ if (IS_ERR(trans)) {
+ error("failed to start transaction: %d", ret);
+ goto out;
+ }
+ ret = btrfs_convert_to_bg_tree(trans);
+ if (ret < 0) {
+ errno = -ret;
+ error(
+ "bg-tree feature will not be enabled, due to error: %m");
+ btrfs_abort_transaction(trans, ret);
+ goto out;
+ }
+ ret = btrfs_commit_transaction(trans, fs_info->tree_root);
+ if (ret < 0) {
+ error("failed to commit transaction: %d", ret);
+ goto out;
+ }
+ }
+
if (source_dir_set) {
ret = btrfs_mkfs_fill_dir(source_dir, root, verbose);
if (ret) {
diff --git a/transaction.c b/transaction.c
index 45bb9e1f9de6..5de967fb015f 100644
--- a/transaction.c
+++ b/transaction.c
@@ -225,6 +225,7 @@ commit_tree:
root->commit_root = NULL;
fs_info->running_transaction = NULL;
fs_info->last_trans_committed = transid;
+ fs_info->convert_to_bg_tree = 0;
list_for_each_entry(sinfo, &fs_info->space_info, list) {
if (sinfo->bytes_reserved) {
warning(
--
2.23.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 5/7] btrfs-progs: dump-tree/dump-super: Introduce support for bg tree
2019-10-10 6:41 [PATCH v3 0/7] btrfs-progs: Support for BG_TREE feature Qu Wenruo
` (3 preceding siblings ...)
2019-10-10 6:41 ` [PATCH v3 4/7] btrfs-progs: mkfs: Introduce -O bg-tree Qu Wenruo
@ 2019-10-10 6:41 ` Qu Wenruo
2019-10-10 6:41 ` [PATCH v3 6/7] btrfs-progs: check: Introduce support for bg-tree feature Qu Wenruo
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2019-10-10 6:41 UTC (permalink / raw)
To: linux-btrfs
Just a new tree called BLOCK_GROUP_TREE.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
cmds/inspect-dump-super.c | 3 ++-
cmds/inspect-dump-tree.c | 5 +++++
print-tree.c | 3 +++
3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/cmds/inspect-dump-super.c b/cmds/inspect-dump-super.c
index 65fb3506eac6..414d9c2317d8 100644
--- a/cmds/inspect-dump-super.c
+++ b/cmds/inspect-dump-super.c
@@ -229,7 +229,8 @@ static struct readable_flag_entry incompat_flags_array[] = {
DEF_INCOMPAT_FLAG_ENTRY(RAID56),
DEF_INCOMPAT_FLAG_ENTRY(SKINNY_METADATA),
DEF_INCOMPAT_FLAG_ENTRY(NO_HOLES),
- DEF_INCOMPAT_FLAG_ENTRY(METADATA_UUID)
+ DEF_INCOMPAT_FLAG_ENTRY(METADATA_UUID),
+ DEF_INCOMPAT_FLAG_ENTRY(BG_TREE)
};
static const int incompat_flags_num = sizeof(incompat_flags_array) /
sizeof(struct readable_flag_entry);
diff --git a/cmds/inspect-dump-tree.c b/cmds/inspect-dump-tree.c
index e50130a4a161..def5bea39a2b 100644
--- a/cmds/inspect-dump-tree.c
+++ b/cmds/inspect-dump-tree.c
@@ -150,6 +150,7 @@ static u64 treeid_from_string(const char *str, const char **end)
{ "CSUM", BTRFS_CSUM_TREE_OBJECTID },
{ "CHECKSUM", BTRFS_CSUM_TREE_OBJECTID },
{ "QUOTA", BTRFS_QUOTA_TREE_OBJECTID },
+ { "BG", BTRFS_BLOCK_GROUP_TREE_OBJECTID },
{ "UUID", BTRFS_UUID_TREE_OBJECTID },
{ "FREE_SPACE", BTRFS_FREE_SPACE_TREE_OBJECTID },
{ "TREE_LOG_FIXUP", BTRFS_TREE_LOG_FIXUP_OBJECTID },
@@ -661,6 +662,10 @@ again:
if (!skip)
printf("free space");
break;
+ case BTRFS_BLOCK_GROUP_TREE_OBJECTID:
+ if (!skip)
+ printf("block group");
+ break;
case BTRFS_MULTIPLE_OBJECTIDS:
if (!skip) {
printf("multiple");
diff --git a/print-tree.c b/print-tree.c
index e079f1a971d3..e2a43226ff87 100644
--- a/print-tree.c
+++ b/print-tree.c
@@ -770,6 +770,9 @@ void print_objectid(FILE *stream, u64 objectid, u8 type)
case BTRFS_FREE_SPACE_TREE_OBJECTID:
fprintf(stream, "FREE_SPACE_TREE");
break;
+ case BTRFS_BLOCK_GROUP_TREE_OBJECTID:
+ fprintf(stream, "BLOCK_GROUP_TREE");
+ break;
case BTRFS_MULTIPLE_OBJECTIDS:
fprintf(stream, "MULTIPLE");
break;
--
2.23.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 6/7] btrfs-progs: check: Introduce support for bg-tree feature
2019-10-10 6:41 [PATCH v3 0/7] btrfs-progs: Support for BG_TREE feature Qu Wenruo
` (4 preceding siblings ...)
2019-10-10 6:41 ` [PATCH v3 5/7] btrfs-progs: dump-tree/dump-super: Introduce support for bg tree Qu Wenruo
@ 2019-10-10 6:41 ` Qu Wenruo
2019-10-10 6:41 ` [PATCH v3 7/7] btrfs-progs: btrfstune: Allow to enable bg-tree feature offline Qu Wenruo
2019-10-21 15:26 ` [PATCH v3 0/7] btrfs-progs: Support for BG_TREE feature David Sterba
7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2019-10-10 6:41 UTC (permalink / raw)
To: linux-btrfs
Just some minor modification.
- original mode:
* Block group item can occur in extent tree and bg tree.
- lowmem mode:
* search block group items in bg tree if BG_TREE feature is set.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
check/main.c | 3 ++-
check/mode-lowmem.c | 9 +++++++--
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/check/main.c b/check/main.c
index 94ffab46cb70..3fd0bb2317bb 100644
--- a/check/main.c
+++ b/check/main.c
@@ -6034,7 +6034,8 @@ static int check_type_with_root(u64 rootid, u8 key_type)
case BTRFS_EXTENT_ITEM_KEY:
case BTRFS_METADATA_ITEM_KEY:
case BTRFS_BLOCK_GROUP_ITEM_KEY:
- if (rootid != BTRFS_EXTENT_TREE_OBJECTID)
+ if (rootid != BTRFS_EXTENT_TREE_OBJECTID &&
+ rootid != BTRFS_BLOCK_GROUP_TREE_OBJECTID)
goto err;
break;
case BTRFS_ROOT_ITEM_KEY:
diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
index 5f7f101daab1..fcb8210984eb 100644
--- a/check/mode-lowmem.c
+++ b/check/mode-lowmem.c
@@ -4365,7 +4365,7 @@ next:
static int check_chunk_item(struct btrfs_fs_info *fs_info,
struct extent_buffer *eb, int slot)
{
- struct btrfs_root *extent_root = fs_info->extent_root;
+ struct btrfs_root *root;
struct btrfs_root *dev_root = fs_info->dev_root;
struct btrfs_path path;
struct btrfs_key chunk_key;
@@ -4387,6 +4387,11 @@ static int check_chunk_item(struct btrfs_fs_info *fs_info,
int ret;
int err = 0;
+ if (btrfs_fs_incompat(fs_info, BG_TREE))
+ root = fs_info->bg_root;
+ else
+ root = fs_info->extent_root;
+
btrfs_item_key_to_cpu(eb, &chunk_key, slot);
chunk = btrfs_item_ptr(eb, slot, struct btrfs_chunk);
length = btrfs_chunk_length(eb, chunk);
@@ -4406,7 +4411,7 @@ static int check_chunk_item(struct btrfs_fs_info *fs_info,
bg_key.offset = length;
btrfs_init_path(&path);
- ret = btrfs_search_slot(NULL, extent_root, &bg_key, &path, 0, 0);
+ ret = btrfs_search_slot(NULL, root, &bg_key, &path, 0, 0);
if (ret) {
error(
"chunk[%llu %llu) did not find the related block group item",
--
2.23.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 7/7] btrfs-progs: btrfstune: Allow to enable bg-tree feature offline
2019-10-10 6:41 [PATCH v3 0/7] btrfs-progs: Support for BG_TREE feature Qu Wenruo
` (5 preceding siblings ...)
2019-10-10 6:41 ` [PATCH v3 6/7] btrfs-progs: check: Introduce support for bg-tree feature Qu Wenruo
@ 2019-10-10 6:41 ` Qu Wenruo
2019-10-21 15:26 ` [PATCH v3 0/7] btrfs-progs: Support for BG_TREE feature David Sterba
7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2019-10-10 6:41 UTC (permalink / raw)
To: linux-btrfs
Add a new option '-b' for btrfstune, to enable bg-tree feature for a
unmounted fs.
This feature will convert all BLOCK_GROUP_ITEMs in extent tree to bg
tree, by reusing the existing btrfs_convert_to_bg_tree() function.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
Documentation/btrfstune.asciidoc | 6 +++++
btrfstune.c | 44 ++++++++++++++++++++++++++++++--
2 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/Documentation/btrfstune.asciidoc b/Documentation/btrfstune.asciidoc
index 1d6bc98deed8..ed54c2e1597f 100644
--- a/Documentation/btrfstune.asciidoc
+++ b/Documentation/btrfstune.asciidoc
@@ -26,6 +26,12 @@ means. Please refer to the 'FILESYSTEM FEATURES' in `btrfs`(5).
OPTIONS
-------
+-b::
+(since kernel: 5.x)
++
+enable bg-tree feature (faster mount time for large fs), enabled by mkfs
+feature 'bg-tree'.
+
-f::
Allow dangerous changes, e.g. clear the seeding flag or change fsid. Make sure
that you are aware of the dangers.
diff --git a/btrfstune.c b/btrfstune.c
index afa3aae35412..aa1ac568aef0 100644
--- a/btrfstune.c
+++ b/btrfstune.c
@@ -476,11 +476,39 @@ static void print_usage(void)
printf("\t-m change fsid in metadata_uuid to a random UUID\n");
printf("\t (incompat change, more lightweight than -u|-U)\n");
printf("\t-M UUID change fsid in metadata_uuid to UUID\n");
+ printf("\t-b enable bg-tree feature (mkfs: bg-tree, for faster mount time)\n");
printf(" general:\n");
printf("\t-f allow dangerous operations, make sure that you are aware of the dangers\n");
printf("\t--help print this help\n");
}
+static int convert_to_bg_tree(struct btrfs_fs_info *fs_info)
+{
+ struct btrfs_trans_handle *trans;
+ int ret;
+
+ trans = btrfs_start_transaction(fs_info->tree_root, 1);
+ if (IS_ERR(trans)) {
+ ret = PTR_ERR(trans);
+ errno = -ret;
+ error("failed to start transaction: %m");
+ return ret;
+ }
+ ret = btrfs_convert_to_bg_tree(trans);
+ if (ret < 0) {
+ errno = -ret;
+ error("failed to convert: %m");
+ btrfs_abort_transaction(trans, ret);
+ return ret;
+ }
+ ret = btrfs_commit_transaction(trans, fs_info->tree_root);
+ if (ret < 0) {
+ errno = -ret;
+ error("failed to commit transaction: %m");
+ }
+ return ret;
+}
+
int BOX_MAIN(btrfstune)(int argc, char *argv[])
{
struct btrfs_root *root;
@@ -491,6 +519,7 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
u64 seeding_value = 0;
int random_fsid = 0;
int change_metadata_uuid = 0;
+ bool to_bg_tree = false;
char *new_fsid_str = NULL;
int ret;
u64 super_flags = 0;
@@ -501,7 +530,7 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
{ "help", no_argument, NULL, GETOPT_VAL_HELP},
{ NULL, 0, NULL, 0 }
};
- int c = getopt_long(argc, argv, "S:rxfuU:nmM:", long_options, NULL);
+ int c = getopt_long(argc, argv, "S:rxfuU:nmM:b", long_options, NULL);
if (c < 0)
break;
@@ -539,6 +568,9 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
ctree_flags |= OPEN_CTREE_IGNORE_FSID_MISMATCH;
change_metadata_uuid = 1;
break;
+ case 'b':
+ to_bg_tree = true;
+ break;
case GETOPT_VAL_HELP:
default:
print_usage();
@@ -556,7 +588,7 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
return 1;
}
if (!super_flags && !seeding_flag && !(random_fsid || new_fsid_str) &&
- !change_metadata_uuid) {
+ !change_metadata_uuid && !to_bg_tree) {
error("at least one option should be specified");
print_usage();
return 1;
@@ -602,6 +634,14 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[])
return 1;
}
+ if (to_bg_tree) {
+ ret = convert_to_bg_tree(root->fs_info);
+ if (ret < 0) {
+ errno = -ret;
+ error("failed to convert to bg-tree feature: %m");
+ goto out;
+ }
+ }
if (seeding_flag) {
if (btrfs_fs_incompat(root->fs_info, METADATA_UUID)) {
fprintf(stderr, "SEED flag cannot be changed on a metadata-uuid changed fs\n");
--
2.23.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v3 0/7] btrfs-progs: Support for BG_TREE feature
2019-10-10 6:41 [PATCH v3 0/7] btrfs-progs: Support for BG_TREE feature Qu Wenruo
` (6 preceding siblings ...)
2019-10-10 6:41 ` [PATCH v3 7/7] btrfs-progs: btrfstune: Allow to enable bg-tree feature offline Qu Wenruo
@ 2019-10-21 15:26 ` David Sterba
7 siblings, 0 replies; 9+ messages in thread
From: David Sterba @ 2019-10-21 15:26 UTC (permalink / raw)
To: Qu Wenruo; +Cc: linux-btrfs
On Thu, Oct 10, 2019 at 02:41:49PM +0800, Qu Wenruo wrote:
> This patchset can be fetched from github:
> https://github.com/adam900710/btrfs-progs/tree/bg_tree
> Which is based on v5.2.2 tag.
>
> This patchset provides the needed user space infrastructure for BG_TREE
> feature.
>
> Since it's an new incompatible feature, unlike SKINNY_METADATA, btrfs-progs
> is needed to convert existing fs (unmounted) to new format.
>
> Now btrfstune can convert regular extent tree fs to bg tree fs to
> improve mount time.
>
> For the performance improvement, please check the kernel patchset cover
> letter or the last patch.
> (SPOILER ALERT: It's super fast)
>
> Changelog:
> v2:
> - Rebase to v5.2.2 tag
> - Add btrfstune ability to convert existing fs to BG_TREE feature
>
> v3:
> - Fix a bug that temp chunks are not cleaned up properly
> This is caused by wrong timing btrfs_convert_to_bg_tree() is called.
> It should be called after temp chunks cleaned up.
>
> - Fix a bug that an extent buffer get leaked
> This is caused by newly created bg tree not added to dirty list.
>
> Qu Wenruo (7):
> btrfs-progs: Refactor excluded extent functions to use fs_info
> btrfs-progs: Refactor btrfs_read_block_groups()
I'll add 1 and 2 to devel as they're independent. Thanks.
^ permalink raw reply [flat|nested] 9+ messages in thread