diff options
Diffstat (limited to 'src/udev/udev-builtin-path_id.c')
-rw-r--r-- | src/udev/udev-builtin-path_id.c | 158 |
1 files changed, 96 insertions, 62 deletions
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c index 4ca0a69d7d..1825ee75a7 100644 --- a/src/udev/udev-builtin-path_id.c +++ b/src/udev/udev-builtin-path_id.c @@ -19,17 +19,19 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <unistd.h> -#include <string.h> #include <ctype.h> -#include <fcntl.h> -#include <errno.h> #include <dirent.h> +#include <errno.h> +#include <fcntl.h> #include <getopt.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "alloc-util.h" +#include "string-util.h" #include "udev.h" _printf_(2,3) @@ -117,8 +119,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 +157,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 +251,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 +312,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 +517,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; } @@ -573,31 +593,23 @@ static struct udev_device *handle_bcma(struct udev_device *parent, char **path) return parent; } -static struct udev_device *handle_ccw(struct udev_device *parent, struct udev_device *dev, char **path) { - struct udev_device *scsi_dev; +/* Handle devices of AP bus in System z platform. */ +static struct udev_device *handle_ap(struct udev_device *parent, char **path) { + const char *type, *func; assert(parent); - assert(dev); assert(path); - scsi_dev = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device"); - if (scsi_dev != NULL) { - const char *wwpn; - const char *lun; - const char *hba_id; - - hba_id = udev_device_get_sysattr_value(scsi_dev, "hba_id"); - wwpn = udev_device_get_sysattr_value(scsi_dev, "wwpn"); - lun = udev_device_get_sysattr_value(scsi_dev, "fcp_lun"); - if (hba_id != NULL && lun != NULL && wwpn != NULL) { - path_prepend(path, "ccw-%s-zfcp-%s:%s", hba_id, wwpn, lun); - goto out; - } - } + type = udev_device_get_sysattr_value(parent, "type"); + func = udev_device_get_sysattr_value(parent, "ap_functions"); - path_prepend(path, "ccw-%s", udev_device_get_sysname(parent)); + if (type != NULL && func != NULL) { + path_prepend(path, "ap-%s-%s", type, func); + goto out; + } + path_prepend(path, "ap-%s", udev_device_get_sysname(parent)); out: - parent = skip_subsystem(parent, "ccw"); + parent = skip_subsystem(parent, "ap"); return parent; } @@ -609,13 +621,6 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool assert(dev); - /* S390 ccw bus */ - parent = udev_device_get_parent_with_subsystem_devtype(dev, "ccw", NULL); - if (parent != NULL) { - handle_ccw(parent, dev, &path); - goto out; - } - /* walk up the chain of devices and compose path */ parent = dev; while (parent != NULL) { @@ -658,11 +663,45 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool path_prepend(&path, "xen-%s", udev_device_get_sysname(parent)); parent = skip_subsystem(parent, "xen"); supported_parent = true; + } else if (streq(subsys, "virtio")) { + while (parent && streq_ptr("virtio", udev_device_get_subsystem(parent))) + parent = udev_device_get_parent(parent); + path_prepend(&path, "virtio-pci-%s", udev_device_get_sysname(parent)); + supported_transport = true; + supported_parent = true; } else if (streq(subsys, "scm")) { path_prepend(&path, "scm-%s", udev_device_get_sysname(parent)); parent = skip_subsystem(parent, "scm"); supported_transport = true; supported_parent = true; + } else if (streq(subsys, "ccw")) { + path_prepend(&path, "ccw-%s", udev_device_get_sysname(parent)); + parent = skip_subsystem(parent, "ccw"); + supported_transport = true; + supported_parent = true; + } else if (streq(subsys, "ccwgroup")) { + path_prepend(&path, "ccwgroup-%s", udev_device_get_sysname(parent)); + parent = skip_subsystem(parent, "ccwgroup"); + supported_transport = true; + supported_parent = true; + } else if (streq(subsys, "ap")) { + parent = handle_ap(parent, &path); + supported_transport = true; + supported_parent = true; + } else if (streq(subsys, "iucv")) { + path_prepend(&path, "iucv-%s", udev_device_get_sysname(parent)); + parent = skip_subsystem(parent, "iucv"); + supported_transport = true; + supported_parent = true; + } else if (streq(subsys, "nvme")) { + const char *nsid = udev_device_get_sysattr_value(dev, "nsid"); + + if (nsid) { + path_prepend(&path, "nvme-%s", nsid); + parent = skip_subsystem(parent, "nvme"); + supported_parent = true; + supported_transport = true; + } } if (parent) @@ -674,22 +713,17 @@ 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_ptr(udev_device_get_subsystem(dev), "block") && !supported_transport) + path = mfree(path); -out: if (path != NULL) { char tag[UTIL_NAME_SIZE]; size_t i; |