Skip to content

Commit 7da8fd0

Browse files
adam900710kdave
authored andcommitted
btrfs-progs: convert: implement the block group tree support properly
Previously there were some problems related to btrfs-convert bgt support, that it doesn't work at all, caused by the following reasons: - We never update the super block with extra compat ro flags Even if we set "-O bgt" flags, it will not set the compat ro flags, and everything just go non-bgt routine. Meanwhile other compat ro flags are for free-space-tree, and free-space-tree is rebuilt after the full convert is done. Thus this bug won't cause any problem for fst features, but only affecting bgt so far. - No extra handling to create block group tree Fix above problems by: - Set the proper compat RO flag for the temporary super block We should only set the compat RO flags except the two FST related bits. As FST is handled after conversion, we should not set the flag at that timing. - Add block group tree root item and its backrefs So the initial temporary fs will have a proper block group tree. The only tricky part is for the extent tree population, where we have to put all block group items into the block group tree other than the extent tree. With these two points addressed, now block group tree can be properly enabled for btrfs-convert. Signed-off-by: Qu Wenruo <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 857e01f commit 7da8fd0

File tree

1 file changed

+85
-23
lines changed

1 file changed

+85
-23
lines changed

convert/common.c

Lines changed: 85 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,13 @@ static int setup_temp_super(int fd, struct btrfs_mkfs_config *cfg,
150150
btrfs_set_super_chunk_root(&super, chunk_bytenr);
151151
btrfs_set_super_cache_generation(&super, -1);
152152
btrfs_set_super_incompat_flags(&super, cfg->features.incompat_flags);
153+
/*
154+
* Do not set fst related flags yet, it will be handled after
155+
* the fs is converted.
156+
*/
157+
btrfs_set_super_compat_ro_flags(&super, cfg->features.compat_ro_flags &
158+
~(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE |
159+
BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID));
153160
if (cfg->label)
154161
strncpy_null(super.label, cfg->label, BTRFS_LABEL_SIZE);
155162

@@ -200,6 +207,12 @@ static u32 get_item_offset(const struct extent_buffer *eb,
200207
return cfg->leaf_data_size;
201208
}
202209

210+
static bool btrfs_is_bgt(const struct btrfs_mkfs_config *cfg)
211+
{
212+
return cfg->features.compat_ro_flags &
213+
BTRFS_FEATURE_COMPAT_RO_BLOCK_GROUP_TREE;
214+
}
215+
203216
static void insert_temp_root_item(struct extent_buffer *buf,
204217
struct btrfs_mkfs_config *cfg,
205218
u64 objectid, u64 bytenr)
@@ -260,7 +273,8 @@ static inline int write_temp_extent_buffer(int fd, struct extent_buffer *buf,
260273

261274
static int setup_temp_root_tree(int fd, struct btrfs_mkfs_config *cfg,
262275
u64 root_bytenr, u64 extent_bytenr,
263-
u64 dev_bytenr, u64 fs_bytenr, u64 csum_bytenr)
276+
u64 dev_bytenr, u64 fs_bytenr, u64 csum_bytenr,
277+
u64 bgt_bytenr)
264278
{
265279
struct extent_buffer *buf = NULL;
266280
int ret;
@@ -270,7 +284,8 @@ static int setup_temp_root_tree(int fd, struct btrfs_mkfs_config *cfg,
270284
* bad key order.
271285
*/
272286
UASSERT(root_bytenr < extent_bytenr && extent_bytenr < dev_bytenr &&
273-
dev_bytenr < fs_bytenr && fs_bytenr < csum_bytenr);
287+
dev_bytenr < fs_bytenr && fs_bytenr < csum_bytenr &&
288+
csum_bytenr < bgt_bytenr);
274289
buf = malloc(sizeof(*buf) + cfg->nodesize);
275290
if (!buf)
276291
return -ENOMEM;
@@ -284,6 +299,9 @@ static int setup_temp_root_tree(int fd, struct btrfs_mkfs_config *cfg,
284299
insert_temp_root_item(buf, cfg, BTRFS_DEV_TREE_OBJECTID, dev_bytenr);
285300
insert_temp_root_item(buf, cfg, BTRFS_FS_TREE_OBJECTID, fs_bytenr);
286301
insert_temp_root_item(buf, cfg, BTRFS_CSUM_TREE_OBJECTID, csum_bytenr);
302+
if (btrfs_is_bgt(cfg))
303+
insert_temp_root_item(buf, cfg, BTRFS_BLOCK_GROUP_TREE_OBJECTID,
304+
bgt_bytenr);
287305

288306
ret = write_temp_extent_buffer(fd, buf, root_bytenr, cfg);
289307
out:
@@ -658,9 +676,12 @@ static void insert_temp_block_group(struct extent_buffer *buf,
658676
static int setup_temp_extent_tree(int fd, struct btrfs_mkfs_config *cfg,
659677
u64 chunk_bytenr, u64 root_bytenr,
660678
u64 extent_bytenr, u64 dev_bytenr,
661-
u64 fs_bytenr, u64 csum_bytenr)
679+
u64 fs_bytenr, u64 csum_bytenr,
680+
u64 bgt_bytenr)
662681
{
663-
struct extent_buffer *buf = NULL;
682+
struct extent_buffer *extent_buf = NULL;
683+
struct extent_buffer *bg_buf = NULL;
684+
const bool is_bgt = btrfs_is_bgt(cfg);
664685
int ret;
665686

666687
/*
@@ -669,55 +690,85 @@ static int setup_temp_extent_tree(int fd, struct btrfs_mkfs_config *cfg,
669690
*/
670691
UASSERT(chunk_bytenr < root_bytenr && root_bytenr < extent_bytenr &&
671692
extent_bytenr < dev_bytenr && dev_bytenr < fs_bytenr &&
672-
fs_bytenr < csum_bytenr);
673-
buf = malloc(sizeof(*buf) + cfg->nodesize);
674-
if (!buf)
675-
return -ENOMEM;
693+
fs_bytenr < csum_bytenr && csum_bytenr < bgt_bytenr);
694+
extent_buf = malloc(sizeof(*extent_buf) + cfg->nodesize);
695+
if (!extent_buf) {
696+
ret = -ENOMEM;
697+
goto out;
698+
}
676699

677-
ret = setup_temp_extent_buffer(buf, cfg, extent_bytenr,
700+
ret = setup_temp_extent_buffer(extent_buf, cfg, extent_bytenr,
678701
BTRFS_EXTENT_TREE_OBJECTID);
679702
if (ret < 0)
680703
goto out;
681704

682-
ret = insert_temp_extent_item(fd, buf, cfg, chunk_bytenr,
705+
if (is_bgt) {
706+
bg_buf = malloc(sizeof(*bg_buf) + cfg->nodesize);
707+
if (!bg_buf) {
708+
ret = -ENOMEM;
709+
goto out;
710+
}
711+
ret = setup_temp_extent_buffer(bg_buf, cfg, bgt_bytenr,
712+
BTRFS_BLOCK_GROUP_TREE_OBJECTID);
713+
if (ret < 0)
714+
goto out;
715+
}
716+
717+
ret = insert_temp_extent_item(fd, extent_buf, cfg, chunk_bytenr,
683718
BTRFS_CHUNK_TREE_OBJECTID);
684719
if (ret < 0)
685720
goto out;
686721

687-
insert_temp_block_group(buf, cfg, chunk_bytenr,
722+
insert_temp_block_group(is_bgt ? bg_buf : extent_buf, cfg, chunk_bytenr,
688723
BTRFS_MKFS_SYSTEM_GROUP_SIZE, cfg->nodesize,
689724
BTRFS_BLOCK_GROUP_SYSTEM);
690725

691-
ret = insert_temp_extent_item(fd, buf, cfg, root_bytenr,
726+
ret = insert_temp_extent_item(fd, extent_buf, cfg, root_bytenr,
692727
BTRFS_ROOT_TREE_OBJECTID);
693728
if (ret < 0)
694729
goto out;
695730

696-
/* 5 tree block used, root, extent, dev, fs and csum*/
697-
insert_temp_block_group(buf, cfg, root_bytenr,
698-
BTRFS_CONVERT_META_GROUP_SIZE, cfg->nodesize * 5,
731+
/*
732+
* 5 tree block used, root, extent, dev, fs and csum.
733+
* Plus bg tree if specified.
734+
*/
735+
insert_temp_block_group(is_bgt ? bg_buf : extent_buf, cfg, root_bytenr,
736+
BTRFS_CONVERT_META_GROUP_SIZE,
737+
is_bgt ? cfg->nodesize * 6 : cfg->nodesize * 5,
699738
BTRFS_BLOCK_GROUP_METADATA);
700739

701-
ret = insert_temp_extent_item(fd, buf, cfg, extent_bytenr,
740+
ret = insert_temp_extent_item(fd, extent_buf, cfg, extent_bytenr,
702741
BTRFS_EXTENT_TREE_OBJECTID);
703742
if (ret < 0)
704743
goto out;
705-
ret = insert_temp_extent_item(fd, buf, cfg, dev_bytenr,
744+
ret = insert_temp_extent_item(fd, extent_buf, cfg, dev_bytenr,
706745
BTRFS_DEV_TREE_OBJECTID);
707746
if (ret < 0)
708747
goto out;
709-
ret = insert_temp_extent_item(fd, buf, cfg, fs_bytenr,
748+
ret = insert_temp_extent_item(fd, extent_buf, cfg, fs_bytenr,
710749
BTRFS_FS_TREE_OBJECTID);
711750
if (ret < 0)
712751
goto out;
713-
ret = insert_temp_extent_item(fd, buf, cfg, csum_bytenr,
752+
ret = insert_temp_extent_item(fd, extent_buf, cfg, csum_bytenr,
714753
BTRFS_CSUM_TREE_OBJECTID);
715754
if (ret < 0)
716755
goto out;
756+
if (btrfs_is_bgt(cfg)) {
757+
ret = insert_temp_extent_item(fd, extent_buf, cfg, bgt_bytenr,
758+
BTRFS_BLOCK_GROUP_TREE_OBJECTID);
759+
if (ret < 0)
760+
goto out;
761+
}
762+
763+
ret = write_temp_extent_buffer(fd, extent_buf, extent_bytenr, cfg);
764+
if (ret < 0)
765+
goto out;
766+
if (is_bgt)
767+
ret = write_temp_extent_buffer(fd, bg_buf, bgt_bytenr, cfg);
717768

718-
ret = write_temp_extent_buffer(fd, buf, extent_bytenr, cfg);
719769
out:
720-
free(buf);
770+
free(extent_buf);
771+
free(bg_buf);
721772
return ret;
722773
}
723774

@@ -751,6 +802,7 @@ int make_convert_btrfs(int fd, struct btrfs_mkfs_config *cfg,
751802
{
752803
struct cache_tree *free_space = &cctx->free_space;
753804
struct cache_tree *used_space = &cctx->used_space;
805+
const bool is_bgt = btrfs_is_bgt(cfg);
754806
u64 sys_chunk_start;
755807
u64 meta_chunk_start;
756808
/* chunk tree bytenr, in system chunk */
@@ -761,6 +813,7 @@ int make_convert_btrfs(int fd, struct btrfs_mkfs_config *cfg,
761813
u64 dev_bytenr;
762814
u64 fs_bytenr;
763815
u64 csum_bytenr;
816+
u64 bgt_bytenr = (u64)-1;
764817
int ret;
765818

766819
/* Source filesystem must be opened, checked and analyzed in advance */
@@ -814,6 +867,7 @@ int make_convert_btrfs(int fd, struct btrfs_mkfs_config *cfg,
814867
* | +nodesize * 2 | device root |
815868
* | +nodesize * 3 | fs tree |
816869
* | +nodesize * 4 | csum tree |
870+
* | +nodesize * 5 | bg tree | (Optional)
817871
* -------------------------------------
818872
* Inside the allocated system chunk, the layout will be:
819873
* | offset | contents |
@@ -827,13 +881,15 @@ int make_convert_btrfs(int fd, struct btrfs_mkfs_config *cfg,
827881
dev_bytenr = meta_chunk_start + cfg->nodesize * 2;
828882
fs_bytenr = meta_chunk_start + cfg->nodesize * 3;
829883
csum_bytenr = meta_chunk_start + cfg->nodesize * 4;
884+
if (is_bgt)
885+
bgt_bytenr = meta_chunk_start + cfg->nodesize * 5;
830886

831887
ret = setup_temp_super(fd, cfg, root_bytenr, chunk_bytenr);
832888
if (ret < 0)
833889
goto out;
834890

835891
ret = setup_temp_root_tree(fd, cfg, root_bytenr, extent_bytenr,
836-
dev_bytenr, fs_bytenr, csum_bytenr);
892+
dev_bytenr, fs_bytenr, csum_bytenr, bgt_bytenr);
837893
if (ret < 0)
838894
goto out;
839895
ret = setup_temp_chunk_tree(fd, cfg, sys_chunk_start, meta_chunk_start,
@@ -850,13 +906,19 @@ int make_convert_btrfs(int fd, struct btrfs_mkfs_config *cfg,
850906
ret = setup_temp_empty_tree(fd, cfg, csum_bytenr, BTRFS_CSUM_TREE_OBJECTID);
851907
if (ret < 0)
852908
goto out;
909+
if (is_bgt) {
910+
ret = setup_temp_empty_tree(fd, cfg, bgt_bytenr,
911+
BTRFS_BLOCK_GROUP_TREE_OBJECTID);
912+
if (ret < 0)
913+
goto out;
914+
}
853915
/*
854916
* Setup extent tree last, since it may need to read tree block key
855917
* for non-skinny metadata case.
856918
*/
857919
ret = setup_temp_extent_tree(fd, cfg, chunk_bytenr, root_bytenr,
858920
extent_bytenr, dev_bytenr, fs_bytenr,
859-
csum_bytenr);
921+
csum_bytenr, bgt_bytenr);
860922
out:
861923
return ret;
862924
}

0 commit comments

Comments
 (0)