diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2020-06-15 14:58:47 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:08:41 -0400 |
commit | 1ada160618d66bc57beacb4c35f13e9a4c269afa (patch) | |
tree | da5f9d4111d5b12bac49a3b53faac7609c331aa1 /fs | |
parent | 7fffc85baf1fa176560a546a0625efc549969ce4 (diff) |
bcachefs: Turn c->state_lock into an rwsem
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bcachefs/bcachefs.h | 4 | ||||
-rw-r--r-- | fs/bcachefs/btree_gc.c | 1 | ||||
-rw-r--r-- | fs/bcachefs/buckets.c | 7 | ||||
-rw-r--r-- | fs/bcachefs/error.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/fs.c | 12 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 60 | ||||
-rw-r--r-- | fs/bcachefs/sysfs.c | 19 |
7 files changed, 50 insertions, 57 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index a219969357bc..8d9cc7eb6ad7 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -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; diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index 6589fe0bad6c..22aa845ea630 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -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); diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index 08e8b578fff5..5ee978c94568 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c @@ -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)) diff --git a/fs/bcachefs/error.c b/fs/bcachefs/error.c index 1662a36244cd..cd46706fb6f5 100644 --- a/fs/bcachefs/error.c +++ b/fs/bcachefs/error.c @@ -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) diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index 6aff3203b4e1..4538551ccca3 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c @@ -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) diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 819d4392d529..3a7c48def9e8 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -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)) diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c index 06b59e991312..663b59e78824 100644 --- a/fs/bcachefs/sysfs.c +++ b/fs/bcachefs/sysfs.c @@ -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[] = { |