btrfs-progs: btrfstune: add ability to restore unfinished fsid change
Now change_uuid() can auto detected unfinished fsid change and restore it. Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.cz>
This commit is contained in:
parent
e737a9d56b
commit
0522713f3c
60
btrfstune.c
60
btrfstune.c
|
@ -267,7 +267,9 @@ out:
|
||||||
|
|
||||||
static int change_fsid_prepare(struct btrfs_fs_info *fs_info)
|
static int change_fsid_prepare(struct btrfs_fs_info *fs_info)
|
||||||
{
|
{
|
||||||
|
struct btrfs_root *tree_root = fs_info->tree_root;
|
||||||
u64 flags = btrfs_super_flags(fs_info->super_copy);
|
u64 flags = btrfs_super_flags(fs_info->super_copy);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (!fs_info->new_fsid && !fs_info->new_chunk_tree_uuid)
|
if (!fs_info->new_fsid && !fs_info->new_chunk_tree_uuid)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -276,7 +278,16 @@ static int change_fsid_prepare(struct btrfs_fs_info *fs_info)
|
||||||
flags |= BTRFS_SUPER_FLAG_CHANGING_FSID;
|
flags |= BTRFS_SUPER_FLAG_CHANGING_FSID;
|
||||||
btrfs_set_super_flags(fs_info->super_copy, flags);
|
btrfs_set_super_flags(fs_info->super_copy, flags);
|
||||||
|
|
||||||
return write_all_supers(fs_info->tree_root);
|
memcpy(fs_info->super_copy->fsid, fs_info->new_fsid, BTRFS_FSID_SIZE);
|
||||||
|
ret = write_all_supers(tree_root);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* also restore new chunk_tree_id into tree_root for restore */
|
||||||
|
write_extent_buffer(tree_root->node, fs_info->new_chunk_tree_uuid,
|
||||||
|
btrfs_header_chunk_tree_uuid(tree_root->node),
|
||||||
|
BTRFS_UUID_SIZE);
|
||||||
|
return write_tree_block(NULL, tree_root, tree_root->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int change_fsid_done(struct btrfs_fs_info *fs_info)
|
static int change_fsid_done(struct btrfs_fs_info *fs_info)
|
||||||
|
@ -293,10 +304,32 @@ static int change_fsid_done(struct btrfs_fs_info *fs_info)
|
||||||
return write_all_supers(fs_info->tree_root);
|
return write_all_supers(fs_info->tree_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return 0 for no unfinished fsid change.
|
||||||
|
* Return >0 for unfinished fsid change, and restore unfinished fsid/
|
||||||
|
* chunk_tree_id into fsid_ret/chunk_id_ret.
|
||||||
|
*/
|
||||||
|
static int check_unfinished_fsid_change(struct btrfs_fs_info *fs_info,
|
||||||
|
uuid_t fsid_ret, uuid_t chunk_id_ret)
|
||||||
|
{
|
||||||
|
struct btrfs_root *tree_root = fs_info->tree_root;
|
||||||
|
u64 flags = btrfs_super_flags(fs_info->super_copy);
|
||||||
|
|
||||||
|
if (flags & BTRFS_SUPER_FLAG_CHANGING_FSID) {
|
||||||
|
memcpy(fsid_ret, fs_info->super_copy->fsid, BTRFS_FSID_SIZE);
|
||||||
|
read_extent_buffer(tree_root->node, chunk_id_ret,
|
||||||
|
btrfs_header_chunk_tree_uuid(tree_root->node),
|
||||||
|
BTRFS_UUID_SIZE);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change fsid of a given fs.
|
* Change fsid of a given fs.
|
||||||
*
|
*
|
||||||
* If new_fsid_str is not given, use a random generated UUID.
|
* If new_fsid_str is not given, use a random generated UUID.
|
||||||
|
* Caller should check new_fsid_str is valid
|
||||||
*/
|
*/
|
||||||
static int change_uuid(struct btrfs_fs_info *fs_info, const char *new_fsid_str)
|
static int change_uuid(struct btrfs_fs_info *fs_info, const char *new_fsid_str)
|
||||||
{
|
{
|
||||||
|
@ -305,13 +338,26 @@ static int change_uuid(struct btrfs_fs_info *fs_info, const char *new_fsid_str)
|
||||||
char uuid_buf[BTRFS_UUID_UNPARSED_SIZE];
|
char uuid_buf[BTRFS_UUID_UNPARSED_SIZE];
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* caller should do extra check on passed uuid */
|
if (check_unfinished_fsid_change(fs_info, new_fsid, new_chunk_id)) {
|
||||||
if (new_fsid_str)
|
if (new_fsid_str) {
|
||||||
uuid_parse(new_fsid_str, new_fsid);
|
uuid_t tmp;
|
||||||
else
|
|
||||||
uuid_generate(new_fsid);
|
|
||||||
|
|
||||||
uuid_generate(new_chunk_id);
|
uuid_parse(new_fsid_str, tmp);
|
||||||
|
if (memcmp(tmp, new_fsid, BTRFS_FSID_SIZE)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"ERROR: New fsid %s is not the same with unfinished fsid change\n",
|
||||||
|
new_fsid_str);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (new_fsid_str)
|
||||||
|
uuid_parse(new_fsid_str, new_fsid);
|
||||||
|
else
|
||||||
|
uuid_generate(new_fsid);
|
||||||
|
|
||||||
|
uuid_generate(new_chunk_id);
|
||||||
|
}
|
||||||
fs_info->new_fsid = new_fsid;
|
fs_info->new_fsid = new_fsid;
|
||||||
fs_info->new_chunk_tree_uuid = new_chunk_id;
|
fs_info->new_chunk_tree_uuid = new_chunk_id;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue