bcachefs: Topology error after insert is now an ERO
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 29 Apr 2025 00:38:04 +0000 (20:38 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Tue, 29 Apr 2025 02:42:17 +0000 (22:42 -0400)
A user hit this, and this will naturally be easier to debug if we don't
panic.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_update_interior.c

index 44b5fe4..0030735 100644 (file)
@@ -1389,7 +1389,7 @@ static void bch2_insert_fixup_btree_ptr(struct btree_update *as,
        printbuf_exit(&buf);
 }
 
-static void
+static int
 bch2_btree_insert_keys_interior(struct btree_update *as,
                                struct btree_trans *trans,
                                struct btree_path *path,
@@ -1411,7 +1411,8 @@ bch2_btree_insert_keys_interior(struct btree_update *as,
             insert = bkey_next(insert))
                bch2_insert_fixup_btree_ptr(as, trans, path, b, &node_iter, insert);
 
-       if (bch2_btree_node_check_topology(trans, b)) {
+       int ret = bch2_btree_node_check_topology(trans, b);
+       if (ret) {
                struct printbuf buf = PRINTBUF;
 
                for (struct bkey_i *k = keys->keys;
@@ -1421,11 +1422,15 @@ bch2_btree_insert_keys_interior(struct btree_update *as,
                        prt_newline(&buf);
                }
 
-               panic("%s(): check_topology error: inserted keys\n%s", __func__, buf.buf);
+               bch2_fs_fatal_error(as->c, "%ps -> %s(): check_topology error %s: inserted keys\n%s",
+                                   (void *) _RET_IP_, __func__, bch2_err_str(ret), buf.buf);
+               dump_stack();
+               return ret;
        }
 
        memmove_u64s_down(keys->keys, insert, keys->top_p - insert->_data);
        keys->top_p -= insert->_data - keys->keys_p;
+       return 0;
 }
 
 static bool key_deleted_in_insert(struct keylist *insert_keys, struct bpos pos)
@@ -1559,11 +1564,11 @@ static void __btree_split_node(struct btree_update *as,
  * nodes that were coalesced, and thus in the middle of a child node post
  * coalescing:
  */
-static void btree_split_insert_keys(struct btree_update *as,
-                                   struct btree_trans *trans,
-                                   btree_path_idx_t path_idx,
-                                   struct btree *b,
-                                   struct keylist *keys)
+static int btree_split_insert_keys(struct btree_update *as,
+                                  struct btree_trans *trans,
+                                  btree_path_idx_t path_idx,
+                                  struct btree *b,
+                                  struct keylist *keys)
 {
        struct btree_path *path = trans->paths + path_idx;
 
@@ -1573,8 +1578,12 @@ static void btree_split_insert_keys(struct btree_update *as,
 
                bch2_btree_node_iter_init(&node_iter, b, &bch2_keylist_front(keys)->k.p);
 
-               bch2_btree_insert_keys_interior(as, trans, path, b, node_iter, keys);
+               int ret = bch2_btree_insert_keys_interior(as, trans, path, b, node_iter, keys);
+               if (ret)
+                       return ret;
        }
+
+       return 0;
 }
 
 static int btree_split(struct btree_update *as, struct btree_trans *trans,
@@ -1607,8 +1616,10 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans,
                __btree_split_node(as, trans, b, n, keys);
 
                if (keys) {
-                       btree_split_insert_keys(as, trans, path, n1, keys);
-                       btree_split_insert_keys(as, trans, path, n2, keys);
+                       ret =   btree_split_insert_keys(as, trans, path, n1, keys) ?:
+                               btree_split_insert_keys(as, trans, path, n2, keys);
+                       if (ret)
+                               goto err;
                        BUG_ON(!bch2_keylist_empty(keys));
                }
 
@@ -1654,7 +1665,9 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans,
                        n3->sib_u64s[0] = U16_MAX;
                        n3->sib_u64s[1] = U16_MAX;
 
-                       btree_split_insert_keys(as, trans, path, n3, &as->parent_keys);
+                       ret = btree_split_insert_keys(as, trans, path, n3, &as->parent_keys);
+                       if (ret)
+                               goto err;
                }
        } else {
                trace_and_count(c, btree_node_compact, trans, b);
@@ -1662,7 +1675,9 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans,
                n1 = bch2_btree_node_alloc_replacement(as, trans, b);
 
                if (keys) {
-                       btree_split_insert_keys(as, trans, path, n1, keys);
+                       ret = btree_split_insert_keys(as, trans, path, n1, keys);
+                       if (ret)
+                               goto err;
                        BUG_ON(!bch2_keylist_empty(keys));
                }
 
@@ -1809,15 +1824,15 @@ static int bch2_btree_insert_node(struct btree_update *as, struct btree_trans *t
                goto split;
        }
 
-       ret = bch2_btree_node_check_topology(trans, b);
+
+       ret =   bch2_btree_node_check_topology(trans, b) ?:
+               bch2_btree_insert_keys_interior(as, trans, path, b,
+                                       path->l[b->c.level].iter, keys);
        if (ret) {
                bch2_btree_node_unlock_write(trans, path, b);
                return ret;
        }
 
-       bch2_btree_insert_keys_interior(as, trans, path, b,
-                                       path->l[b->c.level].iter, keys);
-
        trans_for_each_path_with_node(trans, b, linked, i)
                bch2_btree_node_iter_peek(&linked->l[b->c.level].iter, b);