forked from pool/s390-tools
125 lines
4.1 KiB
Diff
125 lines
4.1 KiB
Diff
|
Subject: zpcictl: Make device node for NVMe optional
|
||
|
From: Jan Hoeppner <jan.hoeppner@de.ibm.com>
|
||
|
|
||
|
Summary: zpcictl: Add tool to manage PCI devices
|
||
|
Description: Use the zpcictl tool to manage PCI devices on the IBM Z
|
||
|
platform. Initial functions include generating firmware
|
||
|
error logs, resetting PCI devices, and preparing a device
|
||
|
for further repair actions.
|
||
|
Upstream-ID: 342c6a3707315514f0f886fabb532f6c8b59b694
|
||
|
Problem-ID: RAS1703
|
||
|
|
||
|
Upstream-Description:
|
||
|
|
||
|
zpcictl: Make device node for NVMe optional
|
||
|
|
||
|
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 <hoeppner@linux.ibm.com>
|
||
|
|
||
|
|
||
|
Signed-off-by: Jan Hoeppner <jan.hoeppner@de.ibm.com>
|
||
|
---
|
||
|
zpcictl/zpcictl.c | 30 ++++++++++++++++++++----------
|
||
|
1 file changed, 20 insertions(+), 10 deletions(-)
|
||
|
|
||
|
--- a/zpcictl/zpcictl.c
|
||
|
+++ b/zpcictl/zpcictl.c
|
||
|
@@ -104,6 +104,9 @@ static char *collect_smart_data(struct z
|
||
|
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
|
||
|
/* 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 ch
|
||
|
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 ch
|
||
|
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_
|
||
|
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_
|
||
|
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);
|