diff mbox series

btrfs-progs: rescue: introduce clear-uuid-tree

Message ID 20211111024138.41687-1-wqu@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs-progs: rescue: introduce clear-uuid-tree | expand

Commit Message

Qu Wenruo Nov. 11, 2021, 2:41 a.m. UTC
[BUG]
There is a bug report that a corrupted key type (expected
UUID_KEY_SUBVOL, has EXTENT_ITEM) causing newer kernel to reject a
mount.

Although the root cause is not determined yet, with roll out of v5.11
kernel to various distros, such problem should be prevented by
tree-checker, no matter if it's hardware problem or not.

And older kernel with "-o uuid_rescan" mount option won't help, as
uuid_rescan will only delete items with
UUID_KEY_SUBVOL/UUID_KEY_RECEIVED_SUBVOL key types, not deleting such
corrupted key.

[FIX]
To fix such problem we have to rely on offline tool, thus there we
introduce a new rescue tool, clear-uuid-tree, to empty and then remove
uuid tree.

Kernel will re-generate the correct uuid tree at next mount.

Reported-by: S. <sb56637@gmail.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 cmds/rescue.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 104 insertions(+)

Comments

Qu Wenruo Nov. 11, 2021, 2:55 a.m. UTC | #1
On 2021/11/11 10:41, Qu Wenruo wrote:
> [BUG]
> There is a bug report that a corrupted key type (expected
> UUID_KEY_SUBVOL, has EXTENT_ITEM) causing newer kernel to reject a
> mount.
> 
> Although the root cause is not determined yet, with roll out of v5.11
> kernel to various distros, such problem should be prevented by
> tree-checker, no matter if it's hardware problem or not.
> 
> And older kernel with "-o uuid_rescan" mount option won't help, as
> uuid_rescan will only delete items with
> UUID_KEY_SUBVOL/UUID_KEY_RECEIVED_SUBVOL key types, not deleting such
> corrupted key.
> 
> [FIX]
> To fix such problem we have to rely on offline tool, thus there we
> introduce a new rescue tool, clear-uuid-tree, to empty and then remove
> uuid tree.
> 
> Kernel will re-generate the correct uuid tree at next mount.
> 
> Reported-by: S. <sb56637@gmail.com>
> Signed-off-by: Qu Wenruo <wqu@suse.com>
> ---
>   cmds/rescue.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++

Oh no, forgot doc again....

