linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Konstantinos Skarlatos <k.skarlatos@gmail.com>
To: Qu Wenruo <wqu@suse.com>, linux-btrfs@vger.kernel.org
Subject: Re: [PATCH] btrfs-progs: fix failed resume due to bad search
Date: Thu, 28 Sep 2023 17:53:11 +0300	[thread overview]
Message-ID: <fc926390-38ea-f764-4377-25576b872b31@gmail.com> (raw)
In-Reply-To: <840a9a762a3a0b8365d79dd7c23d812d95761dcf.1695855009.git.wqu@suse.com>

Hi Qu, thanks for your patch. I just tried it on a clean btrfs-progs 
tree with my filesystem:

❯ ./btrfstune --convert-to-block-group-tree /dev/sda
[1]    796483 segmentation fault (core dumped)  ./btrfstune 
--convert-to-block-group-tree /dev/sda

Sep 28 17:46:17 elsinki kernel: btrfstune[796483]: segfault at 
ffffffffff000f2f ip 0000564b6c2107aa sp 00007ffdc8ad25c8 error 5 in 
btrfstune[564b6c1d1000+5b000] likely on CPU 3 (core 2, socket 0)
Sep 28 17:46:17 elsinki kernel: Code: ff 48 8b 34 24 48 8d 3d 5a d8 01 
00 b8 00 00 00 00 e8 5a 37 00 00 48 8b 33 bf 0a 00 00 00 e8 1d 0c fc ff 
eb a8 e8 86 0a fc ff <48> 8b 4f 20 48 8b 56 08 48 89 c8 48 03 47 28 48 
89 c7 b8 01 00 00
Sep 28 17:46:17 elsinki systemd[1]: Created slice Slice 
/system/systemd-coredump.
Sep 28 17:46:17 elsinki systemd[1]: Started Process Core Dump (PID 
796493/UID 0).
Sep 28 17:46:21 elsinki systemd-coredump[796494]: [🡕] Process 796483 
(btrfstune) of user 0 dumped core.

                                                   Stack trace of thread 
796483:
                                                   #0 0x0000564b6c2107aa 
n/a (/root/btrfs-progs/btrfstune + 0x4d7aa)
                                                   ELF object binary 
architecture: AMD x86-64
Sep 28 17:46:21 elsinki systemd[1]: systemd-coredump@0-796493-0.service: 
Deactivated successfully.
Sep 28 17:46:21 elsinki systemd[1]: systemd-coredump@0-796493-0.service: 
Consumed 4.248s CPU time.


