diff --git a/cmd_device.c b/cmd_device.c index 161e6692..f9e975ab 100644 --- a/cmd_device.c +++ b/cmd_device.c @@ -123,11 +123,9 @@ static void device_remove_usage(void) { puts("bcachefs device_remove - remove a device from a filesystem\n" "Usage:\n" - " bcachefs device remove device\n" - " bcachefs device remove --by-id path devid\n" + " bcachefs device remove | \n" "\n" "Options:\n" - " -i, --by-id Remove device by device id\n" " -f, --force Force removal, even if some data\n" " couldn't be migrated\n" " -F, --force-metadata Force removal, even if some metadata\n" @@ -148,14 +146,10 @@ int cmd_device_remove(int argc, char *argv[]) }; struct bchfs_handle fs; bool by_id = false; - int opt, flags = BCH_FORCE_IF_DEGRADED; - unsigned dev_idx; + int opt, flags = BCH_FORCE_IF_DEGRADED, dev_idx; while ((opt = getopt_long(argc, argv, "fh", longopts, NULL)) != -1) switch (opt) { - case 'i': - by_id = true; - break; case 'f': flags |= BCH_FORCE_IF_DATA_LOST; break; @@ -167,32 +161,31 @@ int cmd_device_remove(int argc, char *argv[]) } args_shift(optind); - if (by_id) { - char *path = arg_pop(); - if (!path) - die("Please supply filesystem to remove device from"); + char *dev_str = arg_pop(); + if (!dev_str) + die("Please supply a device"); - char *dev_str = arg_pop(); - if (!dev_str) - die("Please supply device id"); + char *end; + dev_idx = strtoul(dev_str, &end, 10); + if (*dev_str && !*end) + by_id = true; - errno = 0; - dev_idx = strtoul(dev_str, NULL, 10); - if (errno) - die("Error parsing device id: %m"); + char *fs_path = arg_pop(); + if (fs_path) { + fs = bcache_fs_open(fs_path); - fs = bcache_fs_open(path); + if (!by_id) { + dev_idx = bchu_dev_path_to_idx(fs, dev_str); + if (dev_idx < 0) + die("%s does not seem to be a member of %s", + dev_str, fs_path); + } + } else if (!by_id) { + fs = bchu_fs_open_by_dev(dev_str, &dev_idx); } else { - char *dev = arg_pop(); - if (!dev) - die("Please supply a device to remove"); - - fs = bchu_fs_open_by_dev(dev, &dev_idx); + die("Filesystem path required when specifying device by id"); } - if (argc) - die("too many arguments"); - bchu_disk_remove(fs, dev_idx, flags); return 0; } @@ -227,7 +220,7 @@ int cmd_device_online(int argc, char *argv[]) if (argc) die("too many arguments"); - unsigned dev_idx; + int dev_idx; struct bchfs_handle fs = bchu_fs_open_by_dev(dev, &dev_idx); bchu_disk_online(fs, dev); return 0; @@ -272,7 +265,7 @@ int cmd_device_offline(int argc, char *argv[]) if (argc) die("too many arguments"); - unsigned dev_idx; + int dev_idx; struct bchfs_handle fs = bchu_fs_open_by_dev(dev, &dev_idx); bchu_disk_offline(fs, dev_idx, flags); return 0; @@ -308,7 +301,7 @@ int cmd_device_evacuate(int argc, char *argv[]) if (argc) die("too many arguments"); - unsigned dev_idx; + int dev_idx; struct bchfs_handle fs = bchu_fs_open_by_dev(dev_path, &dev_idx); struct bch_ioctl_dev_usage u = bchu_dev_usage(fs, dev_idx); @@ -331,7 +324,10 @@ int cmd_device_evacuate(int argc, char *argv[]) static void device_set_state_usage(void) { puts("bcachefs device set-state\n" - "Usage: bcachefs device set-state device new-state\n" + "Usage: bcachefs device set-state | \n" + "\n" + ": one of rw, ro, failed or spare\n" + ": path to mounted filesystem, optional unless specifying device by id\n" "\n" "Options:\n" " -f, --force Force, if data redundancy will be degraded\n" @@ -349,7 +345,9 @@ int cmd_device_set_state(int argc, char *argv[]) { "help", 0, NULL, 'h' }, { NULL } }; - int opt, flags = 0; + struct bchfs_handle fs; + bool by_id = false; + int opt, flags = 0, dev_idx; bool offline = false; while ((opt = getopt_long(argc, argv, "foh", longopts, NULL)) != -1) @@ -365,10 +363,6 @@ int cmd_device_set_state(int argc, char *argv[]) } args_shift(optind); - char *dev_path = arg_pop(); - if (!dev_path) - die("Please supply a device"); - char *new_state_str = arg_pop(); if (!new_state_str) die("Please supply a device state"); @@ -376,20 +370,25 @@ int cmd_device_set_state(int argc, char *argv[]) unsigned new_state = read_string_list_or_die(new_state_str, bch2_member_states, "device state"); - if (!offline) { - unsigned dev_idx; - struct bchfs_handle fs = bchu_fs_open_by_dev(dev_path, &dev_idx); + char *dev_str = arg_pop(); + if (!dev_str) + die("Please supply a device"); - bchu_disk_set_state(fs, dev_idx, new_state, flags); + char *end; + dev_idx = strtoul(dev_str, &end, 10); + if (*dev_str && !*end) + by_id = true; - bcache_fs_close(fs); - } else { + if (offline) { struct bch_opts opts = bch2_opts_empty(); struct bch_sb_handle sb = { NULL }; - int ret = bch2_read_super(dev_path, &opts, &sb); + if (by_id) + die("Cannot specify offline device by id"); + + int ret = bch2_read_super(dev_str, &opts, &sb); if (ret) - die("error opening %s: %s", dev_path, strerror(-ret)); + die("error opening %s: %s", dev_str, strerror(-ret)); struct bch_member *m = bch2_sb_get_members(sb.sb)->members + sb.sb->dev_idx; @@ -399,8 +398,27 @@ int cmd_device_set_state(int argc, char *argv[]) bch2_super_write(sb.bdev->bd_fd, sb.sb); bch2_free_super(&sb); + return 0; } + char *fs_path = arg_pop(); + if (fs_path) { + fs = bcache_fs_open(fs_path); + + if (!by_id) { + dev_idx = bchu_dev_path_to_idx(fs, dev_str); + if (dev_idx < 0) + die("%s does not seem to be a member of %s", + dev_str, fs_path); + } + } else if (!by_id) { + fs = bchu_fs_open_by_dev(dev_str, &dev_idx); + } else { + die("Filesystem path required when specifying device by id"); + } + + bchu_disk_set_state(fs, dev_idx, new_state, flags); + return 0; } diff --git a/libbcachefs.c b/libbcachefs.c index 1ae9b9ab..e917c6ca 100644 --- a/libbcachefs.c +++ b/libbcachefs.c @@ -900,7 +900,7 @@ struct bchfs_handle bcache_fs_open(const char *path) * Given a path to a block device, open the filesystem it belongs to; also * return the device's idx: */ -struct bchfs_handle bchu_fs_open_by_dev(const char *path, unsigned *idx) +struct bchfs_handle bchu_fs_open_by_dev(const char *path, int *idx) { char buf[1024], *uuid_str; @@ -944,6 +944,17 @@ struct bchfs_handle bchu_fs_open_by_dev(const char *path, unsigned *idx) return bcache_fs_open(uuid_str); } +int bchu_dev_path_to_idx(struct bchfs_handle fs, const char *dev_path) +{ + int idx; + struct bchfs_handle fs2 = bchu_fs_open_by_dev(dev_path, &idx); + + if (memcmp(&fs.uuid, &fs2.uuid, sizeof(fs.uuid))) + idx = -1; + bcache_fs_close(fs2); + return idx; +} + int bchu_data(struct bchfs_handle fs, struct bch_ioctl_data cmd) { int progress_fd = xioctl(fs.ioctl_fd, BCH_IOCTL_DATA, &cmd); diff --git a/libbcachefs.h b/libbcachefs.h index 59c62df3..45d2f874 100644 --- a/libbcachefs.h +++ b/libbcachefs.h @@ -94,7 +94,8 @@ struct bchfs_handle { void bcache_fs_close(struct bchfs_handle); struct bchfs_handle bcache_fs_open(const char *); -struct bchfs_handle bchu_fs_open_by_dev(const char *, unsigned *); +struct bchfs_handle bchu_fs_open_by_dev(const char *, int *); +int bchu_dev_path_to_idx(struct bchfs_handle, const char *); static inline void bchu_disk_add(struct bchfs_handle fs, char *dev) {