803fb7
From b9146e4dab45e2f76ceca3772564c0f01e227a9f Mon Sep 17 00:00:00 2001
803fb7
From: Liu Yuan Yuan <bjyyliu@linux.vnet.ibm.com>
803fb7
Date: Fri, 13 Nov 2015 11:50:42 +0100
803fb7
Subject: [PATCH] udev/path_id: improve and enhance bus detection for Linux on
803fb7
 z Systems
803fb7
803fb7
Improve and enhance the path_id udev builtin to correctly handle bus'
803fb7
available on Linux on z Systems (s390).
803fb7
803fb7
Previously, the CCW bus and, in particular, any FCP devices on it, have
803fb7
been treated separately.  This commit integrates the CCW bus into the
803fb7
device chain loop.  FCP devices and their associated SCSI disks are now
803fb7
handled through the common SCSI handling functions in path_id.
803fb7
803fb7
This implies also a change in the naming of the symbolic links created
803fb7
by udev.  So any backports of this commit to existing Linux distribution
803fb7
must be done with care.  If a backport is required, a udev rule must be
803fb7
created to also create the "old-style" symbolic links.
803fb7
803fb7
Apart from the CCW bus, this commit adds bus support for the:
803fb7
803fb7
- ccwgroup bus which manages network devices, and
803fb7
- ap bus which manages cryptographic adapters
803fb7
- iucv bus which manages IUCV devices on z/VM
803fb7
803fb7
Cherry-picked from: e7eb5a8d88367a755944fdda3023a308e5272953
803fb7
Resolves: #1274401
803fb7
---
803fb7
 rules/40-redhat.rules           | 25 ++++++++++++++++
803fb7
 src/udev/udev-builtin-path_id.c | 63 +++++++++++++++++++++++------------------
803fb7
 2 files changed, 60 insertions(+), 28 deletions(-)
803fb7
803fb7
diff --git a/rules/40-redhat.rules b/rules/40-redhat.rules
803fb7
index 0164dc921..c928d412b 100644
803fb7
--- a/rules/40-redhat.rules
803fb7
+++ b/rules/40-redhat.rules
803fb7
@@ -15,3 +15,28 @@ SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_target", TEST!="[module/sg]", RUN+="/sbin
803fb7
 
803fb7
 # Rule for prandom character device node permissions
803fb7
 KERNEL=="prandom", MODE="0644"
803fb7
+
803fb7
+
803fb7
+# Rules for creating the ID_PATH for SCSI devices based on the CCW bus
803fb7
+# using the form: ccw-<BUS_ID>-zfcp-<WWPN>:<LUN>
803fb7
+#
803fb7
+ACTION=="remove", GOTO="zfcp_scsi_device_end"
803fb7
+
803fb7
+#
803fb7
+# Set environment variable "ID_ZFCP_BUS" to "1" if the devices
803fb7
+# (both disk and partition) are SCSI devices based on FCP devices
803fb7
+#
803fb7
+KERNEL=="sd*", SUBSYSTEMS=="ccw", DRIVERS=="zfcp", ENV{.ID_ZFCP_BUS}="1"
803fb7
+
803fb7
+# For SCSI disks
803fb7
+KERNEL=="sd*[!0-9]", SUBSYSTEMS=="scsi",
803fb7
+        ENV{.ID_ZFCP_BUS}=="1", ENV{DEVTYPE}=="disk",
803fb7
+        SYMLINK+="disk/by-path/ccw-$attr{hba_id}-zfcp-$attr{wwpn}:$attr{fcp_lun}"
803fb7
+
803fb7
+
803fb7
+# For partitions on a SCSI disk
803fb7
+KERNEL=="sd*[0-9]", SUBSYSTEMS=="scsi",
803fb7
+        ENV{.ID_ZFCP_BUS}=="1", ENV{DEVTYPE}=="partition",
803fb7
+        SYMLINK+="disk/by-path/ccw-$attr{hba_id}-zfcp-$attr{wwpn}:$attr{fcp_lun}-part%n"
803fb7
+
803fb7
+LABEL="zfcp_scsi_device_end"
803fb7
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
803fb7
index 88a812ff5..19447201b 100644
803fb7
--- a/src/udev/udev-builtin-path_id.c
803fb7
+++ b/src/udev/udev-builtin-path_id.c
803fb7
@@ -615,27 +615,23 @@ static struct udev_device *handle_bcma(struct udev_device *parent, char **path)
803fb7
         return parent;
803fb7
 }
803fb7
 
