@@ -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+
203216static 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
261274static 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 );
289307out :
@@ -658,9 +676,12 @@ static void insert_temp_block_group(struct extent_buffer *buf,
658676static 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 );
719769out :
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 );
860922out :
861923 return ret ;
862924}
0 commit comments