diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-07-16 03:44:31 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-07-16 03:45:21 -0400 |
commit | 821d66df4406ab1be7de8cc79e5ae0ffae265ff0 (patch) | |
tree | ce640155d073ab74e5c44983ca0ffd3dfc87ddc0 | |
parent | 20ae9b49848ceb416966fbfddbab9bb403cf2678 (diff) |
bcachefs: Fix a bug when dropping invalid btree keys
There was a missing set_btree_bset_end() call, leading to popped
assertions later. Also add a quick and dirty debug option for injecting
invalid keys.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | fs/bcachefs/bcachefs.h | 6 | ||||
-rw-r--r-- | fs/bcachefs/bkey.h | 8 | ||||
-rw-r--r-- | fs/bcachefs/btree_io.c | 5 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 12 |
4 files changed, 20 insertions, 11 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index 1482b80a8672..41ec25b6d42b 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -262,7 +262,11 @@ do { \ BCH_DEBUG_PARAM(journal_seq_verify, \ "Store the journal sequence number in the version " \ "number of every btree key, and verify that btree " \ - "update ordering is preserved during recovery") + "update ordering is preserved during recovery") \ + BCH_DEBUG_PARAM(inject_invalid_keys, \ + "Store the journal sequence number in the version " \ + "number of every btree key, and verify that btree " \ + "update ordering is preserved during recovery") \ #define BCH_DEBUG_PARAMS_ALL() BCH_DEBUG_PARAMS_ALWAYS() BCH_DEBUG_PARAMS_DEBUG() diff --git a/fs/bcachefs/bkey.h b/fs/bcachefs/bkey.h index 2f62bd8e3258..bd1d21b0e49b 100644 --- a/fs/bcachefs/bkey.h +++ b/fs/bcachefs/bkey.h @@ -206,14 +206,12 @@ void bch2_bkey_swab_key(const struct bkey_format *, struct bkey_packed *); static __always_inline int bversion_cmp(struct bversion l, struct bversion r) { - if (l.hi != r.hi) - return l.hi < r.hi ? -1 : 1; - if (l.lo != r.lo) - return l.lo < r.lo ? -1 : 1; - return 0; + return (l.hi > r.hi) - (l.hi < r.hi) ?: + (l.lo > r.lo) - (l.lo < r.lo); } #define ZERO_VERSION ((struct bversion) { .hi = 0, .lo = 0 }) +#define MAX_VERSION ((struct bversion) { .hi = ~0, .lo = ~0ULL }) static __always_inline int bversion_zero(struct bversion v) { diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index 847dfd685eac..94f56dbbeac3 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c @@ -1298,7 +1298,9 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct btree *b, bool have_retry struct bkey_s_c u = bkey_disassemble(b, k, &tmp); const char *invalid = bch2_bkey_val_invalid(c, type, u); - if (invalid) { + if (invalid || + (inject_invalid_keys(c) && + !bversion_cmp(u.k->version, MAX_VERSION))) { char buf[160]; bch2_bkey_val_to_text(c, type, buf, sizeof(buf), u); @@ -1310,6 +1312,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct btree *b, bool have_retry i->u64s = cpu_to_le16(le16_to_cpu(i->u64s) - k->u64s); memmove_u64s_down(k, bkey_next(k), (u64 *) vstruct_end(i) - (u64 *) k); + set_btree_bset_end(b, b->set); continue; } diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index 588a1997e5ee..00e711116769 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -354,10 +354,14 @@ static inline int do_btree_insert_at(struct btree_insert *trans, } } - if (journal_seq_verify(c) && - !(trans->flags & BTREE_INSERT_JOURNAL_REPLAY)) - trans_for_each_entry(trans, i) - i->k->k.version.lo = trans->journal_res.seq; + if (!(trans->flags & BTREE_INSERT_JOURNAL_REPLAY)) { + if (journal_seq_verify(c)) + trans_for_each_entry(trans, i) + i->k->k.version.lo = trans->journal_res.seq; + else if (inject_invalid_keys(c)) + trans_for_each_entry(trans, i) + i->k->k.version = MAX_VERSION; + } trans_for_each_entry(trans, i) { switch (btree_insert_key_leaf(trans, i)) { |