aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Bo <bo.li.liu@oracle.com>2016-09-14 11:51:46 -0400
committerDavid Sterba <dsterba@suse.com>2016-09-26 11:59:49 -0400
commit3561b9db70928f207be4570b48fc19898eeaef54 (patch)
treeda7291956ca31e0717a99d2d8471fe42bb19065f
parent9c8e63db1de98c5cc3c6fb32d11b5cf55f228601 (diff)
Btrfs: return gracefully from balance if fs tree is corrupted
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> Reviewed-by: Josef Bacik <jbacik@fb.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/relocation.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 83fc51f786ab..8e7c78ba77d9 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -923,9 +923,16 @@ again:
923 path2->slots[level]--; 923 path2->slots[level]--;
924 924
925 eb = path2->nodes[level]; 925 eb = path2->nodes[level];
926 WARN_ON(btrfs_node_blockptr(eb, path2->slots[level]) != 926 if (btrfs_node_blockptr(eb, path2->slots[level]) !=
927 cur->bytenr); 927 cur->bytenr) {
928 928 btrfs_err(root->fs_info,
929 "couldn't find block (%llu) (level %d) in tree (%llu) with key (%llu %u %llu)",
930 cur->bytenr, level - 1, root->objectid,
931 node_key->objectid, node_key->type,
932 node_key->offset);
933 err = -ENOENT;
934 goto out;
935 }
929 lower = cur; 936 lower = cur;
930 need_check = true; 937 need_check = true;
931 for (; level < BTRFS_MAX_LEVEL; level++) { 938 for (; level < BTRFS_MAX_LEVEL; level++) {
@@ -2686,11 +2693,15 @@ static int do_relocation(struct btrfs_trans_handle *trans,
2686 2693
2687 if (!upper->eb) { 2694 if (!upper->eb) {
2688 ret = btrfs_search_slot(trans, root, key, path, 0, 1); 2695 ret = btrfs_search_slot(trans, root, key, path, 0, 1);
2689 if (ret < 0) { 2696 if (ret) {
2690 err = ret; 2697 if (ret < 0)
2698 err = ret;
2699 else
2700 err = -ENOENT;
2701
2702 btrfs_release_path(path);
2691 break; 2703 break;
2692 } 2704 }
2693 BUG_ON(ret > 0);
2694 2705
2695 if (!upper->eb) { 2706 if (!upper->eb) {
2696 upper->eb = path->nodes[upper->level]; 2707 upper->eb = path->nodes[upper->level];