mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-18 19:27:13 +00:00
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>
This commit is contained in:
parent
7fffc85baf
commit
1ada160618
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
|
@ -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[] = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user