summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-04-03 19:41:09 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:59 -0400
commit9c2e624290f24c69c835bc82b1abe349810e338f (patch)
tree8fd8e882d2c314e00cc0c4f357f626e85418ee2c
parent2940295c97f49ffe0b2f564dea394094581073e7 (diff)
downloadlwn-9c2e624290f24c69c835bc82b1abe349810e338f.tar.gz
lwn-9c2e624290f24c69c835bc82b1abe349810e338f.zip
bcachefs: Fix livelock calling bch2_mark_bkey_replicas()
The bug was that we were trying to find a replicas entry that wasn't sorted - but, we can also simplify the code by not using bch2_mark_bkey_replicas and instead ensuring the list of replicas entries exists directly. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/btree_update_leaf.c8
-rw-r--r--fs/bcachefs/buckets.c13
-rw-r--r--fs/bcachefs/buckets.h2
3 files changed, 18 insertions, 5 deletions
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index ee1c26f2901f..54e3850df009 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -707,11 +707,9 @@ int bch2_trans_commit_error(struct btree_trans *trans,
case BTREE_INSERT_NEED_MARK_REPLICAS:
bch2_trans_unlock(trans);
- trans_for_each_update(trans, i) {
- ret = bch2_mark_bkey_replicas(c, bkey_i_to_s_c(i->k));
- if (ret)
- return ret;
- }
+ ret = bch2_replicas_delta_list_mark(c, trans->fs_usage_deltas);
+ if (ret)
+ return ret;
if (bch2_trans_relock(trans))
return 0;
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c
index 4c2485afe43c..0b90104ffe7b 100644
--- a/fs/bcachefs/buckets.c
+++ b/fs/bcachefs/buckets.c
@@ -565,6 +565,7 @@ static inline void update_replicas_list(struct btree_trans *trans,
n->delta = sectors;
memcpy((void *) n + offsetof(struct replicas_delta, r),
r, replicas_entry_bytes(r));
+ bch2_replicas_entry_sort(&n->r);
d->used += b;
}
@@ -615,6 +616,18 @@ unwind:
return -1;
}
+int bch2_replicas_delta_list_mark(struct bch_fs *c,
+ struct replicas_delta_list *r)
+{
+ struct replicas_delta *d = r->d;
+ struct replicas_delta *top = (void *) r->d + r->used;
+ int ret = 0;
+
+ for (d = r->d; !ret && d != top; d = replicas_delta_next(d))
+ ret = bch2_mark_replicas(c, &d->r);
+ return ret;
+}
+
#define do_mark_fn(fn, c, pos, flags, ...) \
({ \
int gc, ret = 0; \
diff --git a/fs/bcachefs/buckets.h b/fs/bcachefs/buckets.h
index af8cb74d71e0..1b83a768ba06 100644
--- a/fs/bcachefs/buckets.h
+++ b/fs/bcachefs/buckets.h
@@ -253,6 +253,8 @@ int bch2_mark_update(struct btree_trans *, struct btree_iter *,
int bch2_replicas_delta_list_apply(struct bch_fs *,
struct bch_fs_usage *,
struct replicas_delta_list *);
+int bch2_replicas_delta_list_mark(struct bch_fs *,
+ struct replicas_delta_list *);
int bch2_trans_mark_key(struct btree_trans *, struct bkey_s_c, struct bkey_s_c,
unsigned, s64, unsigned);
int bch2_trans_mark_update(struct btree_trans *, struct btree_iter *iter,