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
> }
> };
>
next prev parent 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