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