bcachefs: Move fsck ioctl code to fsck.c
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 6 Nov 2024 18:13:25 +0000 (13:13 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Dec 2024 06:36:17 +0000 (01:36 -0500)
chardev.c and fs-ioctl.c are not organized by subject; let's try to fix
this.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/chardev.c
fs/bcachefs/fsck.c
fs/bcachefs/fsck.h

index 2182b555c112cc6c66949e2ebf84937971a185ba..46e9e32105a9fb393be4df9b7c4bf1caf0c23de7 100644 (file)
@@ -6,11 +6,11 @@
 #include "buckets.h"
 #include "chardev.h"
 #include "disk_accounting.h"
+#include "fsck.h"
 #include "journal.h"
 #include "move.h"
 #include "recovery_passes.h"
 #include "replicas.h"
-#include "super.h"
 #include "super-io.h"
 #include "thread_with_file.h"
 
@@ -127,130 +127,6 @@ static long bch2_ioctl_incremental(struct bch_ioctl_incremental __user *user_arg
 }
 #endif
 
-struct fsck_thread {
-       struct thread_with_stdio thr;
-       struct bch_fs           *c;
-       struct bch_opts         opts;
-};
-
-static void bch2_fsck_thread_exit(struct thread_with_stdio *_thr)
-{
-       struct fsck_thread *thr = container_of(_thr, struct fsck_thread, thr);
-       kfree(thr);
-}
-
-static int bch2_fsck_offline_thread_fn(struct thread_with_stdio *stdio)
-{
-       struct fsck_thread *thr = container_of(stdio, struct fsck_thread, thr);
-       struct bch_fs *c = thr->c;
-
-       int ret = PTR_ERR_OR_ZERO(c);
-       if (ret)
-               return ret;
-
-       ret = bch2_fs_start(thr->c);
-       if (ret)
-               goto err;
-
-       if (test_bit(BCH_FS_errors_fixed, &c->flags)) {
-               bch2_stdio_redirect_printf(&stdio->stdio, false, "%s: errors fixed\n", c->name);
-               ret |= 1;
-       }
-       if (test_bit(BCH_FS_error, &c->flags)) {
-               bch2_stdio_redirect_printf(&stdio->stdio, false, "%s: still has errors\n", c->name);
-               ret |= 4;
-       }
-err:
-       bch2_fs_stop(c);
-       return ret;
-}
-
-static const struct thread_with_stdio_ops bch2_offline_fsck_ops = {
-       .exit           = bch2_fsck_thread_exit,
-       .fn             = bch2_fsck_offline_thread_fn,
-};
-
-static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_arg)
-{
-       struct bch_ioctl_fsck_offline arg;
-       struct fsck_thread *thr = NULL;
-       darray_str(devs) = {};
-       long ret = 0;
-
-       if (copy_from_user(&arg, user_arg, sizeof(arg)))
-               return -EFAULT;
-
-       if (arg.flags)
-               return -EINVAL;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       for (size_t i = 0; i < arg.nr_devs; i++) {
-               u64 dev_u64;
-               ret = copy_from_user_errcode(&dev_u64, &user_arg->devs[i], sizeof(u64));
-               if (ret)
-                       goto err;
-
-               char *dev_str = strndup_user((char __user *)(unsigned long) dev_u64, PATH_MAX);
-               ret = PTR_ERR_OR_ZERO(dev_str);
-               if (ret)
-                       goto err;
-
-               ret = darray_push(&devs, dev_str);
-               if (ret) {
-                       kfree(dev_str);
-                       goto err;
-               }
-       }
-
-       thr = kzalloc(sizeof(*thr), GFP_KERNEL);
-       if (!thr) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       thr->opts = bch2_opts_empty();
-
-       if (arg.opts) {
-               char *optstr = strndup_user((char __user *)(unsigned long) arg.opts, 1 << 16);
-               ret =   PTR_ERR_OR_ZERO(optstr) ?:
-                       bch2_parse_mount_opts(NULL, &thr->opts, NULL, optstr);
-               if (!IS_ERR(optstr))
-                       kfree(optstr);
-
-               if (ret)
-                       goto err;
-       }
-
-       opt_set(thr->opts, stdio, (u64)(unsigned long)&thr->thr.stdio);
-       opt_set(thr->opts, read_only, 1);
-       opt_set(thr->opts, ratelimit_errors, 0);
-
-       /* We need request_key() to be called before we punt to kthread: */
-       opt_set(thr->opts, nostart, true);
-
-       bch2_thread_with_stdio_init(&thr->thr, &bch2_offline_fsck_ops);
-
-       thr->c = bch2_fs_open(devs.data, arg.nr_devs, thr->opts);
-
-       if (!IS_ERR(thr->c) &&
-           thr->c->opts.errors == BCH_ON_ERROR_panic)
-               thr->c->opts.errors = BCH_ON_ERROR_ro;
-
-       ret = __bch2_run_thread_with_stdio(&thr->thr);
-out:
-       darray_for_each(devs, i)
-               kfree(*i);
-       darray_exit(&devs);
-       return ret;
-err:
-       if (thr)
-               bch2_fsck_thread_exit(&thr->thr);
-       pr_err("ret %s", bch2_err_str(ret));
-       goto out;
-}
-
 static long bch2_global_ioctl(unsigned cmd, void __user *arg)
 {
        long ret;
@@ -775,99 +651,6 @@ static long bch2_ioctl_disk_resize_journal(struct bch_fs *c,
        return ret;
 }
 
-static int bch2_fsck_online_thread_fn(struct thread_with_stdio *stdio)
-{
-       struct fsck_thread *thr = container_of(stdio, struct fsck_thread, thr);
-       struct bch_fs *c = thr->c;
-
-       c->stdio_filter = current;
-       c->stdio = &thr->thr.stdio;
-
-       /*
-        * XXX: can we figure out a way to do this without mucking with c->opts?
-        */
-       unsigned old_fix_errors = c->opts.fix_errors;
-       if (opt_defined(thr->opts, fix_errors))
-               c->opts.fix_errors = thr->opts.fix_errors;
-       else
-               c->opts.fix_errors = FSCK_FIX_ask;
-
-       c->opts.fsck = true;
-       set_bit(BCH_FS_fsck_running, &c->flags);
-
-       c->curr_recovery_pass = BCH_RECOVERY_PASS_check_alloc_info;
-       int ret = bch2_run_online_recovery_passes(c);
-
-       clear_bit(BCH_FS_fsck_running, &c->flags);
-       bch_err_fn(c, ret);
-
-       c->stdio = NULL;
-       c->stdio_filter = NULL;
-       c->opts.fix_errors = old_fix_errors;
-
-       up(&c->online_fsck_mutex);
-       bch2_ro_ref_put(c);
-       return ret;
-}
-
-static const struct thread_with_stdio_ops bch2_online_fsck_ops = {
-       .exit           = bch2_fsck_thread_exit,
-       .fn             = bch2_fsck_online_thread_fn,
-};
-
-static long bch2_ioctl_fsck_online(struct bch_fs *c,
-                                  struct bch_ioctl_fsck_online arg)
-{
-       struct fsck_thread *thr = NULL;
-       long ret = 0;
-
-       if (arg.flags)
-               return -EINVAL;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       if (!bch2_ro_ref_tryget(c))
-               return -EROFS;
-
-       if (down_trylock(&c->online_fsck_mutex)) {
-               bch2_ro_ref_put(c);
-               return -EAGAIN;
-       }
-
-       thr = kzalloc(sizeof(*thr), GFP_KERNEL);
-       if (!thr) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       thr->c = c;
-       thr->opts = bch2_opts_empty();
-
-       if (arg.opts) {
-               char *optstr = strndup_user((char __user *)(unsigned long) arg.opts, 1 << 16);
-
-               ret =   PTR_ERR_OR_ZERO(optstr) ?:
-                       bch2_parse_mount_opts(c, &thr->opts, NULL, optstr);
-               if (!IS_ERR(optstr))
-                       kfree(optstr);
-
-               if (ret)
-                       goto err;
-       }
-
-       ret = bch2_run_thread_with_stdio(&thr->thr, &bch2_online_fsck_ops);
-err:
-       if (ret < 0) {
-               bch_err_fn(c, ret);
-               if (thr)
-                       bch2_fsck_thread_exit(&thr->thr);
-               up(&c->online_fsck_mutex);
-               bch2_ro_ref_put(c);
-       }
-       return ret;
-}
-
 #define BCH_IOCTL(_name, _argtype)                                     \
 do {                                                                   \
        _argtype i;                                                     \
index 2229f0dcc8603344cc407927998804d6ab983018..e0335265de3d17e43e1e2663e43f2aac1e03d5e2 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
 #include "bcachefs.h"
+#include "bcachefs_ioctl.h"
 #include "bkey_buf.h"
 #include "btree_cache.h"
 #include "btree_update.h"
@@ -16,6 +17,7 @@
 #include "recovery_passes.h"
 #include "snapshot.h"
 #include "super.h"
+#include "thread_with_file.h"
 #include "xattr.h"
 
 #include <linux/bsearch.h>
@@ -3192,3 +3194,219 @@ int bch2_fix_reflink_p(struct bch_fs *c)
        bch_err_fn(c, ret);
        return ret;
 }
+
+struct fsck_thread {
+       struct thread_with_stdio thr;
+       struct bch_fs           *c;
+       struct bch_opts         opts;
+};
+
+static void bch2_fsck_thread_exit(struct thread_with_stdio *_thr)
+{
+       struct fsck_thread *thr = container_of(_thr, struct fsck_thread, thr);
+       kfree(thr);
+}
+
+static int bch2_fsck_offline_thread_fn(struct thread_with_stdio *stdio)
+{
+       struct fsck_thread *thr = container_of(stdio, struct fsck_thread, thr);
+       struct bch_fs *c = thr->c;
+
+       int ret = PTR_ERR_OR_ZERO(c);
+       if (ret)
+               return ret;
+
+       ret = bch2_fs_start(thr->c);
+       if (ret)
+               goto err;
+
+       if (test_bit(BCH_FS_errors_fixed, &c->flags)) {
+               bch2_stdio_redirect_printf(&stdio->stdio, false, "%s: errors fixed\n", c->name);
+               ret |= 1;
+       }
+       if (test_bit(BCH_FS_error, &c->flags)) {
+               bch2_stdio_redirect_printf(&stdio->stdio, false, "%s: still has errors\n", c->name);
+               ret |= 4;
+       }
+err:
+       bch2_fs_stop(c);
+       return ret;
+}
+
+static const struct thread_with_stdio_ops bch2_offline_fsck_ops = {
+       .exit           = bch2_fsck_thread_exit,
+       .fn             = bch2_fsck_offline_thread_fn,
+};
+
+long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_arg)
+{
+       struct bch_ioctl_fsck_offline arg;
+       struct fsck_thread *thr = NULL;
+       darray_str(devs) = {};
+       long ret = 0;
+
+       if (copy_from_user(&arg, user_arg, sizeof(arg)))
+               return -EFAULT;
+
+       if (arg.flags)
+               return -EINVAL;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       for (size_t i = 0; i < arg.nr_devs; i++) {
+               u64 dev_u64;
+               ret = copy_from_user_errcode(&dev_u64, &user_arg->devs[i], sizeof(u64));
+               if (ret)
+                       goto err;
+
+               char *dev_str = strndup_user((char __user *)(unsigned long) dev_u64, PATH_MAX);
+               ret = PTR_ERR_OR_ZERO(dev_str);
+               if (ret)
+                       goto err;
+
+               ret = darray_push(&devs, dev_str);
+               if (ret) {
+                       kfree(dev_str);
+                       goto err;
+               }
+       }
+
+       thr = kzalloc(sizeof(*thr), GFP_KERNEL);
+       if (!thr) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       thr->opts = bch2_opts_empty();
+
+       if (arg.opts) {
+               char *optstr = strndup_user((char __user *)(unsigned long) arg.opts, 1 << 16);
+               ret =   PTR_ERR_OR_ZERO(optstr) ?:
+                       bch2_parse_mount_opts(NULL, &thr->opts, NULL, optstr);
+               if (!IS_ERR(optstr))
+                       kfree(optstr);
+
+               if (ret)
+                       goto err;
+       }
+
+       opt_set(thr->opts, stdio, (u64)(unsigned long)&thr->thr.stdio);
+       opt_set(thr->opts, read_only, 1);
+       opt_set(thr->opts, ratelimit_errors, 0);
+
+       /* We need request_key() to be called before we punt to kthread: */
+       opt_set(thr->opts, nostart, true);
+
+       bch2_thread_with_stdio_init(&thr->thr, &bch2_offline_fsck_ops);
+
+       thr->c = bch2_fs_open(devs.data, arg.nr_devs, thr->opts);
+
+       if (!IS_ERR(thr->c) &&
+           thr->c->opts.errors == BCH_ON_ERROR_panic)
+               thr->c->opts.errors = BCH_ON_ERROR_ro;
+
+       ret = __bch2_run_thread_with_stdio(&thr->thr);
+out:
+       darray_for_each(devs, i)
+               kfree(*i);
+       darray_exit(&devs);
+       return ret;
+err:
+       if (thr)
+               bch2_fsck_thread_exit(&thr->thr);
+       pr_err("ret %s", bch2_err_str(ret));
+       goto out;
+}
+
+static int bch2_fsck_online_thread_fn(struct thread_with_stdio *stdio)
+{
+       struct fsck_thread *thr = container_of(stdio, struct fsck_thread, thr);
+       struct bch_fs *c = thr->c;
+
+       c->stdio_filter = current;
+       c->stdio = &thr->thr.stdio;
+
+       /*
+        * XXX: can we figure out a way to do this without mucking with c->opts?
+        */
+       unsigned old_fix_errors = c->opts.fix_errors;
+       if (opt_defined(thr->opts, fix_errors))
+               c->opts.fix_errors = thr->opts.fix_errors;
+       else
+               c->opts.fix_errors = FSCK_FIX_ask;
+
+       c->opts.fsck = true;
+       set_bit(BCH_FS_fsck_running, &c->flags);
+
+       c->curr_recovery_pass = BCH_RECOVERY_PASS_check_alloc_info;
+       int ret = bch2_run_online_recovery_passes(c);
+
+       clear_bit(BCH_FS_fsck_running, &c->flags);
+       bch_err_fn(c, ret);
+
+       c->stdio = NULL;
+       c->stdio_filter = NULL;
+       c->opts.fix_errors = old_fix_errors;
+
+       up(&c->online_fsck_mutex);
+       bch2_ro_ref_put(c);
+       return ret;
+}
+
+static const struct thread_with_stdio_ops bch2_online_fsck_ops = {
+       .exit           = bch2_fsck_thread_exit,
+       .fn             = bch2_fsck_online_thread_fn,
+};
+
+long bch2_ioctl_fsck_online(struct bch_fs *c, struct bch_ioctl_fsck_online arg)
+{
+       struct fsck_thread *thr = NULL;
+       long ret = 0;
+
+       if (arg.flags)
+               return -EINVAL;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       if (!bch2_ro_ref_tryget(c))
+               return -EROFS;
+
+       if (down_trylock(&c->online_fsck_mutex)) {
+               bch2_ro_ref_put(c);
+               return -EAGAIN;
+       }
+
+       thr = kzalloc(sizeof(*thr), GFP_KERNEL);
+       if (!thr) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       thr->c = c;
+       thr->opts = bch2_opts_empty();
+
+       if (arg.opts) {
+               char *optstr = strndup_user((char __user *)(unsigned long) arg.opts, 1 << 16);
+
+               ret =   PTR_ERR_OR_ZERO(optstr) ?:
+                       bch2_parse_mount_opts(c, &thr->opts, NULL, optstr);
+               if (!IS_ERR(optstr))
+                       kfree(optstr);
+
+               if (ret)
+                       goto err;
+       }
+
+       ret = bch2_run_thread_with_stdio(&thr->thr, &bch2_online_fsck_ops);
+err:
+       if (ret < 0) {
+               bch_err_fn(c, ret);
+               if (thr)
+                       bch2_fsck_thread_exit(&thr->thr);
+               up(&c->online_fsck_mutex);
+               bch2_ro_ref_put(c);
+       }
+       return ret;
+}
index 1cca31011530979b3fb103205090e3e252c9067c..4481b40a881d8cf9ad1314b975c7f23d1372e84d 100644 (file)
@@ -14,4 +14,7 @@ int bch2_check_directory_structure(struct bch_fs *);
 int bch2_check_nlinks(struct bch_fs *);
 int bch2_fix_reflink_p(struct bch_fs *);
 
+long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *);
+long bch2_ioctl_fsck_online(struct bch_fs *, struct bch_ioctl_fsck_online);
+
 #endif /* _BCACHEFS_FSCK_H */