[ 3.5.y.z extended stable ] Patch "Btrfs: fix panic when recovering tree log" has been added to staging queue

Luis Henriques luis.henriques at canonical.com
Tue Mar 12 14:29:19 UTC 2013

This is a note to let you know that I have just added a patch titled

    Btrfs: fix panic when recovering tree log

to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree 
which can be found at:


If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.y.z tree, see



>From 1d558c6e90f1ffab131843b56a4c1c5483730dda Mon Sep 17 00:00:00 2001
From: Josef Bacik <jbacik at fusionio.com>
Date: Tue, 18 Dec 2012 11:39:19 -0500
Subject: [PATCH] Btrfs: fix panic when recovering tree log

commit b0175117b9376a69978bbe80af26fb95dddbd53e upstream.

A user reported a BUG_ON(ret) that occured during tree log replay.  Ret was
-EAGAIN, so what I think happened is that we removed an extent that covered
a bitmap entry and an extent entry.  We remove the part from the bitmap and
return -EAGAIN and then search for the next piece we want to remove, which
happens to be an entire extent entry, so we just free the sucker and return.
The problem is ret is still set to -EAGAIN so we trip the BUG_ON().  The
user used btrfs-zero-log so I'm not 100% sure this is what happened so I've
added a WARN_ON() to catch the other possibility.  Thanks,

Reported-by: Jan Steffens <jan.steffens at gmail.com>
Signed-off-by: Josef Bacik <jbacik at fusionio.com>
Signed-off-by: Luis Henriques <luis.henriques at canonical.com>
 fs/btrfs/free-space-cache.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 6c4e2ba..c6ae3f4 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -1876,11 +1876,13 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
 	struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
 	struct btrfs_free_space *info;
-	int ret = 0;
+	int ret;
+	bool re_search = false;


+	ret = 0;
 	if (!bytes)
 		goto out_lock;

@@ -1893,17 +1895,17 @@ again:
 		info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset),
 					  1, 0);
 		if (!info) {
-			/* the tree logging code might be calling us before we
-			 * have fully loaded the free space rbtree for this
-			 * block group.  So it is possible the entry won't
-			 * be in the rbtree yet at all.  The caching code
-			 * will make sure not to put it in the rbtree if
-			 * the logging code has pinned it.
+			/*
+			 * If we found a partial bit of our free space in a
+			 * bitmap but then couldn't find the other part this may
+			 * be a problem, so WARN about it.
+			WARN_ON(re_search);
 			goto out_lock;

+	re_search = false;
 	if (!info->bitmap) {
 		unlink_free_space(ctl, info);
 		if (offset == info->offset) {
@@ -1949,8 +1951,10 @@ again:

 	ret = remove_from_bitmap(ctl, info, &offset, &bytes);
-	if (ret == -EAGAIN)
+	if (ret == -EAGAIN) {
+		re_search = true;
 		goto again;
+	}
 	BUG_ON(ret); /* logic error */

More information about the kernel-team mailing list