mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 07:59:42 -04:00
bcachefs: Split out accounting in transaction commit
There can be a lot of rendundancy in accounting updates within a single btree transaction. Split out accounting updates so that they can be deduped, in the next commit. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
@@ -663,19 +663,17 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
|
||||
h = h->next;
|
||||
}
|
||||
|
||||
struct jset_entry *entry;
|
||||
struct bkey_i *accounting;
|
||||
|
||||
percpu_down_read(&c->mark_lock);
|
||||
for (entry = btree_trans_journal_entries_start(trans);
|
||||
entry != btree_trans_journal_entries_top(trans);
|
||||
entry = vstruct_next(entry))
|
||||
if (entry->type == BCH_JSET_ENTRY_write_buffer_keys &&
|
||||
entry->start->k.type == KEY_TYPE_accounting) {
|
||||
ret = bch2_accounting_trans_commit_hook(trans,
|
||||
bkey_i_to_accounting(entry->start), flags);
|
||||
if (ret)
|
||||
goto revert_fs_usage;
|
||||
}
|
||||
for (accounting = btree_trans_subbuf_base(trans, &trans->accounting);
|
||||
accounting != btree_trans_subbuf_top(trans, &trans->accounting);
|
||||
accounting = bkey_next(accounting)) {
|
||||
ret = bch2_accounting_trans_commit_hook(trans,
|
||||
bkey_i_to_accounting(accounting), flags);
|
||||
if (ret)
|
||||
goto revert_fs_usage;
|
||||
}
|
||||
percpu_up_read(&c->mark_lock);
|
||||
|
||||
/* XXX: we only want to run this if deltas are nonzero */
|
||||
@@ -761,6 +759,13 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
|
||||
trans->journal_res.offset += trans->journal_entries.u64s;
|
||||
trans->journal_res.u64s -= trans->journal_entries.u64s;
|
||||
|
||||
memcpy_u64s_small(bch2_journal_add_entry(j, &trans->journal_res,
|
||||
BCH_JSET_ENTRY_write_buffer_keys,
|
||||
BTREE_ID_accounting, 0,
|
||||
trans->accounting.u64s)->_data,
|
||||
btree_trans_subbuf_base(trans, &trans->accounting),
|
||||
trans->accounting.u64s);
|
||||
|
||||
if (trans->journal_seq)
|
||||
*trans->journal_seq = trans->journal_res.seq;
|
||||
}
|
||||
@@ -781,13 +786,10 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
|
||||
bch2_fs_fatal_error(c, "fatal error in transaction commit: %s", bch2_err_str(ret));
|
||||
percpu_down_read(&c->mark_lock);
|
||||
revert_fs_usage:
|
||||
for (struct jset_entry *entry2 = btree_trans_journal_entries_start(trans);
|
||||
entry2 != entry;
|
||||
entry2 = vstruct_next(entry2))
|
||||
if (entry2->type == BCH_JSET_ENTRY_write_buffer_keys &&
|
||||
entry2->start->k.type == KEY_TYPE_accounting)
|
||||
bch2_accounting_trans_commit_revert(trans,
|
||||
bkey_i_to_accounting(entry2->start), flags);
|
||||
for (struct bkey_i *i = btree_trans_subbuf_base(trans, &trans->accounting);
|
||||
i != accounting;
|
||||
i = bkey_next(i))
|
||||
bch2_accounting_trans_commit_revert(trans, bkey_i_to_accounting(i), flags);
|
||||
percpu_up_read(&c->mark_lock);
|
||||
return ret;
|
||||
}
|
||||
@@ -972,6 +974,14 @@ do_bch2_trans_commit_to_journal_replay(struct btree_trans *trans)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (struct bkey_i *i = btree_trans_subbuf_base(trans, &trans->accounting);
|
||||
i != btree_trans_subbuf_top(trans, &trans->accounting);
|
||||
i = bkey_next(i)) {
|
||||
int ret = bch2_journal_key_insert(c, BTREE_ID_accounting, 0, i);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -988,7 +998,8 @@ int __bch2_trans_commit(struct btree_trans *trans, unsigned flags)
|
||||
goto out_reset;
|
||||
|
||||
if (!trans->nr_updates &&
|
||||
!trans->journal_entries.u64s)
|
||||
!trans->journal_entries.u64s &&
|
||||
!trans->accounting.u64s)
|
||||
goto out_reset;
|
||||
|
||||
ret = bch2_trans_commit_run_triggers(trans);
|
||||
@@ -1006,7 +1017,7 @@ int __bch2_trans_commit(struct btree_trans *trans, unsigned flags)
|
||||
|
||||
EBUG_ON(test_bit(BCH_FS_clean_shutdown, &c->flags));
|
||||
|
||||
trans->journal_u64s = trans->journal_entries.u64s;
|
||||
trans->journal_u64s = trans->journal_entries.u64s + jset_u64s(trans->accounting.u64s);
|
||||
trans->journal_transaction_names = READ_ONCE(c->opts.journal_transaction_names);
|
||||
if (trans->journal_transaction_names)
|
||||
trans->journal_u64s += jset_u64s(JSET_ENTRY_LOG_U64s);
|
||||
|
||||
@@ -541,6 +541,7 @@ struct btree_trans {
|
||||
|
||||
/* update path: */
|
||||
struct btree_trans_subbuf journal_entries;
|
||||
struct btree_trans_subbuf accounting;
|
||||
|
||||
struct btree_trans_commit_hook *hooks;
|
||||
struct journal_entry_pin *journal_pin;
|
||||
|
||||
@@ -255,6 +255,8 @@ static inline void bch2_trans_reset_updates(struct btree_trans *trans)
|
||||
trans->nr_updates = 0;
|
||||
trans->journal_entries.u64s = 0;
|
||||
trans->journal_entries.size = 0;
|
||||
trans->accounting.u64s = 0;
|
||||
trans->accounting.size = 0;
|
||||
trans->hooks = NULL;
|
||||
trans->extra_disk_res = 0;
|
||||
}
|
||||
|
||||
@@ -96,13 +96,13 @@ int bch2_disk_accounting_mod(struct btree_trans *trans,
|
||||
|
||||
if (likely(!gc)) {
|
||||
unsigned u64s = sizeof(struct bkey_i_accounting) / sizeof(u64) + nr;
|
||||
struct jset_entry *e = bch2_trans_jset_entry_alloc(trans, jset_u64s(u64s));
|
||||
int ret = PTR_ERR_OR_ZERO(e);
|
||||
struct bkey_i_accounting *a =
|
||||
bch2_trans_subbuf_alloc(trans, &trans->accounting, u64s);
|
||||
int ret = PTR_ERR_OR_ZERO(a);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
journal_entry_init(e, BCH_JSET_ENTRY_write_buffer_keys, BTREE_ID_accounting, 0, u64s);
|
||||
accounting_key_init(e->start, k, d, nr);
|
||||
accounting_key_init(&a->k_i, k, d, nr);
|
||||
return 0;
|
||||
} else {
|
||||
struct { __BKEY_PADDED(k, BCH_ACCOUNTING_MAX_COUNTERS); } k_i;
|
||||
@@ -307,14 +307,13 @@ static int bch2_accounting_update_sb_one(struct bch_fs *c, struct bpos p)
|
||||
*/
|
||||
int bch2_accounting_update_sb(struct btree_trans *trans)
|
||||
{
|
||||
for (struct jset_entry *i = btree_trans_journal_entries_start(trans);
|
||||
i != btree_trans_journal_entries_top(trans);
|
||||
i = vstruct_next(i))
|
||||
if (jset_entry_is_key(i) && i->start->k.type == KEY_TYPE_accounting) {
|
||||
int ret = bch2_accounting_update_sb_one(trans->c, i->start->k.p);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
for (struct bkey_i *i = btree_trans_subbuf_base(trans, &trans->accounting);
|
||||
i != btree_trans_subbuf_top(trans, &trans->accounting);
|
||||
i = bkey_next(i)) {
|
||||
int ret = bch2_accounting_update_sb_one(trans->c, i->k.p);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ static inline int bch2_accounting_trans_commit_hook(struct btree_trans *trans,
|
||||
struct bkey_i_accounting *a,
|
||||
unsigned commit_flags)
|
||||
{
|
||||
u64 *base = (u64 *) btree_trans_subbuf_base(trans, &trans->journal_entries);
|
||||
u64 *base = (u64 *) btree_trans_subbuf_base(trans, &trans->accounting);
|
||||
a->k.bversion = journal_pos_to_bversion(&trans->journal_res, (u64 *) a - base);
|
||||
|
||||
EBUG_ON(bversion_zero(a->k.bversion));
|
||||
|
||||
@@ -286,7 +286,12 @@ static int bch2_journal_replay_key(struct btree_trans *trans,
|
||||
goto out;
|
||||
|
||||
if (k->k->k.type == KEY_TYPE_accounting) {
|
||||
ret = bch2_trans_update_buffered(trans, BTREE_ID_accounting, k->k);
|
||||
struct bkey_i *n = bch2_trans_subbuf_alloc(trans, &trans->accounting, k->k->k.u64s);
|
||||
ret = PTR_ERR_OR_ZERO(n);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
bkey_copy(n, k->k);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user