>   1 file changed, 104 insertions(+)
> 
> diff --git a/cmds/rescue.c b/cmds/rescue.c
> index a98b255ad328..8b5b619da4f6 100644
> --- a/cmds/rescue.c
> +++ b/cmds/rescue.c
> @@ -296,6 +296,109 @@ static int cmd_rescue_create_control_device(const struct cmd_struct *cmd,
>   }
>   static DEFINE_SIMPLE_COMMAND(rescue_create_control_device, "create-control-device");
>   
> +static int clear_uuid_tree(struct btrfs_fs_info *fs_info)
> +{
> +	struct btrfs_root *uuid_root = fs_info->uuid_root;
> +	struct btrfs_trans_handle *trans;
> +	struct btrfs_path path = {};
> +	struct btrfs_key key = {};
> +	int ret;
> +
> +	if (!uuid_root)
> +		return 0;
> +
> +	fs_info->uuid_root = NULL;
> +	trans = btrfs_start_transaction(fs_info->tree_root, 0);
> +	if (IS_ERR(trans))
> +		return PTR_ERR(trans);
> +
> +	while (1) {
> +		int nr;
> +
> +		ret = btrfs_search_slot(trans, uuid_root, &key, &path, -1, 1);
> +		if (ret < 0)
> +			goto out;
> +		ASSERT(ret > 0);
> +		ASSERT(path.slots[0] == 0);
> +
> +		nr = btrfs_header_nritems(path.nodes[0]);
> +		if (nr == 0) {
> +			btrfs_release_path(&path);
> +			break;
> +		}
> +
> +		ret = btrfs_del_items(trans, uuid_root, &path, 0, nr);
> +		btrfs_release_path(&path);
> +		if (ret < 0)
> +			goto out;
> +	}
> +	ret = btrfs_del_root(trans, fs_info->tree_root, &uuid_root->root_key);
> +	if (ret < 0)
> +		goto out;
> +	list_del(&uuid_root->dirty_list);
> +	ret = clean_tree_block(uuid_root->node);
> +	if (ret < 0)
> +		goto out;
> +	ret = btrfs_free_tree_block(trans, uuid_root, uuid_root->node, 0, 1);
> +	if (ret < 0)
> +		goto out;
> +	free_extent_buffer(uuid_root->node);
> +	free_extent_buffer(uuid_root->commit_root);
> +	kfree(uuid_root);
> +out:
> +	if (ret < 0)
> +		btrfs_abort_transaction(trans, ret);
> +	else
> +		ret = btrfs_commit_transaction(trans, fs_info->tree_root);
> +	return ret;
> +}
> +
> +static const char * const cmd_rescue_clear_uuid_tree_usage[] = {
> +	"btrfs rescue clear-uuid-tree",
> +	"Delete uuid tree so that kernel can rebuild it at mount time",
> +	NULL,
> +};
> +
> +static int cmd_rescue_clear_uuid_tree(const struct cmd_struct *cmd,
> +				      int argc, char **argv)
> +{
> +	struct btrfs_fs_info *fs_info;
> +	struct open_ctree_flags ocf = {};
> +	char *devname;
> +	int ret;
> +
> +	clean_args_no_options(cmd, argc, argv);
> +	if (check_argc_exact(argc, 2))
> +		return -EINVAL;
> +
> +	devname = argv[optind];
> +	ret = check_mounted(devname);
> +	if (ret < 0) {
> +		errno = -ret;
> +		error("could not check mount status: %m");
> +		goto out;
> +	} else if (ret) {
> +		error("%s is currently mounted", devname);
> +		ret = -EBUSY;
> +		goto out;
> +	}
> +	ocf.filename = devname;
> +	ocf.flags = OPEN_CTREE_WRITES | OPEN_CTREE_PARTIAL;
> +	fs_info = open_ctree_fs_info(&ocf);
> +	if (!fs_info) {
> +		error("could not open btrfs");
> +		ret = -EIO;
> +		goto out;
> +	}
> +
> +	ret = clear_uuid_tree(fs_info);
> +	close_ctree(fs_info->tree_root);
> +out:
> +	return !!ret;
> +}
> +
> +static DEFINE_SIMPLE_COMMAND(rescue_clear_uuid_tree, "clear-uuid-tree");
> +
>   static const char rescue_cmd_group_info[] =
>   "toolbox for specific rescue operations";
>   
> @@ -306,6 +409,7 @@ static const struct cmd_group rescue_cmd_group = {
>   		&cmd_struct_rescue_zero_log,
>   		&cmd_struct_rescue_fix_device_size,
>   		&cmd_struct_rescue_create_control_device,
> +		&cmd_struct_rescue_clear_uuid_tree,
>   		NULL
>   	}
>   };
>
Nikolay Borisov Nov. 11, 2021, 6:37 a.m. UTC | #2
On 11.11.21 г. 4:41, Qu Wenruo wrote:
> [BUG]
> There is a bug report that a corrupted key type (expected
> UUID_KEY_SUBVOL, has EXTENT_ITEM) causing newer kernel to reject a
> mount.
> 
> Although the root cause is not determined yet, with roll out of v5.11
> kernel to various distros, such problem should be prevented by
> tree-checker, no matter if it's hardware problem or not.
> 
> And older kernel with "-o uuid_rescan" mount option won't help, as
> uuid_rescan will only delete items with
> UUID_KEY_SUBVOL/UUID_KEY_RECEIVED_SUBVOL key types, not deleting such
> corrupted key.
> 
> [FIX]
> To fix such problem we have to rely on offline tool, thus there we
> introduce a new rescue tool, clear-uuid-tree, to empty and then remove
> uuid tree.
> 
> Kernel will re-generate the correct uuid tree at next mount.

SHouldn't this be made part of btrfs repair, why do we need specific
rescue subcom ?

