Linux Btrfs filesystem development
 help / color / mirror / Atom feed
From: Qu Wenruo <wqu@suse.com>
To: linux-btrfs@vger.kernel.org
Cc: "S ." <sb56637@gmail.com>
Subject: Re: [PATCH] btrfs-progs: rescue: introduce clear-uuid-tree
Date: Thu, 11 Nov 2021 10:55:43 +0800	[thread overview]
Message-ID: <03f2bdbd-c2de-e492-84f9-19a78826ab9b@suse.com> (raw)
In-Reply-To: <20211111024138.41687-1-wqu@suse.com>



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
>   	}
>   };
> 


  reply	other threads:[~2021-11-11  2:55 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-11  2:41 [PATCH] btrfs-progs: rescue: introduce clear-uuid-tree Qu Wenruo
2021-11-11  2:55 ` Qu Wenruo [this message]
2021-11-11  6:37 ` Nikolay Borisov
2021-11-11  6:53   ` Qu Wenruo
2021-11-15 16:33   ` David Sterba

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=03f2bdbd-c2de-e492-84f9-19a78826ab9b@suse.com \
    --to=wqu@suse.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=sb56637@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox