summaryrefslogtreecommitdiff
path: root/c_src
diff options
context:
space:
mode:
Diffstat (limited to 'c_src')
-rw-r--r--c_src/bcachefs.c17
-rw-r--r--c_src/cmd_fs.c15
-rw-r--r--c_src/cmd_fsck.c126
-rw-r--r--c_src/cmd_migrate.c3
-rw-r--r--c_src/cmds.h1
5 files changed, 129 insertions, 33 deletions
diff --git a/c_src/bcachefs.c b/c_src/bcachefs.c
index f4712597..9e9cf647 100644
--- a/c_src/bcachefs.c
+++ b/c_src/bcachefs.c
@@ -40,11 +40,13 @@ void bcachefs_usage(void)
"\n"
"Commands for managing images:\n"
" image create Create a new compact disk image\n"
+ "\n"
"Mount:\n"
" mount Mount a filesystem\n"
"\n"
"Repair:\n"
" fsck Check an existing filesystem for errors\n"
+ " recovery-pass Schedule or deschedule recovery passes\n"
"\n"
#if 0
"Startup/shutdown, assembly of multi device filesystems:\n"
@@ -105,18 +107,3 @@ void bcachefs_usage(void)
" completions Generate shell completions\n"
" version Display the version of the invoked bcachefs tool\n");
}
-
-int fs_cmds(int argc, char *argv[])
-{
- char *cmd = pop_cmd(&argc, argv);
-
- if (argc < 1)
- return fs_usage();
- if (!strcmp(cmd, "usage"))
- return cmd_fs_usage(argc, argv);
- if (!strcmp(cmd, "top"))
- return cmd_fs_top(argc, argv);
-
- fs_usage();
- return -EINVAL;
-}
diff --git a/c_src/cmd_fs.c b/c_src/cmd_fs.c
index 79826cb2..aa825e90 100644
--- a/c_src/cmd_fs.c
+++ b/c_src/cmd_fs.c
@@ -559,3 +559,18 @@ int cmd_fs_usage(int argc, char *argv[])
printbuf_exit(&buf);
return 0;
}
+
+int fs_cmds(int argc, char *argv[])
+{
+ char *cmd = pop_cmd(&argc, argv);
+
+ if (argc < 1)
+ return fs_usage();
+ if (!strcmp(cmd, "usage"))
+ return cmd_fs_usage(argc, argv);
+ if (!strcmp(cmd, "top"))
+ return cmd_fs_top(argc, argv);
+
+ fs_usage();
+ return -EINVAL;
+}
diff --git a/c_src/cmd_fsck.c b/c_src/cmd_fsck.c
index 66669e67..8c37b1ba 100644
--- a/c_src/cmd_fsck.c
+++ b/c_src/cmd_fsck.c
@@ -6,27 +6,11 @@
#include "cmds.h"
#include "libbcachefs/error.h"
#include "libbcachefs.h"
+#include "libbcachefs/recovery_passes.h"
#include "libbcachefs/super.h"
#include "libbcachefs/super-io.h"
#include "tools-util.h"
-static void fsck_usage(void)
-{
- puts("bcachefs fsck - filesystem check and repair\n"
- "Usage: bcachefs fsck [OPTION]... <devices>\n"
- "\n"
- "Options:\n"
- " -p Automatic repair (no questions)\n"
- " -n Don't repair, only check for errors\n"
- " -y Assume \"yes\" to all questions\n"
- " -f Force checking even if filesystem is marked clean\n"
- " -r, --ratelimit_errors Don't display more than 10 errors of a given type\n"
- " -k, --kernel Use the in-kernel fsck implementation\n"
- " -v Be verbose\n"
- " -h, --help Display this help and exit\n"
- "Report bugs to <linux-bcachefs@vger.kernel.org>");
-}
-
static void setnonblocking(int fd)
{
int flags = fcntl(fd, F_GETFL);
@@ -212,6 +196,23 @@ static char *loopdev_alloc(const char *path)
return line;
}
+static void fsck_usage(void)
+{
+ puts("bcachefs fsck - filesystem check and repair\n"
+ "Usage: bcachefs fsck [OPTION]... <devices>\n"
+ "\n"
+ "Options:\n"
+ " -p Automatic repair (no questions)\n"
+ " -n Don't repair, only check for errors\n"
+ " -y Assume \"yes\" to all questions\n"
+ " -f Force checking even if filesystem is marked clean\n"
+ " -r, --ratelimit_errors Don't display more than 10 errors of a given type\n"
+ " -k, --kernel Use the in-kernel fsck implementation\n"
+ " -v Be verbose\n"
+ " -h, --help Display this help and exit\n"
+ "Report bugs to <linux-bcachefs@vger.kernel.org>");
+}
+
int cmd_fsck(int argc, char *argv[])
{
static const struct option longopts[] = {
@@ -370,3 +371,94 @@ userland_fsck:
printbuf_exit(&opts_str);
return ret;
}
+
+static void recovery_pass_usage(void)
+{
+ puts("bcachefs recovery-pass - list and manage scheduled recovery passes\n"
+ "Usage: bcachefs recovery-pass [OPTION]... <devices>\n"
+ "\n"
+ "Currently only supports unmounted/offline filesystems\n"
+ "\n"
+ "Options:\n"
+ " -s, --set Schedule a recovery pass in the superblock\n"
+ " -u, --unset Deschedule a recovery pass\n"
+ " -h, --help Display this help and exit\n"
+ "Report bugs to <linux-bcachefs@vger.kernel.org>");
+}
+
+int cmd_recovery_pass(int argc, char *argv[])
+{
+ static const struct option longopts[] = {
+ { "set", required_argument, NULL, 's' },
+ { "unset", required_argument, NULL, 'u' },
+ { "help", no_argument, NULL, 'h' },
+ { NULL }
+ };
+ u64 passes_to_set = 0, passes_to_unset = 0;
+ int opt;
+
+ while ((opt = getopt_long(argc, argv, "s:u:h", longopts, NULL)) != -1)
+ switch (opt) {
+ case 's':
+ passes_to_set |= read_flag_list_or_die(optarg,
+ bch2_recovery_passes,
+ "recovery pass");
+ break;
+ case 'u':
+ passes_to_unset |= read_flag_list_or_die(optarg,
+ bch2_recovery_passes,
+ "recovery pass");
+ break;
+ case 'h':
+ recovery_pass_usage();
+ exit(EXIT_SUCCESS);
+ }
+ args_shift(optind);
+
+ passes_to_set = bch2_recovery_passes_to_stable(passes_to_set);
+ passes_to_unset = bch2_recovery_passes_to_stable(passes_to_unset);
+
+ darray_const_str devs = get_or_split_cmdline_devs(argc, argv);
+
+ struct bch_opts opts = bch2_opts_empty();
+ opt_set(opts, nostart, true);
+
+ struct bch_fs *c = bch2_fs_open(&devs, &opts);
+ int ret = PTR_ERR_OR_ZERO(c);
+ if (ret)
+ die("Error opening filesystem: %s", bch2_err_str(ret));
+
+ scoped_guard(mutex, &c->sb_lock) {
+ struct bch_sb_field_ext *ext =
+ bch2_sb_field_get_minsize(&c->disk_sb, ext,
+ sizeof(struct bch_sb_field_ext) / sizeof(u64));
+ if (!ext) {
+ fprintf(stderr, "Error getting sb_field_ext\n");
+ goto err;
+ }
+
+ u64 scheduled = le64_to_cpu(ext->recovery_passes_required[0]);
+
+ if (passes_to_set || passes_to_unset) {
+ ext->recovery_passes_required[0] &= ~cpu_to_le64(passes_to_unset);
+ ext->recovery_passes_required[0] |= cpu_to_le64(passes_to_set);
+
+ scheduled = le64_to_cpu(ext->recovery_passes_required[0]);
+
+ bch2_write_super(c);
+ }
+
+ CLASS(printbuf, buf)();
+ prt_str(&buf, "Scheduled recovery passes: ");
+ if (scheduled)
+ prt_bitflags(&buf, bch2_recovery_passes,
+ bch2_recovery_passes_from_stable(scheduled));
+ else
+ prt_str(&buf, "(none)");
+ printf("%s\n", buf.buf);
+ }
+err:
+ bch2_fs_stop(c);
+ return ret;
+}
+
diff --git a/c_src/cmd_migrate.c b/c_src/cmd_migrate.c
index 0d24018c..b4da4e5b 100644
--- a/c_src/cmd_migrate.c
+++ b/c_src/cmd_migrate.c
@@ -244,7 +244,6 @@ static int migrate_fs(const char *fs_path,
find_superblock_space(extents, format_opts, dev);
struct bch_sb *sb = bch2_format(fs_opt_strs, fs_opts, format_opts, devs);
- darray_exit(&devs);
u64 sb_offset = le64_to_cpu(sb->layout.sb_offset[0]);
@@ -316,6 +315,8 @@ static int migrate_fs(const char *fs_path,
"no longer needed (and should be deleted prior to running\n"
"bcachefs migrate-superblock)\n",
sb_offset, dev->path, dev->path, sb_offset);
+
+ darray_exit(&devs);
return 0;
}
diff --git a/c_src/cmds.h b/c_src/cmds.h
index 4454f33f..30b47286 100644
--- a/c_src/cmds.h
+++ b/c_src/cmds.h
@@ -31,6 +31,7 @@ int cmd_set_passphrase(int argc, char *argv[]);
int cmd_remove_passphrase(int argc, char *argv[]);
int cmd_fsck(int argc, char *argv[]);
+int cmd_recovery_pass(int argc, char *argv[]);
int cmd_dump(int argc, char *argv[]);
int cmd_list_journal(int argc, char *argv[]);