chiark / gitweb /
udevd: SAS: use SAS addr + PHY id in by-path whenever possible.
authorMaurizio Lombardi <mlombard@redhat.com>
Mon, 22 Sep 2014 09:48:57 +0000 (11:48 +0200)
committerHarald Hoyer <harald@redhat.com>
Thu, 4 Dec 2014 12:15:58 +0000 (13:15 +0100)
This patch changes the naming scheme for sas disks. The original names used
disk's sas address and lun, the new scheme uses sas address of the
nearest expander (if available) and a phy id of the used connection.
If no expander is used, the phy id of hba phy is used.
Note that names that refer to RAID or other abstract devices are
unchanged.

Name in raid configuration:
hba_pci_address-sas-raid_sas_address-lunY-partZ

Name in expander bare disk configuration:
hba_pci_address-sas-expander_sas_address-phyX-lunY-partZ

Name format without expanders:
hba_pci_address-sas-phyX-lunY-partZ

Signed-off-by: Maurizio Lombardi <mlombard@redhat.com>
src/udev/udev-builtin-path_id.c

index df996cb17aca160fd4496b6769adf82a62f52826..d540ba8392b11debb5a8a5d49dccfe84fb71c777 100644 (file)
@@ -118,7 +118,7 @@ out:
         return parent;
 }
 
-static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **path) {
+static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent, char **path) {
         struct udev *udev  = udev_device_get_udev(parent);
         struct udev_device *targetdev;
         struct udev_device *target_parent;
@@ -154,6 +154,100 @@ out:
         return parent;
 }
 
+static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **path)
+{
+        struct udev *udev  = udev_device_get_udev(parent);
+        struct udev_device *targetdev;
+        struct udev_device *target_parent;
+        struct udev_device *port;
+        struct udev_device *expander;
+        struct udev_device *target_sasdev = NULL;
+        struct udev_device *expander_sasdev = NULL;
+        struct udev_device *port_sasdev = NULL;
+        const char *sas_address = NULL;
+        const char *phy_id;
+        const char *phy_count;
+        char *lun = NULL;
+
+        targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target");
+        if (targetdev == NULL)
+                return NULL;
+
+        target_parent = udev_device_get_parent(targetdev);
+        if (target_parent == NULL)
+                return NULL;
+
+        /* Get sas device */
+        target_sasdev = udev_device_new_from_subsystem_sysname(udev,
+                          "sas_device", udev_device_get_sysname(target_parent));
+        if (target_sasdev == NULL)
+                return NULL;
+
+        /* The next parent is sas port */
+        port = udev_device_get_parent(target_parent);
+        if (port == NULL) {
+                parent = NULL;
+                goto out;
+        }
+
+        /* Get port device */
+        port_sasdev = udev_device_new_from_subsystem_sysname(udev,
+                          "sas_port", udev_device_get_sysname(port));
+
+        phy_count = udev_device_get_sysattr_value(port_sasdev, "num_phys");
+        if (phy_count == NULL) {
+               parent = NULL;
+               goto out;
+        }
+
+        /* Check if we are simple disk */
+        if (strncmp(phy_count, "1", 2) != 0) {
+                 parent = handle_scsi_sas_wide_port(parent, path);
+                 goto out;
+        }
+
+        /* Get connected phy */
+        phy_id = udev_device_get_sysattr_value(target_sasdev, "phy_identifier");
+        if (phy_id == NULL) {
+                parent = NULL;
+                goto out;
+        }
+
+        /* The port's parent is either hba or expander */
+        expander = udev_device_get_parent(port);
+        if (expander == NULL) {
+                parent = NULL;
+                goto out;
+        }
+
+        /* Get expander device */
+        expander_sasdev = udev_device_new_from_subsystem_sysname(udev,
+                          "sas_device", udev_device_get_sysname(expander));
+        if (expander_sasdev != NULL) {
+                 /* Get expander's address */
+                 sas_address = udev_device_get_sysattr_value(expander_sasdev,
+                                                    "sas_address");
+                 if (sas_address == NULL) {
+                        parent = NULL;
+                        goto out;
+                 }
+        }
+
+        format_lun_number(parent, &lun);
+        if (sas_address)
+                 path_prepend(path, "sas-exp%s-phy%s-%s", sas_address, phy_id, lun);
+        else
+                 path_prepend(path, "sas-phy%s-%s", phy_id, lun);
+
+        if (lun)
+                free(lun);
+out:
+        udev_device_unref(target_sasdev);
+        udev_device_unref(expander_sasdev);
+        udev_device_unref(port_sasdev);
+        return parent;
+}
+
 static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **path) {
         struct udev *udev  = udev_device_get_udev(parent);
         struct udev_device *transportdev;