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 <behlendorf1@llnl.gov>
This commit is contained in:
Ned Bass 2010-10-13 17:27:41 -07:00 committed by Brian Behlendorf
parent 79e7242a91
commit a2c6816c34
1 changed files with 12 additions and 64 deletions

View File

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