From b85f47efd094dc9ebe210c364e235c6ef99f8417 Mon Sep 17 00:00:00 2001 From: Matthew Ahrens Date: Fri, 26 Mar 2021 11:12:22 -0700 Subject: [PATCH] When specifying raidz vdev name, parity count should match When specifying the name of a RAIDZ vdev on the command line, it can be specified as raidz- or raidzP-. e.g. `zpool clear poolname raidz-0` or `zpool clear poolname raidz2-0` If the parity is specified in the vdev name, it should match the actual parity of that RAIDZ vdev, otherwise the command should fail. This commit makes it so. Reviewed-by: Brian Behlendorf Co-authored-by: Stuart Maybee Signed-off-by: Matthew Ahrens Closes #11742 --- lib/libzfs/libzfs_pool.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index 0af56ec321..9ef97cd677 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -2669,6 +2669,36 @@ vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare, errno = 0; vdev_id = strtoull(idx, &end, 10); + /* + * If we are looking for a raidz and a parity is + * specified, make sure it matches. + */ + int rzlen = strlen(VDEV_TYPE_RAIDZ); + assert(rzlen == strlen(VDEV_TYPE_DRAID)); + int typlen = strlen(type); + if ((strncmp(type, VDEV_TYPE_RAIDZ, rzlen) == 0 || + strncmp(type, VDEV_TYPE_DRAID, rzlen) == 0) && + typlen != rzlen) { + uint64_t vdev_parity; + int parity = *(type + rzlen) - '0'; + + if (parity <= 0 || parity > 3 || + (typlen - rzlen) != 1) { + /* + * Nonsense parity specified, can + * never match + */ + free(type); + return (NULL); + } + verify(nvlist_lookup_uint64(nv, + ZPOOL_CONFIG_NPARITY, &vdev_parity) == 0); + if ((int)vdev_parity != parity) { + free(type); + break; + } + } + free(type); if (errno != 0) return (NULL);