Skip to content

Commit

Permalink
zgetdump: Fix device node determination via sysfs
Browse files Browse the repository at this point in the history
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: 70a79fa ("zgetdump: Avoid using PATH_MAX")
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
  • Loading branch information
hoeppnerj committed Oct 28, 2020
1 parent da4fdee commit d55b787
Showing 1 changed file with 36 additions and 42 deletions.
78 changes: 36 additions & 42 deletions zdump/dfi_s390mv.c
Expand Up @@ -21,6 +21,7 @@
#include <time.h>
#include <unistd.h>

#include "lib/util_file.h"
#include "lib/util_path.h"

#include "zgetdump.h"
Expand Down Expand Up @@ -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.
Expand All @@ -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;
Expand All @@ -178,6 +170,8 @@ static enum dev_status dev_from_busid(char *bus_id, dev_t *dev)
return DEV_ONLINE;

err:
if (fh_dir)
closedir(fh_dir);
free(sysfs);
exit(EXIT_FAILURE);
}
Expand Down

0 comments on commit d55b787

Please sign in to comment.