diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2025-07-20 12:21:03 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2025-07-20 12:21:03 -0400 |
commit | c00f25b3cc8d9bfce2551541da8459702f39dea7 (patch) | |
tree | 9a5375bca06e5ee0241188fa2a93a5af092227d1 | |
parent | 191d5b4b093e07f5243bd2c1ebecbf5a9fe76df0 (diff) |
cmd_dump: split out dump_fs()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | c_src/cmd_dump.c | 174 |
1 files changed, 96 insertions, 78 deletions
diff --git a/c_src/cmd_dump.c b/c_src/cmd_dump.c index de4330d6..2de44c58 100644 --- a/c_src/cmd_dump.c +++ b/c_src/cmd_dump.c @@ -17,20 +17,6 @@ #include "libbcachefs/sb-members.h" #include "libbcachefs/super.h" -static void dump_usage(void) -{ - puts("bcachefs dump - dump filesystem metadata\n" - "Usage: bcachefs dump [OPTION]... <devices>\n" - "\n" - "Options:\n" - " -o output Output qcow2 image(s)\n" - " -f, --force Force; overwrite when needed\n" - " --nojournal Don't dump entire journal, just dirty entries\n" - " --noexcl Open devices with O_NOEXCL (not recommended)\n" - " -h, --help Display this help and exit\n" - "Report bugs to <linux-bcachefs@vger.kernel.org>"); -} - struct dump_dev { ranges sb, journal, btree; }; @@ -73,65 +59,16 @@ static void get_sb_journal(struct bch_fs *c, struct bch_dev *ca, } } -int cmd_dump(int argc, char *argv[]) -{ - static const struct option longopts[] = { - { "force", no_argument, NULL, 'f' }, - { "nojournal", no_argument, NULL, 'j' }, - { "noexcl", no_argument, NULL, 'e' }, - { "verbose", no_argument, NULL, 'v' }, - { "help", no_argument, NULL, 'h' }, - { NULL } - }; - struct bch_opts opts = bch2_opts_empty(); - char *out = NULL; - bool force = false, entire_journal = true; - int fd, opt; - - opt_set(opts, direct_io, false); - opt_set(opts, read_only, true); - opt_set(opts, nochanges, true); - opt_set(opts, norecovery, true); - opt_set(opts, degraded, BCH_DEGRADED_very); - opt_set(opts, errors, BCH_ON_ERROR_continue); - opt_set(opts, fix_errors, FSCK_FIX_no); - - while ((opt = getopt_long(argc, argv, "o:fvh", - longopts, NULL)) != -1) - switch (opt) { - case 'o': - out = optarg; - break; - case 'f': - force = true; - break; - case 'j': - entire_journal = false; - break; - case 'e': - opt_set(opts, noexcl, true); - break; - case 'v': - opt_set(opts, verbose, true); - break; - case 'h': - dump_usage(); - exit(EXIT_SUCCESS); - } - args_shift(optind); - - if (!out) - die("Please supply output filename"); - - if (!argc) - die("Please supply device(s) to check"); - - darray_const_str dev_names = get_or_split_cmdline_devs(argc, argv); - - struct bch_fs *c = bch2_fs_open(&dev_names, &opts); - if (IS_ERR(c)) - die("error opening devices: %s", bch2_err_str(PTR_ERR(c))); +struct dump_opts { + char *out; + bool force; + bool sanitize; + bool entire_journal; + bool noexcl; +}; +static int dump_fs(struct bch_fs *c, struct dump_opts opts) +{ dump_devs devs = {}; while (devs.nr < c->sb.nr_devices) darray_push(&devs, (struct dump_dev) {}); @@ -140,7 +77,7 @@ int cmd_dump(int argc, char *argv[]) unsigned nr_online = 0; for_each_online_member(c, ca, 0) { - get_sb_journal(c, ca, entire_journal, &devs.data[ca->dev_idx]); + get_sb_journal(c, ca, opts.entire_journal, &devs.data[ca->dev_idx]); nr_online++; } @@ -168,13 +105,13 @@ int cmd_dump(int argc, char *argv[]) for_each_online_member(c, ca, 0) { int flags = O_WRONLY|O_CREAT|O_TRUNC; - if (!force) + if (!opts.force) flags |= O_EXCL; char *path = nr_online > 1 - ? mprintf("%s.%u.qcow2", out, ca->dev_idx) - : mprintf("%s.qcow2", out); - fd = xopen(path, flags, 0600); + ? mprintf("%s.%u.qcow2", opts.out, ca->dev_idx) + : mprintf("%s.qcow2", opts.out); + int fd = xopen(path, flags, 0600); free(path); struct qcow2_image img; @@ -198,6 +135,87 @@ int cmd_dump(int argc, char *argv[]) darray_exit(&d->btree); } darray_exit(&devs); - darray_exit(&dev_names); return 0; } + +static void dump_usage(void) +{ + puts("bcachefs dump - dump filesystem metadata\n" + "Usage: bcachefs dump [OPTION]... <devices>\n" + "\n" + "Options:\n" + " -o output Output qcow2 image(s)\n" + " -f, --force Force; overwrite when needed\n" + " -s, --sanitize Zero out inline data extents\n" + " --nojournal Don't dump entire journal, just dirty entries\n" + " --noexcl Open devices with O_NOEXCL (not recommended)\n" + " -v, --verbose\n" + " -h, --help Display this help and exit\n" + "Report bugs to <linux-bcachefs@vger.kernel.org>"); +} + +int cmd_dump(int argc, char *argv[]) +{ + static const struct option longopts[] = { + { "force", no_argument, NULL, 'f' }, + { "sanitize", no_argument, NULL, 's' }, + { "nojournal", no_argument, NULL, 'j' }, + { "noexcl", no_argument, NULL, 'e' }, + { "verbose", no_argument, NULL, 'v' }, + { "help", no_argument, NULL, 'h' }, + { NULL } + }; + struct bch_opts fs_opts = bch2_opts_empty(); + struct dump_opts opts = { .entire_journal = true }; + int opt; + + opt_set(fs_opts, direct_io, false); + opt_set(fs_opts, read_only, true); + opt_set(fs_opts, nochanges, true); + opt_set(fs_opts, norecovery, true); + opt_set(fs_opts, degraded, BCH_DEGRADED_very); + opt_set(fs_opts, errors, BCH_ON_ERROR_continue); + opt_set(fs_opts, fix_errors, FSCK_FIX_no); + + while ((opt = getopt_long(argc, argv, "o:fsvh", + longopts, NULL)) != -1) + switch (opt) { + case 'o': + opts.out = optarg; + break; + case 'f': + opts.force = true; + break; + case 's': + opts.sanitize = true; + case 'j': + opts.entire_journal = false; + break; + case 'e': + opt_set(fs_opts, noexcl, true); + break; + case 'v': + opt_set(fs_opts, verbose, true); + break; + case 'h': + dump_usage(); + exit(EXIT_SUCCESS); + } + args_shift(optind); + + if (!opts.out) + die("Please supply output filename"); + + if (!argc) + die("Please supply device(s) to check"); + + darray_const_str dev_names = get_or_split_cmdline_devs(argc, argv); + + struct bch_fs *c = bch2_fs_open(&dev_names, &fs_opts); + if (IS_ERR(c)) + die("error opening devices: %s", bch2_err_str(PTR_ERR(c))); + + int ret = dump_fs(c, opts); + darray_exit(&dev_names); + return ret; +} |