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