diff options
-rw-r--r-- | fs/bcachefs/bcachefs_format.h | 3 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 79 | ||||
-rw-r--r-- | fs/bcachefs/journal_io.c | 35 |
3 files changed, 69 insertions, 48 deletions
diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h index 08ae6a36aec6..5af9f2e7ea86 100644 --- a/fs/bcachefs/bcachefs_format.h +++ b/fs/bcachefs/bcachefs_format.h @@ -1790,7 +1790,8 @@ static inline __u64 __bset_magic(struct bch_sb *sb) x(data_usage, 6) \ x(clock, 7) \ x(dev_usage, 8) \ - x(log, 9) + x(log, 9) \ + x(overwrite, 10) enum { #define x(f, nr) BCH_JSET_ENTRY_##f = nr, diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index 73196c9f88b5..5f7e6ad6287d 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -384,40 +384,6 @@ btree_key_can_insert_cached(struct btree_trans *trans, return -EINTR; } -static inline void do_btree_insert_one(struct btree_trans *trans, - struct btree_insert_entry *i) -{ - struct bch_fs *c = trans->c; - struct journal *j = &c->journal; - - EBUG_ON(trans->journal_res.ref != - !(trans->flags & BTREE_INSERT_JOURNAL_REPLAY)); - - i->k->k.needs_whiteout = false; - - if (!i->cached) - btree_insert_key_leaf(trans, i); - else if (!i->key_cache_already_flushed) - bch2_btree_insert_key_cached(trans, i->path, i->k); - else { - bch2_btree_key_cache_drop(trans, i->path); - return; - } - - if (likely(!(trans->flags & BTREE_INSERT_JOURNAL_REPLAY))) { - struct jset_entry *entry; - - entry = bch2_journal_add_entry(j, &trans->journal_res, - BCH_JSET_ENTRY_btree_keys, - i->btree_id, i->level, - i->k->k.u64s); - bkey_copy(&entry->start[0], i->k); - - if (trans->journal_seq) - *trans->journal_seq = trans->journal_res.seq; - } -} - /* Triggers: */ static int run_one_mem_trigger(struct btree_trans *trans, @@ -727,8 +693,42 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, return ret; } - trans_for_each_update(trans, i) - do_btree_insert_one(trans, i); + if (likely(!(trans->flags & BTREE_INSERT_JOURNAL_REPLAY))) { + trans_for_each_update(trans, i) { + struct journal *j = &c->journal; + struct jset_entry *entry; + + if (i->key_cache_already_flushed) + continue; + + entry = bch2_journal_add_entry(j, &trans->journal_res, + BCH_JSET_ENTRY_overwrite, + i->btree_id, i->level, + i->old_k.u64s); + bkey_reassemble(&entry->start[0], + (struct bkey_s_c) { &i->old_k, i->old_v }); + + entry = bch2_journal_add_entry(j, &trans->journal_res, + BCH_JSET_ENTRY_btree_keys, + i->btree_id, i->level, + i->k->k.u64s); + bkey_copy(&entry->start[0], i->k); + } + + if (trans->journal_seq) + *trans->journal_seq = trans->journal_res.seq; + } + + trans_for_each_update(trans, i) { + i->k->k.needs_whiteout = false; + + if (!i->cached) + btree_insert_key_leaf(trans, i); + else if (!i->key_cache_already_flushed) + bch2_btree_insert_key_cached(trans, i->path, i->k); + else + bch2_btree_key_cache_drop(trans, i->path); + } return ret; } @@ -1130,11 +1130,18 @@ int __bch2_trans_commit(struct btree_trans *trans) BUG_ON(!btree_node_intent_locked(i->path, i->level)); + if (i->key_cache_already_flushed) + continue; + + /* we're going to journal the key being updated: */ u64s = jset_u64s(i->k->k.u64s); if (i->cached && likely(!(trans->flags & BTREE_INSERT_JOURNAL_REPLAY))) trans->journal_preres_u64s += u64s; trans->journal_u64s += u64s; + + /* and we're also going to log the overwrite: */ + trans->journal_u64s += jset_u64s(i->old_k.u64s); } if (trans->extra_journal_res) { diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c index d59a49a55fdb..a1df385674ea 100644 --- a/fs/bcachefs/journal_io.c +++ b/fs/bcachefs/journal_io.c @@ -213,7 +213,7 @@ static void journal_entry_null_range(void *start, void *end) static int journal_validate_key(struct bch_fs *c, const char *where, struct jset_entry *entry, unsigned level, enum btree_id btree_id, - struct bkey_i *k, const char *type, + struct bkey_i *k, unsigned version, int big_endian, int write) { void *next = vstruct_next(entry); @@ -221,8 +221,8 @@ static int journal_validate_key(struct bch_fs *c, const char *where, int ret = 0; if (journal_entry_err_on(!k->k.u64s, c, - "invalid %s in %s entry offset %zi/%u: k->u64s 0", - type, where, + "invalid key in %s at %s offset %zi/%u: k->u64s 0", + bch2_jset_entry_types[entry->type], where, (u64 *) k - entry->_data, le16_to_cpu(entry->u64s))) { entry->u64s = cpu_to_le16((u64 *) k - entry->_data); @@ -232,8 +232,8 @@ static int journal_validate_key(struct bch_fs *c, const char *where, if (journal_entry_err_on((void *) bkey_next(k) > (void *) vstruct_next(entry), c, - "invalid %s in %s entry offset %zi/%u: extends past end of journal entry", - type, where, + "invalid key in %s at %s offset %zi/%u: extends past end of journal entry", + bch2_jset_entry_types[entry->type], where, (u64 *) k - entry->_data, le16_to_cpu(entry->u64s))) { entry->u64s = cpu_to_le16((u64 *) k - entry->_data); @@ -242,8 +242,8 @@ static int journal_validate_key(struct bch_fs *c, const char *where, } if (journal_entry_err_on(k->k.format != KEY_FORMAT_CURRENT, c, - "invalid %s in %s entry offset %zi/%u: bad format %u", - type, where, + "invalid key in %s at %s offset %zi/%u: bad format %u", + bch2_jset_entry_types[entry->type], where, (u64 *) k - entry->_data, le16_to_cpu(entry->u64s), k->k.format)) { @@ -260,8 +260,8 @@ static int journal_validate_key(struct bch_fs *c, const char *where, if (bch2_bkey_invalid(c, bkey_i_to_s_c(k), __btree_node_type(level, btree_id), write, &buf)) { printbuf_reset(&buf); - pr_buf(&buf, "invalid %s in %s entry offset %zi/%u:", - type, where, + pr_buf(&buf, "invalid key in %s at %s offset %zi/%u:", + bch2_jset_entry_types[entry->type], where, (u64 *) k - entry->_data, le16_to_cpu(entry->u64s)); pr_newline(&buf); @@ -301,7 +301,7 @@ static int journal_entry_btree_keys_validate(struct bch_fs *c, int ret = journal_validate_key(c, where, entry, entry->level, entry->btree_id, - k, "key", version, big_endian, write); + k, version, big_endian, write); if (ret == FSCK_DELETED_KEY) continue; @@ -351,7 +351,7 @@ static int journal_entry_btree_root_validate(struct bch_fs *c, } return journal_validate_key(c, where, entry, 1, entry->btree_id, k, - "btree root", version, big_endian, write); + version, big_endian, write); fsck_err: return ret; } @@ -613,6 +613,19 @@ static void journal_entry_log_to_text(struct printbuf *out, struct bch_fs *c, pr_buf(out, "%.*s", bytes, l->d); } +static int journal_entry_overwrite_validate(struct bch_fs *c, const char *where, + struct jset_entry *entry, + unsigned version, int big_endian, int write) +{ + return journal_entry_btree_keys_validate(c, where, entry, version, big_endian, write); +} + +static void journal_entry_overwrite_to_text(struct printbuf *out, struct bch_fs *c, + struct jset_entry *entry) +{ + journal_entry_btree_keys_to_text(out, c, entry); +} + struct jset_entry_ops { int (*validate)(struct bch_fs *, const char *, struct jset_entry *, unsigned, int, int); |