Skip to content

Commit

Permalink
Allow platform dependent path stripping for vdevs
Browse files Browse the repository at this point in the history
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 <behlendorf1@llnl.gov>
Signed-off-by: Ryan Moeller <ryan@ixsystems.com>
Closes #9565
  • Loading branch information
Ryan Moeller authored and behlendorf committed Nov 11, 2019
1 parent 5a6ac4c commit 035ebb3
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 77 deletions.
2 changes: 1 addition & 1 deletion include/libzutil.h
Expand Up @@ -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);

Expand Down
3 changes: 1 addition & 2 deletions lib/libzfs/libzfs_pool.c
Expand Up @@ -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);
}

/*
Expand Down
157 changes: 83 additions & 74 deletions lib/libzutil/os/linux/zutil_device_path_os.c
Expand Up @@ -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.
Expand Down Expand Up @@ -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

/*
Expand Down

0 comments on commit 035ebb3

Please sign in to comment.