Commit a3581ca3 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: Fix BCH_TRANS_COMMIT_skip_accounting_apply



This was added to avoid double-counting accounting keys in journal
replay. But applied incorrectly (easily done since it applies to the
transaction commit, not a particular update), it leads to skipping
in-mem accounting for real accounting updates, and failure to give them
a version number - which leads to journal replay becoming very confused
the next time around.

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent f8911ad8
Loading
Loading
Loading
Loading
+20 −16
Original line number Diff line number Diff line
@@ -700,27 +700,31 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,

	struct jset_entry *entry = trans->journal_entries;

	if (likely(!(flags & BCH_TRANS_COMMIT_skip_accounting_apply))) {
	percpu_down_read(&c->mark_lock);

	for (entry = trans->journal_entries;
	     entry != (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
	     entry = vstruct_next(entry))
			if (jset_entry_is_key(entry) && entry->start->k.type == KEY_TYPE_accounting) {
		if (entry->type == BCH_JSET_ENTRY_write_buffer_keys &&
		    entry->start->k.type == KEY_TYPE_accounting) {
			BUG_ON(!trans->journal_res.ref);

			struct bkey_i_accounting *a = bkey_i_to_accounting(entry->start);

			a->k.bversion = journal_pos_to_bversion(&trans->journal_res,
							(u64 *) entry - (u64 *) trans->journal_entries);
			BUG_ON(bversion_zero(a->k.bversion));

			if (likely(!(flags & BCH_TRANS_COMMIT_skip_accounting_apply))) {
				ret = bch2_accounting_mem_mod_locked(trans, accounting_i_to_s_c(a), BCH_ACCOUNTING_normal);
				if (ret)
					goto revert_fs_usage;
			}
		}
	percpu_up_read(&c->mark_lock);

	/* XXX: we only want to run this if deltas are nonzero */
	bch2_trans_account_disk_usage_change(trans);
	}

	trans_for_each_update(trans, i)
		if (btree_node_type_has_atomic_triggers(i->bkey_type)) {