On 28/9/2023 1:50 π.μ., Qu Wenruo wrote:
> [BUG]
> There is a bug report that when converting to bg tree crashed, the
> resulted fs is unable to be resumed.
>
> This problems comes with the following error messages:
>
>    ./btrfstune --convert-to-block-group-tree /dev/sda
>    ERROR: Corrupted fs, no valid METADATA block group found
>    ERROR: failed to delete block group item from the old root: -117
>    ERROR: failed to convert the filesystem to block group tree feature
>    ERROR: btrfstune failed
>    extent buffer leak: start 17825576632320 len 16384
>
> [CAUSE]
> When resuming a interrupted conversion, we go through
> read_converting_block_groups() to handle block group items in both
> extent and block group trees.
>
> However for the block group items in the extent tree, there are several
> problems involved:
>
> - Uninitialized @key inside read_old_block_groups_from_root()
>    Here we only set @key.type, not setting @key.objectid for the initial
>    search.
>
>    Thus if we're unlukcy, we can got (u64)-1 as key.objectid, and exit
>    the search immediately.
>
> - Wrong search direction
>    The conversion is converting block groups in descending order, but the
>    block groups read is in ascending order.
>    Meaning if we start from the last converted block group, we would at
>    most read one block group.
>
> [FIX]
> To fix the problems, this patch would just remove
> read_old_block_groups_from_root() function completely.
>
> As for the conversion, we ensured the block group item is either in the
> old extent or the new block group tree.
> Thus there is no special handling needed reading block groups.
>
> We only need to read all block groups from both trees, using the same
> read_old_block_groups_from_root() function.
>
> Reported-by: Konstantinos Skarlatos <k.skarlatos@gmail.com>
> Signed-off-by: Qu Wenruo <wqu@suse.com>
> ---
> To Konstantinos:
>
> The bug I fixed here can explain all the failures you hit (the initial
> one and the one after the quick diff).
>
> Please verify if this helps and report back (without the quick diff in
> the original thread).
>
> We may have other corner cases to go, but I believe the patch itself is
> necessary no matter what, as the deleted code is really
> over-engineered and buggy.
> ---
>   kernel-shared/extent-tree.c | 79 +------------------------------------
>   1 file changed, 1 insertion(+), 78 deletions(-)
>
> diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c
> index 7022643a9843..4d6bf2b228e9 100644
> --- a/kernel-shared/extent-tree.c
> +++ b/kernel-shared/extent-tree.c
> @@ -2852,83 +2852,6 @@ out:
>   	return ret;
>   }
>   
> -/*
> - * Helper to read old block groups items from specified root.
> - *
> - * The difference between this and read_block_groups_from_root() is,
> - * we will exit if we have already read the last bg in the old root.
> - *
> - * This is to avoid wasting time finding bg items which should be in the
> - * new root.
> - */
> -static int read_old_block_groups_from_root(struct btrfs_fs_info *fs_info,
> -					   struct btrfs_root *root)
> -{
> -	struct btrfs_path path = {0};
> -	struct btrfs_key key;
> -	struct cache_extent *ce;
> -	/* The last block group bytenr in the old root. */
> -	u64 last_bg_in_old_root;
> -	int ret;
> -
> -	if (fs_info->last_converted_bg_bytenr != (u64)-1) {
> -		/*
> -		 * We know the last converted bg in the other tree, load the chunk
> -		 * before that last converted as our last bg in the tree.
> -		 */
> -		ce = search_cache_extent(&fs_info->mapping_tree.cache_tree,
> -			         fs_info->last_converted_bg_bytenr);
> -		if (!ce || ce->start != fs_info->last_converted_bg_bytenr) {
> -			error("no chunk found for bytenr %llu",
> -			      fs_info->last_converted_bg_bytenr);
> -			return -ENOENT;
> -		}
> -		ce = prev_cache_extent(ce);
> -		/*
> -		 * We should have previous unconverted chunk, or we have
> -		 * already finished the convert.
> -		 */
> -		ASSERT(ce);
> -
> -		last_bg_in_old_root = ce->start;
> -	} else {
> -		last_bg_in_old_root = (u64)-1;
> -	}
> -
> -	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
> -
> -	while (true) {
> -		ret = find_first_block_group(root, &path, &key);
> -		if (ret > 0) {
> -			ret = 0;
> -			goto out;
> -		}
> -		if (ret != 0) {
> -			goto out;
> -		}
> -		btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
> -
> -		ret = read_one_block_group(fs_info, &path);
> -		if (ret < 0 && ret != -ENOENT)
> -			goto out;
> -
> -		/* We have reached last bg in the old root, no need to continue */
> -		if (key.objectid >= last_bg_in_old_root)
> -			break;
> -
> -		if (key.offset == 0)
> -			key.objectid++;
> -		else
> -			key.objectid = key.objectid + key.offset;
> -		key.offset = 0;
> -		btrfs_release_path(&path);
> -	}
> -	ret = 0;
> -out:
> -	btrfs_release_path(&path);
> -	return ret;
> -}
> -
>   /* Helper to read all block groups items from specified root. */
>   static int read_block_groups_from_root(struct btrfs_fs_info *fs_info,
>   					   struct btrfs_root *root)
> @@ -2989,7 +2912,7 @@ static int read_converting_block_groups(struct btrfs_fs_info *fs_info)
>   		return ret;
>   	}
>   
> -	ret = read_old_block_groups_from_root(fs_info, old_root);
> +	ret = read_block_groups_from_root(fs_info, old_root);
>   	if (ret < 0) {
>   		error("failed to load block groups from the old root: %d", ret);
>   		return ret;

  reply	other threads:[~2023-09-28 14:53 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-27 22:50 [PATCH] btrfs-progs: fix failed resume due to bad search Qu Wenruo
2023-09-28 14:53 ` Konstantinos Skarlatos [this message]
2023-09-28 21:56   ` Qu Wenruo
2023-09-29  9:33     ` Konstantinos Skarlatos
2023-09-29 10:54       ` Qu Wenruo
2023-09-29 11:31         ` Konstantinos Skarlatos
2023-09-29 22:25           ` Qu Wenruo
2023-09-30 13:01             ` Konstantinos Skarlatos
2023-09-30 21:22               ` Qu Wenruo
2023-10-01 13:09                 ` Konstantinos Skarlatos
2023-10-01 23:33                   ` Qu Wenruo
2023-10-02 10:32                     ` Konstantinos Skarlatos
2023-10-03  0:01                       ` Qu Wenruo
2023-10-03 10:21                         ` Konstantinos Skarlatos

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=fc926390-38ea-f764-4377-25576b872b31@gmail.com \
    --to=k.skarlatos@gmail.com \
    --cc=linux-btrfs@vger.kernel.org \
    --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;
as well as URLs for NNTP newsgroup(s).