From: Qu Wenruo <quwenruo.btrfs@gmx.com>
To: Nikolay Borisov <nborisov@suse.com>, Qu Wenruo <wqu@suse.com>,
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 14:53:58 +0800 [thread overview]
Message-ID: <68ad2de1-6b5e-7709-36f5-84c61d0e5079@gmx.com> (raw)
In-Reply-To: <3644e6ea-1756-5fd0-106b-2d130f6a2c2b@suse.com>
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
>> }
>> };
>>
next prev parent reply other threads:[~2021-11-11 6:54 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
2021-11-11 6:37 ` Nikolay Borisov
2021-11-11 6:53 ` Qu Wenruo [this message]
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=68ad2de1-6b5e-7709-36f5-84c61d0e5079@gmx.com \
--to=quwenruo.btrfs@gmx.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=nborisov@suse.com \
--cc=sb56637@gmail.com \
--cc=wqu@suse.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