All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gui Hecheng <guihc.fnst@cn.fujitsu.com>
To: <linux-btrfs@vger.kernel.org>
Cc: Gui Hecheng <guihc.fnst@cn.fujitsu.com>
Subject: [PATCH 2/2] btrfs-progs: convert: fix unable to rollback case with removed empty block groups
Date: Wed, 26 Nov 2014 10:43:41 +0800	[thread overview]
Message-ID: <1416969821-2729-2-git-send-email-guihc.fnst@cn.fujitsu.com> (raw)
In-Reply-To: <1416969821-2729-1-git-send-email-guihc.fnst@cn.fujitsu.com>

Run fstests: btrfs/012 will fail with message:
	unable to do rollback

It is because the rollback function checks sequentially each piece of space
to map to a certain block group. If some piece doesn't, rollback refuses to continue.

After kernel commit:
	commit 47ab2a6c689913db23ccae38349714edf8365e0a
	Btrfs: remove empty block groups automatically

Empty block groups are removed, so there are possible gaps:

	|--block group 1--|	|--block group 2--|
			     ^
			     |
			    gap

So the piece of space of the gap belongs to a removed empty block group,
and rollback should detect this case, and feel free to continue.

Signed-off-by: Gui Hecheng <guihc.fnst@cn.fujitsu.com>
---
 btrfs-convert.c | 13 +++++++++++--
 volumes.c       |  2 ++
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/btrfs-convert.c b/btrfs-convert.c
index a544fc6..504c7b3 100644
--- a/btrfs-convert.c
+++ b/btrfs-convert.c
@@ -2368,8 +2368,17 @@ static int may_rollback(struct btrfs_root *root)
 	while (1) {
 		ret = btrfs_map_block(&info->mapping_tree, WRITE, bytenr,
 				      &length, &multi, 0, NULL);
-		if (ret)
+		if (ret) {
+			if (ret == -ENOENT) {
+				/* removed block group at the tail */
+				if (length == (u64)-1)
+					break;
+
+				/* removed block group in the middle */
+				goto next;
+			}
 			goto fail;
+		}
 
 		num_stripes = multi->num_stripes;
 		physical = multi->stripes[0].physical;
@@ -2377,7 +2386,7 @@ static int may_rollback(struct btrfs_root *root)
 
 		if (num_stripes != 1 || physical != bytenr)
 			goto fail;
-
+next:
 		bytenr += length;
 		if (bytenr >= total_bytes)
 			break;
diff --git a/volumes.c b/volumes.c
index a1fd162..a988cdb 100644
--- a/volumes.c
+++ b/volumes.c
@@ -1318,10 +1318,12 @@ again:
 	ce = search_cache_extent(&map_tree->cache_tree, logical);
 	if (!ce) {
 		kfree(multi);
+		*length = (u64)-1;
 		return -ENOENT;
 	}
 	if (ce->start > logical) {
 		kfree(multi);
+		*length = ce->start - logical;
 		return -ENOENT;
 	}
 
-- 
1.8.1.4


      reply	other threads:[~2014-11-26  2:45 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-26  2:43 [PATCH 1/2] btrfs-progs: remove dead condition for btrfs_map_block Gui Hecheng
2014-11-26  2:43 ` Gui Hecheng [this message]

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=1416969821-2729-2-git-send-email-guihc.fnst@cn.fujitsu.com \
    --to=guihc.fnst@cn.fujitsu.com \
    --cc=linux-btrfs@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.