diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h index d77a45041ff0..079ad93ab34e 100644 --- a/fs/bcachefs/bcachefs_format.h +++ b/fs/bcachefs/bcachefs_format.h @@ -1796,7 +1796,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 df2b21245d00..eac601d6a397 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -384,41 +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)) && - !(i->flags & BTREE_UPDATE_NOJOURNAL)) { - 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, @@ -729,8 +694,47 @@ 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; + + if (i->flags & BTREE_UPDATE_NOJOURNAL) + continue; + + if (trans->journal_transaction_names) { + 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; } @@ -1134,13 +1138,23 @@ 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; - if (!(i->flags & BTREE_UPDATE_NOJOURNAL)) - trans->journal_u64s += u64s; + if (i->flags & BTREE_UPDATE_NOJOURNAL) + continue; + + trans->journal_u64s += u64s; + + /* and we're also going to log the overwrite: */ + if (trans->journal_transaction_names) + 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 351d5d9d8225..163b18340fa1 100644 --- a/fs/bcachefs/journal_io.c +++ b/fs/bcachefs/journal_io.c @@ -212,7 +212,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); @@ -220,8 +220,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); @@ -231,8 +231,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); @@ -241,8 +241,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)) { @@ -259,8 +259,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); @@ -300,7 +300,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; @@ -350,7 +350,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; } @@ -612,6 +612,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);