bcachefs: Don't issue btree writes that weren't journalled
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 3 Dec 2020 21:20:18 +0000 (16:20 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:49 +0000 (17:08 -0400)
If we have an error in the btree interior update path that prevents us
from journalling the update, we can't issue the corresponding btree node
write - we didn't get a journal sequence number that would cause it to
be ignored in recovery.

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

index 520eef531d397ac454cda72ea7d57896689f503a..b2ffdff48637ccaf7562c7ff6f7080e5ddfb3934 100644 (file)
@@ -1499,6 +1499,9 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b,
                if (!btree_node_may_write(b))
                        return;
 
+               if (old & (1 << BTREE_NODE_never_write))
+                       return;
+
                if (old & (1 << BTREE_NODE_write_in_flight)) {
                        btree_node_wait_on_io(b);
                        continue;
@@ -1545,6 +1548,8 @@ void __bch2_btree_node_write(struct bch_fs *c, struct btree *b,
                seq = max(seq, le64_to_cpu(i->journal_seq));
        }
 
+       BUG_ON(b->written && !seq);
+
        /* bch2_varint_decode may read up to 7 bytes past the end of the buffer: */
        bytes += 8;
 
index d30c31f0f11fdae4c6c06ca010118fb036bd4ad8..51ad87abc763852efeeec6d7cb1285341f3dad5b 100644 (file)
@@ -415,6 +415,7 @@ enum btree_flags {
        BTREE_NODE_fake,
        BTREE_NODE_old_extent_overwrite,
        BTREE_NODE_need_rewrite,
+       BTREE_NODE_never_write,
 };
 
 BTREE_FLAG(read_in_flight);
@@ -429,6 +430,7 @@ BTREE_FLAG(dying);
 BTREE_FLAG(fake);
 BTREE_FLAG(old_extent_overwrite);
 BTREE_FLAG(need_rewrite);
+BTREE_FLAG(never_write);
 
 static inline struct btree_write *btree_current_write(struct btree *b)
 {
index aed54d5b5251e6c2a7b9467ec11d83fbc5e5d870..594bcd7975169f581043d4375f55af92a10af6f9 100644 (file)
@@ -603,17 +603,30 @@ err:
 
                list_del(&as->write_blocked_list);
 
-               if (!ret && as->b == b) {
+               /*
+                * Node might have been freed, recheck under
+                * btree_interior_update_lock:
+                */
+               if (as->b == b) {
                        struct bset *i = btree_bset_last(b);
 
                        BUG_ON(!b->c.level);
                        BUG_ON(!btree_node_dirty(b));
 
-                       i->journal_seq = cpu_to_le64(
-                               max(journal_seq,
-                                   le64_to_cpu(i->journal_seq)));
-
-                       bch2_btree_add_journal_pin(c, b, journal_seq);
+                       if (!ret) {
+                               i->journal_seq = cpu_to_le64(
+                                       max(journal_seq,
+                                           le64_to_cpu(i->journal_seq)));
+
+                               bch2_btree_add_journal_pin(c, b, journal_seq);
+                       } else {
+                               /*
+                                * If we didn't get a journal sequence number we
+                                * can't write this btree node, because recovery
+                                * won't know to ignore this write:
+                                */
+                               set_btree_node_never_write(b);
+                       }
                }
 
                mutex_unlock(&c->btree_interior_update_lock);