mirror of
https://github.com/kdave/btrfs-progs
synced 2025-01-31 09:51:38 +00:00
btrfs-progs: Introduce function to setup temporary tree root
Introduce new function, setup_temp_tree_root(), to initialize temporary tree root for make_btrfs_v2(). The new function will setup tree root at metadata chunk and ensure data won't be written into metadata chunk. Also, new make_btrfs_v2() will have a much better code structure than old make_btrfs(). Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
e86e5441a0
commit
df20ed3e5e
147
utils.c
147
utils.c
@ -306,6 +306,136 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup an extent buffer for tree block.
|
||||||
|
*/
|
||||||
|
static int setup_temp_extent_buffer(struct extent_buffer *buf,
|
||||||
|
struct btrfs_mkfs_config *cfg,
|
||||||
|
u64 bytenr, u64 owner)
|
||||||
|
{
|
||||||
|
unsigned char fsid[BTRFS_FSID_SIZE];
|
||||||
|
unsigned char chunk_uuid[BTRFS_UUID_SIZE];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* We rely on cfg->fs_uuid and chunk_uuid to fsid and chunk uuid */
|
||||||
|
BUG_ON(!cfg->fs_uuid || !cfg->chunk_uuid);
|
||||||
|
ret = uuid_parse(cfg->fs_uuid, fsid);
|
||||||
|
if (ret)
|
||||||
|
return -EINVAL;
|
||||||
|
ret = uuid_parse(cfg->chunk_uuid, chunk_uuid);
|
||||||
|
if (ret)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memset(buf->data, 0, cfg->nodesize);
|
||||||
|
buf->len = cfg->nodesize;
|
||||||
|
btrfs_set_header_bytenr(buf, bytenr);
|
||||||
|
btrfs_set_header_generation(buf, 1);
|
||||||
|
btrfs_set_header_backref_rev(buf, BTRFS_MIXED_BACKREF_REV);
|
||||||
|
btrfs_set_header_owner(buf, owner);
|
||||||
|
btrfs_set_header_flags(buf, BTRFS_HEADER_FLAG_WRITTEN);
|
||||||
|
write_extent_buffer(buf, chunk_uuid, btrfs_header_chunk_tree_uuid(buf),
|
||||||
|
BTRFS_UUID_SIZE);
|
||||||
|
write_extent_buffer(buf, fsid, btrfs_header_fsid(), BTRFS_FSID_SIZE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int write_temp_extent_buffer(int fd, struct extent_buffer *buf,
|
||||||
|
u64 bytenr)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
csum_tree_block_size(buf, BTRFS_CRC32_SIZE, 0);
|
||||||
|
|
||||||
|
/* Temporary extent buffer is always mapped 1:1 on disk */
|
||||||
|
ret = pwrite(fd, buf->data, buf->len, bytenr);
|
||||||
|
if (ret < buf->len)
|
||||||
|
ret = (ret < 0 ? ret : -EIO);
|
||||||
|
else
|
||||||
|
ret = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert a root item for temporary tree root
|
||||||
|
*
|
||||||
|
* Only used in make_btrfs_v2().
|
||||||
|
*/
|
||||||
|
static void insert_temp_root_item(struct extent_buffer *buf,
|
||||||
|
struct btrfs_mkfs_config *cfg,
|
||||||
|
int *slot, u32 *itemoff, u64 objectid,
|
||||||
|
u64 bytenr)
|
||||||
|
{
|
||||||
|
struct btrfs_root_item root_item;
|
||||||
|
struct btrfs_inode_item *inode_item;
|
||||||
|
struct btrfs_disk_key disk_key;
|
||||||
|
|
||||||
|
btrfs_set_header_nritems(buf, *slot + 1);
|
||||||
|
(*itemoff) -= sizeof(root_item);
|
||||||
|
memset(&root_item, 0, sizeof(root_item));
|
||||||
|
inode_item = &root_item.inode;
|
||||||
|
btrfs_set_stack_inode_generation(inode_item, 1);
|
||||||
|
btrfs_set_stack_inode_size(inode_item, 3);
|
||||||
|
btrfs_set_stack_inode_nlink(inode_item, 1);
|
||||||
|
btrfs_set_stack_inode_nbytes(inode_item, cfg->nodesize);
|
||||||
|
btrfs_set_stack_inode_mode(inode_item, S_IFDIR | 0755);
|
||||||
|
btrfs_set_root_refs(&root_item, 1);
|
||||||
|
btrfs_set_root_used(&root_item, cfg->nodesize);
|
||||||
|
btrfs_set_root_generation(&root_item, 1);
|
||||||
|
btrfs_set_root_bytenr(&root_item, bytenr);
|
||||||
|
|
||||||
|
memset(&disk_key, 0, sizeof(disk_key));
|
||||||
|
btrfs_set_disk_key_type(&disk_key, BTRFS_ROOT_ITEM_KEY);
|
||||||
|
btrfs_set_disk_key_objectid(&disk_key, objectid);
|
||||||
|
btrfs_set_disk_key_offset(&disk_key, 0);
|
||||||
|
|
||||||
|
btrfs_set_item_key(buf, &disk_key, *slot);
|
||||||
|
btrfs_set_item_offset(buf, btrfs_item_nr(*slot), *itemoff);
|
||||||
|
btrfs_set_item_size(buf, btrfs_item_nr(*slot), sizeof(root_item));
|
||||||
|
write_extent_buffer(buf, &root_item,
|
||||||
|
btrfs_item_ptr_offset(buf, *slot),
|
||||||
|
sizeof(root_item));
|
||||||
|
(*slot)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setup_temp_root_tree(int fd, struct btrfs_mkfs_config *cfg,
|
||||||
|
u64 root_bytenr, u64 extent_bytenr,
|
||||||
|
u64 dev_bytenr, u64 fs_bytenr, u64 csum_bytenr)
|
||||||
|
{
|
||||||
|
struct extent_buffer *buf = NULL;
|
||||||
|
u32 itemoff = __BTRFS_LEAF_DATA_SIZE(cfg->nodesize);
|
||||||
|
int slot = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Provided bytenr must in ascending order, or tree root will have a
|
||||||
|
* bad key order.
|
||||||
|
*/
|
||||||
|
BUG_ON(!(root_bytenr < extent_bytenr && extent_bytenr < dev_bytenr &&
|
||||||
|
dev_bytenr < fs_bytenr && fs_bytenr < csum_bytenr));
|
||||||
|
buf = malloc(sizeof(*buf) + cfg->nodesize);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = setup_temp_extent_buffer(buf, cfg, root_bytenr,
|
||||||
|
BTRFS_ROOT_TREE_OBJECTID);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
insert_temp_root_item(buf, cfg, &slot, &itemoff,
|
||||||
|
BTRFS_EXTENT_TREE_OBJECTID, extent_bytenr);
|
||||||
|
insert_temp_root_item(buf, cfg, &slot, &itemoff,
|
||||||
|
BTRFS_DEV_TREE_OBJECTID, dev_bytenr);
|
||||||
|
insert_temp_root_item(buf, cfg, &slot, &itemoff,
|
||||||
|
BTRFS_FS_TREE_OBJECTID, fs_bytenr);
|
||||||
|
insert_temp_root_item(buf, cfg, &slot, &itemoff,
|
||||||
|
BTRFS_CSUM_TREE_OBJECTID, csum_bytenr);
|
||||||
|
|
||||||
|
ret = write_temp_extent_buffer(fd, buf, root_bytenr);
|
||||||
|
out:
|
||||||
|
free(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Improved version of make_btrfs().
|
* Improved version of make_btrfs().
|
||||||
*
|
*
|
||||||
@ -328,6 +458,10 @@ static int make_convert_btrfs(int fd, struct btrfs_mkfs_config *cfg,
|
|||||||
u64 chunk_bytenr;
|
u64 chunk_bytenr;
|
||||||
/* metadata trees bytenr, in metadata chunk */
|
/* metadata trees bytenr, in metadata chunk */
|
||||||
u64 root_bytenr;
|
u64 root_bytenr;
|
||||||
|
u64 extent_bytenr;
|
||||||
|
u64 dev_bytenr;
|
||||||
|
u64 fs_bytenr;
|
||||||
|
u64 csum_bytenr;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Shouldn't happen */
|
/* Shouldn't happen */
|
||||||
@ -359,6 +493,8 @@ static int make_convert_btrfs(int fd, struct btrfs_mkfs_config *cfg,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* Allocated meta/sys chunks will be mapped 1:1 with device offset.
|
||||||
|
*
|
||||||
* Inside the allocated metadata chunk, the layout will be:
|
* Inside the allocated metadata chunk, the layout will be:
|
||||||
* | offset | contents |
|
* | offset | contents |
|
||||||
* -------------------------------------
|
* -------------------------------------
|
||||||
@ -376,9 +512,20 @@ static int make_convert_btrfs(int fd, struct btrfs_mkfs_config *cfg,
|
|||||||
*/
|
*/
|
||||||
chunk_bytenr = sys_chunk_start;
|
chunk_bytenr = sys_chunk_start;
|
||||||
root_bytenr = meta_chunk_start;
|
root_bytenr = meta_chunk_start;
|
||||||
|
extent_bytenr = meta_chunk_start + cfg->nodesize;
|
||||||
|
dev_bytenr = meta_chunk_start + cfg->nodesize * 2;
|
||||||
|
fs_bytenr = meta_chunk_start + cfg->nodesize * 3;
|
||||||
|
csum_bytenr = meta_chunk_start + cfg->nodesize * 4;
|
||||||
|
|
||||||
ret = setup_temp_super(fd, cfg, root_bytenr, chunk_bytenr);
|
ret = setup_temp_super(fd, cfg, root_bytenr, chunk_bytenr);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
ret = setup_temp_root_tree(fd, cfg, root_bytenr, extent_bytenr,
|
||||||
|
dev_bytenr, fs_bytenr, csum_bytenr);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user