diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-04-03 19:41:09 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:08:59 -0400 |
commit | 9c2e624290f24c69c835bc82b1abe349810e338f (patch) | |
tree | 8fd8e882d2c314e00cc0c4f357f626e85418ee2c | |
parent | 2940295c97f49ffe0b2f564dea394094581073e7 (diff) | |
download | lwn-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.c | 8 | ||||
-rw-r--r-- | fs/bcachefs/buckets.c | 13 | ||||
-rw-r--r-- | fs/bcachefs/buckets.h | 2 |
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, |