]> www.infradead.org Git - nvme.git/commitdiff
bcachefs: Be careful about btree node splits during journal replay
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 26 Mar 2024 21:14:43 +0000 (17:14 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Mon, 1 Apr 2024 00:36:11 +0000 (20:36 -0400)
Don't pick a pivot that's going to be deleted.

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

index 0272ef0d731099d7e9fbe21f7b29d13c62c169a1..1f588264575db2d854df283c6bd1ef1e9bc14056 100644 (file)
@@ -261,6 +261,22 @@ int bch2_journal_key_delete(struct bch_fs *c, enum btree_id id,
        return bch2_journal_key_insert(c, id, level, &whiteout);
 }
 
+bool bch2_key_deleted_in_journal(struct btree_trans *trans, enum btree_id btree,
+                                unsigned level, struct bpos pos)
+{
+       struct journal_keys *keys = &trans->c->journal_keys;
+       size_t idx = bch2_journal_key_search(keys, btree, level, pos);
+
+       if (!trans->journal_replay_not_finished)
+               return false;
+
+       return (idx < keys->size &&
+               keys->data[idx].btree_id        == btree &&
+               keys->data[idx].level           == level &&
+               bpos_eq(keys->data[idx].k->k.p, pos) &&
+               bkey_deleted(&keys->data[idx].k->k));
+}
+
 void bch2_journal_key_overwritten(struct bch_fs *c, enum btree_id btree,
                                  unsigned level, struct bpos pos)
 {
index c9d19da3ea04803a360a683fa0e01a2838f2433f..09cd53091a05b48036e96e8cd2ac4c58b35f69b2 100644 (file)
@@ -40,8 +40,8 @@ int bch2_journal_key_insert(struct bch_fs *, enum btree_id,
                            unsigned, struct bkey_i *);
 int bch2_journal_key_delete(struct bch_fs *, enum btree_id,
                            unsigned, struct bpos);
-void bch2_journal_key_overwritten(struct bch_fs *, enum btree_id,
-                                 unsigned, struct bpos);
+bool bch2_key_deleted_in_journal(struct btree_trans *, enum btree_id, unsigned, struct bpos);
+void bch2_journal_key_overwritten(struct bch_fs *, enum btree_id, unsigned, struct bpos);
 
 void bch2_btree_and_journal_iter_advance(struct btree_and_journal_iter *);
 struct bkey_s_c bch2_btree_and_journal_iter_peek(struct btree_and_journal_iter *);
index b2f5f2e50f7e19ccd59502a1471ee9bb6d14a988..b45c7ced15d8a171690431f8517ff6406b4cf584 100644 (file)
@@ -1380,9 +1380,16 @@ static void __btree_split_node(struct btree_update *as,
                if (bkey_deleted(k))
                        continue;
 
+               uk = bkey_unpack_key(b, k);
+
+               if (b->c.level &&
+                   u64s < n1_u64s &&
+                   u64s + k->u64s >= n1_u64s &&
+                   bch2_key_deleted_in_journal(trans, b->c.btree_id, b->c.level, uk.p))
+                       n1_u64s += k->u64s;
+
                i = u64s >= n1_u64s;
                u64s += k->u64s;
-               uk = bkey_unpack_key(b, k);
                if (!i)
                        n1_pos = uk.p;
                bch2_bkey_format_add_key(&format[i], &uk);