Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
500 changes: 495 additions & 5 deletions cmd/zdb/zdb.c

Large diffs are not rendered by default.

96 changes: 73 additions & 23 deletions cmd/zpool/zpool_vdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
#include "zpool_util.h"
#include <sys/zfs_context.h>
#include <sys/stat.h>
#include <sys/vdev_anyraid.h>

/*
* For any given vdev specification, we can have multiple errors. The
Expand Down Expand Up @@ -431,7 +432,8 @@ is_raidz_mirror(replication_level_t *a, replication_level_t *b,
{
if ((strcmp(a->zprl_type, "raidz") == 0 ||
strcmp(a->zprl_type, "draid") == 0) &&
strcmp(b->zprl_type, "mirror") == 0) {
(strcmp(b->zprl_type, "mirror") == 0 ||
strcmp(b->zprl_type, "anymirror") == 0)) {
*raidz = a;
*mirror = b;
return (B_TRUE);
Expand Down Expand Up @@ -527,11 +529,11 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
rep.zprl_children = 0;

if (strcmp(type, VDEV_TYPE_RAIDZ) == 0 ||
strcmp(type, VDEV_TYPE_DRAID) == 0) {
strcmp(type, VDEV_TYPE_DRAID) == 0 ||
strcmp(type, VDEV_TYPE_ANYRAID) == 0) {
verify(nvlist_lookup_uint64(nv,
ZPOOL_CONFIG_NPARITY,
&rep.zprl_parity) == 0);
assert(rep.zprl_parity != 0);
} else {
rep.zprl_parity = 0;
}
Expand All @@ -541,6 +543,7 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
* already reported an error for this spec, so don't
* bother doing it again.
*/
const char *orig_type = type;
type = NULL;
dontreport = 0;
vdev_size = -1LL;
Expand Down Expand Up @@ -646,7 +649,8 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
if (!dontreport &&
(vdev_size != -1LL &&
(llabs(size - vdev_size) >
ZPOOL_FUZZ))) {
ZPOOL_FUZZ)) && strcmp(orig_type,
VDEV_TYPE_ANYRAID) != 0) {
if (ret != NULL)
free(ret);
ret = NULL;
Expand Down Expand Up @@ -726,19 +730,6 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
else
return (NULL);
}
} else if (strcmp(lastrep.zprl_type, rep.zprl_type) !=
0) {
if (ret != NULL)
free(ret);
ret = NULL;
if (fatal)
vdev_error(gettext(
"mismatched replication level: "
"both %s and %s vdevs are "
"present\n"),
lastrep.zprl_type, rep.zprl_type);
else
return (NULL);
} else if (lastrep.zprl_parity != rep.zprl_parity) {
if (ret)
free(ret);
Expand All @@ -754,7 +745,9 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
rep.zprl_type);
else
return (NULL);
} else if (lastrep.zprl_children != rep.zprl_children) {
} else if (lastrep.zprl_children !=
rep.zprl_children && strcmp(rep.zprl_type,
VDEV_TYPE_ANYRAID) != 0) {
if (ret)
free(ret);
ret = NULL;
Expand Down Expand Up @@ -1200,7 +1193,7 @@ is_device_in_use(nvlist_t *config, nvlist_t *nv, boolean_t force,
}

/*
* Returns the parity level extracted from a raidz or draid type.
* Returns the parity level extracted from a raidz, anyraid, or draid type.
* If the parity cannot be determined zero is returned.
*/
static int
Expand Down Expand Up @@ -1228,6 +1221,22 @@ get_parity(const char *type)
return (0);
}
}
} else if (strncmp(type, VDEV_TYPE_ANYRAID,
strlen(VDEV_TYPE_ANYRAID)) == 0) {
p = type + strlen(VDEV_TYPE_ANYRAID);

if (*p == '\0') {
/* when unspecified default to 1-parity mirror */
return (1);
} else {
char *end;
errno = 0;
parity = strtol(p, &end, 10);
if (errno != 0 || *end != '\0' ||
parity < 0 || parity > VDEV_ANYRAID_MAXPARITY) {
return (-1);
}
}
} else if (strncmp(type, VDEV_TYPE_DRAID,
strlen(VDEV_TYPE_DRAID)) == 0) {
p = type + strlen(VDEV_TYPE_DRAID);
Expand Down Expand Up @@ -1285,6 +1294,17 @@ is_grouping(const char *type, int *mindev, int *maxdev)
if (maxdev != NULL)
*maxdev = INT_MAX;

if (strncmp(type, VDEV_TYPE_ANYRAID, strlen(VDEV_TYPE_ANYRAID)) == 0) {
nparity = get_parity(type);
if (nparity < 0)
return (NULL);
if (mindev != NULL)
*mindev = nparity + 1;
if (maxdev != NULL)
*maxdev = 255;
return (VDEV_TYPE_ANYRAID);
}

if (strcmp(type, "mirror") == 0) {
if (mindev != NULL)
*mindev = 2;
Expand Down Expand Up @@ -1319,6 +1339,22 @@ is_grouping(const char *type, int *mindev, int *maxdev)
return (NULL);
}

static int
anyraid_config_by_type(nvlist_t *nv, const char *type)
{
uint64_t nparity = 0;

if (strncmp(type, VDEV_TYPE_ANYRAID, strlen(VDEV_TYPE_ANYRAID)) != 0)
return (EINVAL);

nparity = (uint64_t)get_parity(type);

fnvlist_add_uint8(nv, ZPOOL_CONFIG_ANYRAID_PARITY_TYPE, VAP_MIRROR);
fnvlist_add_uint64(nv, ZPOOL_CONFIG_NPARITY, nparity);

return (0);
}

/*
* Extract the configuration parameters encoded in the dRAID type and
* use them to generate a dRAID configuration. The expected format is:
Expand Down Expand Up @@ -1527,9 +1563,9 @@ construct_spec(nvlist_t *props, int argc, char **argv)
nv = NULL;

/*
* If it's a mirror, raidz, or draid the subsequent arguments
* are its leaves -- until we encounter the next mirror,
* raidz or draid.
* If it's a mirror, raidz, anyraid, or draid the subsequent
* arguments are its leaves -- until we encounter the next
* mirror, raidz, anyraid, or draid.
*/
if ((type = is_grouping(fulltype, &mindev, &maxdev)) != NULL) {
nvlist_t **child = NULL;
Expand Down Expand Up @@ -1596,7 +1632,12 @@ construct_spec(nvlist_t *props, int argc, char **argv)
}

if (is_log) {
if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
/*
* TODO: only AnyRAID mirror is expected to be
* allowed.
*/
if (strcmp(type, VDEV_TYPE_MIRROR) != 0 &&
strcmp(type, VDEV_TYPE_ANYRAID) != 0) {
(void) fprintf(stderr,
gettext("invalid vdev "
"specification: unsupported 'log' "
Expand Down Expand Up @@ -1690,6 +1731,15 @@ construct_spec(nvlist_t *props, int argc, char **argv)
ZPOOL_CONFIG_NPARITY,
mindev - 1) == 0);
}
if (strcmp(type, VDEV_TYPE_ANYRAID) == 0) {
if (anyraid_config_by_type(nv, fulltype)
!= 0) {
for (c = 0; c < children; c++)
nvlist_free(child[c]);
free(child);
goto spec_out;
}
}
if (strcmp(type, VDEV_TYPE_DRAID) == 0) {
if (draid_config_by_type(nv,
fulltype, children) != 0) {
Expand Down
Loading
Loading