Blob Blame History Raw
From b9146e4dab45e2f76ceca3772564c0f01e227a9f Mon Sep 17 00:00:00 2001
From: Liu Yuan Yuan <bjyyliu@linux.vnet.ibm.com>
Date: Fri, 13 Nov 2015 11:50:42 +0100
Subject: [PATCH] udev/path_id: improve and enhance bus detection for Linux on
 z Systems

Improve and enhance the path_id udev builtin to correctly handle bus'
available on Linux on z Systems (s390).

Previously, the CCW bus and, in particular, any FCP devices on it, have
been treated separately.  This commit integrates the CCW bus into the
device chain loop.  FCP devices and their associated SCSI disks are now
handled through the common SCSI handling functions in path_id.

This implies also a change in the naming of the symbolic links created
by udev.  So any backports of this commit to existing Linux distribution
must be done with care.  If a backport is required, a udev rule must be
created to also create the "old-style" symbolic links.

Apart from the CCW bus, this commit adds bus support for the:

- ccwgroup bus which manages network devices, and
- ap bus which manages cryptographic adapters
- iucv bus which manages IUCV devices on z/VM

Cherry-picked from: e7eb5a8d88367a755944fdda3023a308e5272953
Resolves: #1274401
---
 rules/40-redhat.rules           | 25 +++++++++++++
 src/udev/udev-builtin-path_id.c | 63 ++++++++++++++++++---------------
 2 files changed, 60 insertions(+), 28 deletions(-)

diff --git a/rules/40-redhat.rules b/rules/40-redhat.rules
index 0164dc921..c928d412b 100644
--- a/rules/40-redhat.rules
+++ b/rules/40-redhat.rules
@@ -15,3 +15,28 @@ SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_target", TEST!="[module/sg]", RUN+="/sbin
 
 # Rule for prandom character device node permissions
 KERNEL=="prandom", MODE="0644"
+
+
+# Rules for creating the ID_PATH for SCSI devices based on the CCW bus
+# using the form: ccw-<BUS_ID>-zfcp-<WWPN>:<LUN>
+#
+ACTION=="remove", GOTO="zfcp_scsi_device_end"
+
+#
+# Set environment variable "ID_ZFCP_BUS" to "1" if the devices
+# (both disk and partition) are SCSI devices based on FCP devices
+#
+KERNEL=="sd*", SUBSYSTEMS=="ccw", DRIVERS=="zfcp", ENV{.ID_ZFCP_BUS}="1"
+
+# For SCSI disks
+KERNEL=="sd*[!0-9]", SUBSYSTEMS=="scsi",
+        ENV{.ID_ZFCP_BUS}=="1", ENV{DEVTYPE}=="disk",
+        SYMLINK+="disk/by-path/ccw-$attr{hba_id}-zfcp-$attr{wwpn}:$attr{fcp_lun}"
+
+
+# For partitions on a SCSI disk
+KERNEL=="sd*[0-9]", SUBSYSTEMS=="scsi",
+        ENV{.ID_ZFCP_BUS}=="1", ENV{DEVTYPE}=="partition",
+        SYMLINK+="disk/by-path/ccw-$attr{hba_id}-zfcp-$attr{wwpn}:$attr{fcp_lun}-part%n"
+
+LABEL="zfcp_scsi_device_end"
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index 88a812ff5..19447201b 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -615,27 +615,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;
-
-        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;
-                }
-        }
+/* 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(path);
+
+        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;
 }
 
@@ -647,15 +643,8 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool
         bool new_sas_path = false;
         bool enable_new_sas_path = true;
 
-        /* S390 ccw bus */
-        parent = udev_device_get_parent_with_subsystem_devtype(dev, "ccw", NULL);
-        if (parent != NULL) {
-                handle_ccw(parent, dev, &path);
-                goto out;
-        }
-
 restart:
-        ;
+
         /* walk up the chain of devices and compose path */
         parent = dev;
         while (parent != NULL) {
@@ -718,6 +707,25 @@ restart:
                                 supported_parent = true;
                                 supported_transport = 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;
                 }
 
                 parent = udev_device_get_parent(parent);
@@ -743,7 +751,6 @@ restart:
                 path = NULL;
         }
 
-out:
         if (path != NULL) {
                 char tag[UTIL_NAME_SIZE];
                 size_t i;