diff options
Diffstat (limited to 'c_src')
-rw-r--r-- | c_src/bcachefs.c | 17 | ||||
-rw-r--r-- | c_src/cmd_fs.c | 15 | ||||
-rw-r--r-- | c_src/cmd_fsck.c | 126 | ||||
-rw-r--r-- | c_src/cmd_migrate.c | 3 | ||||
-rw-r--r-- | c_src/cmds.h | 1 |
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[]); |