]> www.infradead.org Git - users/willy/pagecache.git/commitdiff
bcachefs: Change btree wb assert to runtime error
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 14 Mar 2025 13:54:43 +0000 (09:54 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Fri, 14 Mar 2025 14:25:25 +0000 (10:25 -0400)
We just had a report of the assert for "btree in write buffer for
non-write buffer btree" popping during the 6.14 upgrade.

- 150TB filesystem, after a reboot the upgrade was able to continue from
  where it left off, so no major damage.

But with 6.14 about to come out we want to get this tracked down asap,
and need more data if other users hit this.

Convert the BUG_ON() to an emergency read-only, and print out btree, the
key itself, and stack trace from the original write buffer update (which
did not have this check before).

Reported-by: Stijn Tintel <stijn@linux-ipv6.be>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_update.h
fs/bcachefs/btree_write_buffer.c

index 8f22ef9a7651aba4bd50f7639d3d4372042901b9..47d8690f01bfc75f7aaa89710ae97fc85cafa548 100644 (file)
@@ -126,10 +126,18 @@ bch2_trans_jset_entry_alloc(struct btree_trans *trans, unsigned u64s)
 
 int bch2_btree_insert_clone_trans(struct btree_trans *, enum btree_id, struct bkey_i *);
 
+int bch2_btree_write_buffer_insert_err(struct btree_trans *,
+                                      enum btree_id, struct bkey_i *);
+
 static inline int __must_check bch2_trans_update_buffered(struct btree_trans *trans,
                                            enum btree_id btree,
                                            struct bkey_i *k)
 {
+       if (unlikely(!btree_type_uses_write_buffer(btree))) {
+               int ret = bch2_btree_write_buffer_insert_err(trans, btree, k);
+               dump_stack();
+               return ret;
+       }
        /*
         * Most updates skip the btree write buffer until journal replay is
         * finished because synchronization with journal replay relies on having
index b56c4987b8c97ac261712083fad4079037768512..2c09d19dd62107e6942eee84bd292d2f0bdcef61 100644 (file)
@@ -264,6 +264,22 @@ out:
        BUG_ON(wb->sorted.size < wb->flushing.keys.nr);
 }
 
+int bch2_btree_write_buffer_insert_err(struct btree_trans *trans,
+                                      enum btree_id btree, struct bkey_i *k)
+{
+       struct bch_fs *c = trans->c;
+       struct printbuf buf = PRINTBUF;
+
+       prt_printf(&buf, "attempting to do write buffer update on non wb btree=");
+       bch2_btree_id_to_text(&buf, btree);
+       prt_str(&buf, "\n");
+       bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k));
+
+       bch2_fs_inconsistent(c, "%s", buf.buf);
+       printbuf_exit(&buf);
+       return -EROFS;
+}
+
 static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans)
 {
        struct bch_fs *c = trans->c;
@@ -312,7 +328,10 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans)
        darray_for_each(wb->sorted, i) {
                struct btree_write_buffered_key *k = &wb->flushing.keys.data[i->idx];
 
-               BUG_ON(!btree_type_uses_write_buffer(k->btree));
+               if (unlikely(!btree_type_uses_write_buffer(k->btree))) {
+                       ret = bch2_btree_write_buffer_insert_err(trans, k->btree, &k->k);
+                       goto err;
+               }
 
                for (struct wb_key_ref *n = i + 1; n < min(i + 4, &darray_top(wb->sorted)); n++)
                        prefetch(&wb->flushing.keys.data[n->idx]);