From 035ebb365383dcca71c4c542093ea1ad2b8e1dea Mon Sep 17 00:00:00 2001 From: Ryan Moeller Date: Mon, 11 Nov 2019 15:15:44 -0500 Subject: Allow platform dependent path stripping for vdevs On Linux the full path preceding devices is stripped when formatting vdev names. On FreeBSD we only want to strip "/dev/". Hide the implementation details of path stripping behind zfs_strip_path(). Make zfs_strip_partition_path() static in Linux implementation while here, since it is never used outside of the file it is defined in. Reviewed-by: Brian Behlendorf Signed-off-by: Ryan Moeller Closes #9565 --- lib/libzfs/libzfs_pool.c | 3 +- lib/libzutil/os/linux/zutil_device_path_os.c | 157 ++++++++++++++------------- 2 files changed, 84 insertions(+), 76 deletions(-) (limited to 'lib') diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index 380229da5..1a97c1666 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -3911,8 +3911,7 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv, */ if ((strcmp(type, VDEV_TYPE_DISK) == 0) && !(name_flags & VDEV_NAME_PATH)) { - path = strrchr(path, '/'); - path++; + path = zfs_strip_path(path); } /* diff --git a/lib/libzutil/os/linux/zutil_device_path_os.c b/lib/libzutil/os/linux/zutil_device_path_os.c index 8ca4f8570..3fff8c358 100644 --- a/lib/libzutil/os/linux/zutil_device_path_os.c +++ b/lib/libzutil/os/linux/zutil_device_path_os.c @@ -71,6 +71,89 @@ zfs_append_partition(char *path, size_t max_len) return (len); } +/* + * Remove partition suffix from a vdev path. Partition suffixes may take three + * forms: "-partX", "pX", or "X", where X is a string of digits. The second + * case only occurs when the suffix is preceded by a digit, i.e. "md0p0" The + * third case only occurs when preceded by a string matching the regular + * expression "^([hsv]|xv)d[a-z]+", i.e. a scsi, ide, virtio or xen disk. + * + * caller must free the returned string + */ +char * +zfs_strip_partition(char *path) +{ + char *tmp = strdup(path); + char *part = NULL, *d = NULL; + if (!tmp) + return (NULL); + + if ((part = strstr(tmp, "-part")) && part != tmp) { + d = part + 5; + } else if ((part = strrchr(tmp, 'p')) && + part > tmp + 1 && isdigit(*(part-1))) { + d = part + 1; + } else if ((tmp[0] == 'h' || tmp[0] == 's' || tmp[0] == 'v') && + tmp[1] == 'd') { + for (d = &tmp[2]; isalpha(*d); part = ++d) { } + } else if (strncmp("xvd", tmp, 3) == 0) { + for (d = &tmp[3]; isalpha(*d); part = ++d) { } + } + if (part && d && *d != '\0') { + for (; isdigit(*d); d++) { } + if (*d == '\0') + *part = '\0'; + } + + return (tmp); +} + +/* + * Same as zfs_strip_partition, but allows "/dev/" to be in the pathname + * + * path: /dev/sda1 + * returns: /dev/sda + * + * Returned string must be freed. + */ +static char * +zfs_strip_partition_path(char *path) +{ + char *newpath = strdup(path); + char *sd_offset; + char *new_sd; + + if (!newpath) + return (NULL); + + /* Point to "sda1" part of "/dev/sda1" */ + sd_offset = strrchr(newpath, '/') + 1; + + /* Get our new name "sda" */ + new_sd = zfs_strip_partition(sd_offset); + if (!new_sd) { + free(newpath); + return (NULL); + } + + /* Paste the "sda" where "sda1" was */ + strlcpy(sd_offset, new_sd, strlen(sd_offset) + 1); + + /* Free temporary "sda" */ + free(new_sd); + + return (newpath); +} + +/* + * Strip the unwanted portion of a device path. + */ +char * +zfs_strip_path(char *path) +{ + return (strrchr(path, '/') + 1); +} + /* * Allocate and return the underlying device name for a device mapper device. * If a device mapper device maps to multiple devices, return the first device. @@ -349,80 +432,6 @@ end: return (path); } -/* - * Remove partition suffix from a vdev path. Partition suffixes may take three - * forms: "-partX", "pX", or "X", where X is a string of digits. The second - * case only occurs when the suffix is preceded by a digit, i.e. "md0p0" The - * third case only occurs when preceded by a string matching the regular - * expression "^([hsv]|xv)d[a-z]+", i.e. a scsi, ide, virtio or xen disk. - * - * caller must free the returned string - */ -char * -zfs_strip_partition(char *path) -{ - char *tmp = strdup(path); - char *part = NULL, *d = NULL; - if (!tmp) - return (NULL); - - if ((part = strstr(tmp, "-part")) && part != tmp) { - d = part + 5; - } else if ((part = strrchr(tmp, 'p')) && - part > tmp + 1 && isdigit(*(part-1))) { - d = part + 1; - } else if ((tmp[0] == 'h' || tmp[0] == 's' || tmp[0] == 'v') && - tmp[1] == 'd') { - for (d = &tmp[2]; isalpha(*d); part = ++d) { } - } else if (strncmp("xvd", tmp, 3) == 0) { - for (d = &tmp[3]; isalpha(*d); part = ++d) { } - } - if (part && d && *d != '\0') { - for (; isdigit(*d); d++) { } - if (*d == '\0') - *part = '\0'; - } - - return (tmp); -} - -/* - * Same as zfs_strip_partition, but allows "/dev/" to be in the pathname - * - * path: /dev/sda1 - * returns: /dev/sda - * - * Returned string must be freed. - */ -char * -zfs_strip_partition_path(char *path) -{ - char *newpath = strdup(path); - char *sd_offset; - char *new_sd; - - if (!newpath) - return (NULL); - - /* Point to "sda1" part of "/dev/sda1" */ - sd_offset = strrchr(newpath, '/') + 1; - - /* Get our new name "sda" */ - new_sd = zfs_strip_partition(sd_offset); - if (!new_sd) { - free(newpath); - return (NULL); - } - - /* Paste the "sda" where "sda1" was */ - strlcpy(sd_offset, new_sd, strlen(sd_offset) + 1); - - /* Free temporary "sda" */ - free(new_sd); - - return (newpath); -} - #ifdef HAVE_LIBUDEV /* -- cgit v1.2.3