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