File s390-tools-sles15sp2-02-zgetdump-Fix-device-node-determination-via-sysfs.patch of Package s390-tools.18705
Subject: [PATCH] [BZ 189020] zgetdump: Fix device node determination via sysfs
From: Jan Hoeppner <hoeppner@linux.ibm.com>
Description: zgetdump: Fix device node determination via sysfs
Symptom: When using zgetdump on a multi-volume device dump, the sysfs
path to determine the device node is incomplete, resulting in
the following error:
$ zgetdump -i /dev/dasdb1
zgetdump: Could not open
"/sys/bus/ccw/devices/0.0.9300/dasdb/dev"
(No such file or directory)
Problem: The sysfs path to determine the device node is incomplete.
Solution: A simple fix would be to add the missing "block" part in the
sysfs path. However, the logic still assumes sysfs links like
"block:" that have been deprecated a decade ago and are no
longer present on modern systems anyway.
Therefore, the logic can greatly be improved. Create a separate
function to determine whether a device is online, remove the
logic for "block:" entries, and use libutil functions to reduce
the complexity even further.
Reproduction: Set up a multi-volume dump using zipl -M (See man page and
corresponding Dump Tool Documentation for more details).
Then simply run:
$ zgetdump -i /dev/dasdb1
on the multi-volume setup.
Upstream-ID: d55b787d05eb9bd70f93c36cf859b66b2ad02038
Problem-ID: 189020
Upstream-Description:
zgetdump: Fix device node determination via sysfs
When using zgetdump on a multi-volume device dump, the sysfs path to
determine the device node is incomplete, resulting in the following
error:
$ zgetdump -i /dev/dasdb1
zgetdump: Could not open "/sys/bus/ccw/devices/0.0.9300/dasdb/dev" (No
such file or directory)
A simple fix would be to add the missing "block" part in the sysfs path.
However, the logic still assumes sysfs links like "block:" that have
been deprecated a decade ago and are no longer present on modern
systems anyway.
Therefore, the logic can greatly be improved. Create a separate function
to determine whether a device is online, remove the logic for "block:"
entries, and use libutil functions to reduce the complexity even further.
Fixes: 70a79fab3cc1 ("zgetdump: Avoid using PATH_MAX")
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
---
zdump/dfi_s390mv.c | 78 ++++++++++++++++++++++++-----------------------------
1 file changed, 36 insertions(+), 42 deletions(-)
--- a/zdump/dfi_s390mv.c
+++ b/zdump/dfi_s390mv.c
@@ -21,6 +21,7 @@
#include <time.h>
#include <unistd.h>
+#include "lib/util_file.h"
#include "lib/util_path.h"
#include "zgetdump.h"
@@ -98,6 +99,24 @@ static void em_init(struct vol *vol)
l.dump_incomplete = 1;
}
+/*
+ * Check whether a device with a given busid is online
+ */
+static unsigned int dev_is_online(const char *busid)
+{
+ unsigned int online;
+ char *path;
+
+ path = util_path_sysfs("%s/%s/online", SYSFS_BUSDIR, busid);
+ if (util_file_read_ui(&online, 10, path) != 0) {
+ warnx("Could not open \"%s\" (%s)", path, strerror(errno));
+ free(path);
+ exit(EXIT_FAILURE);
+ }
+ free(path);
+
+ return online;
+}
/*
* Check sysfs, whether a device specified by its bus ID is defined and online.
@@ -106,67 +125,40 @@ static void em_init(struct vol *vol)
static enum dev_status dev_from_busid(char *bus_id, dev_t *dev)
{
struct dirent *direntp;
- int fh, minor, major;
+ int minor, major;
char buf[10];
DIR *fh_dir;
char *sysfs;
sysfs = util_path_sysfs("%s/%s", SYSFS_BUSDIR, bus_id);
- fh_dir = opendir(sysfs);
- free(sysfs);
- if (!fh_dir)
+ if (!util_path_is_dir(sysfs)) {
+ free(sysfs);
return DEV_UNDEFINED;
-
- sysfs = util_path_sysfs("%s/%s/online", SYSFS_BUSDIR, bus_id);
- fh = open(sysfs, O_RDONLY);
- if (fh == -1) {
- warnx("Could not open \"%s\" (%s)", sysfs, strerror(errno));
- goto err;
}
free(sysfs);
- if (read(fh, buf, 1) == -1)
- ERR_EXIT_ERRNO("Could not read online attribute");
- close(fh);
- if (buf[0] != '1')
+ if (!dev_is_online(bus_id))
return DEV_OFFLINE;
+ sysfs = util_path_sysfs("%s/%s/block", SYSFS_BUSDIR, bus_id);
+ fh_dir = opendir(sysfs);
+ if (!fh_dir) {
+ warnx("Could not open \"%s\" (%s) ", sysfs, strerror(errno));
+ goto err;
+ }
while ((direntp = readdir(fh_dir)))
- if (strncmp(direntp->d_name, "block:", 6) == 0)
+ if (strncmp(direntp->d_name, "dasd", 4) == 0)
break;
- closedir(fh_dir);
-
if (direntp == NULL) {
- sysfs = util_path_sysfs("%s/%s/block", SYSFS_BUSDIR, bus_id);
- fh_dir = opendir(sysfs);
- if (!fh_dir) {
- warnx("Could not open \"%s\" (%s) ",
- sysfs, strerror(errno));
- goto err;
- }
- while ((direntp = readdir(fh_dir)))
- if (strncmp(direntp->d_name, "dasd", 4) == 0)
- break;
- closedir(fh_dir);
- if (direntp == NULL) {
- warnx("Problem with contents of \"%s\"", sysfs);
- goto err;
- }
- free(sysfs);
- }
-
- sysfs = util_path_sysfs("%s/%s/%s/dev",
- SYSFS_BUSDIR, bus_id, direntp->d_name);
- fh = open(sysfs, O_RDONLY);
- if (fh == -1) {
- warnx("Could not open \"%s\" (%s)", sysfs, strerror(errno));
+ warnx("Problem with contents of \"%s\"", sysfs);
goto err;
}
- if (read(fh, buf, sizeof(buf)) == -1) {
+ if (util_file_read_line(buf, sizeof(buf), "%s/%s/dev", sysfs, direntp->d_name)) {
warnx("Could not read dev file (%s)", strerror(errno));
goto err;
}
- close(fh);
+ closedir(fh_dir);
+
if (sscanf(buf, "%i:%i", &major, &minor) != 2) {
warnx("Malformed content of \"%s\": %s", sysfs, buf);
goto err;
@@ -178,6 +170,8 @@ static enum dev_status dev_from_busid(ch
return DEV_ONLINE;
err:
+ if (fh_dir)
+ closedir(fh_dir);
free(sysfs);
exit(EXIT_FAILURE);
}