923a60
From 569d98e9caae425120bf28f6b440e6cc117abc0d Mon Sep 17 00:00:00 2001
923a60
From: Maurizio Lombardi <mlombard@redhat.com>
923a60
Date: Mon, 1 Feb 2016 14:44:22 +0100
923a60
Subject: [PATCH] udev: fibre channel: fix NPIV support
923a60
923a60
When using NPIV, you can create multiple virtual HBAs on top of the
923a60
physical one, this means that the physical N_Port can have multiple
923a60
port IDs associated to it.
923a60
Suppose a LUN is assigned to the physical HBA and to a virtual HBA,
923a60
in both cases the original code uses the ID of the physical HBA
923a60
to build the by-path link and udev will end up trying to create two by-path
923a60
links with the same name.
923a60
923a60
This patch fixes the problem by using the port ID of the virtual HBA
923a60
whenever it detects that the device belongs to a virtual HBA,
923a60
otherwise it uses the port ID of the physical HBA.
923a60
923a60
(cherry-picked from 155a760bcedd11b7f3b430350a46f10736286895)
923a60
923a60
Resolves: #1266934
923a60
---
923a60
 src/udev/udev-builtin-path_id.c | 27 ++++++++++++++++++++++++---
923a60
 1 file changed, 24 insertions(+), 3 deletions(-)
923a60
923a60
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
923a60
index 9ca608468c..695ac7fc1f 100644
923a60
--- a/src/udev/udev-builtin-path_id.c
923a60
+++ b/src/udev/udev-builtin-path_id.c
923a60
@@ -92,6 +92,9 @@ static struct udev_device *skip_subsystem(struct udev_device *dev, const char *s
923a60
 static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, char **path) {
923a60
         struct udev *udev  = udev_device_get_udev(parent);
923a60
         struct udev_device *targetdev;
923a60
+        struct udev_device *rportdev;
923a60
+        struct udev_device *hostdev;
923a60
+        struct udev_device *vportdev;
923a60
         struct udev_device *fcdev = NULL;
923a60
         const char *port;
923a60
         char *lun = NULL;
923a60
@@ -100,9 +103,27 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent,
923a60
         if (targetdev == NULL)
923a60
                 return NULL;
923a60
 
923a60
-        fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev));
923a60
-        if (fcdev == NULL)
923a60
-                return NULL;
923a60
+        rportdev = udev_device_get_parent(targetdev);
923a60
+        if (rportdev == NULL)
923a60
+                goto skip_npiv_check;
923a60
+
923a60
+        hostdev = udev_device_get_parent(rportdev);
923a60
+        if (hostdev == NULL)
923a60
+                goto skip_npiv_check;
923a60
+
923a60
+        vportdev = udev_device_get_parent(hostdev);
923a60
+        if (vportdev == NULL)
923a60
+                goto skip_npiv_check;
923a60
+
923a60
+        fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_vports", udev_device_get_sysname(vportdev));
923a60
+
923a60
+skip_npiv_check:
923a60
+        if (fcdev == NULL) {
923a60
+                fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev));
923a60
+                if (fcdev == NULL)
923a60
+                        return NULL;
923a60
+        }
923a60
+
923a60
         port = udev_device_get_sysattr_value(fcdev, "port_name");
923a60
         if (port == NULL) {
923a60
                 parent = NULL;