diff options
author | Anand Jain <Anand.Jain@oracle.com> | 2016-03-14 16:31:49 +0800 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2016-03-14 14:11:33 +0100 |
commit | 2490de5da527969a9178418155120bf50f2a8421 (patch) | |
tree | 4ae37e53ae99a6eaf7aa1d82a0508103ed4fda35 /cmds-device.c | |
parent | 5f17513313ddd39d4348b382cf2224dbf4d35e7b (diff) |
btrfs-progs: Introduce device delete by devid
This patch introduces new option <devid> for the command
btrfs device delete <device_path|devid>[..] <mnt>
In a user reported issue on a 3-disk-RAID1, one disk failed with its
SB unreadable. Now with this patch user will have a choice to delete
the device using devid.
The other method we could do, is to match the input device_path
to the available device_paths with in the kernel. But that won't
work in all the cases, like what if user provided mapper path
when the path within the kernel is a non-mapper path.
This patch depends on the below kernel patch for the new feature to work,
however it will fail-back to the old interface for the kernel without the
patch
Btrfs: Introduce device delete by devid
Signed-off-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'cmds-device.c')
-rw-r--r-- | cmds-device.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/cmds-device.c b/cmds-device.c index 9906d4a3..b17b6c6f 100644 --- a/cmds-device.c +++ b/cmds-device.c @@ -159,20 +159,46 @@ static int _cmd_device_remove(int argc, char **argv, for(i = optind; i < argc - 1; i++) { struct btrfs_ioctl_vol_args arg; + struct btrfs_ioctl_vol_args_v2 argv2 = {0}; + int is_devid = 0; int res; - if (is_block_device(argv[i]) != 1 && strcmp(argv[i], "missing")) { + if (string_is_numerical(argv[i])) { + argv2.devid = arg_strtou64(argv[i]); + argv2.flags = BTRFS_DEVICE_SPEC_BY_ID; + is_devid = 1; + } else if (is_block_device(argv[i]) == 1 || + strcmp(argv[i], "missing") == 0) { + strncpy_null(argv2.name, argv[i]); + } else { error("not a block device: %s", argv[i]); ret++; continue; } - memset(&arg, 0, sizeof(arg)); - strncpy_null(arg.name, argv[i]); + /* * Positive values are from BTRFS_ERROR_DEV_*, * otherwise it's a generic error, one of errnos */ - res = ioctl(fdmnt, BTRFS_IOC_RM_DEV, &arg); + res = ioctl(fdmnt, BTRFS_IOC_RM_DEV_V2, &argv2); + + /* + * If BTRFS_IOC_RM_DEV_V2 is not supported we get ENOTTY and if + * argv2.flags includes a flag which kernel doesn't understand then + * we shall get EOPNOTSUPP + */ + if (res < 0 && (errno == ENOTTY || errno == EOPNOTSUPP)) { + if (is_devid) { + error("device delete by id failed: %s", + strerror(errno)); + ret++; + continue; + } + memset(&arg, 0, sizeof(arg)); + strncpy_null(arg.name, argv[i]); + res = ioctl(fdmnt, BTRFS_IOC_RM_DEV, &arg); + } + if (res) { const char *msg; @@ -180,8 +206,13 @@ static int _cmd_device_remove(int argc, char **argv, msg = btrfs_err_str(res); else msg = strerror(errno); - error("error removing device '%s': %s", - argv[i], msg); + if (is_devid) { + error("error removing devid %llu: %s", + (unsigned long long)argv2.devid, msg); + } else { + error("error removing device '%s': %s", + argv[i], msg); + } ret++; } } @@ -191,7 +222,7 @@ static int _cmd_device_remove(int argc, char **argv, } static const char * const cmd_device_remove_usage[] = { - "btrfs device remove <device> [<device>...] <path>", + "btrfs device remove <device>|<devid> [<device>|<devid>...] <path>", "Remove a device from a filesystem", NULL }; @@ -202,7 +233,7 @@ static int cmd_device_remove(int argc, char **argv) } static const char * const cmd_device_delete_usage[] = { - "btrfs device delete <device> [<device>...] <path>", + "btrfs device delete <device>|<devid> [<device>|<devid>...] <path>", "Remove a device from a filesystem", NULL }; |