> 
> Reported-by: S. <sb56637@gmail.com>
> Signed-off-by: Qu Wenruo <wqu@suse.com>
> ---
>  cmds/rescue.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 104 insertions(+)
> 
> diff --git a/cmds/rescue.c b/cmds/rescue.c
> index a98b255ad328..8b5b619da4f6 100644
> --- a/cmds/rescue.c
> +++ b/cmds/rescue.c
> @@ -296,6 +296,109 @@ static int cmd_rescue_create_control_device(const struct cmd_struct *cmd,
>  }
>  static DEFINE_SIMPLE_COMMAND(rescue_create_control_device, "create-control-device");
>  
> +static int clear_uuid_tree(struct btrfs_fs_info *fs_info)
> +{
> +	struct btrfs_root *uuid_root = fs_info->uuid_root;
> +	struct btrfs_trans_handle *trans;
> +	struct btrfs_path path = {};
> +	struct btrfs_key key = {};
> +	int ret;
> +
> +	if (!uuid_root)
> +		return 0;
> +
> +	fs_info->uuid_root = NULL;
> +	trans = btrfs_start_transaction(fs_info->tree_root, 0);
> +	if (IS_ERR(trans))
> +		return PTR_ERR(trans);
> +
> +	while (1) {
> +		int nr;
> +
> +		ret = btrfs_search_slot(trans, uuid_root, &key, &path, -1, 1);
> +		if (ret < 0)
> +			goto out;
> +		ASSERT(ret > 0);
> +		ASSERT(path.slots[0] == 0);
> +
> +		nr = btrfs_header_nritems(path.nodes[0]);
> +		if (nr == 0) {
> +			btrfs_release_path(&path);
> +			break;
> +		}
> +
> +		ret = btrfs_del_items(trans, uuid_root, &path, 0, nr);
> +		btrfs_release_path(&path);
> +		if (ret < 0)
> +			goto out;
> +	}
> +	ret = btrfs_del_root(trans, fs_info->tree_root, &uuid_root->root_key);
> +	if (ret < 0)
> +		goto out;
> +	list_del(&uuid_root->dirty_list);
> +	ret = clean_tree_block(uuid_root->node);
> +	if (ret < 0)
> +		goto out;
> +	ret = btrfs_free_tree_block(trans, uuid_root, uuid_root->node, 0, 1);
> +	if (ret < 0)
> +		goto out;
> +	free_extent_buffer(uuid_root->node);
> +	free_extent_buffer(uuid_root->commit_root);
> +	kfree(uuid_root);
> +out:
> +	if (ret < 0)
> +		btrfs_abort_transaction(trans, ret);
> +	else
> +		ret = btrfs_commit_transaction(trans, fs_info->tree_root);
> +	return ret;
> +}
> +
> +static const char * const cmd_rescue_clear_uuid_tree_usage[] = {
> +	"btrfs rescue clear-uuid-tree",
> +	"Delete uuid tree so that kernel can rebuild it at mount time",
> +	NULL,
> +};
> +
> +static int cmd_rescue_clear_uuid_tree(const struct cmd_struct *cmd,
> +				      int argc, char **argv)
> +{
> +	struct btrfs_fs_info *fs_info;
> +	struct open_ctree_flags ocf = {};
> +	char *devname;
> +	int ret;
> +
> +	clean_args_no_options(cmd, argc, argv);
> +	if (check_argc_exact(argc, 2))
> +		return -EINVAL;
> +
> +	devname = argv[optind];
> +	ret = check_mounted(devname);
> +	if (ret < 0) {
> +		errno = -ret;
> +		error("could not check mount status: %m");
> +		goto out;
> +	} else if (ret) {
> +		error("%s is currently mounted", devname);
> +		ret = -EBUSY;
> +		goto out;
> +	}
> +	ocf.filename = devname;
> +	ocf.flags = OPEN_CTREE_WRITES | OPEN_CTREE_PARTIAL;
> +	fs_info = open_ctree_fs_info(&ocf);
> +	if (!fs_info) {
> +		error("could not open btrfs");
> +		ret = -EIO;
> +		goto out;
> +	}
> +
> +	ret = clear_uuid_tree(fs_info);
> +	close_ctree(fs_info->tree_root);
> +out:
> +	return !!ret;
> +}
> +
> +static DEFINE_SIMPLE_COMMAND(rescue_clear_uuid_tree, "clear-uuid-tree");
> +
>  static const char rescue_cmd_group_info[] =
>  "toolbox for specific rescue operations";
>  
> @@ -306,6 +409,7 @@ static const struct cmd_group rescue_cmd_group = {
>  		&cmd_struct_rescue_zero_log,
>  		&cmd_struct_rescue_fix_device_size,
>  		&cmd_struct_rescue_create_control_device,
> +		&cmd_struct_rescue_clear_uuid_tree,
>  		NULL
>  	}
>  };
>
Qu Wenruo Nov. 11, 2021, 6:53 a.m. UTC | #3
On 2021/11/11 14:37, Nikolay Borisov wrote:
>
>
> On 11.11.21 г. 4:41, Qu Wenruo wrote:
>> [BUG]
>> There is a bug report that a corrupted key type (expected
>> UUID_KEY_SUBVOL, has EXTENT_ITEM) causing newer kernel to reject a
>> mount.
>>
>> Although the root cause is not determined yet, with roll out of v5.11
>> kernel to various distros, such problem should be prevented by
>> tree-checker, no matter if it's hardware problem or not.
>>
>> And older kernel with "-o uuid_rescan" mount option won't help, as
>> uuid_rescan will only delete items with
>> UUID_KEY_SUBVOL/UUID_KEY_RECEIVED_SUBVOL key types, not deleting such
>> corrupted key.
>>
>> [FIX]
>> To fix such problem we have to rely on offline tool, thus there we
>> introduce a new rescue tool, clear-uuid-tree, to empty and then remove
>> uuid tree.
>>
>> Kernel will re-generate the correct uuid tree at next mount.
>
> SHouldn't this be made part of btrfs repair, why do we need specific
> rescue subcom ?

