X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fudev%2Fudev-builtin-path_id.c;fp=src%2Fudev%2Fudev-builtin-path_id.c;h=d540ba8392b11debb5a8a5d49dccfe84fb71c777;hp=df996cb17aca160fd4496b6769adf82a62f52826;hb=66bba0e701b95dc42ed53e8f0799a7e2b944c147;hpb=00e8d83a5a6fce20443b53bc42066bc756d5caeb diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c index df996cb17..d540ba839 100644 --- a/src/udev/udev-builtin-path_id.c +++ b/src/udev/udev-builtin-path_id.c @@ -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;