803fb7
-static struct udev_device *handle_ccw(struct udev_device *parent, struct udev_device *dev, char **path) {
803fb7
-        struct udev_device *scsi_dev;
803fb7
-
803fb7
-        scsi_dev = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device");
803fb7
-        if (scsi_dev != NULL) {
803fb7
-                const char *wwpn;
803fb7
-                const char *lun;
803fb7
-                const char *hba_id;
803fb7
-
803fb7
-                hba_id = udev_device_get_sysattr_value(scsi_dev, "hba_id");
803fb7
-                wwpn = udev_device_get_sysattr_value(scsi_dev, "wwpn");
803fb7
-                lun = udev_device_get_sysattr_value(scsi_dev, "fcp_lun");
803fb7
-                if (hba_id != NULL && lun != NULL && wwpn != NULL) {
803fb7
-                        path_prepend(path, "ccw-%s-zfcp-%s:%s", hba_id, wwpn, lun);
803fb7
-                        goto out;
803fb7
-                }
803fb7
-        }
803fb7
+/* Handle devices of AP bus in System z platform. */
803fb7
+static struct udev_device *handle_ap(struct udev_device *parent, char **path) {
803fb7
+        const char *type, *func;
803fb7
+
803fb7
+        assert(parent);
803fb7
+        assert(path);
803fb7
+
803fb7
+        type = udev_device_get_sysattr_value(parent, "type");
803fb7
+        func = udev_device_get_sysattr_value(parent, "ap_functions");
803fb7
 
803fb7
-        path_prepend(path, "ccw-%s", udev_device_get_sysname(parent));
803fb7
+        if (type != NULL && func != NULL) {
803fb7
+                path_prepend(path, "ap-%s-%s", type, func);
803fb7
+                goto out;
803fb7
+        }
803fb7
+        path_prepend(path, "ap-%s", udev_device_get_sysname(parent));
803fb7
 out:
803fb7
-        parent = skip_subsystem(parent, "ccw");
803fb7
+        parent = skip_subsystem(parent, "ap");
803fb7
         return parent;
803fb7
 }
803fb7
 
803fb7
@@ -647,15 +643,8 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool
803fb7
         bool new_sas_path = false;
803fb7
         bool enable_new_sas_path = true;
803fb7
 
803fb7
-        /* S390 ccw bus */
803fb7
-        parent = udev_device_get_parent_with_subsystem_devtype(dev, "ccw", NULL);
803fb7
-        if (parent != NULL) {
803fb7
-                handle_ccw(parent, dev, &path);
803fb7
-                goto out;
803fb7
-        }
803fb7
-
803fb7
 restart:
803fb7
-        ;
803fb7
+
803fb7
         /* walk up the chain of devices and compose path */
803fb7
         parent = dev;
803fb7
         while (parent != NULL) {
803fb7
@@ -718,6 +707,25 @@ restart:
803fb7
                                 supported_parent = true;
803fb7
                                 supported_transport = true;
803fb7
                         }
803fb7
+                } else if (streq(subsys, "ccw")) {
803fb7
+                        path_prepend(&path, "ccw-%s", udev_device_get_sysname(parent));
803fb7
+                        parent = skip_subsystem(parent, "ccw");
803fb7
+                        supported_transport = true;
803fb7
+                        supported_parent = true;
803fb7
+                } else if (streq(subsys, "ccwgroup")) {
803fb7
+                        path_prepend(&path, "ccwgroup-%s", udev_device_get_sysname(parent));
803fb7
+                        parent = skip_subsystem(parent, "ccwgroup");
803fb7
+                        supported_transport = true;
803fb7
+                        supported_parent = true;
803fb7
+                } else if (streq(subsys, "ap")) {
803fb7
+                        parent = handle_ap(parent, &path);
803fb7
+                        supported_transport = true;
803fb7
+                        supported_parent = true;
803fb7
+                } else if (streq(subsys, "iucv")) {
803fb7
+                        path_prepend(&path, "iucv-%s", udev_device_get_sysname(parent));
803fb7
+                        parent = skip_subsystem(parent, "iucv");
803fb7
+                        supported_transport = true;
803fb7
+                        supported_parent = true;
803fb7
                 }
803fb7
 
803fb7
                 parent = udev_device_get_parent(parent);
803fb7
@@ -743,7 +751,6 @@ restart:
803fb7
                 path = NULL;
803fb7
         }
803fb7
 
803fb7
-out:
803fb7
         if (path != NULL) {
803fb7
                 char tag[UTIL_NAME_SIZE];
803fb7
                 size_t i;