summaryrefslogtreecommitdiff
path: root/src/udev/udev-builtin-path_id.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/udev/udev-builtin-path_id.c')
-rw-r--r--src/udev/udev-builtin-path_id.c70
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) {