diff mbox

Btrfs: return gracefully from balance if fs tree is corrupted

Message ID 1473868306-30578-1-git-send-email-bo.li.liu@oracle.com (mailing list archive)
State Accepted
Headers show

Commit Message

Liu Bo Sept. 14, 2016, 3:51 p.m. UTC
When relocating tree blocks, we firstly get block information from
back references in the extent tree, we then search fs tree to try to
find all parents of a block.

However, if fs tree is corrupted, eg. if there're some missing
items, we could come across these WARN_ONs and BUG_ONs.

This makes us print some error messages and return gracefully
from balance.

Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
---
 fs/btrfs/relocation.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

Comments

Josef Bacik Sept. 14, 2016, 5:04 p.m. UTC | #1
On 09/14/2016 11:51 AM, Liu Bo wrote:
> When relocating tree blocks, we firstly get block information from
> back references in the extent tree, we then search fs tree to try to
> find all parents of a block.
>
> However, if fs tree is corrupted, eg. if there're some missing
> items, we could come across these WARN_ONs and BUG_ONs.
>
> This makes us print some error messages and return gracefully
> from balance.
>
> Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
> ---
>  fs/btrfs/relocation.c | 23 +++++++++++++++++------
>  1 file changed, 17 insertions(+), 6 deletions(-)
>
> diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
> index c0c13dc..680e234 100644
> --- a/fs/btrfs/relocation.c
> +++ b/fs/btrfs/relocation.c
> @@ -923,9 +923,16 @@ again:
>  			path2->slots[level]--;
>
>  		eb = path2->nodes[level];
> -		WARN_ON(btrfs_node_blockptr(eb, path2->slots[level]) !=
> -			cur->bytenr);
> -
> +		if (btrfs_node_blockptr(eb, path2->slots[level]) !=
> +		    cur->bytenr) {
> +			btrfs_err(root->fs_info,
> +	"couldn't find block (%llu) (level %d) in tree (%llu) with key (%llu %u %llu)",
> +				  cur->bytenr, level - 1, root->objectid,
> +				  node_key->objectid, node_key->type,
> +				  node_key->offset);
> +			err = -ENOENT;
> +			goto out;
> +		}
>  		lower = cur;
>  		need_check = true;
>  		for (; level < BTRFS_MAX_LEVEL; level++) {
> @@ -2686,11 +2693,15 @@ static int do_relocation(struct btrfs_trans_handle *trans,
>
>  		if (!upper->eb) {
>  			ret = btrfs_search_slot(trans, root, key, path, 0, 1);
> -			if (ret < 0) {
> -				err = ret;
> +			if (ret) {
> +				if (ret < 0)
> +					err = ret;
> +				else
> +					err = -ENOENT;
> +
> +				btrfs_release_path(path);
>  				break;
>  			}
> -			BUG_ON(ret > 0);
>
>  			if (!upper->eb) {
>  				upper->eb = path->nodes[upper->level];
>

Reviewed-by: Josef Bacik <jbacik@fb.com>

Thanks,

Josef
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index c0c13dc..680e234 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -923,9 +923,16 @@  again:
 			path2->slots[level]--;
 
 		eb = path2->nodes[level];
-		WARN_ON(btrfs_node_blockptr(eb, path2->slots[level]) !=
-			cur->bytenr);
-
+		if (btrfs_node_blockptr(eb, path2->slots[level]) !=
+		    cur->bytenr) {
+			btrfs_err(root->fs_info,
+	"couldn't find block (%llu) (level %d) in tree (%llu) with key (%llu %u %llu)",
+				  cur->bytenr, level - 1, root->objectid,
+				  node_key->objectid, node_key->type,
+				  node_key->offset);
+			err = -ENOENT;
+			goto out;
+		}
 		lower = cur;
 		need_check = true;
 		for (; level < BTRFS_MAX_LEVEL; level++) {
@@ -2686,11 +2693,15 @@  static int do_relocation(struct btrfs_trans_handle *trans,
 
 		if (!upper->eb) {
 			ret = btrfs_search_slot(trans, root, key, path, 0, 1);
-			if (ret < 0) {
-				err = ret;
+			if (ret) {
+				if (ret < 0)
+					err = ret;
+				else
+					err = -ENOENT;
+
+				btrfs_release_path(path);
 				break;
 			}
-			BUG_ON(ret > 0);
 
 			if (!upper->eb) {
 				upper->eb = path->nodes[upper->level];