]> www.infradead.org Git - users/hch/configfs.git/commitdiff
bcachefs: Fix refcounting in discard path
authorKent Overstreet <kent.overstreet@linux.dev>
Thu, 22 Aug 2024 03:21:52 +0000 (23:21 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 22 Aug 2024 06:07:23 +0000 (02:07 -0400)
bch_dev->io_ref does not protect against the filesystem going away;
bch_fs->writes does.

Thus the filesystem write ref needs to be the last ref we release.

Reported-by: syzbot+9e0404b505e604f67e41@syzkaller.appspotmail.com
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/alloc_background.c

index dc97b1f8bc084a48e950195f5ff6f08339542838..ba46f1c1d78aad32650a7735632530944d4e98ad 100644 (file)
@@ -1874,26 +1874,26 @@ static void bch2_do_discards_work(struct work_struct *work)
        trace_discard_buckets(c, s.seen, s.open, s.need_journal_commit, s.discarded,
                              bch2_err_str(ret));
 
-       bch2_write_ref_put(c, BCH_WRITE_REF_discard);
        percpu_ref_put(&ca->io_ref);
+       bch2_write_ref_put(c, BCH_WRITE_REF_discard);
 }
 
 void bch2_dev_do_discards(struct bch_dev *ca)
 {
        struct bch_fs *c = ca->fs;
 
-       if (!bch2_dev_get_ioref(c, ca->dev_idx, WRITE))
+       if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_discard))
                return;
 
-       if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_discard))
-               goto put_ioref;
+       if (!bch2_dev_get_ioref(c, ca->dev_idx, WRITE))
+               goto put_write_ref;
 
        if (queue_work(c->write_ref_wq, &ca->discard_work))
                return;
 
-       bch2_write_ref_put(c, BCH_WRITE_REF_discard);
-put_ioref:
        percpu_ref_put(&ca->io_ref);
+put_write_ref:
+       bch2_write_ref_put(c, BCH_WRITE_REF_discard);
 }
 
 void bch2_do_discards(struct bch_fs *c)