btrfs-progs: mkfs: add support for the block group tree
Add the extent tree v2 table with the block group tree as a root, and then create the empty root and use the proper root for cleanup up the temporary block groups. Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
c7a8363276
commit
7e3bf7fc44
|
@ -39,6 +39,7 @@ static u64 reference_root_table[] = {
|
|||
[MKFS_FS_TREE] = BTRFS_FS_TREE_OBJECTID,
|
||||
[MKFS_CSUM_TREE] = BTRFS_CSUM_TREE_OBJECTID,
|
||||
[MKFS_FREE_SPACE_TREE] = BTRFS_FREE_SPACE_TREE_OBJECTID,
|
||||
[MKFS_BLOCK_GROUP_TREE] = BTRFS_BLOCK_GROUP_TREE_OBJECTID,
|
||||
};
|
||||
|
||||
static int btrfs_write_empty_tree(int fd, struct btrfs_mkfs_config *cfg,
|
||||
|
@ -97,7 +98,8 @@ static int btrfs_create_tree_root(int fd, struct btrfs_mkfs_config *cfg,
|
|||
|
||||
for (i = 0; i < blocks_nr; i++) {
|
||||
blk = blocks[i];
|
||||
if (blk == MKFS_ROOT_TREE || blk == MKFS_CHUNK_TREE)
|
||||
if (blk == MKFS_ROOT_TREE || blk == MKFS_CHUNK_TREE ||
|
||||
blk == MKFS_BLOCK_GROUP_TREE)
|
||||
continue;
|
||||
|
||||
btrfs_set_root_bytenr(&root_item, cfg->blocks[blk]);
|
||||
|
@ -187,6 +189,50 @@ static int create_free_space_tree(int fd, struct btrfs_mkfs_config *cfg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void write_block_group_item(struct extent_buffer *buf, u32 nr,
|
||||
u64 objectid, u64 offset, u64 used,
|
||||
u32 itemoff)
|
||||
{
|
||||
struct btrfs_block_group_item *bg_item;
|
||||
struct btrfs_disk_key disk_key;
|
||||
|
||||
btrfs_set_disk_key_objectid(&disk_key, objectid);
|
||||
btrfs_set_disk_key_offset(&disk_key, offset);
|
||||
btrfs_set_disk_key_type(&disk_key, BTRFS_BLOCK_GROUP_ITEM_KEY);
|
||||
btrfs_set_item_key(buf, &disk_key, nr);
|
||||
btrfs_set_item_offset(buf, nr, itemoff);
|
||||
btrfs_set_item_size(buf, nr, sizeof(*bg_item));
|
||||
|
||||
bg_item = btrfs_item_ptr(buf, nr, struct btrfs_block_group_item);
|
||||
btrfs_set_block_group_used(buf, bg_item, used);
|
||||
btrfs_set_block_group_flags(buf, bg_item, BTRFS_BLOCK_GROUP_SYSTEM);
|
||||
btrfs_set_block_group_chunk_objectid(buf, bg_item,
|
||||
BTRFS_FIRST_CHUNK_TREE_OBJECTID);
|
||||
}
|
||||
|
||||
static int create_block_group_tree(int fd, struct btrfs_mkfs_config *cfg,
|
||||
struct extent_buffer *buf,
|
||||
u64 bg_offset, u64 bg_size, u64 bg_used)
|
||||
{
|
||||
int ret;
|
||||
|
||||
memset(buf->data + sizeof(struct btrfs_header), 0,
|
||||
cfg->nodesize - sizeof(struct btrfs_header));
|
||||
write_block_group_item(buf, 0, bg_offset, bg_size, bg_used,
|
||||
cfg->leaf_data_size -
|
||||
sizeof(struct btrfs_block_group_item));
|
||||
btrfs_set_header_bytenr(buf, cfg->blocks[MKFS_BLOCK_GROUP_TREE]);
|
||||
btrfs_set_header_owner(buf, BTRFS_BLOCK_GROUP_TREE_OBJECTID);
|
||||
btrfs_set_header_nritems(buf, 1);
|
||||
csum_tree_block_size(buf, btrfs_csum_type_size(cfg->csum_type), 0,
|
||||
cfg->csum_type);
|
||||
ret = pwrite(fd, buf->data, cfg->nodesize,
|
||||
cfg->blocks[MKFS_BLOCK_GROUP_TREE]);
|
||||
if (ret != cfg->nodesize)
|
||||
return ret < 0 ? -errno : -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @fs_uuid - if NULL, generates a UUID, returns back the new filesystem UUID
|
||||
*
|
||||
|
@ -239,11 +285,19 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
|
|||
bool add_block_group = true;
|
||||
bool free_space_tree = !!(cfg->runtime_features &
|
||||
BTRFS_RUNTIME_FEATURE_FREE_SPACE_TREE);
|
||||
bool extent_tree_v2 = !!(cfg->features &
|
||||
BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2);
|
||||
|
||||
/* Don't include the free space tree in the blocks to process. */
|
||||
if (!free_space_tree)
|
||||
blocks_nr--;
|
||||
|
||||
if (extent_tree_v2) {
|
||||
blocks = extent_tree_v2_blocks;
|
||||
blocks_nr = ARRAY_SIZE(extent_tree_v2_blocks);
|
||||
add_block_group = false;
|
||||
}
|
||||
|
||||
if ((cfg->features & BTRFS_FEATURE_INCOMPAT_ZONED)) {
|
||||
system_group_offset = cfg->zone_size * BTRFS_NR_SB_LOG_ZONES;
|
||||
system_group_size = cfg->zone_size;
|
||||
|
@ -300,6 +354,12 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
|
|||
btrfs_set_super_compat_ro_flags(&super, ro_flags);
|
||||
btrfs_set_super_cache_generation(&super, 0);
|
||||
}
|
||||
if (extent_tree_v2) {
|
||||
btrfs_set_super_block_group_root(&super,
|
||||
cfg->blocks[MKFS_BLOCK_GROUP_TREE]);
|
||||
btrfs_set_super_block_group_root_generation(&super, 1);
|
||||
btrfs_set_super_block_group_root_level(&super, 0);
|
||||
}
|
||||
if (cfg->label)
|
||||
__strncpy_null(super.label, cfg->label, BTRFS_LABEL_SIZE - 1);
|
||||
|
||||
|
@ -331,25 +391,12 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
|
|||
|
||||
/* Add the block group item for our temporary chunk. */
|
||||
if (cfg->blocks[blk] > system_group_offset && add_block_group) {
|
||||
struct btrfs_block_group_item *bg_item;
|
||||
|
||||
itemoff -= sizeof(struct btrfs_block_group_item);
|
||||
write_block_group_item(buf, nritems,
|
||||
system_group_offset,
|
||||
system_group_size, total_used,
|
||||
itemoff);
|
||||
add_block_group = false;
|
||||
|
||||
itemoff -= sizeof(*bg_item);
|
||||
btrfs_set_disk_key_objectid(&disk_key, system_group_offset);
|
||||
btrfs_set_disk_key_offset(&disk_key, system_group_size);
|
||||
btrfs_set_disk_key_type(&disk_key, BTRFS_BLOCK_GROUP_ITEM_KEY);
|
||||
btrfs_set_item_key(buf, &disk_key, nritems);
|
||||
btrfs_set_item_offset(buf, nritems, itemoff);
|
||||
btrfs_set_item_size(buf, nritems, sizeof(*bg_item));
|
||||
|
||||
bg_item = btrfs_item_ptr(buf, nritems,
|
||||
struct btrfs_block_group_item);
|
||||
btrfs_set_block_group_used(buf, bg_item, total_used);
|
||||
btrfs_set_block_group_flags(buf, bg_item,
|
||||
BTRFS_BLOCK_GROUP_SYSTEM);
|
||||
btrfs_set_block_group_chunk_objectid(buf, bg_item,
|
||||
BTRFS_FIRST_CHUNK_TREE_OBJECTID);
|
||||
nritems++;
|
||||
}
|
||||
|
||||
|
@ -565,6 +612,14 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (extent_tree_v2) {
|
||||
ret = create_block_group_tree(fd, cfg, buf,
|
||||
system_group_offset,
|
||||
system_group_size, total_used);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* and write out the super block */
|
||||
memset(buf->data, 0, BTRFS_SUPER_INFO_SIZE);
|
||||
memcpy(buf->data, &super, sizeof(super));
|
||||
|
|
|
@ -51,6 +51,7 @@ enum btrfs_mkfs_block {
|
|||
MKFS_FS_TREE,
|
||||
MKFS_CSUM_TREE,
|
||||
MKFS_FREE_SPACE_TREE,
|
||||
MKFS_BLOCK_GROUP_TREE,
|
||||
MKFS_BLOCK_COUNT
|
||||
};
|
||||
|
||||
|
@ -69,6 +70,17 @@ static const enum btrfs_mkfs_block extent_tree_v1_blocks[] = {
|
|||
MKFS_FREE_SPACE_TREE,
|
||||
};
|
||||
|
||||
static const enum btrfs_mkfs_block extent_tree_v2_blocks[] = {
|
||||
MKFS_ROOT_TREE,
|
||||
MKFS_EXTENT_TREE,
|
||||
MKFS_CHUNK_TREE,
|
||||
MKFS_DEV_TREE,
|
||||
MKFS_FS_TREE,
|
||||
MKFS_CSUM_TREE,
|
||||
MKFS_FREE_SPACE_TREE,
|
||||
MKFS_BLOCK_GROUP_TREE,
|
||||
};
|
||||
|
||||
struct btrfs_mkfs_config {
|
||||
/* Label of the new filesystem */
|
||||
const char *label;
|
||||
|
|
|
@ -299,6 +299,11 @@ static int recow_roots(struct btrfs_trans_handle *trans,
|
|||
ret = __recow_root(trans, info->dev_root);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (btrfs_fs_incompat(info, EXTENT_TREE_V2)) {
|
||||
ret = __recow_root(trans, info->block_group_root);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = recow_global_roots(trans);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
Loading…
Reference in New Issue