mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
bcachefs: btree_trans_subbuf
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
81c42933a5
commit
247abee6ae
8 changed files with 82 additions and 54 deletions
|
@ -712,7 +712,6 @@ struct btree_transaction_stats {
|
|||
struct bch2_time_stats lock_hold_times;
|
||||
struct mutex lock;
|
||||
unsigned nr_max_paths;
|
||||
unsigned journal_entries_size;
|
||||
unsigned max_mem;
|
||||
#ifdef CONFIG_BCACHEFS_TRANS_KMALLOC_TRACE
|
||||
darray_trans_kmalloc_trace trans_kmalloc_trace;
|
||||
|
|
|
@ -1499,7 +1499,7 @@ void bch2_trans_updates_to_text(struct printbuf *buf, struct btree_trans *trans)
|
|||
prt_newline(buf);
|
||||
}
|
||||
|
||||
for (struct jset_entry *e = trans->journal_entries;
|
||||
for (struct jset_entry *e = btree_trans_journal_entries_start(trans);
|
||||
e != btree_trans_journal_entries_top(trans);
|
||||
e = vstruct_next(e)) {
|
||||
bch2_journal_entry_to_text(buf, trans->c, e);
|
||||
|
@ -3280,7 +3280,6 @@ u32 bch2_trans_begin(struct btree_trans *trans)
|
|||
|
||||
trans->restart_count++;
|
||||
trans->mem_top = 0;
|
||||
trans->journal_entries = NULL;
|
||||
|
||||
trans_for_each_path(trans, path, i) {
|
||||
path->should_be_locked = false;
|
||||
|
@ -3438,7 +3437,6 @@ got_trans:
|
|||
}
|
||||
|
||||
trans->nr_paths_max = s->nr_max_paths;
|
||||
trans->journal_entries_size = s->journal_entries_size;
|
||||
}
|
||||
|
||||
trans->srcu_idx = srcu_read_lock(&c->btree_trans_barrier);
|
||||
|
|
|
@ -663,15 +663,16 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
|
|||
h = h->next;
|
||||
}
|
||||
|
||||
struct jset_entry *entry = trans->journal_entries;
|
||||
struct jset_entry *entry;
|
||||
|
||||
percpu_down_read(&c->mark_lock);
|
||||
for (entry = trans->journal_entries;
|
||||
entry != (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
|
||||
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);
|
||||
ret = bch2_accounting_trans_commit_hook(trans,
|
||||
bkey_i_to_accounting(entry->start), flags);
|
||||
if (ret)
|
||||
goto revert_fs_usage;
|
||||
}
|
||||
|
@ -698,8 +699,8 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
|
|||
if (!(flags & BCH_TRANS_COMMIT_no_journal_res))
|
||||
validate_context.flags = BCH_VALIDATE_write|BCH_VALIDATE_commit;
|
||||
|
||||
for (struct jset_entry *i = trans->journal_entries;
|
||||
i != (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
|
||||
for (struct jset_entry *i = btree_trans_journal_entries_start(trans);
|
||||
i != btree_trans_journal_entries_top(trans);
|
||||
i = vstruct_next(i)) {
|
||||
ret = bch2_journal_entry_validate(c, NULL, i,
|
||||
bcachefs_metadata_version_current,
|
||||
|
@ -754,11 +755,11 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
|
|||
}
|
||||
|
||||
memcpy_u64s_small(journal_res_entry(&c->journal, &trans->journal_res),
|
||||
trans->journal_entries,
|
||||
trans->journal_entries_u64s);
|
||||
btree_trans_journal_entries_start(trans),
|
||||
trans->journal_entries.u64s);
|
||||
|
||||
trans->journal_res.offset += trans->journal_entries_u64s;
|
||||
trans->journal_res.u64s -= trans->journal_entries_u64s;
|
||||
trans->journal_res.offset += trans->journal_entries.u64s;
|
||||
trans->journal_res.u64s -= trans->journal_entries.u64s;
|
||||
|
||||
if (trans->journal_seq)
|
||||
*trans->journal_seq = trans->journal_res.seq;
|
||||
|
@ -780,7 +781,7 @@ fatal_err:
|
|||
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 = trans->journal_entries;
|
||||
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 &&
|
||||
|
@ -961,8 +962,8 @@ do_bch2_trans_commit_to_journal_replay(struct btree_trans *trans)
|
|||
return ret;
|
||||
}
|
||||
|
||||
for (struct jset_entry *i = trans->journal_entries;
|
||||
i != (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
|
||||
for (struct jset_entry *i = btree_trans_journal_entries_start(trans);
|
||||
i != btree_trans_journal_entries_top(trans);
|
||||
i = vstruct_next(i))
|
||||
if (i->type == BCH_JSET_ENTRY_btree_keys ||
|
||||
i->type == BCH_JSET_ENTRY_write_buffer_keys) {
|
||||
|
@ -987,7 +988,7 @@ 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)
|
||||
goto out_reset;
|
||||
|
||||
ret = bch2_trans_commit_run_triggers(trans);
|
||||
|
@ -1005,7 +1006,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;
|
||||
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);
|
||||
|
|
|
@ -480,6 +480,12 @@ struct trans_kmalloc_trace {
|
|||
};
|
||||
typedef DARRAY(struct trans_kmalloc_trace) darray_trans_kmalloc_trace;
|
||||
|
||||
struct btree_trans_subbuf {
|
||||
u16 base;
|
||||
u16 u64s;
|
||||
u16 size;;
|
||||
};
|
||||
|
||||
struct btree_trans {
|
||||
struct bch_fs *c;
|
||||
|
||||
|
@ -534,9 +540,7 @@ struct btree_trans {
|
|||
int srcu_idx;
|
||||
|
||||
/* update path: */
|
||||
u16 journal_entries_u64s;
|
||||
u16 journal_entries_size;
|
||||
struct jset_entry *journal_entries;
|
||||
struct btree_trans_subbuf journal_entries;
|
||||
|
||||
struct btree_trans_commit_hook *hooks;
|
||||
struct journal_entry_pin *journal_pin;
|
||||
|
|
|
@ -565,30 +565,29 @@ int bch2_btree_insert_clone_trans(struct btree_trans *trans,
|
|||
return bch2_btree_insert_trans(trans, btree, n, 0);
|
||||
}
|
||||
|
||||
struct jset_entry *__bch2_trans_jset_entry_alloc(struct btree_trans *trans, unsigned u64s)
|
||||
void *__bch2_trans_subbuf_alloc(struct btree_trans *trans,
|
||||
struct btree_trans_subbuf *buf,
|
||||
unsigned u64s)
|
||||
{
|
||||
unsigned new_top = trans->journal_entries_u64s + u64s;
|
||||
unsigned old_size = trans->journal_entries_size;
|
||||
unsigned new_top = buf->u64s + u64s;
|
||||
unsigned old_size = buf->size;
|
||||
|
||||
if (new_top > trans->journal_entries_size) {
|
||||
trans->journal_entries_size = roundup_pow_of_two(new_top);
|
||||
if (new_top > buf->size)
|
||||
buf->size = roundup_pow_of_two(new_top);
|
||||
|
||||
btree_trans_stats(trans)->journal_entries_size = trans->journal_entries_size;
|
||||
}
|
||||
|
||||
struct jset_entry *n =
|
||||
bch2_trans_kmalloc_nomemzero(trans,
|
||||
trans->journal_entries_size * sizeof(u64));
|
||||
void *n = bch2_trans_kmalloc_nomemzero(trans, buf->size * sizeof(u64));
|
||||
if (IS_ERR(n))
|
||||
return ERR_CAST(n);
|
||||
return n;
|
||||
|
||||
if (trans->journal_entries)
|
||||
memcpy(n, trans->journal_entries, old_size * sizeof(u64));
|
||||
trans->journal_entries = n;
|
||||
if (buf->u64s)
|
||||
memcpy(n,
|
||||
btree_trans_subbuf_base(trans, buf),
|
||||
old_size * sizeof(u64));
|
||||
buf->base = (u64 *) n - (u64 *) trans->mem;
|
||||
|
||||
struct jset_entry *e = btree_trans_journal_entries_top(trans);
|
||||
trans->journal_entries_u64s = new_top;
|
||||
return e;
|
||||
void *p = btree_trans_subbuf_top(trans, buf);
|
||||
buf->u64s = new_top;
|
||||
return p;
|
||||
}
|
||||
|
||||
int bch2_bkey_get_empty_slot(struct btree_trans *trans, struct btree_iter *iter,
|
||||
|
|
|
@ -113,23 +113,49 @@ bch2_trans_update(struct btree_trans *trans, struct btree_iter *iter,
|
|||
return bch2_trans_update_ip(trans, iter, k, flags, _THIS_IP_);
|
||||
}
|
||||
|
||||
struct jset_entry *__bch2_trans_jset_entry_alloc(struct btree_trans *, unsigned);
|
||||
static inline void *btree_trans_subbuf_base(struct btree_trans *trans,
|
||||
struct btree_trans_subbuf *buf)
|
||||
{
|
||||
return (u64 *) trans->mem + buf->base;
|
||||
}
|
||||
|
||||
static inline void *btree_trans_subbuf_top(struct btree_trans *trans,
|
||||
struct btree_trans_subbuf *buf)
|
||||
{
|
||||
return (u64 *) trans->mem + buf->base + buf->u64s;
|
||||
}
|
||||
|
||||
void *__bch2_trans_subbuf_alloc(struct btree_trans *,
|
||||
struct btree_trans_subbuf *,
|
||||
unsigned);
|
||||
|
||||
static inline void *
|
||||
bch2_trans_subbuf_alloc(struct btree_trans *trans,
|
||||
struct btree_trans_subbuf *buf,
|
||||
unsigned u64s)
|
||||
{
|
||||
if (buf->u64s + u64s > buf->size)
|
||||
return __bch2_trans_subbuf_alloc(trans, buf, u64s);
|
||||
|
||||
void *p = btree_trans_subbuf_top(trans, buf);
|
||||
buf->u64s += u64s;
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline struct jset_entry *btree_trans_journal_entries_start(struct btree_trans *trans)
|
||||
{
|
||||
return btree_trans_subbuf_base(trans, &trans->journal_entries);
|
||||
}
|
||||
|
||||
static inline struct jset_entry *btree_trans_journal_entries_top(struct btree_trans *trans)
|
||||
{
|
||||
return (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
|
||||
return btree_trans_subbuf_top(trans, &trans->journal_entries);
|
||||
}
|
||||
|
||||
static inline struct jset_entry *
|
||||
bch2_trans_jset_entry_alloc(struct btree_trans *trans, unsigned u64s)
|
||||
{
|
||||
if (!trans->journal_entries ||
|
||||
trans->journal_entries_u64s + u64s > trans->journal_entries_size)
|
||||
return __bch2_trans_jset_entry_alloc(trans, u64s);
|
||||
|
||||
struct jset_entry *e = btree_trans_journal_entries_top(trans);
|
||||
trans->journal_entries_u64s += u64s;
|
||||
return e;
|
||||
return bch2_trans_subbuf_alloc(trans, &trans->journal_entries, u64s);
|
||||
}
|
||||
|
||||
int bch2_btree_insert_clone_trans(struct btree_trans *, enum btree_id, struct bkey_i *);
|
||||
|
@ -227,7 +253,8 @@ static inline void bch2_trans_reset_updates(struct btree_trans *trans)
|
|||
bch2_path_put(trans, i->path, true);
|
||||
|
||||
trans->nr_updates = 0;
|
||||
trans->journal_entries_u64s = 0;
|
||||
trans->journal_entries.u64s = 0;
|
||||
trans->journal_entries.size = 0;
|
||||
trans->hooks = NULL;
|
||||
trans->extra_disk_res = 0;
|
||||
}
|
||||
|
|
|
@ -307,8 +307,8 @@ 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 = trans->journal_entries;
|
||||
i != (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
|
||||
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);
|
||||
|
|
|
@ -259,8 +259,8 @@ static inline int bch2_accounting_trans_commit_hook(struct btree_trans *trans,
|
|||
struct bkey_i_accounting *a,
|
||||
unsigned commit_flags)
|
||||
{
|
||||
a->k.bversion = journal_pos_to_bversion(&trans->journal_res,
|
||||
(u64 *) a - (u64 *) trans->journal_entries);
|
||||
u64 *base = (u64 *) btree_trans_subbuf_base(trans, &trans->journal_entries);
|
||||
a->k.bversion = journal_pos_to_bversion(&trans->journal_res, (u64 *) a - base);
|
||||
|
||||
EBUG_ON(bversion_zero(a->k.bversion));
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue