summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-06-24 17:50:52 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:23 -0400
commit88767d65d84257f9b5dfed1aa89404f1b6ddf142 (patch)
tree5796773313bd997142f61b5372c7cada6dda8d44
parent44da9767bb32467ac660ce6bacf75162f5abf9a1 (diff)
bcachefs: Update path now handles triggers that generate more triggers
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/btree_types.h1
-rw-r--r--fs/bcachefs/btree_update_leaf.c29
-rw-r--r--fs/bcachefs/buckets.c24
-rw-r--r--fs/bcachefs/buckets.h3
4 files changed, 37 insertions, 20 deletions
diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h
index bdcf9288d749..ec14e2deecb7 100644
--- a/fs/bcachefs/btree_types.h
+++ b/fs/bcachefs/btree_types.h
@@ -265,6 +265,7 @@ struct btree_insert_entry {
bool deferred;
bool triggered;
+ bool marked;
};
#define BTREE_ITER_MAX 64
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index 6e63c916986e..4461e42f2367 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -542,6 +542,7 @@ static inline int do_btree_insert_at(struct btree_trans *trans,
struct bch_fs *c = trans->c;
struct bch_fs_usage_online *fs_usage = NULL;
struct btree_insert_entry *i;
+ bool saw_non_marked;
unsigned mark_flags = trans->flags & BTREE_INSERT_BUCKET_INVALIDATE
? BCH_BUCKET_MARK_BUCKET_INVALIDATE
: 0;
@@ -551,14 +552,28 @@ static inline int do_btree_insert_at(struct btree_trans *trans,
BUG_ON(i->iter->uptodate >= BTREE_ITER_NEED_RELOCK);
trans_for_each_update_iter(trans, i)
- if (update_has_triggers(trans, i) &&
- update_triggers_transactional(trans, i)) {
- ret = bch2_trans_mark_update(trans, i);
- if (ret == -EINTR)
- trace_trans_restart_mark(trans->ip);
- if (ret)
- goto out_clear_replicas;
+ i->marked = false;
+
+ do {
+ saw_non_marked = false;
+
+ trans_for_each_update_iter(trans, i) {
+ if (i->marked)
+ continue;
+
+ saw_non_marked = true;
+ i->marked = true;
+
+ if (update_has_triggers(trans, i) &&
+ update_triggers_transactional(trans, i)) {
+ ret = bch2_trans_mark_update(trans, i->iter, i->k);
+ if (ret == -EINTR)
+ trace_trans_restart_mark(trans->ip);
+ if (ret)
+ goto out_clear_replicas;
+ }
}
+ } while (saw_non_marked);
btree_trans_lock_write(c, trans);
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c
index 0d96ea572bd0..911c39c4872e 100644
--- a/fs/bcachefs/buckets.c
+++ b/fs/bcachefs/buckets.c
@@ -1590,9 +1590,9 @@ int bch2_trans_mark_key(struct btree_trans *trans, struct bkey_s_c k,
}
int bch2_trans_mark_update(struct btree_trans *trans,
- struct btree_insert_entry *insert)
+ struct btree_iter *iter,
+ struct bkey_i *insert)
{
- struct btree_iter *iter = insert->iter;
struct btree *b = iter->l[0].b;
struct btree_node_iter node_iter = iter->l[0].iter;
struct bkey_packed *_k;
@@ -1602,9 +1602,9 @@ int bch2_trans_mark_update(struct btree_trans *trans,
return 0;
ret = bch2_trans_mark_key(trans,
- bkey_i_to_s_c(insert->k),
- bpos_min(insert->k->k.p, b->key.k.p).offset -
- bkey_start_offset(&insert->k->k),
+ bkey_i_to_s_c(insert),
+ bpos_min(insert->k.p, b->key.k.p).offset -
+ bkey_start_offset(&insert->k),
BCH_BUCKET_MARK_INSERT);
if (ret)
return ret;
@@ -1618,25 +1618,25 @@ int bch2_trans_mark_update(struct btree_trans *trans,
k = bkey_disassemble(b, _k, &unpacked);
if (btree_node_is_extents(b)
- ? bkey_cmp(insert->k->k.p, bkey_start_pos(k.k)) <= 0
- : bkey_cmp(insert->k->k.p, k.k->p))
+ ? bkey_cmp(insert->k.p, bkey_start_pos(k.k)) <= 0
+ : bkey_cmp(insert->k.p, k.k->p))
break;
if (btree_node_is_extents(b)) {
- switch (bch2_extent_overlap(&insert->k->k, k.k)) {
+ switch (bch2_extent_overlap(&insert->k, k.k)) {
case BCH_EXTENT_OVERLAP_ALL:
sectors = -((s64) k.k->size);
break;
case BCH_EXTENT_OVERLAP_BACK:
- sectors = bkey_start_offset(&insert->k->k) -
+ sectors = bkey_start_offset(&insert->k) -
k.k->p.offset;
break;
case BCH_EXTENT_OVERLAP_FRONT:
sectors = bkey_start_offset(k.k) -
- insert->k->k.p.offset;
+ insert->k.p.offset;
break;
case BCH_EXTENT_OVERLAP_MIDDLE:
- sectors = k.k->p.offset - insert->k->k.p.offset;
+ sectors = k.k->p.offset - insert->k.p.offset;
BUG_ON(sectors <= 0);
ret = bch2_trans_mark_key(trans, k, sectors,
@@ -1644,7 +1644,7 @@ int bch2_trans_mark_update(struct btree_trans *trans,
if (ret)
return ret;
- sectors = bkey_start_offset(&insert->k->k) -
+ sectors = bkey_start_offset(&insert->k) -
k.k->p.offset;
break;
}
diff --git a/fs/bcachefs/buckets.h b/fs/bcachefs/buckets.h
index 793bb8cb2527..46eb493b42ca 100644
--- a/fs/bcachefs/buckets.h
+++ b/fs/bcachefs/buckets.h
@@ -274,7 +274,8 @@ void bch2_replicas_delta_list_apply(struct bch_fs *,
struct replicas_delta_list *);
int bch2_trans_mark_key(struct btree_trans *, struct bkey_s_c, s64, unsigned);
int bch2_trans_mark_update(struct btree_trans *,
- struct btree_insert_entry *);
+ struct btree_iter *iter,
+ struct bkey_i *insert);
void bch2_trans_fs_usage_apply(struct btree_trans *, struct bch_fs_usage_online *);
/* disk reservations: */