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_FS_TREE] = BTRFS_FS_TREE_OBJECTID,
|
||||||
[MKFS_CSUM_TREE] = BTRFS_CSUM_TREE_OBJECTID,
|
[MKFS_CSUM_TREE] = BTRFS_CSUM_TREE_OBJECTID,
|
||||||
[MKFS_FREE_SPACE_TREE] = BTRFS_FREE_SPACE_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,
|
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++) {
|
for (i = 0; i < blocks_nr; i++) {
|
||||||
blk = blocks[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;
|
continue;
|
||||||
|
|
||||||
btrfs_set_root_bytenr(&root_item, cfg->blocks[blk]);
|
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;
|
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
|
* @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 add_block_group = true;
|
||||||
bool free_space_tree = !!(cfg->runtime_features &
|
bool free_space_tree = !!(cfg->runtime_features &
|
||||||
BTRFS_RUNTIME_FEATURE_FREE_SPACE_TREE);
|
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. */
|
/* Don't include the free space tree in the blocks to process. */
|
||||||
if (!free_space_tree)
|
if (!free_space_tree)
|
||||||
blocks_nr--;
|
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)) {
|
if ((cfg->features & BTRFS_FEATURE_INCOMPAT_ZONED)) {
|
||||||
system_group_offset = cfg->zone_size * BTRFS_NR_SB_LOG_ZONES;
|
system_group_offset = cfg->zone_size * BTRFS_NR_SB_LOG_ZONES;
|
||||||
system_group_size = cfg->zone_size;
|
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_compat_ro_flags(&super, ro_flags);
|
||||||
btrfs_set_super_cache_generation(&super, 0);
|
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)
|
if (cfg->label)
|
||||||
__strncpy_null(super.label, cfg->label, BTRFS_LABEL_SIZE - 1);
|
__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. */
|
/* Add the block group item for our temporary chunk. */
|
||||||
if (cfg->blocks[blk] > system_group_offset && add_block_group) {
|
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;
|
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++;
|
nritems++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,6 +612,14 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
|
||||||
goto out;
|
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 */
|
/* and write out the super block */
|
||||||
memset(buf->data, 0, BTRFS_SUPER_INFO_SIZE);
|
memset(buf->data, 0, BTRFS_SUPER_INFO_SIZE);
|
||||||
memcpy(buf->data, &super, sizeof(super));
|
memcpy(buf->data, &super, sizeof(super));
|
||||||
|
|
|
@ -51,6 +51,7 @@ enum btrfs_mkfs_block {
|
||||||
MKFS_FS_TREE,
|
MKFS_FS_TREE,
|
||||||
MKFS_CSUM_TREE,
|
MKFS_CSUM_TREE,
|
||||||
MKFS_FREE_SPACE_TREE,
|
MKFS_FREE_SPACE_TREE,
|
||||||
|
MKFS_BLOCK_GROUP_TREE,
|
||||||
MKFS_BLOCK_COUNT
|
MKFS_BLOCK_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -69,6 +70,17 @@ static const enum btrfs_mkfs_block extent_tree_v1_blocks[] = {
|
||||||
MKFS_FREE_SPACE_TREE,
|
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 {
|
struct btrfs_mkfs_config {
|
||||||
/* Label of the new filesystem */
|
/* Label of the new filesystem */
|
||||||
const char *label;
|
const char *label;
|
||||||
|
|
|
@ -299,6 +299,11 @@ static int recow_roots(struct btrfs_trans_handle *trans,
|
||||||
ret = __recow_root(trans, info->dev_root);
|
ret = __recow_root(trans, info->dev_root);
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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);
|
ret = recow_global_roots(trans);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in New Issue