mirror of
https://github.com/kdave/btrfs-progs
synced 2025-01-11 16:29:42 +00:00
btrfs-progs: image: pin down log tree blocks before fixup
Although btrfs-image will dump log tree, we will modify the restored image if it's not a multi-device restore. In that case, since log tree blocks are not recorded in the extent tree, extent allocator will try to re-use the tree blocks belonging to log trees, this would lead to transid mismatch if btrfs-restore chooses to do device/chunk fixup. This patch will fix such problem by pinning down all the log trees blocks before fixing up the device and chunk trees. Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
73dd4e3c87
commit
b602b22884
64
image/main.c
64
image/main.c
@ -2500,6 +2500,66 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iter_tree_blocks(struct btrfs_fs_info *fs_info,
|
||||
struct extent_buffer *eb, bool pin)
|
||||
{
|
||||
void (*func)(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes);
|
||||
int nritems;
|
||||
int level;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (pin)
|
||||
func = btrfs_pin_extent;
|
||||
else
|
||||
func = btrfs_unpin_extent;
|
||||
|
||||
func(fs_info, eb->start, eb->len);
|
||||
|
||||
level = btrfs_header_level(eb);
|
||||
nritems = btrfs_header_nritems(eb);
|
||||
if (level == 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < nritems; i++) {
|
||||
u64 bytenr;
|
||||
struct extent_buffer *tmp;
|
||||
|
||||
if (level == 0) {
|
||||
struct btrfs_root_item *ri;
|
||||
struct btrfs_key key;
|
||||
|
||||
btrfs_item_key_to_cpu(eb, &key, i);
|
||||
if (key.type != BTRFS_ROOT_ITEM_KEY)
|
||||
continue;
|
||||
ri = btrfs_item_ptr(eb, i, struct btrfs_root_item);
|
||||
bytenr = btrfs_disk_root_bytenr(eb, ri);
|
||||
tmp = read_tree_block(fs_info, bytenr, 0);
|
||||
if (!extent_buffer_uptodate(tmp)) {
|
||||
error("unable to read log root block");
|
||||
return -EIO;
|
||||
}
|
||||
ret = iter_tree_blocks(fs_info, tmp, pin);
|
||||
free_extent_buffer(tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
bytenr = btrfs_node_blockptr(eb, i);
|
||||
tmp = read_tree_block(fs_info, bytenr, 0);
|
||||
if (!extent_buffer_uptodate(tmp)) {
|
||||
error("unable to read log root block");
|
||||
return -EIO;
|
||||
}
|
||||
ret = iter_tree_blocks(fs_info, tmp, pin);
|
||||
free_extent_buffer(tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fixup_chunks_and_devices(struct btrfs_fs_info *fs_info,
|
||||
struct mdrestore_struct *mdres, int out_fd)
|
||||
{
|
||||
@ -2516,6 +2576,8 @@ static int fixup_chunks_and_devices(struct btrfs_fs_info *fs_info,
|
||||
return PTR_ERR(trans);
|
||||
}
|
||||
|
||||
if (btrfs_super_log_root(fs_info->super_copy) && fs_info->log_root_tree)
|
||||
iter_tree_blocks(fs_info, fs_info->log_root_tree->node, true);
|
||||
fixup_block_groups(trans);
|
||||
ret = fixup_dev_extents(trans);
|
||||
if (ret < 0)
|
||||
@ -2530,6 +2592,8 @@ static int fixup_chunks_and_devices(struct btrfs_fs_info *fs_info,
|
||||
error("unable to commit transaction: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (btrfs_super_log_root(fs_info->super_copy) && fs_info->log_root_tree)
|
||||
iter_tree_blocks(fs_info, fs_info->log_root_tree->node, false);
|
||||
return 0;
|
||||
error:
|
||||
errno = -ret;
|
||||
|
Loading…
Reference in New Issue
Block a user