]> www.infradead.org Git - linux.git/commitdiff
bcachefs: Fix lifetime issue in device iterator helpers
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 4 May 2024 16:55:44 +0000 (12:55 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Mon, 6 May 2024 14:58:17 +0000 (10:58 -0400)
bch2_get_next_dev() and bch2_get_next_online_dev() iterate over devices,
dropping and taking refs as they go; we can't access the previous device
(for ca->dev_idx) after we've dropped our ref to it, unless we take
rcu_read_lock() first.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/sb-members.h

index 5efa64eca5f85af5637faa12aa85b83fbcde6ad3..5bf27d30ca2969017c6d33edde8c99ce1a36cb7b 100644 (file)
@@ -107,10 +107,10 @@ static inline struct bch_dev *__bch2_next_dev(struct bch_fs *c, struct bch_dev *
 
 static inline struct bch_dev *bch2_get_next_dev(struct bch_fs *c, struct bch_dev *ca)
 {
+       rcu_read_lock();
        if (ca)
                percpu_ref_put(&ca->ref);
 
-       rcu_read_lock();
        if ((ca = __bch2_next_dev(c, ca, NULL)))
                percpu_ref_get(&ca->ref);
        rcu_read_unlock();
@@ -132,10 +132,10 @@ static inline struct bch_dev *bch2_get_next_online_dev(struct bch_fs *c,
                                                       struct bch_dev *ca,
                                                       unsigned state_mask)
 {
+       rcu_read_lock();
        if (ca)
                percpu_ref_put(&ca->io_ref);
 
-       rcu_read_lock();
        while ((ca = __bch2_next_dev(c, ca, NULL)) &&
               (!((1 << ca->mi.state) & state_mask) ||
                !percpu_ref_tryget(&ca->io_ref)))