aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fb.com>2014-09-19 10:40:00 -0400
committerChris Mason <clm@fb.com>2014-10-03 19:14:58 -0400
commit75bfb9aff45e44625260f52a5fd581b92ace3e62 (patch)
tree32fc26b1b21a237ed5e864b9fd94990a9b23932d
parent1d52c78afbbf80b58299e076a159617d6b42fe3c (diff)
Btrfs: cleanup error handling in build_backref_tree
When balance panics it tends to panic in the BUG_ON(!upper->checked); test, because it means it couldn't build the backref tree properly. This is annoying to users and frankly a recoverable error, nothing in this function is actually fatal since it is just an in-memory building of the backrefs for a given bytenr. So go through and change all the BUG_ON()'s to ASSERT()'s, and fix the BUG_ON(!upper->checked) thing to just return an error. This patch also fixes the error handling so it tears down the work we've done properly. This code was horribly broken since we always just panic'ed instead of actually erroring out, so it needed to be completely re-worked. With this patch my broken image no longer panics when I mount it. Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r--fs/btrfs/relocation.c88
1 files changed, 59 insertions, 29 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 2d221c46180c..19726af21230 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -736,7 +736,8 @@ again:
736 err = ret; 736 err = ret;
737 goto out; 737 goto out;
738 } 738 }
739 BUG_ON(!ret || !path1->slots[0]); 739 ASSERT(ret);
740 ASSERT(path1->slots[0]);
740 741
741 path1->slots[0]--; 742 path1->slots[0]--;
742 743
@@ -746,10 +747,10 @@ again:
746 * the backref was added previously when processing 747 * the backref was added previously when processing
747 * backref of type BTRFS_TREE_BLOCK_REF_KEY 748 * backref of type BTRFS_TREE_BLOCK_REF_KEY
748 */ 749 */
749 BUG_ON(!list_is_singular(&cur->upper)); 750 ASSERT(list_is_singular(&cur->upper));
750 edge = list_entry(cur->upper.next, struct backref_edge, 751 edge = list_entry(cur->upper.next, struct backref_edge,
751 list[LOWER]); 752 list[LOWER]);
752 BUG_ON(!list_empty(&edge->list[UPPER])); 753 ASSERT(list_empty(&edge->list[UPPER]));
753 exist = edge->node[UPPER]; 754 exist = edge->node[UPPER];
754 /* 755 /*
755 * add the upper level block to pending list if we need 756 * add the upper level block to pending list if we need
@@ -831,7 +832,7 @@ again:
831 cur->cowonly = 1; 832 cur->cowonly = 1;
832 } 833 }
833#else 834#else
834 BUG_ON(key.type == BTRFS_EXTENT_REF_V0_KEY); 835 ASSERT(key.type != BTRFS_EXTENT_REF_V0_KEY);
835 if (key.type == BTRFS_SHARED_BLOCK_REF_KEY) { 836 if (key.type == BTRFS_SHARED_BLOCK_REF_KEY) {
836#endif 837#endif
837 if (key.objectid == key.offset) { 838 if (key.objectid == key.offset) {
@@ -840,7 +841,7 @@ again:
840 * backref of this type. 841 * backref of this type.
841 */ 842 */
842 root = find_reloc_root(rc, cur->bytenr); 843 root = find_reloc_root(rc, cur->bytenr);
843 BUG_ON(!root); 844 ASSERT(root);
844 cur->root = root; 845 cur->root = root;
845 break; 846 break;
846 } 847 }
@@ -868,7 +869,7 @@ again:
868 } else { 869 } else {
869 upper = rb_entry(rb_node, struct backref_node, 870 upper = rb_entry(rb_node, struct backref_node,
870 rb_node); 871 rb_node);
871 BUG_ON(!upper->checked); 872 ASSERT(upper->checked);
872 INIT_LIST_HEAD(&edge->list[UPPER]); 873 INIT_LIST_HEAD(&edge->list[UPPER]);
873 } 874 }
874 list_add_tail(&edge->list[LOWER], &cur->upper); 875 list_add_tail(&edge->list[LOWER], &cur->upper);
@@ -892,7 +893,7 @@ again:
892 893
893 if (btrfs_root_level(&root->root_item) == cur->level) { 894 if (btrfs_root_level(&root->root_item) == cur->level) {
894 /* tree root */ 895 /* tree root */
895 BUG_ON(btrfs_root_bytenr(&root->root_item) != 896 ASSERT(btrfs_root_bytenr(&root->root_item) ==
896 cur->bytenr); 897 cur->bytenr);
897 if (should_ignore_root(root)) 898 if (should_ignore_root(root))
898 list_add(&cur->list, &useless); 899 list_add(&cur->list, &useless);
@@ -927,7 +928,7 @@ again:
927 need_check = true; 928 need_check = true;
928 for (; level < BTRFS_MAX_LEVEL; level++) { 929 for (; level < BTRFS_MAX_LEVEL; level++) {
929 if (!path2->nodes[level]) { 930 if (!path2->nodes[level]) {
930 BUG_ON(btrfs_root_bytenr(&root->root_item) != 931 ASSERT(btrfs_root_bytenr(&root->root_item) ==
931 lower->bytenr); 932 lower->bytenr);
932 if (should_ignore_root(root)) 933 if (should_ignore_root(root))
933 list_add(&lower->list, &useless); 934 list_add(&lower->list, &useless);
@@ -982,7 +983,7 @@ again:
982 } else { 983 } else {
983 upper = rb_entry(rb_node, struct backref_node, 984 upper = rb_entry(rb_node, struct backref_node,
984 rb_node); 985 rb_node);
985 BUG_ON(!upper->checked); 986 ASSERT(upper->checked);
986 INIT_LIST_HEAD(&edge->list[UPPER]); 987 INIT_LIST_HEAD(&edge->list[UPPER]);
987 if (!upper->owner) 988 if (!upper->owner)
988 upper->owner = btrfs_header_owner(eb); 989 upper->owner = btrfs_header_owner(eb);
@@ -1026,7 +1027,7 @@ next:
1026 * everything goes well, connect backref nodes and insert backref nodes 1027 * everything goes well, connect backref nodes and insert backref nodes
1027 * into the cache. 1028 * into the cache.
1028 */ 1029 */
1029 BUG_ON(!node->checked); 1030 ASSERT(node->checked);
1030 cowonly = node->cowonly; 1031 cowonly = node->cowonly;
1031 if (!cowonly) { 1032 if (!cowonly) {
1032 rb_node = tree_insert(&cache->rb_root, node->bytenr, 1033 rb_node = tree_insert(&cache->rb_root, node->bytenr,
@@ -1062,8 +1063,21 @@ next:
1062 continue; 1063 continue;
1063 } 1064 }
1064 1065
1065 BUG_ON(!upper->checked); 1066 if (!upper->checked) {
1066 BUG_ON(cowonly != upper->cowonly); 1067 /*
1068 * Still want to blow up for developers since this is a
1069 * logic bug.
1070 */
1071 ASSERT(0);
1072 err = -EINVAL;
1073 goto out;
1074 }
1075 if (cowonly != upper->cowonly) {
1076 ASSERT(0);
1077 err = -EINVAL;
1078 goto out;
1079 }
1080
1067 if (!cowonly) { 1081 if (!cowonly) {
1068 rb_node = tree_insert(&cache->rb_root, upper->bytenr, 1082 rb_node = tree_insert(&cache->rb_root, upper->bytenr,
1069 &upper->rb_node); 1083 &upper->rb_node);
@@ -1086,7 +1100,7 @@ next:
1086 while (!list_empty(&useless)) { 1100 while (!list_empty(&useless)) {
1087 upper = list_entry(useless.next, struct backref_node, list); 1101 upper = list_entry(useless.next, struct backref_node, list);
1088 list_del_init(&upper->list); 1102 list_del_init(&upper->list);
1089 BUG_ON(!list_empty(&upper->upper)); 1103 ASSERT(list_empty(&upper->upper));
1090 if (upper == node) 1104 if (upper == node)
1091 node = NULL; 1105 node = NULL;
1092 if (upper->lowest) { 1106 if (upper->lowest) {
@@ -1119,29 +1133,45 @@ out:
1119 if (err) { 1133 if (err) {
1120 while (!list_empty(&useless)) { 1134 while (!list_empty(&useless)) {
1121 lower = list_entry(useless.next, 1135 lower = list_entry(useless.next,
1122 struct backref_node, upper); 1136 struct backref_node, list);
1123 list_del_init(&lower->upper); 1137 list_del_init(&lower->list);
1124 } 1138 }
1125 upper = node; 1139 while (!list_empty(&list)) {
1126 INIT_LIST_HEAD(&list); 1140 edge = list_first_entry(&list, struct backref_edge,
1127 while (upper) { 1141 list[UPPER]);
1128 if (RB_EMPTY_NODE(&upper->rb_node)) { 1142 list_del(&edge->list[UPPER]);
1129 list_splice_tail(&upper->upper, &list);
1130 free_backref_node(cache, upper);
1131 }
1132
1133 if (list_empty(&list))
1134 break;
1135
1136 edge = list_entry(list.next, struct backref_edge,
1137 list[LOWER]);
1138 list_del(&edge->list[LOWER]); 1143 list_del(&edge->list[LOWER]);
1144 lower = edge->node[LOWER];
1139 upper = edge->node[UPPER]; 1145 upper = edge->node[UPPER];
1140 free_backref_edge(cache, edge); 1146 free_backref_edge(cache, edge);
1147
1148 /*
1149 * Lower is no longer linked to any upper backref nodes
1150 * and isn't in the cache, we can free it ourselves.
1151 */
1152 if (list_empty(&lower->upper) &&
1153 RB_EMPTY_NODE(&lower->rb_node))
1154 list_add(&lower->list, &useless);
1155
1156 if (!RB_EMPTY_NODE(&upper->rb_node))
1157 continue;
1158
1159 /* Add this guy's upper edges to the list to proces */
1160 list_for_each_entry(edge, &upper->upper, list[LOWER])
1161 list_add_tail(&edge->list[UPPER], &list);
1162 if (list_empty(&upper->upper))
1163 list_add(&upper->list, &useless);
1164 }
1165
1166 while (!list_empty(&useless)) {
1167 lower = list_entry(useless.next,
1168 struct backref_node, list);
1169 list_del_init(&lower->list);
1170 free_backref_node(cache, lower);
1141 } 1171 }
1142 return ERR_PTR(err); 1172 return ERR_PTR(err);
1143 } 1173 }
1144 BUG_ON(node && node->detached); 1174 ASSERT(!node || !node->detached);
1145 return node; 1175 return node;
1146} 1176}
1147 1177