]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
bcachefs: Fix some refcounting bugs
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 8 May 2021 00:43:43 +0000 (20:43 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:03 +0000 (17:09 -0400)
We really need debug mode assertions that ca->ref and ca->io_ref are
used correctly.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/alloc_background.c
fs/bcachefs/btree_gc.c
fs/bcachefs/buckets.c
fs/bcachefs/recovery.c
fs/bcachefs/super.c
fs/bcachefs/super.h

index 996b1afd138026bae295120938d2116bedf80024..791066b6b39b4b43735eb2bfad311017e791aa8e 100644 (file)
@@ -371,7 +371,7 @@ int bch2_alloc_write(struct bch_fs *c, unsigned flags)
 
                        ret = bch2_alloc_write_key(&trans, iter, flags);
                        if (ret) {
-                               percpu_ref_put(&ca->io_ref);
+                               percpu_ref_put(&ca->ref);
                                goto err;
                        }
                        bch2_btree_iter_next_slot(iter);
index 1c2eab41f7ca42340d079ccbfa0c9abbe871569f..bd4dd1d67a1d84b23ffdf8d4af64357ccddbef5d 100644 (file)
@@ -1023,7 +1023,7 @@ static void bch2_gc_free(struct bch_fs *c)
 static int bch2_gc_done(struct bch_fs *c,
                        bool initial, bool metadata_only)
 {
-       struct bch_dev *ca;
+       struct bch_dev *ca = NULL;
        bool verify = !metadata_only && (!initial ||
                       (c->sb.compat & (1ULL << BCH_COMPAT_alloc_info)));
        unsigned i, dev;
@@ -1169,6 +1169,8 @@ static int bch2_gc_done(struct bch_fs *c,
 #undef copy_stripe_field
 #undef copy_field
 fsck_err:
+       if (ca)
+               percpu_ref_put(&ca->ref);
        if (ret)
                bch_err(c, "%s: ret %i", __func__, ret);
        return ret;
@@ -1177,7 +1179,7 @@ fsck_err:
 static int bch2_gc_start(struct bch_fs *c,
                         bool metadata_only)
 {
-       struct bch_dev *ca;
+       struct bch_dev *ca = NULL;
        unsigned i;
        int ret;
 
index d6f0325affcc5d89796fc8b42166fa5756884ca2..a83d5de87d39108e579c1af72aeaf0771097e85a 100644 (file)
@@ -2071,7 +2071,7 @@ static int __bch2_trans_mark_dev_sb(struct btree_trans *trans,
 
 int bch2_trans_mark_dev_sb(struct bch_fs *c, struct bch_dev *ca)
 {
-       return bch2_trans_do(c, NULL, NULL, 0,
+       return bch2_trans_do(c, NULL, NULL, BTREE_INSERT_LAZY_RW,
                        __bch2_trans_mark_dev_sb(&trans, ca));
 }
 
index b35b297d4446891a2aa812e8c31746602e8e3be9..cd538ecc1f3f871689520bdffb599955c4915adb 100644 (file)
@@ -1328,8 +1328,10 @@ int bch2_fs_initialize(struct bch_fs *c)
        err = "error marking superblock and journal";
        for_each_member_device(ca, c, i) {
                ret = bch2_trans_mark_dev_sb(c, ca);
-               if (ret)
+               if (ret) {
+                       percpu_ref_put(&ca->ref);
                        goto err;
+               }
        }
 
        bch2_inode_init(c, &root_inode, 0, 0,
index 78db2c0a5f5a01c8e19d2382b17d431a4571605d..9065e264c5675d7cab65b8b19ad558571bb9c3ca 100644 (file)
@@ -629,9 +629,11 @@ static const char *bch2_fs_online(struct bch_fs *c)
        down_write(&c->state_lock);
 
        err = "error creating sysfs objects";
-       __for_each_member_device(ca, c, i, NULL)
-               if (bch2_dev_sysfs_online(c, ca))
+       for_each_member_device(ca, c, i)
+               if (bch2_dev_sysfs_online(c, ca)) {
+                       percpu_ref_put(&ca->ref);
                        goto err;
+               }
 
        list_add(&c->list, &bch_fs_list);
        err = NULL;
@@ -1839,12 +1841,14 @@ struct bch_dev *bch2_dev_lookup(struct bch_fs *c, const char *path)
        if (ret)
                return ERR_PTR(ret);
 
-       for_each_member_device(ca, c, i)
+       rcu_read_lock();
+       for_each_member_device_rcu(ca, c, i, NULL)
                if (ca->disk_sb.bdev->bd_dev == dev)
                        goto found;
-
        ca = ERR_PTR(-ENOENT);
 found:
+       rcu_read_unlock();
+
        return ca;
 }
 
index 28e6d78f9fcd5dd00f0968de79602495314740c5..b151bffcd3a38a471b8697dfca0029f3dc4bb05a 100644 (file)
@@ -107,11 +107,8 @@ static inline struct bch_dev *__bch2_next_dev(struct bch_fs *c, unsigned *iter,
        return ca;
 }
 
-#define __for_each_member_device(ca, c, iter, mask)                    \
-       for ((iter) = 0; ((ca) = __bch2_next_dev((c), &(iter), mask)); (iter)++)
-
 #define for_each_member_device_rcu(ca, c, iter, mask)                  \
-       __for_each_member_device(ca, c, iter, mask)
+       for ((iter) = 0; ((ca) = __bch2_next_dev((c), &(iter), mask)); (iter)++)
 
 static inline struct bch_dev *bch2_get_next_dev(struct bch_fs *c, unsigned *iter)
 {