mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 07:51:16 -04:00
bcachefs: Consolidate trigger code a bit
Upcoming patches are doing more work on the triggers code, this patch just moves code around. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
This commit is contained in:
committed by
Kent Overstreet
parent
ae94c78fb1
commit
3598c56eb9
@@ -406,7 +406,151 @@ static inline void do_btree_insert_one(struct btree_trans *trans,
|
||||
}
|
||||
}
|
||||
|
||||
static noinline int bch2_trans_mark_gc(struct btree_trans *trans)
|
||||
/* Triggers: */
|
||||
|
||||
static int run_one_mem_trigger(struct btree_trans *trans,
|
||||
struct btree_insert_entry *i,
|
||||
unsigned flags)
|
||||
{
|
||||
struct bkey _deleted = KEY(0, 0, 0);
|
||||
struct bkey_s_c deleted = (struct bkey_s_c) { &_deleted, NULL };
|
||||
struct bkey_s_c old;
|
||||
struct bkey unpacked;
|
||||
struct bkey_i *new = i->k;
|
||||
int ret;
|
||||
|
||||
_deleted.p = i->path->pos;
|
||||
|
||||
if (unlikely(flags & BTREE_TRIGGER_NORUN))
|
||||
return 0;
|
||||
|
||||
if (!btree_node_type_needs_gc(i->path->btree_id))
|
||||
return 0;
|
||||
|
||||
old = bch2_btree_path_peek_slot(i->path, &unpacked);
|
||||
|
||||
if (old.k->type == new->k.type &&
|
||||
((1U << old.k->type) & BTREE_TRIGGER_WANTS_OLD_AND_NEW)) {
|
||||
ret = bch2_mark_key(trans, old, bkey_i_to_s_c(new),
|
||||
BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE|flags);
|
||||
} else {
|
||||
ret = bch2_mark_key(trans, deleted, bkey_i_to_s_c(new),
|
||||
BTREE_TRIGGER_INSERT|flags) ?:
|
||||
bch2_mark_key(trans, old, deleted,
|
||||
BTREE_TRIGGER_OVERWRITE|flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int run_one_trans_trigger(struct btree_trans *trans,
|
||||
struct btree_insert_entry *i,
|
||||
bool overwrite)
|
||||
{
|
||||
struct bkey_s_c old;
|
||||
struct bkey unpacked;
|
||||
int ret = 0;
|
||||
|
||||
if ((i->flags & BTREE_TRIGGER_NORUN) ||
|
||||
!(BTREE_NODE_TYPE_HAS_TRANS_TRIGGERS & (1U << i->bkey_type)))
|
||||
return 0;
|
||||
|
||||
if (!overwrite) {
|
||||
if (i->insert_trigger_run)
|
||||
return 0;
|
||||
|
||||
BUG_ON(i->overwrite_trigger_run);
|
||||
i->insert_trigger_run = true;
|
||||
} else {
|
||||
if (i->overwrite_trigger_run)
|
||||
return 0;
|
||||
|
||||
BUG_ON(!i->insert_trigger_run);
|
||||
i->overwrite_trigger_run = true;
|
||||
}
|
||||
|
||||
old = bch2_btree_path_peek_slot(i->path, &unpacked);
|
||||
|
||||
if (overwrite) {
|
||||
ret = bch2_trans_mark_old(trans, old, i->flags);
|
||||
} else if (old.k->type == i->k->k.type &&
|
||||
((1U << old.k->type) & BTREE_TRIGGER_WANTS_OLD_AND_NEW)) {
|
||||
i->overwrite_trigger_run = true;
|
||||
ret = bch2_trans_mark_key(trans, old, i->k,
|
||||
BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE|i->flags);
|
||||
} else {
|
||||
ret = bch2_trans_mark_new(trans, i->k, i->flags);
|
||||
}
|
||||
|
||||
if (ret == -EINTR)
|
||||
trace_trans_restart_mark(trans->fn, _RET_IP_,
|
||||
i->btree_id, &i->path->pos);
|
||||
return ret ?: 1;
|
||||
}
|
||||
|
||||
static int run_btree_triggers(struct btree_trans *trans, enum btree_id btree_id,
|
||||
struct btree_insert_entry *btree_id_start)
|
||||
{
|
||||
struct btree_insert_entry *i;
|
||||
bool trans_trigger_run;
|
||||
int ret, overwrite;
|
||||
|
||||
for (overwrite = 0; overwrite < 2; overwrite++) {
|
||||
|
||||
/*
|
||||
* Running triggers will append more updates to the list of updates as
|
||||
* we're walking it:
|
||||
*/
|
||||
do {
|
||||
trans_trigger_run = false;
|
||||
|
||||
for (i = btree_id_start;
|
||||
i < trans->updates + trans->nr_updates && i->btree_id <= btree_id;
|
||||
i++) {
|
||||
ret = run_one_trans_trigger(trans, i, overwrite);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret)
|
||||
trans_trigger_run = true;
|
||||
}
|
||||
} while (trans_trigger_run);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bch2_trans_commit_run_triggers(struct btree_trans *trans)
|
||||
{
|
||||
struct btree_insert_entry *i = NULL, *btree_id_start = trans->updates;
|
||||
unsigned btree_id = 0;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
*
|
||||
* For a given btree, this algorithm runs insert triggers before
|
||||
* overwrite triggers: this is so that when extents are being moved
|
||||
* (e.g. by FALLOCATE_FL_INSERT_RANGE), we don't drop references before
|
||||
* they are re-added.
|
||||
*/
|
||||
for (btree_id = 0; btree_id < BTREE_ID_NR; btree_id++) {
|
||||
while (btree_id_start < trans->updates + trans->nr_updates &&
|
||||
btree_id_start->btree_id < btree_id)
|
||||
btree_id_start++;
|
||||
|
||||
ret = run_btree_triggers(trans, btree_id, btree_id_start);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
trans_for_each_update(trans, i)
|
||||
BUG_ON(!(i->flags & BTREE_TRIGGER_NORUN) &&
|
||||
(BTREE_NODE_TYPE_HAS_TRANS_TRIGGERS & (1U << i->bkey_type)) &&
|
||||
(!i->insert_trigger_run || !i->overwrite_trigger_run));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static noinline int bch2_trans_commit_run_gc_triggers(struct btree_trans *trans)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct btree_insert_entry *i;
|
||||
@@ -420,8 +564,7 @@ static noinline int bch2_trans_mark_gc(struct btree_trans *trans)
|
||||
BUG_ON(i->cached || i->level);
|
||||
|
||||
if (gc_visited(c, gc_pos_btree_node(insert_l(i)->b))) {
|
||||
ret = bch2_mark_update(trans, i->path, i->k,
|
||||
i->flags|BTREE_TRIGGER_GC);
|
||||
ret = run_one_mem_trigger(trans, i, i->flags|BTREE_TRIGGER_GC);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
@@ -527,13 +670,13 @@ bch2_trans_commit_write_locked(struct btree_trans *trans,
|
||||
|
||||
trans_for_each_update(trans, i)
|
||||
if (BTREE_NODE_TYPE_HAS_MEM_TRIGGERS & (1U << i->bkey_type)) {
|
||||
ret = bch2_mark_update(trans, i->path, i->k, i->flags);
|
||||
ret = run_one_mem_trigger(trans, i, i->flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (unlikely(c->gc_pos.phase)) {
|
||||
ret = bch2_trans_mark_gc(trans);
|
||||
ret = bch2_trans_commit_run_gc_triggers(trans);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -857,112 +1000,6 @@ bch2_trans_commit_get_rw_cold(struct btree_trans *trans)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_one_trigger(struct btree_trans *trans, struct btree_insert_entry *i,
|
||||
bool overwrite)
|
||||
{
|
||||
struct bkey_s_c old;
|
||||
struct bkey unpacked;
|
||||
int ret = 0;
|
||||
|
||||
if ((i->flags & BTREE_TRIGGER_NORUN) ||
|
||||
!(BTREE_NODE_TYPE_HAS_TRANS_TRIGGERS & (1U << i->bkey_type)))
|
||||
return 0;
|
||||
|
||||
if (!overwrite) {
|
||||
if (i->insert_trigger_run)
|
||||
return 0;
|
||||
|
||||
BUG_ON(i->overwrite_trigger_run);
|
||||
i->insert_trigger_run = true;
|
||||
} else {
|
||||
if (i->overwrite_trigger_run)
|
||||
return 0;
|
||||
|
||||
BUG_ON(!i->insert_trigger_run);
|
||||
i->overwrite_trigger_run = true;
|
||||
}
|
||||
|
||||
old = bch2_btree_path_peek_slot(i->path, &unpacked);
|
||||
|
||||
if (overwrite) {
|
||||
ret = bch2_trans_mark_old(trans, old, i->flags);
|
||||
} else if (old.k->type == i->k->k.type &&
|
||||
((1U << old.k->type) & BTREE_TRIGGER_WANTS_OLD_AND_NEW)) {
|
||||
i->overwrite_trigger_run = true;
|
||||
ret = bch2_trans_mark_key(trans, old, i->k,
|
||||
BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE|i->flags);
|
||||
} else {
|
||||
ret = bch2_trans_mark_new(trans, i->k, i->flags);
|
||||
}
|
||||
|
||||
if (ret == -EINTR)
|
||||
trace_trans_restart_mark(trans->fn, _RET_IP_,
|
||||
i->btree_id, &i->path->pos);
|
||||
return ret ?: 1;
|
||||
}
|
||||
|
||||
static int run_btree_triggers(struct btree_trans *trans, enum btree_id btree_id,
|
||||
struct btree_insert_entry *btree_id_start)
|
||||
{
|
||||
struct btree_insert_entry *i;
|
||||
bool trans_trigger_run;
|
||||
int ret, overwrite;
|
||||
|
||||
for (overwrite = 0; overwrite < 2; overwrite++) {
|
||||
|
||||
/*
|
||||
* Running triggers will append more updates to the list of updates as
|
||||
* we're walking it:
|
||||
*/
|
||||
do {
|
||||
trans_trigger_run = false;
|
||||
|
||||
for (i = btree_id_start;
|
||||
i < trans->updates + trans->nr_updates && i->btree_id <= btree_id;
|
||||
i++) {
|
||||
ret = run_one_trigger(trans, i, overwrite);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret)
|
||||
trans_trigger_run = true;
|
||||
}
|
||||
} while (trans_trigger_run);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bch2_trans_commit_run_triggers(struct btree_trans *trans)
|
||||
{
|
||||
struct btree_insert_entry *i = NULL, *btree_id_start = trans->updates;
|
||||
unsigned btree_id = 0;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
*
|
||||
* For a given btree, this algorithm runs insert triggers before
|
||||
* overwrite triggers: this is so that when extents are being moved
|
||||
* (e.g. by FALLOCATE_FL_INSERT_RANGE), we don't drop references before
|
||||
* they are re-added.
|
||||
*/
|
||||
for (btree_id = 0; btree_id < BTREE_ID_NR; btree_id++) {
|
||||
while (btree_id_start < trans->updates + trans->nr_updates &&
|
||||
btree_id_start->btree_id < btree_id)
|
||||
btree_id_start++;
|
||||
|
||||
ret = run_btree_triggers(trans, btree_id, btree_id_start);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
trans_for_each_update(trans, i)
|
||||
BUG_ON(!(i->flags & BTREE_TRIGGER_NORUN) &&
|
||||
(BTREE_NODE_TYPE_HAS_TRANS_TRIGGERS & (1U << i->bkey_type)) &&
|
||||
(!i->insert_trigger_run || !i->overwrite_trigger_run));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is for updates done in the early part of fsck - btree_gc - before we've
|
||||
* gone RW. we only add the new key to the list of keys for journal replay to
|
||||
|
||||
@@ -1282,39 +1282,6 @@ int bch2_mark_key(struct btree_trans *trans,
|
||||
}
|
||||
}
|
||||
|
||||
int bch2_mark_update(struct btree_trans *trans, struct btree_path *path,
|
||||
struct bkey_i *new, unsigned flags)
|
||||
{
|
||||
struct bkey _deleted = KEY(0, 0, 0);
|
||||
struct bkey_s_c deleted = (struct bkey_s_c) { &_deleted, NULL };
|
||||
struct bkey_s_c old;
|
||||
struct bkey unpacked;
|
||||
int ret;
|
||||
|
||||
_deleted.p = path->pos;
|
||||
|
||||
if (unlikely(flags & BTREE_TRIGGER_NORUN))
|
||||
return 0;
|
||||
|
||||
if (!btree_node_type_needs_gc(path->btree_id))
|
||||
return 0;
|
||||
|
||||
old = bch2_btree_path_peek_slot(path, &unpacked);
|
||||
|
||||
if (old.k->type == new->k.type &&
|
||||
((1U << old.k->type) & BTREE_TRIGGER_WANTS_OLD_AND_NEW)) {
|
||||
ret = bch2_mark_key(trans, old, bkey_i_to_s_c(new),
|
||||
BTREE_TRIGGER_INSERT|BTREE_TRIGGER_OVERWRITE|flags);
|
||||
} else {
|
||||
ret = bch2_mark_key(trans, deleted, bkey_i_to_s_c(new),
|
||||
BTREE_TRIGGER_INSERT|flags) ?:
|
||||
bch2_mark_key(trans, old, deleted,
|
||||
BTREE_TRIGGER_OVERWRITE|flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static noinline __cold
|
||||
void fs_usage_apply_warn(struct btree_trans *trans,
|
||||
unsigned disk_res_sectors,
|
||||
|
||||
@@ -231,9 +231,6 @@ void bch2_mark_metadata_bucket(struct bch_fs *, struct bch_dev *,
|
||||
|
||||
int bch2_mark_key(struct btree_trans *, struct bkey_s_c, struct bkey_s_c, unsigned);
|
||||
|
||||
int bch2_mark_update(struct btree_trans *, struct btree_path *,
|
||||
struct bkey_i *, unsigned);
|
||||
|
||||
int bch2_trans_mark_key(struct btree_trans *, struct bkey_s_c,
|
||||
struct bkey_i *, unsigned);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user