diff options
author | Don Brady <[email protected]> | 2016-03-14 10:04:21 -0600 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2016-03-31 13:45:53 -0700 |
commit | 39fc0cb5577e409f415e25d35a452b46996c08b1 (patch) | |
tree | 400e9790da6d1d470ffb65b63758320c37875eb0 /tests/zfs-tests/cmd | |
parent | bebd73f2c3822a86863e7508e7a3e2929d871113 (diff) |
Add support for devid and phys_path keys in vdev disk labels
This is foundational work for ZED.
Updates a leaf vdev's persistent device strings on Linux platform
* only applies for a dedicated leaf vdev (aka whole disk)
* updated during pool create|add|attach|import
* used for matching device matching during auto-{online,expand,replace}
* stored in a leaf disk config label (i.e. alongside 'path' NVP)
* can opt-out using env var ZFS_VDEV_DEVID_OPT_OUT=YES
Some examples:
path: '/dev/sdb1'
devid: 'scsi-350000394a8ca4fbc-part1'
phys_path: 'pci-0000:04:00.0-sas-0x50000394a8ca4fbf-lun-0'
path: '/dev/mapper/mpatha'
devid: 'dm-uuid-mpath-35000c5006304de3f'
Signed-off-by: Don Brady <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #2856
Closes #3978
Closes #4416
Diffstat (limited to 'tests/zfs-tests/cmd')
-rw-r--r-- | tests/zfs-tests/cmd/devname2devid/Makefile.am | 8 | ||||
-rw-r--r-- | tests/zfs-tests/cmd/devname2devid/devname2devid.c | 141 |
2 files changed, 94 insertions, 55 deletions
diff --git a/tests/zfs-tests/cmd/devname2devid/Makefile.am b/tests/zfs-tests/cmd/devname2devid/Makefile.am index 2eb03e9cf..55811b7a7 100644 --- a/tests/zfs-tests/cmd/devname2devid/Makefile.am +++ b/tests/zfs-tests/cmd/devname2devid/Makefile.am @@ -1,7 +1,7 @@ include $(top_srcdir)/config/Rules.am -pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/bin +pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/bin -# DISABLED: Not supported under Linux -# pkgdata_PROGRAMS = devname2devid -# devname2devid_SOURCES = devname2devid.c +pkgexec_PROGRAMS = devname2devid +devname2devid_SOURCES = devname2devid.c +devname2devid_LDADD = -ludev diff --git a/tests/zfs-tests/cmd/devname2devid/devname2devid.c b/tests/zfs-tests/cmd/devname2devid/devname2devid.c index fd3287491..59fbcdddb 100644 --- a/tests/zfs-tests/cmd/devname2devid/devname2devid.c +++ b/tests/zfs-tests/cmd/devname2devid/devname2devid.c @@ -22,27 +22,85 @@ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2016, Intel Corporation. */ #include <sys/types.h> +#include <sys/param.h> #include <sys/stat.h> -#include <devid.h> +#include <libudev.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <fcntl.h> /* + * Linux persistent device strings for vdev labels + * + * based on udev_device_get_devid() at zfs/lib/libzfs/libzfs_import.c + */ + +#define DEV_BYID_PATH "/dev/disk/by-id/" + +static int +udev_device_get_devid(struct udev_device *dev, char *bufptr, size_t buflen) +{ + struct udev_list_entry *entry; + const char *bus; + char devbyid[MAXPATHLEN]; + + /* The bus based by-id path is preferred */ + bus = udev_device_get_property_value(dev, "ID_BUS"); + + if (bus == NULL) { + const char *dm_uuid; + + /* + * For multipath nodes use the persistent uuid based identifier + * + * Example: 'dm-uuid-mpath-35000c5006304de3f' + */ + dm_uuid = udev_device_get_property_value(dev, "DM_UUID"); + if (dm_uuid != NULL) { + (void) snprintf(bufptr, buflen, "dm-uuid-%s", dm_uuid); + return (0); + } + return (ENODATA); + } + + /* + * locate the bus specific by-id link + * + * Example: 'scsi-MG03SCA300_350000494a8cb3d67-part1' + */ + (void) snprintf(devbyid, sizeof (devbyid), "%s%s-", DEV_BYID_PATH, bus); + entry = udev_device_get_devlinks_list_entry(dev); + while (entry != NULL) { + const char *name; + + name = udev_list_entry_get_name(entry); + if (strncmp(name, devbyid, strlen(devbyid)) == 0) { + name += strlen(DEV_BYID_PATH); + (void) stpncpy(bufptr, name, buflen); + return (0); + } + entry = udev_list_entry_get_next(entry); + } + + return (ENODATA); +} + +/* * Usage: devname2devid <devicepath> * * Examples: - * # ./devname2devid /dev/dsk/c1t4d0s0 - * devid id1,sd@SSEAGATE_ST318404LSUN18G_3BT2G0Z300002146G4CR/a - * # ./devname2devid /dev/dsk/c1t4d0 - * devid id1,sd@SSEAGATE_ST318404LSUN18G_3BT2G0Z300002146G4CR/wd - * # ./devname2devid /dev/dsk/c1t4d0s1 - * devid id1,sd@SSEAGATE_ST318404LSUN18G_3BT2G0Z300002146G4CR/b - * # + * # ./devname2devid /dev/sda1 + * devid scsi-350000394a8caede4-part1 + * + * # ./devname2devid /dev/dm-1 + * devid: 'dm-uuid-mpath-35000c5006304de3f' * * This program accepts a disk or disk slice path and prints a * device id. @@ -55,66 +113,47 @@ int main(int argc, char *argv[]) { - int fd; - ddi_devid_t devid; - char *minor_name, *devidstr, *device; -#ifdef DEBUG - devid_nmlist_t *list = NULL; - char *search_path; - int i; -#endif + struct udev *udev; + struct udev_device *dev = NULL; + char devid[128], nodepath[MAXPATHLEN]; + char *device, *sysname; + int ret; if (argc == 1) { - (void) printf("%s <devicepath> [search path]\n", - argv[0]); + (void) printf("%s <devicepath> [search path]\n", argv[0]); exit(1); } device = argv[1]; - if ((fd = open(device, O_RDONLY|O_NDELAY)) < 0) { - perror(device); - exit(1); - } - if (devid_get(fd, &devid) != 0) { - perror("devid_get"); - exit(1); - } - if (devid_get_minor_name(fd, &minor_name) != 0) { - perror("devid_get_minor_name"); - exit(1); - } - if ((devidstr = devid_str_encode(devid, minor_name)) == 0) { - perror("devid_str_encode"); + if ((udev = udev_new()) == NULL) { + perror("udev_new"); exit(1); } - (void) printf("devid %s\n", devidstr); - - devid_str_free(devidstr); - -#ifdef DEBUG - if (argc == 3) { - search_path = argv[2]; - } else { - search_path = "/dev/rdsk"; + /* resolve path to a runtime device node instance */ + if (realpath(device, nodepath) == NULL) { + perror("realpath"); + exit(1); } + sysname = strrchr(nodepath, '/') + 1; - if (devid_deviceid_to_nmlist(search_path, devid, DEVID_MINOR_NAME_ALL, - &list)) { - perror("devid_deviceid_to_nmlist"); + if ((dev = udev_device_new_from_subsystem_sysname(udev, "block", + sysname)) == NULL) { + perror(sysname); exit(1); } - /* loop through list and process device names and numbers */ - for (i = 0; list[i].devname != NULL; i++) { - (void) printf("devname: %s %p\n", list[i].devname, list[i].dev); + if ((ret = udev_device_get_devid(dev, devid, sizeof (devid))) != 0) { + udev_device_unref(dev); + errno = ret; + perror(sysname); + exit(1); } - devid_free_nmlist(list); -#endif /* DEBUG */ + (void) printf("devid %s\n", devid); - devid_str_free(minor_name); - devid_free(devid); + udev_device_unref(dev); + udev_unref(udev); return (0); } |