Because btrfs check doesn't yet check uuid tree at all, and the problem
we hit here should be pretty rare, thus I prefer to just remove the uuid
tree and let newer kernel to regenerate it.

Thanks,
Qu
>
>>
>> Reported-by: S. <sb56637@gmail.com>
>> Signed-off-by: Qu Wenruo <wqu@suse.com>
>> ---
>>   cmds/rescue.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 104 insertions(+)
>>
>> diff --git a/cmds/rescue.c b/cmds/rescue.c
>> index a98b255ad328..8b5b619da4f6 100644
>> --- a/cmds/rescue.c
>> +++ b/cmds/rescue.c
>> @@ -296,6 +296,109 @@ static int cmd_rescue_create_control_device(const struct cmd_struct *cmd,
>>   }
>>   static DEFINE_SIMPLE_COMMAND(rescue_create_control_device, "create-control-device");
>>
>> +static int clear_uuid_tree(struct btrfs_fs_info *fs_info)
>> +{
>> +	struct btrfs_root *uuid_root = fs_info->uuid_root;
>> +	struct btrfs_trans_handle *trans;
>> +	struct btrfs_path path = {};
>> +	struct btrfs_key key = {};
>> +	int ret;
>> +
>> +	if (!uuid_root)
>> +		return 0;
>> +
>> +	fs_info->uuid_root = NULL;
>> +	trans = btrfs_start_transaction(fs_info->tree_root, 0);
>> +	if (IS_ERR(trans))
>> +		return PTR_ERR(trans);
>> +
>> +	while (1) {
>> +		int nr;
>> +
>> +		ret = btrfs_search_slot(trans, uuid_root, &key, &path, -1, 1);
>> +		if (ret < 0)
>> +			goto out;
>> +		ASSERT(ret > 0);
>> +		ASSERT(path.slots[0] == 0);
>> +
>> +		nr = btrfs_header_nritems(path.nodes[0]);
>> +		if (nr == 0) {
>> +			btrfs_release_path(&path);
>> +			break;
>> +		}
>> +
>> +		ret = btrfs_del_items(trans, uuid_root, &path, 0, nr);
>> +		btrfs_release_path(&path);
>> +		if (ret < 0)
>> +			goto out;
>> +	}
>> +	ret = btrfs_del_root(trans, fs_info->tree_root, &uuid_root->root_key);
>> +	if (ret < 0)
>> +		goto out;
>> +	list_del(&uuid_root->dirty_list);
>> +	ret = clean_tree_block(uuid_root->node);
>> +	if (ret < 0)
>> +		goto out;
>> +	ret = btrfs_free_tree_block(trans, uuid_root, uuid_root->node, 0, 1);
>> +	if (ret < 0)
>> +		goto out;
>> +	free_extent_buffer(uuid_root->node);
>> +	free_extent_buffer(uuid_root->commit_root);
>> +	kfree(uuid_root);
>> +out:
>> +	if (ret < 0)
>> +		btrfs_abort_transaction(trans, ret);
>> +	else
>> +		ret = btrfs_commit_transaction(trans, fs_info->tree_root);
>> +	return ret;
>> +}
>> +
>> +static const char * const cmd_rescue_clear_uuid_tree_usage[] = {
>> +	"btrfs rescue clear-uuid-tree",
>> +	"Delete uuid tree so that kernel can rebuild it at mount time",
>> +	NULL,
>> +};
>> +
>> +static int cmd_rescue_clear_uuid_tree(const struct cmd_struct *cmd,
>> +				      int argc, char **argv)
>> +{
>> +	struct btrfs_fs_info *fs_info;
>> +	struct open_ctree_flags ocf = {};
>> +	char *devname;
>> +	int ret;
>> +
>> +	clean_args_no_options(cmd, argc, argv);
>> +	if (check_argc_exact(argc, 2))
>> +		return -EINVAL;
>> +
>> +	devname = argv[optind];
>> +	ret = check_mounted(devname);
>> +	if (ret < 0) {
>> +		errno = -ret;
>> +		error("could not check mount status: %m");
>> +		goto out;
>> +	} else if (ret) {
>> +		error("%s is currently mounted", devname);
>> +		ret = -EBUSY;
>> +		goto out;
>> +	}
>> +	ocf.filename = devname;
>> +	ocf.flags = OPEN_CTREE_WRITES | OPEN_CTREE_PARTIAL;
>> +	fs_info = open_ctree_fs_info(&ocf);
>> +	if (!fs_info) {
>> +		error("could not open btrfs");
>> +		ret = -EIO;
>> +		goto out;
>> +	}
>> +
>> +	ret = clear_uuid_tree(fs_info);
>> +	close_ctree(fs_info->tree_root);
>> +out:
>> +	return !!ret;
>> +}
>> +
>> +static DEFINE_SIMPLE_COMMAND(rescue_clear_uuid_tree, "clear-uuid-tree");
>> +
>>   static const char rescue_cmd_group_info[] =
>>   "toolbox for specific rescue operations";
>>
>> @@ -306,6 +409,7 @@ static const struct cmd_group rescue_cmd_group = {
>>   		&cmd_struct_rescue_zero_log,
>>   		&cmd_struct_rescue_fix_device_size,
>>   		&cmd_struct_rescue_create_control_device,
>> +		&cmd_struct_rescue_clear_uuid_tree,
>>   		NULL
>>   	}
>>   };
>>
David Sterba Nov. 15, 2021, 4:33 p.m. UTC | #4
On Thu, Nov 11, 2021 at 08:37:24AM +0200, Nikolay Borisov wrote:
> On 11.11.21 г. 4:41, Qu Wenruo wrote:
> > [BUG]
> > There is a bug report that a corrupted key type (expected
> > UUID_KEY_SUBVOL, has EXTENT_ITEM) causing newer kernel to reject a
> > mount.
> > 
> > Although the root cause is not determined yet, with roll out of v5.11
> > kernel to various distros, such problem should be prevented by
> > tree-checker, no matter if it's hardware problem or not.
> > 
> > And older kernel with "-o uuid_rescan" mount option won't help, as
> > uuid_rescan will only delete items with
> > UUID_KEY_SUBVOL/UUID_KEY_RECEIVED_SUBVOL key types, not deleting such
> > corrupted key.
> > 
> > [FIX]
> > To fix such problem we have to rely on offline tool, thus there we
> > introduce a new rescue tool, clear-uuid-tree, to empty and then remove
> > uuid tree.
> > 
> > Kernel will re-generate the correct uuid tree at next mount.
> 
> SHouldn't this be made part of btrfs repair, why do we need specific
> rescue subcom ?

