Linux Btrfs filesystem development
 help / color / mirror / Atom feed
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
>>   	}
>>   };
>>

  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