Skip to content
Permalink
Browse files

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.

Signed-off-by: Ryan Moeller <ryan@ixsystems.com>
  • Loading branch information...
freqlabs committed Nov 8, 2019
1 parent 734de7c commit 98af872661fd72d99ff0e565ab9b9024c29cdda4
Showing with 85 additions and 77 deletions.
  1. +1 −1 include/libzutil.h
  2. +1 −2 lib/libzfs/libzfs_pool.c
  3. +83 −74 lib/libzutil/os/linux/zutil_device_path_os.c
@@ -97,7 +97,7 @@ extern int zfs_append_partition(char *path, size_t max_len);
extern int zfs_resolve_shortname(const char *name, char *path, size_t pathlen);

extern char *zfs_strip_partition(char *);
extern char *zfs_strip_partition_path(char *);
extern char *zfs_strip_path(char *);

extern int zfs_strcmp_pathname(const char *, const char *, int);

@@ -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);
}

/*
@@ -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 @@ zfs_get_enclosure_sysfs_path(const char *dev_name)
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

/*

0 comments on commit 98af872

Please sign in to comment.
You can’t perform that action at this time.