This is a one-shot fix for that we have the rescue subcommand, check
could do a normal pass and verify the tree but that's a bit different
what this patch does and requiring --repair goes opposite to what we
recommend to do.
diff mbox series

Patch

diff --git a/cmds/rescue.c b/cmds/rescue.c
index a98b255ad328..8b5b619da4f6 100644
--- a/cmds/rescue.c
+++ b/cmds/rescue.c
@@ -296,6 +296,109 @@  static int cmd_rescue_create_control_device(const struct cmd_struct *cmd,
 }
 static DEFINE_SIMPLE_COMMAND(rescue_create_control_device, "create-control-device");
 
+static int clear_uuid_tree(struct btrfs_fs_info *fs_info)
+{
+	struct btrfs_root *uuid_root = fs_info->uuid_root;
+	struct btrfs_trans_handle *trans;
+	struct btrfs_path path = {};
+	struct btrfs_key key = {};
+	int ret;
+
+	if (!uuid_root)
+		return 0;
+
+	fs_info->uuid_root = NULL;
+	trans = btrfs_start_transaction(fs_info->tree_root, 0);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
+
+	while (1) {
+		int nr;
+
+		ret = btrfs_search_slot(trans, uuid_root, &key, &path, -1, 1);
+		if (ret < 0)
+			goto out;
+		ASSERT(ret > 0);
+		ASSERT(path.slots[0] == 0);
+
+		nr = btrfs_header_nritems(path.nodes[0]);
+		if (nr == 0) {
+			btrfs_release_path(&path);
+			break;
+		}
+
+		ret = btrfs_del_items(trans, uuid_root, &path, 0, nr);
+		btrfs_release_path(&path);
+		if (ret < 0)
+			goto out;
+	}
+	ret = btrfs_del_root(trans, fs_info->tree_root, &uuid_root->root_key);
+	if (ret < 0)
+		goto out;
+	list_del(&uuid_root->dirty_list);
+	ret = clean_tree_block(uuid_root->node);
+	if (ret < 0)
+		goto out;
+	ret = btrfs_free_tree_block(trans, uuid_root, uuid_root->node, 0, 1);
+	if (ret < 0)
+		goto out;
+	free_extent_buffer(uuid_root->node);
+	free_extent_buffer(uuid_root->commit_root);
+	kfree(uuid_root);
+out:
+	if (ret < 0)
+		btrfs_abort_transaction(trans, ret);
+	else
+		ret = btrfs_commit_transaction(trans, fs_info->tree_root);
+	return ret;
+}
+
+static const char * const cmd_rescue_clear_uuid_tree_usage[] = {
+	"btrfs rescue clear-uuid-tree",
+	"Delete uuid tree so that kernel can rebuild it at mount time",
+	NULL,
+};
+
+static int cmd_rescue_clear_uuid_tree(const struct cmd_struct *cmd,
+				      int argc, char **argv)
+{
+	struct btrfs_fs_info *fs_info;
+	struct open_ctree_flags ocf = {};
+	char *devname;
+	int ret;
+
+	clean_args_no_options(cmd, argc, argv);
+	if (check_argc_exact(argc, 2))
+		return -EINVAL;
+
+	devname = argv[optind];
+	ret = check_mounted(devname);
+	if (ret < 0) {
+		errno = -ret;
+		error("could not check mount status: %m");
+		goto out;
+	} else if (ret) {
+		error("%s is currently mounted", devname);
+		ret = -EBUSY;
+		goto out;
+	}
+	ocf.filename = devname;
+	ocf.flags = OPEN_CTREE_WRITES | OPEN_CTREE_PARTIAL;
+	fs_info = open_ctree_fs_info(&ocf);
+	if (!fs_info) {
+		error("could not open btrfs");
+		ret = -EIO;
+		goto out;
+	}
+
+	ret = clear_uuid_tree(fs_info);
+	close_ctree(fs_info->tree_root);
+out:
+	return !!ret;
+}
+
+static DEFINE_SIMPLE_COMMAND(rescue_clear_uuid_tree, "clear-uuid-tree");
+
 static const char rescue_cmd_group_info[] =
 "toolbox for specific rescue operations";
 
@@ -306,6 +409,7 @@  static const struct cmd_group rescue_cmd_group = {
 		&cmd_struct_rescue_zero_log,
 		&cmd_struct_rescue_fix_device_size,
 		&cmd_struct_rescue_create_control_device,
+		&cmd_struct_rescue_clear_uuid_tree,
 		NULL
 	}
 };