bcachefs: Fix read path io_ref handling
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 28 Feb 2025 18:59:15 +0000 (13:59 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 15 Mar 2025 01:02:16 +0000 (21:02 -0400)
We were using our device pointer after we'd released our ref to it.

Unlikely to be a race that's practical to hit, since actually removing a
member device is a whole process besides just taking it offline, but -
needs to be fixed.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/io_read.c

index dcd5a2aee0f12f496e1d688bfdb4b71d3d905567..f97716e525563d0a3f22a506e75fba0e20728f70 100644 (file)
@@ -375,6 +375,11 @@ static inline struct bch_read_bio *bch2_rbio_free(struct bch_read_bio *rbio)
 {
        BUG_ON(rbio->bounce && !rbio->split);
 
+       if (rbio->have_ioref) {
+               struct bch_dev *ca = bch2_dev_have_ref(rbio->c, rbio->pick.ptr.dev);
+               percpu_ref_put(&ca->io_ref);
+       }
+
        if (rbio->split) {
                struct bch_read_bio *parent = rbio->parent;
 
@@ -790,10 +795,8 @@ static void bch2_read_endio(struct bio *bio)
        struct workqueue_struct *wq = NULL;
        enum rbio_context context = RBIO_CONTEXT_NULL;
 
-       if (rbio->have_ioref) {
+       if (ca)
                bch2_latency_acct(ca, rbio->submit_time, READ);
-               percpu_ref_put(&ca->io_ref);
-       }
 
        if (!rbio->split)
                rbio->bio.bi_end_io = rbio->end_io;