diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-03-22 03:38:43 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-03-22 04:03:01 -0400 |
commit | ef097245223f66434a6b0d3156fd27ef842f5342 (patch) | |
tree | 357d6e4b622f146ee31c53a6db697234fc3159c1 | |
parent | 67de55671cebd30548395ea59599de56fd596ce5 (diff) |
bcachefs: go online before bch2_fs_start()
-rw-r--r-- | fs/bcachefs/bcachefs.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/chardev.c | 18 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 126 |
3 files changed, 70 insertions, 75 deletions
diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index 369d078c3d2e..c144f8f498d4 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -436,6 +436,7 @@ enum { BCH_FS_ALLOCATOR_STARTED, BCH_FS_INITIAL_GC_DONE, BCH_FS_FSCK_DONE, + BCH_FS_STARTED, /* shutdown: */ BCH_FS_EMERGENCY_RO, diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c index ab6dc665186e..ab5adca496bb 100644 --- a/fs/bcachefs/chardev.c +++ b/fs/bcachefs/chardev.c @@ -372,6 +372,9 @@ static long bch2_ioctl_usage(struct bch_fs *c, unsigned i, j; int ret; + if (!test_bit(BCH_FS_STARTED, &c->flags)) + return -EINVAL; + if (copy_from_user(&arg, user_arg, sizeof(arg))) return -EFAULT; @@ -535,13 +538,22 @@ long bch2_fs_ioctl(struct bch_fs *c, unsigned cmd, void __user *arg) if (!capable(CAP_SYS_ADMIN)) return -EPERM; - /* ioctls that do require admin cap: */ switch (cmd) { case BCH_IOCTL_START: BCH_IOCTL(start, struct bch_ioctl_start); case BCH_IOCTL_STOP: return bch2_ioctl_stop(c); + case BCH_IOCTL_READ_SUPER: + BCH_IOCTL(read_super, struct bch_ioctl_read_super); + case BCH_IOCTL_DISK_GET_IDX: + BCH_IOCTL(disk_get_idx, struct bch_ioctl_disk_get_idx); + } + if (!test_bit(BCH_FS_STARTED, &c->flags)) + return -EINVAL; + + /* ioctls that do require admin cap: */ + switch (cmd) { case BCH_IOCTL_DISK_ADD: BCH_IOCTL(disk_add, struct bch_ioctl_disk); case BCH_IOCTL_DISK_REMOVE: @@ -554,10 +566,6 @@ long bch2_fs_ioctl(struct bch_fs *c, unsigned cmd, void __user *arg) BCH_IOCTL(disk_set_state, struct bch_ioctl_disk_set_state); case BCH_IOCTL_DATA: BCH_IOCTL(data, struct bch_ioctl_data); - case BCH_IOCTL_READ_SUPER: - BCH_IOCTL(read_super, struct bch_ioctl_read_super); - case BCH_IOCTL_DISK_GET_IDX: - BCH_IOCTL(disk_get_idx, struct bch_ioctl_disk_get_idx); case BCH_IOCTL_DISK_RESIZE: BCH_IOCTL(disk_resize, struct bch_ioctl_disk_resize); diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 77670ea6e077..f901c3757651 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -501,11 +501,54 @@ void bch2_fs_stop(struct bch_fs *c) kobject_put(&c->kobj); } +static const char *bch2_fs_online(struct bch_fs *c) +{ + struct bch_dev *ca; + const char *err = NULL; + unsigned i; + int ret; + + lockdep_assert_held(&bch_fs_list_lock); + + if (!list_empty(&c->list)) + return NULL; + + if (__bch2_uuid_to_fs(c->sb.uuid)) + return "filesystem UUID already open"; + + ret = bch2_fs_chardev_init(c); + if (ret) + return "error creating character device"; + + bch2_fs_debug_init(c); + + if (kobject_add(&c->kobj, NULL, "%pU", c->sb.user_uuid.b) || + kobject_add(&c->internal, &c->kobj, "internal") || + kobject_add(&c->opts_dir, &c->kobj, "options") || + kobject_add(&c->time_stats, &c->kobj, "time_stats") || + bch2_opts_create_sysfs_files(&c->opts_dir)) + return "error creating sysfs objects"; + + mutex_lock(&c->state_lock); + + err = "error creating sysfs objects"; + __for_each_member_device(ca, c, i, NULL) + if (bch2_dev_sysfs_online(c, ca)) + goto err; + + list_add(&c->list, &bch_fs_list); + err = NULL; +err: + mutex_unlock(&c->state_lock); + return err; +} + static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) { struct bch_sb_field_members *mi; struct bch_fs *c; unsigned i, iter_size; + const char *err; pr_verbose_init(opts, ""); @@ -644,6 +687,14 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) kobject_init(&c->internal, &bch2_fs_internal_ktype); kobject_init(&c->opts_dir, &bch2_fs_opts_dir_ktype); kobject_init(&c->time_stats, &bch2_fs_time_stats_ktype); + + mutex_lock(&bch_fs_list_lock); + err = bch2_fs_online(c); + mutex_unlock(&bch_fs_list_lock); + if (err) { + bch_err(c, "bch2_fs_online() error: %s", err); + goto err; + } out: pr_verbose_init(opts, "ret %i", c ? 0 : -ENOMEM); return c; @@ -653,60 +704,7 @@ err: goto out; } -static const char *__bch2_fs_online(struct bch_fs *c) -{ - struct bch_dev *ca; - const char *err = NULL; - unsigned i; - int ret; - - lockdep_assert_held(&bch_fs_list_lock); - - if (!list_empty(&c->list)) - return NULL; - - if (__bch2_uuid_to_fs(c->sb.uuid)) - return "filesystem UUID already open"; - - ret = bch2_fs_chardev_init(c); - if (ret) - return "error creating character device"; - - bch2_fs_debug_init(c); - - if (kobject_add(&c->kobj, NULL, "%pU", c->sb.user_uuid.b) || - kobject_add(&c->internal, &c->kobj, "internal") || - kobject_add(&c->opts_dir, &c->kobj, "options") || - kobject_add(&c->time_stats, &c->kobj, "time_stats") || - bch2_opts_create_sysfs_files(&c->opts_dir)) - return "error creating sysfs objects"; - - mutex_lock(&c->state_lock); - - err = "error creating sysfs objects"; - __for_each_member_device(ca, c, i, NULL) - if (bch2_dev_sysfs_online(c, ca)) - goto err; - - list_add(&c->list, &bch_fs_list); - err = NULL; -err: - mutex_unlock(&c->state_lock); - return err; -} - -static const char *bch2_fs_online(struct bch_fs *c) -{ - const char *err; - - mutex_lock(&bch_fs_list_lock); - err = __bch2_fs_online(c); - mutex_unlock(&bch_fs_list_lock); - - return err; -} - -static const char *__bch2_fs_start(struct bch_fs *c) +const char *bch2_fs_start(struct bch_fs *c) { const char *err = "cannot allocate memory"; struct bch_sb_field_members *mi; @@ -901,6 +899,8 @@ recovery_done: bch2_write_super(c); mutex_unlock(&c->sb_lock); + set_bit(BCH_FS_STARTED, &c->flags); + err = NULL; out: mutex_unlock(&c->state_lock); @@ -939,11 +939,6 @@ fsck_err: goto out; } -const char *bch2_fs_start(struct bch_fs *c) -{ - return __bch2_fs_start(c) ?: bch2_fs_online(c); -} - static const char *bch2_dev_may_add(struct bch_sb *sb, struct bch_fs *c) { struct bch_sb_field_members *sb_mi; @@ -1856,15 +1851,10 @@ struct bch_fs *bch2_fs_open(char * const *devices, unsigned nr_devices, goto err_print; if (!c->opts.nostart) { - err = __bch2_fs_start(c); + err = bch2_fs_start(c); if (err) goto err_print; } - - err = bch2_fs_online(c); - if (err) - goto err_print; - out: kfree(sb); module_put(THIS_MODULE); @@ -1922,15 +1912,11 @@ static const char *__bch2_fs_open_incremental(struct bch_sb_handle *sb, mutex_unlock(&c->sb_lock); if (!c->opts.nostart && bch2_fs_may_start(c)) { - err = __bch2_fs_start(c); + err = bch2_fs_start(c); if (err) goto err; } - err = __bch2_fs_online(c); - if (err) - goto err; - closure_put(&c->cl); mutex_unlock(&bch_fs_list_lock); |