From 342c6a3707315514f0f886fabb532f6c8b59b694 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B6ppner?= Date: Wed, 10 Oct 2018 16:57:23 +0200 Subject: [PATCH] zpcictl: Make device node for NVMe optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At the moment, if we specify the slot address of an NVMe device but can't find the corresponding device node, the execution is terminated. This is a bit harsh as the device node is rather optional and only necessary to collect S.M.A.R.T. data. We should still be able to issue the error reporting, even if we couldn't determine the device node. Therefore, make sure the device node for NVMe devices is optional by changing various error messages to warnings. Change sysfs_get_slot_addr() to have a return value and work with that accordingly. Also make sure, that execution is terminated when a valid device node was specified but no matching slot address was determined. The slot address is necessary to issue the error reporting commands. Signed-off-by: Jan Höppner --- zpcictl/zpcictl.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/zpcictl/zpcictl.c b/zpcictl/zpcictl.c index 74831faa..a9e38fb6 100644 --- a/zpcictl/zpcictl.c +++ b/zpcictl/zpcictl.c @@ -104,6 +104,9 @@ static char *collect_smart_data(struct zpci_device *pdev) char *cmd; FILE *fd; + if (!pdev->device) + return NULL; + util_asprintf(&cmd, SMARTCTL_CMDLINE, pdev->device); fd = popen(cmd, "r"); if (!fd) @@ -175,7 +178,7 @@ static void sysfs_write_data(struct zpci_report_error *report, char *slot) /* lstat() doesn't work for sysfs files, so we have to work with a fixed size */ #define READLINK_SIZE 256 -static void sysfs_get_slot_addr(const char *dev, char *slot) +static int sysfs_get_slot_addr(const char *dev, char *slot) { char device[READLINK_SIZE], *result; unsigned int major, minor; @@ -184,8 +187,9 @@ static void sysfs_get_slot_addr(const char *dev, char *slot) char *path; if (stat(dev, &dev_stat) != 0) { - errx(EXIT_FAILURE, "Could not get stat information for %s: %s", - dev, strerror(errno)); + warnx("Could not get stat information for %s: %s", + dev, strerror(errno)); + return 0; } major = major(dev_stat.st_rdev); minor = minor(dev_stat.st_rdev); @@ -193,18 +197,21 @@ static void sysfs_get_slot_addr(const char *dev, char *slot) path = util_path_sysfs("dev/char/%u:%u/device", major, minor); len = readlink(path, device, READLINK_SIZE - 1); free(path); - if (len != -1) + if (len != -1) { device[len] = '\0'; - else - errx(EXIT_FAILURE, "Could not read device link for %s", dev); + } else { + warnx("Could not read device link for %s", dev); + return 0; + } result = strrchr(device, '/'); if (result) result++; else result = device; - strcpy(slot, result); + + return 1; } static void get_device_node(struct zpci_device *pdev) @@ -219,12 +226,13 @@ static void get_device_node(struct zpci_device *pdev) if (count == -1) { warnx("Could not read directory %s: %s", path, strerror(errno)); free(path); - exit(EXIT_FAILURE); + return; } for (i = 0; i < count; i++) { util_asprintf(&dev, "/dev/%s", de_vec[i]->d_name); - sysfs_get_slot_addr(dev, slot); + if (!sysfs_get_slot_addr(dev, slot)) + continue; if (strcmp(slot, pdev->slot) == 0) { pdev->device = dev; break; @@ -255,7 +263,9 @@ static void get_device_info(struct zpci_device *pdev, char *dev) if (is_blk_dev(dev)) errx(EXIT_FAILURE, "Unsupported device type %s", dev); if (is_char_dev(dev)) { - sysfs_get_slot_addr(dev, pdev->slot); + if (!sysfs_get_slot_addr(dev, pdev->slot)) + errx(EXIT_FAILURE, + "Could not determine slot address for %s", dev); pdev->device = dev; } else { strcpy(pdev->slot, dev);