aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fb.com>2016-09-23 07:23:28 -0400
committerDavid Sterba <dsterba@suse.com>2016-09-26 13:37:06 -0400
commit4867268c57ff709a7b6b86ae6f6537d846d1443a (patch)
treee0237d6308ff83ad8dde872e0f3f4eedbe5b6952
parent2fd57fcb16483d718043940fd6dfeb176d4dc09c (diff)
Btrfs: don't BUG() during drop snapshot
Really there's lots of things that can go wrong here, kill all the BUG_ON()'s and replace the logic ones with ASSERT()'s and return EIO instead. Signed-off-by: Josef Bacik <jbacik@fb.com> [ switched to btrfs_err, errors go to common label ] Reviewed-by: Liu Bo <bo.li.liu@oracle.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/extent-tree.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index a23597f6d3cd..11802eaaab54 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -8886,15 +8886,13 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
8886 ret = btrfs_lookup_extent_info(trans, root, bytenr, level - 1, 1, 8886 ret = btrfs_lookup_extent_info(trans, root, bytenr, level - 1, 1,
8887 &wc->refs[level - 1], 8887 &wc->refs[level - 1],
8888 &wc->flags[level - 1]); 8888 &wc->flags[level - 1]);
8889 if (ret < 0) { 8889 if (ret < 0)
8890 btrfs_tree_unlock(next); 8890 goto out_unlock;
8891 free_extent_buffer(next);
8892 return ret;
8893 }
8894 8891
8895 if (unlikely(wc->refs[level - 1] == 0)) { 8892 if (unlikely(wc->refs[level - 1] == 0)) {
8896 btrfs_err(root->fs_info, "Missing references."); 8893 btrfs_err(root->fs_info, "Missing references.");
8897 BUG(); 8894 ret = -EIO;
8895 goto out_unlock;
8898 } 8896 }
8899 *lookup_info = 0; 8897 *lookup_info = 0;
8900 8898
@@ -8946,7 +8944,12 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
8946 } 8944 }
8947 8945
8948 level--; 8946 level--;
8949 BUG_ON(level != btrfs_header_level(next)); 8947 ASSERT(level == btrfs_header_level(next));
8948 if (level != btrfs_header_level(next)) {
8949 btrfs_err(root->fs_info, "mismatched level");
8950 ret = -EIO;
8951 goto out_unlock;
8952 }
8950 path->nodes[level] = next; 8953 path->nodes[level] = next;
8951 path->slots[level] = 0; 8954 path->slots[level] = 0;
8952 path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; 8955 path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
@@ -8961,8 +8964,15 @@ skip:
8961 if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) { 8964 if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
8962 parent = path->nodes[level]->start; 8965 parent = path->nodes[level]->start;
8963 } else { 8966 } else {
8964 BUG_ON(root->root_key.objectid != 8967 ASSERT(root->root_key.objectid ==
8965 btrfs_header_owner(path->nodes[level])); 8968 btrfs_header_owner(path->nodes[level]));
8969 if (root->root_key.objectid !=
8970 btrfs_header_owner(path->nodes[level])) {
8971 btrfs_err(root->fs_info,
8972 "mismatched block owner");
8973 ret = -EIO;
8974 goto out_unlock;
8975 }
8966 parent = 0; 8976 parent = 0;
8967 } 8977 }
8968 8978
@@ -8977,12 +8987,18 @@ skip:
8977 } 8987 }
8978 ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent, 8988 ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent,
8979 root->root_key.objectid, level - 1, 0); 8989 root->root_key.objectid, level - 1, 0);
8980 BUG_ON(ret); /* -ENOMEM */ 8990 if (ret)
8991 goto out_unlock;
8981 } 8992 }
8993
8994 *lookup_info = 1;
8995 ret = 1;
8996
8997out_unlock:
8982 btrfs_tree_unlock(next); 8998 btrfs_tree_unlock(next);
8983 free_extent_buffer(next); 8999 free_extent_buffer(next);
8984 *lookup_info = 1; 9000
8985 return 1; 9001 return ret;
8986} 9002}
8987 9003
8988/* 9004/*