summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2024-05-19 12:23:51 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2024-05-20 05:37:26 -0400
commit427ba555036e85ed0805f45ca3896b68602e0a80 (patch)
treeaf97bca5f78ea54f1ec07ff708552e304d17540b
parenteb6a9339efeb6f3d2b5c86fdf2382cdc293eca2c (diff)
bcachefs: Fix rcu splat in check_fix_ptrs()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/buckets.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c
index e28d28ac2a13..02bb02b70981 100644
--- a/fs/bcachefs/buckets.c
+++ b/fs/bcachefs/buckets.c
@@ -479,9 +479,8 @@ int bch2_check_fix_ptrs(struct btree_trans *trans,
percpu_down_read(&c->mark_lock);
- rcu_read_lock();
bkey_for_each_ptr_decode(k.k, ptrs_c, p, entry_c) {
- struct bch_dev *ca = bch2_dev_rcu(c, p.ptr.dev);
+ struct bch_dev *ca = bch2_dev_tryget(c, p.ptr.dev);
if (!ca) {
if (fsck_err(c, ptr_to_invalid_device,
"pointer to missing device %u\n"
@@ -558,7 +557,7 @@ int bch2_check_fix_ptrs(struct btree_trans *trans,
do_update = true;
if (data_type != BCH_DATA_btree && p.ptr.gen != g->gen)
- continue;
+ goto next;
if (fsck_err_on(bucket_data_type_mismatch(g->data_type, data_type),
c, ptr_bucket_data_type_mismatch,
@@ -601,8 +600,9 @@ int bch2_check_fix_ptrs(struct btree_trans *trans,
bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
do_update = true;
}
+next:
+ bch2_dev_put(ca);
}
- rcu_read_unlock();
if (do_update) {
if (flags & BTREE_TRIGGER_is_root) {
@@ -638,9 +638,10 @@ int bch2_check_fix_ptrs(struct btree_trans *trans,
} else {
struct bkey_ptrs ptrs;
union bch_extent_entry *entry;
+
+ rcu_read_lock();
restart_drop_ptrs:
ptrs = bch2_bkey_ptrs(bkey_i_to_s(new));
- rcu_read_lock();
bkey_for_each_ptr_decode(bkey_i_to_s(new).k, ptrs, p, entry) {
struct bch_dev *ca = bch2_dev_rcu(c, p.ptr.dev);
struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr);