From 2aeeac7785d647c02ef5612795025f3c9ce436ec Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 6 Dec 2024 16:30:19 -0500 Subject: [PATCH] bcachefs: cmd_set_option() can now set device options on multi device filesystems Currently, 'bcachefs set-fs-option' requires all devices to be specified when setting options on an offline multidevice filesystem - it can't yet scan for the rest of the filesystem members. We do need to fix this, but the scan code is written in Rust, so that either means a lot of ugly FFI code or rewriting cmd_set_option() in Rust - neither of which are happening today. So as an interim hack, add a --dev-idx option: this can be specified (multiple times if desired) for indicating which devices the device specific options should be applied to. Signed-off-by: Kent Overstreet --- c_src/cmd_option.c | 47 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/c_src/cmd_option.c b/c_src/cmd_option.c index 21048d7dc..07c0d03d9 100644 --- a/c_src/cmd_option.c +++ b/c_src/cmd_option.c @@ -31,7 +31,8 @@ static void set_option_usage(void) "\n" "Options:\n"); bch2_opts_usage(OPT_MOUNT); - puts(" -h, --help display this help and exit\n" + puts(" -d, --dev-idx index for device specific options\n" + " -h, --help display this help and exit\n" "Report bugs to "); exit(EXIT_SUCCESS); } @@ -55,11 +56,23 @@ int cmd_set_option(int argc, char *argv[]) { struct bch_opt_strs new_opt_strs = bch2_cmdline_opts_get(&argc, argv, OPT_MOUNT|OPT_DEVICE); struct bch_opts new_opts = bch2_parse_opts(new_opt_strs); - unsigned i; + DARRAY(unsigned) dev_idxs = {}; int opt, ret = 0; - while ((opt = getopt(argc, argv, "h")) != -1) + static const struct option longopts[] = { + { "dev-idx", required_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { NULL } + }; + + while ((opt = getopt_long(argc, argv, "d:h", longopts, NULL)) != -1) switch (opt) { + case 'd': { + unsigned dev_idx; + if (kstrtoint(optarg, 10, &dev_idx)) + die("error parsing %s", optarg); + darray_push(&dev_idxs, dev_idx); + } case 'h': set_option_usage(); break; @@ -72,6 +85,7 @@ int cmd_set_option(int argc, char *argv[]) } bool online = false; + unsigned i; for (i = 0; i < argc; i++) if (dev_mounted(argv[i])) { online = true; @@ -110,14 +124,27 @@ int cmd_set_option(int argc, char *argv[]) } if (opt->flags & OPT_DEVICE) { - for (unsigned dev = 0; dev < argc; dev++) { - int dev_idx = name_to_dev_idx(c, argv[dev]); - if (dev_idx < 0) { - fprintf(stderr, "Couldn't look up device %s\n", argv[i]); - continue; + if (dev_idxs.nr) { + darray_for_each(dev_idxs, dev) { + struct bch_dev *ca = bch2_dev_tryget_noerror(c, *dev); + if (!ca) { + fprintf(stderr, "Couldn't look up device %u\n", *dev); + continue; + } + + bch2_opt_set_sb(c, ca, opt, v); + bch2_dev_put(ca); + } + } else { + for (unsigned dev = 0; dev < argc; dev++) { + int dev_idx = name_to_dev_idx(c, argv[dev]); + if (dev_idx < 0) { + fprintf(stderr, "Couldn't look up device %s\n", argv[i]); + continue; + } + + bch2_opt_set_sb(c, c->devs[dev_idx], opt, v); } - - bch2_opt_set_sb(c, c->devs[dev_idx], opt, v); } } }