]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
bcachefs: Turn c->state_lock into an rwsem
authorKent Overstreet <kent.overstreet@gmail.com>
Mon, 15 Jun 2020 18:58:47 +0000 (14:58 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:41 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bcachefs.h
fs/bcachefs/btree_gc.c
fs/bcachefs/buckets.c
fs/bcachefs/error.c
fs/bcachefs/fs.c
fs/bcachefs/super.c
fs/bcachefs/sysfs.c

index a219969357bc2394ab595dd47592204cd51c4a2c..8d9cc7eb6ad7ae91b13be2096a7c47534b525d95 100644 (file)
@@ -551,8 +551,8 @@ struct bch_fs {
        struct super_block      *vfs_sb;
        char                    name[40];
 
-       /* ro/rw, add/remove devices: */
-       struct mutex            state_lock;
+       /* ro/rw, add/remove/resize devices: */
+       struct rw_semaphore     state_lock;
 
        /* Counts outstanding writes, for clean transition to read-only */
        struct percpu_ref       writes;
index 6589fe0bad6c3d674b614c7b9ca4f50cb726c1a3..22aa845ea630d73574f2190e2c433c9e7ae48d6a 100644 (file)
@@ -800,6 +800,7 @@ int bch2_gc(struct bch_fs *c, struct journal_keys *journal_keys,
        unsigned i, iter = 0;
        int ret;
 
+       lockdep_assert_held(&c->state_lock);
        trace_gc_start(c);
 
        down_write(&c->gc_lock);
index 08e8b578fff5a190bbb677dca215f5980f7e1587..5ee978c94568db531cb54b0d6c5851b5846582aa 100644 (file)
@@ -1967,6 +1967,8 @@ int bch2_dev_buckets_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
        int ret = -ENOMEM;
        unsigned i;
 
+       lockdep_assert_held(&c->state_lock);
+
        memset(&free,           0, sizeof(free));
        memset(&free_inc,       0, sizeof(free_inc));
        memset(&alloc_heap,     0, sizeof(alloc_heap));
@@ -1993,7 +1995,6 @@ int bch2_dev_buckets_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
        bch2_copygc_stop(ca);
 
        if (resize) {
-               down_write(&c->gc_lock);
                down_write(&ca->bucket_lock);
                percpu_down_write(&c->mark_lock);
        }
@@ -2036,10 +2037,8 @@ int bch2_dev_buckets_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
 
        nbuckets = ca->mi.nbuckets;
 
-       if (resize) {
+       if (resize)
                up_write(&ca->bucket_lock);
-               up_write(&c->gc_lock);
-       }
 
        if (start_copygc &&
            bch2_copygc_start(c, ca))
index 1662a36244cda36e67455afed32fd1f77ffef3eb..cd46706fb6f5a8020ad63a128b5c28fc910163b8 100644 (file)
@@ -37,7 +37,7 @@ void bch2_io_error_work(struct work_struct *work)
        struct bch_fs *c = ca->fs;
        bool dev;
 
-       mutex_lock(&c->state_lock);
+       down_write(&c->state_lock);
        dev = bch2_dev_state_allowed(c, ca, BCH_MEMBER_STATE_RO,
                                    BCH_FORCE_IF_DEGRADED);
        if (dev
@@ -47,7 +47,7 @@ void bch2_io_error_work(struct work_struct *work)
                bch_err(ca,
                        "too many IO errors, setting %s RO",
                        dev ? "device" : "filesystem");
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
 }
 
 void bch2_io_error(struct bch_dev *ca)
index 6aff3203b4e101ec142c0133b02bf88aa5a14576..4538551ccca36148ea24cb524df271ffddf0c33d 100644 (file)
@@ -1342,16 +1342,16 @@ static struct bch_fs *__bch2_open_as_blockdevs(const char *dev_name, char * cons
        if (IS_ERR(c))
                return c;
 
-       mutex_lock(&c->state_lock);
+       down_write(&c->state_lock);
 
        if (!test_bit(BCH_FS_STARTED, &c->flags)) {
-               mutex_unlock(&c->state_lock);
+               up_write(&c->state_lock);
                closure_put(&c->cl);
                pr_err("err mounting %s: incomplete filesystem", dev_name);
                return ERR_PTR(-EINVAL);
        }
 
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
 
        set_bit(BCH_FS_BDEV_MOUNTED, &c->flags);
        return c;
@@ -1400,7 +1400,7 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data)
                return ret;
 
        if (opts.read_only != c->opts.read_only) {
-               mutex_lock(&c->state_lock);
+               down_write(&c->state_lock);
 
                if (opts.read_only) {
                        bch2_fs_read_only(c);
@@ -1410,7 +1410,7 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data)
                        ret = bch2_fs_read_write(c);
                        if (ret) {
                                bch_err(c, "error going rw: %i", ret);
-                               mutex_unlock(&c->state_lock);
+                               up_write(&c->state_lock);
                                return -EINVAL;
                        }
 
@@ -1419,7 +1419,7 @@ static int bch2_remount(struct super_block *sb, int *flags, char *data)
 
                c->opts.read_only = opts.read_only;
 
-               mutex_unlock(&c->state_lock);
+               up_write(&c->state_lock);
        }
 
        if (opts.errors >= 0)
index 819d4392d5294643bfaa411ef6f369ce308894ca..3a7c48def9e8e7d068f4f3069e1170e5b7c5ad36 100644 (file)
@@ -340,9 +340,9 @@ static void bch2_fs_read_only_work(struct work_struct *work)
        struct bch_fs *c =
                container_of(work, struct bch_fs, read_only_work);
 
-       mutex_lock(&c->state_lock);
+       down_write(&c->state_lock);
        bch2_fs_read_only(c);
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
 }
 
 static void bch2_fs_read_only_async(struct bch_fs *c)
@@ -534,9 +534,9 @@ void bch2_fs_stop(struct bch_fs *c)
 
        cancel_work_sync(&c->journal_seq_blacklist_gc_work);
 
-       mutex_lock(&c->state_lock);
+       down_write(&c->state_lock);
        bch2_fs_read_only(c);
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
 
        for_each_member_device(ca, c, i)
                if (ca->kobj.state_in_sysfs &&
@@ -607,7 +607,7 @@ static const char *bch2_fs_online(struct bch_fs *c)
            bch2_opts_create_sysfs_files(&c->opts_dir))
                return "error creating sysfs objects";
 
-       mutex_lock(&c->state_lock);
+       down_write(&c->state_lock);
 
        err = "error creating sysfs objects";
        __for_each_member_device(ca, c, i, NULL)
@@ -617,7 +617,7 @@ static const char *bch2_fs_online(struct bch_fs *c)
        list_add(&c->list, &bch_fs_list);
        err = NULL;
 err:
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
        return err;
 }
 
@@ -639,7 +639,7 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
        c->minor                = -1;
        c->disk_sb.fs_sb        = true;
 
-       mutex_init(&c->state_lock);
+       init_rwsem(&c->state_lock);
        mutex_init(&c->sb_lock);
        mutex_init(&c->replicas_gc_lock);
        mutex_init(&c->btree_root_lock);
@@ -832,7 +832,7 @@ int bch2_fs_start(struct bch_fs *c)
        unsigned i;
        int ret = -EINVAL;
 
-       mutex_lock(&c->state_lock);
+       down_write(&c->state_lock);
 
        BUG_ON(test_bit(BCH_FS_STARTED, &c->flags));
 
@@ -882,7 +882,7 @@ int bch2_fs_start(struct bch_fs *c)
        print_mount_opts(c);
        ret = 0;
 out:
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
        return ret;
 err:
        switch (ret) {
@@ -1376,9 +1376,9 @@ int bch2_dev_set_state(struct bch_fs *c, struct bch_dev *ca,
 {
        int ret;
 
-       mutex_lock(&c->state_lock);
+       down_write(&c->state_lock);
        ret = __bch2_dev_set_state(c, ca, new_state, flags);
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
 
        return ret;
 }
@@ -1391,7 +1391,7 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
        unsigned dev_idx = ca->dev_idx, data;
        int ret = -EINVAL;
 
-       mutex_lock(&c->state_lock);
+       down_write(&c->state_lock);
 
        /*
         * We consume a reference to ca->ref, regardless of whether we succeed
@@ -1481,13 +1481,13 @@ int bch2_dev_remove(struct bch_fs *c, struct bch_dev *ca, int flags)
        bch2_write_super(c);
 
        mutex_unlock(&c->sb_lock);
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
        return 0;
 err:
        if (ca->mi.state == BCH_MEMBER_STATE_RW &&
            !percpu_ref_is_zero(&ca->io_ref))
                __bch2_dev_read_write(c, ca);
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
        return ret;
 }
 
@@ -1563,7 +1563,7 @@ int bch2_dev_add(struct bch_fs *c, const char *path)
 
        dev_usage_clear(ca);
 
-       mutex_lock(&c->state_lock);
+       down_write(&c->state_lock);
        mutex_lock(&c->sb_lock);
 
        err = "insufficient space in new superblock";
@@ -1624,12 +1624,12 @@ have_slot:
                        goto err_late;
        }
 
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
        return 0;
 
 err_unlock:
        mutex_unlock(&c->sb_lock);
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
 err:
        if (ca)
                bch2_dev_free(ca);
@@ -1652,11 +1652,11 @@ int bch2_dev_online(struct bch_fs *c, const char *path)
        const char *err;
        int ret;
 
-       mutex_lock(&c->state_lock);
+       down_write(&c->state_lock);
 
        ret = bch2_read_super(path, &opts, &sb);
        if (ret) {
-               mutex_unlock(&c->state_lock);
+               up_write(&c->state_lock);
                return ret;
        }
 
@@ -1687,10 +1687,10 @@ int bch2_dev_online(struct bch_fs *c, const char *path)
        bch2_write_super(c);
        mutex_unlock(&c->sb_lock);
 
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
        return 0;
 err:
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
        bch2_free_super(&sb);
        bch_err(c, "error bringing %s online: %s", path, err);
        return -EINVAL;
@@ -1698,23 +1698,23 @@ err:
 
 int bch2_dev_offline(struct bch_fs *c, struct bch_dev *ca, int flags)
 {
-       mutex_lock(&c->state_lock);
+       down_write(&c->state_lock);
 
        if (!bch2_dev_is_online(ca)) {
                bch_err(ca, "Already offline");
-               mutex_unlock(&c->state_lock);
+               up_write(&c->state_lock);
                return 0;
        }
 
        if (!bch2_dev_state_allowed(c, ca, BCH_MEMBER_STATE_FAILED, flags)) {
                bch_err(ca, "Cannot offline required disk");
-               mutex_unlock(&c->state_lock);
+               up_write(&c->state_lock);
                return -EINVAL;
        }
 
        __bch2_dev_offline(c, ca);
 
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
        return 0;
 }
 
@@ -1723,7 +1723,7 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
        struct bch_member *mi;
        int ret = 0;
 
-       mutex_lock(&c->state_lock);
+       down_write(&c->state_lock);
 
        if (nbuckets < ca->mi.nbuckets) {
                bch_err(ca, "Cannot shrink yet");
@@ -1754,7 +1754,7 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
 
        bch2_recalc_capacity(c);
 err:
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
        return ret;
 }
 
@@ -1834,13 +1834,13 @@ struct bch_fs *bch2_fs_open(char * const *devices, unsigned nr_devices,
                goto err;
 
        err = "bch2_dev_online() error";
-       mutex_lock(&c->state_lock);
+       down_write(&c->state_lock);
        for (i = 0; i < nr_devices; i++)
                if (bch2_dev_attach_bdev(c, &sb[i])) {
-                       mutex_unlock(&c->state_lock);
+                       up_write(&c->state_lock);
                        goto err_print;
                }
-       mutex_unlock(&c->state_lock);
+       up_write(&c->state_lock);
 
        err = "insufficient devices";
        if (!bch2_fs_may_start(c))
index 06b59e99131284d294ff539b07ce0b641e05dd1c..663b59e788246a778c29b55b63f315cfbfd00bc8 100644 (file)
@@ -427,7 +427,7 @@ SHOW(bch2_fs)
        return 0;
 }
 
-STORE(__bch2_fs)
+STORE(bch2_fs)
 {
        struct bch_fs *c = container_of(kobj, struct bch_fs, kobj);
 
@@ -485,8 +485,11 @@ STORE(__bch2_fs)
        if (attr == &sysfs_trigger_btree_coalesce)
                bch2_coalesce(c);
 
-       if (attr == &sysfs_trigger_gc)
+       if (attr == &sysfs_trigger_gc) {
+               down_read(&c->state_lock);
                bch2_gc(c, NULL, false, false);
+               up_read(&c->state_lock);
+       }
 
        if (attr == &sysfs_trigger_alloc_write) {
                bool wrote;
@@ -501,6 +504,7 @@ STORE(__bch2_fs)
                sc.nr_to_scan = strtoul_or_return(buf);
                c->btree_cache.shrink.scan_objects(&c->btree_cache.shrink, &sc);
        }
+
 #ifdef CONFIG_BCACHEFS_TESTS
        if (attr == &sysfs_perf_test) {
                char *tmp = kstrdup(buf, GFP_KERNEL), *p = tmp;
@@ -522,17 +526,6 @@ STORE(__bch2_fs)
 #endif
        return size;
 }
-
-STORE(bch2_fs)
-{
-       struct bch_fs *c = container_of(kobj, struct bch_fs, kobj);
-
-       mutex_lock(&c->state_lock);
-       size = __bch2_fs_store(kobj, attr, buf, size);
-       mutex_unlock(&c->state_lock);
-
-       return size;
-}
 SYSFS_OPS(bch2_fs);
 
 struct attribute *bch2_fs_files[] = {