X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=extras%2Fpath_id%2Fpath_id.c;h=683f78d26e2d1374f5c95fde3afc1e19ca493240;hb=693b6344e193f5aeca21df5f1c98fd32148006ac;hp=4b57dec0d31caf3ba7b4f560e5fc2eca582137f8;hpb=9060b066d9e7aaca9795010ac5fff61018947f87;p=elogind.git diff --git a/extras/path_id/path_id.c b/extras/path_id/path_id.c index 4b57dec0d..683f78d26 100644 --- a/extras/path_id/path_id.c +++ b/extras/path_id/path_id.c @@ -1,8 +1,10 @@ /* - * compose persisistent device path + * compose persistent device path * * Copyright (C) 2009 Kay Sievers * + * Logic based on Hannes Reinecke's shell script. + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or @@ -31,7 +33,7 @@ #include "libudev.h" #include "libudev-private.h" -int debug; +static int debug; static void log_fn(struct udev *udev, int priority, const char *file, int line, const char *fn, @@ -73,6 +75,21 @@ static int path_prepend(char **path, const char *fmt, ...) return 0; } +/* +** Linux only supports 32 bit luns. +** See drivers/scsi/scsi_scan.c::scsilun_to_int() for more details. +*/ +static int format_lun_number(struct udev_device *dev, char **path) +{ + unsigned long lun = strtoul(udev_device_get_sysnum(dev), NULL, 10); + + /* address method 0, peripheral device addressing with bus id of zero */ + if (lun < 256) + return path_prepend(path, "lun-%d", lun); + /* handle all other lun addressing methods by using a variant of the original lun format */ + return path_prepend(path, "lun-0x%04x%04x00000000", (lun & 0xffff), (lun >> 16) & 0xffff); +} + static struct udev_device *skip_subsystem(struct udev_device *dev, const char *subsys) { struct udev_device *parent = dev; @@ -95,7 +112,7 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, struct udev_device *targetdev; struct udev_device *fcdev = NULL; const char *port; - unsigned int lun; + char *lun = NULL;; targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); if (targetdev == NULL) @@ -110,8 +127,10 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, goto out; } - lun = strtoul(udev_device_get_sysnum(parent), NULL, 10); - path_prepend(path, "fc-%s:0x%04x%04x00000000", port, lun & 0xffff, (lun >> 16) & 0xffff); + format_lun_number(parent, &lun); + path_prepend(path, "fc-%s-%s", port, lun); + if (lun) + free(lun); out: udev_device_unref(fcdev); return parent; @@ -119,7 +138,39 @@ out: static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **path) { - return NULL; + struct udev *udev = udev_device_get_udev(parent); + struct udev_device *targetdev; + struct udev_device *target_parent; + struct udev_device *sasdev; + const char *sas_address; + 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; + + sasdev = udev_device_new_from_subsystem_sysname(udev, "sas_device", + udev_device_get_sysname(target_parent)); + if (sasdev == NULL) + return NULL; + + sas_address = udev_device_get_sysattr_value(sasdev, "sas_address"); + if (sas_address == NULL) { + parent = NULL; + goto out; + } + + format_lun_number(parent, &lun); + path_prepend(path, "sas-%s-%s", sas_address, lun); + if (lun) + free(lun); +out: + udev_device_unref(sasdev); + return parent; } static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **path) @@ -132,18 +183,17 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char ** struct udev_device *conndev = NULL; const char *addr; const char *port; + char *lun = NULL; /* find iscsi session */ transportdev = parent; - while (1) { + for (;;) { transportdev = udev_device_get_parent(transportdev); if (transportdev == NULL) return NULL; if (strncmp(udev_device_get_sysname(transportdev), "session", 7) == 0) break; } - if (transportdev == NULL) - return NULL; /* find iscsi session device */ sessiondev = udev_device_new_from_subsystem_sysname(udev, "iscsi_session", udev_device_get_sysname(transportdev)); @@ -172,7 +222,10 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char ** goto out; } - path_prepend(path, "ip-%s:%s-iscsi-%s-lun-%s", addr, port, target, udev_device_get_sysnum(parent)); + format_lun_number(parent, &lun); + path_prepend(path, "ip-%s:%s-iscsi-%s-%s", addr, port, target, lun); + if (lun) + free(lun); out: udev_device_unref(sessiondev); udev_device_unref(conndev); @@ -302,7 +355,9 @@ static struct udev_device *handle_usb(struct udev_device *parent, char **path) const char *port; devtype = udev_device_get_devtype(parent); - if (devtype == NULL || strcmp(devtype, "usb_interface") != 0) + if (devtype == NULL) + return parent; + if (strcmp(devtype, "usb_interface") != 0 && strcmp(devtype, "usb_device") != 0) return parent; str = udev_device_get_sysname(parent); @@ -386,8 +441,6 @@ int main(int argc, char **argv) printf("Usage: path_id [--debug] [--help] \n" " --debug print debug information\n" " --help print this help text\n\n"); - default: - rc = 1; goto exit; } } @@ -446,6 +499,9 @@ int main(int argc, char **argv) } else if (strcmp(subsys, "xen") == 0) { path_prepend(&path, "xen-%s", udev_device_get_sysname(parent)); parent = skip_subsystem(parent, "xen"); + } else if (strcmp(subsys, "virtio") == 0) { + path_prepend(&path, "virtio-pci-%s", udev_device_get_sysname(parent)); + parent = skip_subsystem(parent, "virtio"); } parent = udev_device_get_parent(parent);