diff options
Diffstat (limited to 'src/udev/udev-builtin-path_id.c')
-rw-r--r-- | src/udev/udev-builtin-path_id.c | 70 |
1 files changed, 42 insertions, 28 deletions
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c index 4ca0a69d7d..01e2c659ae 100644 --- a/src/udev/udev-builtin-path_id.c +++ b/src/udev/udev-builtin-path_id.c @@ -117,8 +117,7 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, format_lun_number(parent, &lun); path_prepend(path, "fc-%s-%s", port, lun); - if (lun) - free(lun); + free(lun); out: udev_device_unref(fcdev); return parent; @@ -156,8 +155,7 @@ static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent, format_lun_number(parent, &lun); path_prepend(path, "sas-%s-%s", sas_address, lun); - if (lun) - free(lun); + free(lun); out: udev_device_unref(sasdev); return parent; @@ -251,8 +249,7 @@ static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **pa else path_prepend(path, "sas-phy%s-%s", phy_id, lun); - if (lun) - free(lun); + free(lun); out: udev_device_unref(target_sasdev); udev_device_unref(expander_sasdev); @@ -313,14 +310,46 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char ** format_lun_number(parent, &lun); path_prepend(path, "ip-%s:%s-iscsi-%s-%s", addr, port, target, lun); - if (lun) - free(lun); + free(lun); out: udev_device_unref(sessiondev); udev_device_unref(conndev); return parent; } +static struct udev_device *handle_scsi_ata(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 *atadev; + const char *port_no; + + assert(parent); + assert(path); + + targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host"); + if (!targetdev) + return NULL; + + target_parent = udev_device_get_parent(targetdev); + if (!target_parent) + return NULL; + + atadev = udev_device_new_from_subsystem_sysname(udev, "ata_port", udev_device_get_sysname(target_parent)); + if (!atadev) + return NULL; + + port_no = udev_device_get_sysattr_value(atadev, "port_no"); + if (!port_no) { + parent = NULL; + goto out; + } + path_prepend(path, "ata-%s", port_no); +out: + udev_device_unref(atadev); + return parent; +} + static struct udev_device *handle_scsi_default(struct udev_device *parent, char **path) { struct udev_device *hostdev; int host, bus, target, lun; @@ -486,19 +515,8 @@ static struct udev_device *handle_scsi(struct udev_device *parent, char **path, goto out; } - /* - * We do not support the ATA transport class, it uses global counters - * to name the ata devices which numbers spread across multiple - * controllers. - * - * The real link numbers are not exported. Also, possible chains of ports - * behind port multipliers cannot be composed that way. - * - * Until all that is solved at the kernel level, there are no by-path/ - * links for ATA devices. - */ if (strstr(name, "/ata") != NULL) { - parent = NULL; + parent = handle_scsi_ata(parent, path); goto out; } @@ -674,20 +692,16 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool * might produce conflicting IDs if the parent does not provide a * unique and predictable name. */ - if (!supported_parent) { - free(path); - path = NULL; - } + if (!supported_parent) + path = mfree(path); /* * Do not return block devices without a well-known transport. Some * devices do not expose their buses and do not provide a unique * and predictable name that way. */ - if (streq(udev_device_get_subsystem(dev), "block") && !supported_transport) { - free(path); - path = NULL; - } + if (streq(udev_device_get_subsystem(dev), "block") && !supported_transport) + path = mfree(path); out: if (path != NULL) { |