From a2c6816c34952eb6dad51248d31172189fba9126 Mon Sep 17 00:00:00 2001 From: Ned Bass Date: Wed, 13 Oct 2010 17:27:41 -0700 Subject: [PATCH] Support shorthand names with zpool remove zpool status displays abbreviated vdev names without leading path components and, in the case of whole disks, without partition information. Also, the zpool subcommands 'create' and 'add' support using shorthand devices names without qualified paths. Prior to this change, however, removing a device generally required specifying its name as it is stored in the vdev label. So while zpool status might list a cache disk with a name like A16, removing it would require a full path such as /dev/disk/zpool/A16-part1, which is non-intuitive. This change adds support for shorthand device names with the remove subcommand so one can simply type, for example, zpool remove tank A16 A consequence of this change is that including the partition information when removing a whole-disk vdev now results in an error. While this is arguably the correct behavior, it is a departure from how zpool previously worked in this project. This change removes the only reference to ctd_check_path(), so that function is also removed to avoid compiler warnings. Signed-off-by: Brian Behlendorf --- lib/libzfs/libzfs_pool.c | 76 +++++++--------------------------------- 1 file changed, 12 insertions(+), 64 deletions(-) diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index 607e2e865fd3..9a0e41af074f 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -1644,38 +1644,6 @@ zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func) } } -/* - * This provides a very minimal check whether a given string is likely a - * c#t#d# style string. Users of this are expected to do their own - * verification of the s# part. - */ -#define CTD_CHECK(str) (str && str[0] == 'c' && isdigit(str[1])) - -/* - * More elaborate version for ones which may start with "/dev/dsk/" - * and the like. - */ -static int -ctd_check_path(char *str) { - /* - * If it starts with a slash, check the last component. - */ - if (str && str[0] == '/') { - char *tmp = strrchr(str, '/'); - - /* - * If it ends in "/old", check the second-to-last - * component of the string instead. - */ - if (tmp != str && strcmp(tmp, "/old") == 0) { - for (tmp--; *tmp != '/'; tmp--) - ; - } - str = tmp + 1; - } - return (CTD_CHECK(str)); -} - /* * Find a vdev that matches the search criteria specified. We use the * the nvpair name to determine how we should look for the device. @@ -1723,47 +1691,24 @@ vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare, /* * Search for the requested value. Special cases: * - * - ZPOOL_CONFIG_PATH for whole disk entries. These end in - * "s0" or "s0/old". The "s0" part is hidden from the user, - * but included in the string, so this matches around it. + * - ZPOOL_CONFIG_PATH for whole disk entries. These end in with a + * partition suffix "1", "-part1", or "p1". The suffix is hidden + * from the user, but included in the string, so this matches around + * it. * - looking for a top-level vdev name (i.e. ZPOOL_CONFIG_TYPE). * * Otherwise, all other searches are simple string compares. */ - if (strcmp(srchkey, ZPOOL_CONFIG_PATH) == 0 && - ctd_check_path(val)) { + if (strcmp(srchkey, ZPOOL_CONFIG_PATH) == 0) { uint64_t wholedisk = 0; (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk); if (wholedisk) { - int slen = strlen(srchval); - int vlen = strlen(val); + char buf[MAXPATHLEN]; - if (slen != vlen - 2) - break; - - /* - * make_leaf_vdev() should only set - * wholedisk for ZPOOL_CONFIG_PATHs which - * will include "/dev/dsk/", giving plenty of - * room for the indices used next. - */ - ASSERT(vlen >= 6); - - /* - * strings identical except trailing "s0" - */ - if (strcmp(&val[vlen - 2], "s0") == 0 && - strncmp(srchval, val, slen) == 0) - return (nv); - - /* - * strings identical except trailing "s0/old" - */ - if (strcmp(&val[vlen - 6], "s0/old") == 0 && - strcmp(&srchval[slen - 4], "/old") == 0 && - strncmp(srchval, val, slen - 4) == 0) + zfs_append_partition(srchval, buf, sizeof (buf)); + if (strcmp(val, buf) == 0) return (nv); break; @@ -1931,7 +1876,10 @@ zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare, } else if (zpool_vdev_is_interior(path)) { verify(nvlist_add_string(search, ZPOOL_CONFIG_TYPE, path) == 0); } else if (path[0] != '/') { - (void) snprintf(buf, sizeof (buf), "%s/%s", DISK_ROOT, path); + if (zfs_resolve_shortname(path, buf, sizeof (buf)) < 0) { + nvlist_free(search); + return (NULL); + } verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, buf) == 0); } else { verify(nvlist_add_string(search, ZPOOL_CONFIG_PATH, path) == 0);