diff --git a/bcache.c b/bcache.c index 9b20e020..7807f7c5 100644 --- a/bcache.c +++ b/bcache.c @@ -1236,6 +1236,36 @@ err: return err; } +char *device_set_failed(const char *dev_uuid, const char *set_uuid) { + int ret, bcachefd; + char *err = NULL; + uuid_le dev, set; + struct bch_ioctl_disk_failed df; + + bcachefd = open("/dev/bcache", O_RDWR); + if (bcachefd < 0) { + err = "Can't open bcache device"; + goto err; + } + + uuid_parse(dev_uuid, dev.b); + uuid_parse(set_uuid, set.b); + df.dev_uuid = dev; + df.set_uuid = set; + + ret = ioctl(bcachefd, BCH_IOCTL_SET_DISK_FAILED, &df); + if (ret < 0) { + char tmp[128]; + snprintf(tmp, 128, "ioctl set disk failed error %s\n", + strerror(ret)); + err = strdup(tmp); + } + +err: + close(bcachefd); + return err; +} + char *probe(char *dev, int udev) { struct cache_sb sb; diff --git a/bcache.h b/bcache.h index 166f6fdf..0133befd 100644 --- a/bcache.h +++ b/bcache.h @@ -110,7 +110,7 @@ char *add_devices(char *const *, char *); char *remove_device(const char *, bool); char *bcache_get_capacity(const char *, const char *, bool); char *dev_name(const char *); - +char *device_set_failed(const char *dev_uuid, const char *set_uuid); #define csum_set(i, type) \ ({ \ diff --git a/bcacheadm.c b/bcacheadm.c index 4fa81a70..d974d99c 100644 --- a/bcacheadm.c +++ b/bcacheadm.c @@ -99,6 +99,10 @@ bool stats_hour = false; bool stats_day = false; bool stats_total = false; +/* set_failed globals */ +static const char *failed_uuid = NULL; +static const char *dev_failed_uuid = NULL; + /* make-bcache option setters */ static int set_block_size(NihOption *option, const char *arg) { @@ -254,6 +258,12 @@ static NihOption stats_options[] = { NIH_OPTION_LAST }; +static NihOption set_failed_options[] = { + {'u', "set", N_("cache_set UUID"), NULL, "UUID", &failed_uuid, NULL}, + {'d', "dev", N_("dev UUID"), NULL, "UUID", &dev_failed_uuid, NULL}, + NIH_OPTION_LAST +}; + static NihOption options[] = { NIH_OPTION_LAST }; @@ -784,6 +794,30 @@ err: return -1; } +int bcache_set_failed(NihCommand *command, char *const *args) +{ + int i; + char *err = NULL; + + if (!failed_uuid) { + printf("Pass in a cacheset uuid\n"); + return -1; + } + + if (!dev_failed_uuid) { + printf("Pass in a dev uuid\n"); + return -1; + } + + err = device_set_failed(dev_failed_uuid, failed_uuid); + if (err) { + printf("bcache_set_failed_ioctl error: %s\n", err); + return -1; + } + + return 0; +} + static NihCommand commands[] = { {"format", N_("format "), "Format one or a list of devices with bcache datastructures." @@ -834,6 +868,10 @@ static NihCommand commands[] = { "List various bcache statistics", N_("List various bcache statistics"), NULL, stats_options, bcache_stats}, + {"set-failed", N_("set-failed --set=UUID --dev=UUID"), + "Sets a device to the FAILED state", + N_("Sets a device to the FAILED state"), + NULL, set_failed_options, bcache_set_failed}, NIH_COMMAND_LAST };