diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2024-05-19 12:23:51 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2024-05-20 05:37:26 -0400 |
commit | 427ba555036e85ed0805f45ca3896b68602e0a80 (patch) | |
tree | af97bca5f78ea54f1ec07ff708552e304d17540b | |
parent | eb6a9339efeb6f3d2b5c86fdf2382cdc293eca2c (diff) |
bcachefs: Fix rcu splat in check_fix_ptrs()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/buckets.c | 11 |
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); |