summaryrefslogtreecommitdiff
path: root/src/udev/udev-builtin-path_id.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/udev/udev-builtin-path_id.c')
-rw-r--r--src/udev/udev-builtin-path_id.c158
1 files changed, 96 insertions, 62 deletions
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index 4ca0a69d7d..1825ee75a7 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -19,17 +19,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <string.h>
#include <ctype.h>
-#include <fcntl.h>
-#include <errno.h>
#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
#include <getopt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "alloc-util.h"
+#include "string-util.h"
#include "udev.h"
_printf_(2,3)
@@ -117,8 +119,7 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent,
format_lun_number(parent, &lun);
path_prepend(path, "fc-%s-%s", port, lun);
- if (lun)
- free(lun);
+ free(lun);
out:
udev_device_unref(fcdev);
return parent;
@@ -156,8 +157,7 @@ static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent,
format_lun_number(parent, &lun);
path_prepend(path, "sas-%s-%s", sas_address, lun);
- if (lun)
- free(lun);
+ free(lun);
out:
udev_device_unref(sasdev);
return parent;
@@ -251,8 +251,7 @@ static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **pa
else
path_prepend(path, "sas-phy%s-%s", phy_id, lun);
- if (lun)
- free(lun);
+ free(lun);
out:
udev_device_unref(target_sasdev);
udev_device_unref(expander_sasdev);
@@ -313,14 +312,46 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **
format_lun_number(parent, &lun);
path_prepend(path, "ip-%s:%s-iscsi-%s-%s", addr, port, target, lun);
- if (lun)
- free(lun);
+ free(lun);
out:
udev_device_unref(sessiondev);
udev_device_unref(conndev);
return parent;
}
+static struct udev_device *handle_scsi_ata(struct udev_device *parent, char **path) {
+ struct udev *udev = udev_device_get_udev(parent);
+ struct udev_device *targetdev;
+ struct udev_device *target_parent;
+ struct udev_device *atadev;
+ const char *port_no;
+
+ assert(parent);
+ assert(path);
+
+ targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host");
+ if (!targetdev)
+ return NULL;
+
+ target_parent = udev_device_get_parent(targetdev);
+ if (!target_parent)
+ return NULL;
+
+ atadev = udev_device_new_from_subsystem_sysname(udev, "ata_port", udev_device_get_sysname(target_parent));
+ if (!atadev)
+ return NULL;
+
+ port_no = udev_device_get_sysattr_value(atadev, "port_no");
+ if (!port_no) {
+ parent = NULL;
+ goto out;
+ }
+ path_prepend(path, "ata-%s", port_no);
+out:
+ udev_device_unref(atadev);
+ return parent;
+}
+
static struct udev_device *handle_scsi_default(struct udev_device *parent, char **path) {
struct udev_device *hostdev;
int host, bus, target, lun;
@@ -486,19 +517,8 @@ static struct udev_device *handle_scsi(struct udev_device *parent, char **path,
goto out;
}
- /*
- * We do not support the ATA transport class, it uses global counters
- * to name the ata devices which numbers spread across multiple
- * controllers.
- *
- * The real link numbers are not exported. Also, possible chains of ports
- * behind port multipliers cannot be composed that way.
- *
- * Until all that is solved at the kernel level, there are no by-path/
- * links for ATA devices.
- */
if (strstr(name, "/ata") != NULL) {
- parent = NULL;
+ parent = handle_scsi_ata(parent, path);
goto out;
}
@@ -573,31 +593,23 @@ static struct udev_device *handle_bcma(struct udev_device *parent, char **path)
return parent;
}
-static struct udev_device *handle_ccw(struct udev_device *parent, struct udev_device *dev, char **path) {
- struct udev_device *scsi_dev;
+/* Handle devices of AP bus in System z platform. */
+static struct udev_device *handle_ap(struct udev_device *parent, char **path) {
+ const char *type, *func;
assert(parent);
- assert(dev);
assert(path);
- scsi_dev = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device");
- if (scsi_dev != NULL) {
- const char *wwpn;
- const char *lun;
- const char *hba_id;
-
- hba_id = udev_device_get_sysattr_value(scsi_dev, "hba_id");
- wwpn = udev_device_get_sysattr_value(scsi_dev, "wwpn");
- lun = udev_device_get_sysattr_value(scsi_dev, "fcp_lun");
- if (hba_id != NULL && lun != NULL && wwpn != NULL) {
- path_prepend(path, "ccw-%s-zfcp-%s:%s", hba_id, wwpn, lun);
- goto out;
- }
- }
+ type = udev_device_get_sysattr_value(parent, "type");
+ func = udev_device_get_sysattr_value(parent, "ap_functions");
- path_prepend(path, "ccw-%s", udev_device_get_sysname(parent));
+ if (type != NULL && func != NULL) {
+ path_prepend(path, "ap-%s-%s", type, func);
+ goto out;
+ }
+ path_prepend(path, "ap-%s", udev_device_get_sysname(parent));
out:
- parent = skip_subsystem(parent, "ccw");
+ parent = skip_subsystem(parent, "ap");
return parent;
}
@@ -609,13 +621,6 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool
assert(dev);
- /* S390 ccw bus */
- parent = udev_device_get_parent_with_subsystem_devtype(dev, "ccw", NULL);
- if (parent != NULL) {
- handle_ccw(parent, dev, &path);
- goto out;
- }
-
/* walk up the chain of devices and compose path */
parent = dev;
while (parent != NULL) {
@@ -658,11 +663,45 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool
path_prepend(&path, "xen-%s", udev_device_get_sysname(parent));
parent = skip_subsystem(parent, "xen");
supported_parent = true;
+ } else if (streq(subsys, "virtio")) {
+ while (parent && streq_ptr("virtio", udev_device_get_subsystem(parent)))
+ parent = udev_device_get_parent(parent);
+ path_prepend(&path, "virtio-pci-%s", udev_device_get_sysname(parent));
+ supported_transport = true;
+ supported_parent = true;
} else if (streq(subsys, "scm")) {
path_prepend(&path, "scm-%s", udev_device_get_sysname(parent));
parent = skip_subsystem(parent, "scm");
supported_transport = true;
supported_parent = true;
+ } else if (streq(subsys, "ccw")) {
+ path_prepend(&path, "ccw-%s", udev_device_get_sysname(parent));
+ parent = skip_subsystem(parent, "ccw");
+ supported_transport = true;
+ supported_parent = true;
+ } else if (streq(subsys, "ccwgroup")) {
+ path_prepend(&path, "ccwgroup-%s", udev_device_get_sysname(parent));
+ parent = skip_subsystem(parent, "ccwgroup");
+ supported_transport = true;
+ supported_parent = true;
+ } else if (streq(subsys, "ap")) {
+ parent = handle_ap(parent, &path);
+ supported_transport = true;
+ supported_parent = true;
+ } else if (streq(subsys, "iucv")) {
+ path_prepend(&path, "iucv-%s", udev_device_get_sysname(parent));
+ parent = skip_subsystem(parent, "iucv");
+ supported_transport = true;
+ supported_parent = true;
+ } else if (streq(subsys, "nvme")) {
+ const char *nsid = udev_device_get_sysattr_value(dev, "nsid");
+
+ if (nsid) {
+ path_prepend(&path, "nvme-%s", nsid);
+ parent = skip_subsystem(parent, "nvme");
+ supported_parent = true;
+ supported_transport = true;
+ }
}
if (parent)
@@ -674,22 +713,17 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool
* might produce conflicting IDs if the parent does not provide a
* unique and predictable name.
*/
- if (!supported_parent) {
- free(path);
- path = NULL;
- }
+ if (!supported_parent)
+ path = mfree(path);
/*
* Do not return block devices without a well-known transport. Some
* devices do not expose their buses and do not provide a unique
* and predictable name that way.
*/
- if (streq(udev_device_get_subsystem(dev), "block") && !supported_transport) {
- free(path);
- path = NULL;
- }
+ if (streq_ptr(udev_device_get_subsystem(dev), "block") && !supported_transport)
+ path = mfree(path);
-out:
if (path != NULL) {
char tag[UTIL_NAME_SIZE];
size_t i;