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;
|
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,
|
static int fixup_chunks_and_devices(struct btrfs_fs_info *fs_info,
|
||||||
struct mdrestore_struct *mdres, int out_fd)
|
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);
|
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);
|
fixup_block_groups(trans);
|
||||||
ret = fixup_dev_extents(trans);
|
ret = fixup_dev_extents(trans);
|
||||||
if (ret < 0)
|
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);
|
error("unable to commit transaction: %d", ret);
|
||||||
return 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;
|
return 0;
|
||||||
error:
|
error:
|
||||||
errno = -ret;
|
errno = -ret;
|
||||||
|
Loading…
Reference in New Issue
Block a user