Print this page
NEX-3558 KRRP Integration
OS-195 itadm needs an easily parsable output mode
OS-207 SUP-817 causes lint warnings in zpool_main.c
Reviewed by: Alek Pinchuk <alek.pinchuk@nexena.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Albert Lee <albert.lee@nexenta.com>
re #12585 rb4049 ZFS++ work port - refactoring to improve separation of open/closed code, bug fixes, performance improvements - open code
Bug 11205: add missing libzfs_closed_stubs.c to fix opensource-only build.
ZFS plus work: special vdevs, cos, cos/vdev properties
@@ -19,10 +19,11 @@
* CDDL HEADER END
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013, 2015 by Delphix. All rights reserved.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
*/
/*
@@ -385,11 +386,11 @@
* /dev/dsk/xxx Complete disk path
* /xxx Full path to file
* xxx Shorthand for /dev/dsk/xxx
*/
static nvlist_t *
-make_leaf_vdev(const char *arg, uint64_t is_log)
+make_leaf_vdev(const char *arg, uint64_t is_log, uint64_t is_special)
{
char path[MAXPATHLEN];
struct stat64 statbuf;
nvlist_t *vdev = NULL;
char *type = NULL;
@@ -469,10 +470,12 @@
*/
verify(nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) == 0);
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0);
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0);
verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_LOG, is_log) == 0);
+ verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_SPECIAL,
+ is_special) == 0);
if (strcmp(type, VDEV_TYPE_DISK) == 0)
verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
(uint64_t)wholedisk) == 0);
/*
@@ -626,15 +629,13 @@
verify(nvlist_lookup_string(cnv,
ZPOOL_CONFIG_TYPE, &childtype) == 0);
/*
* If this is a replacing or spare vdev, then
- * get the real first child of the vdev: do this
- * in a loop because replacing and spare vdevs
- * can be nested.
+ * get the real first child of the vdev.
*/
- while (strcmp(childtype,
+ if (strcmp(childtype,
VDEV_TYPE_REPLACING) == 0 ||
strcmp(childtype, VDEV_TYPE_SPARE) == 0) {
nvlist_t **rchild;
uint_t rchildren;
@@ -1181,10 +1182,16 @@
if (mindev != NULL)
*mindev = 1;
return (VDEV_TYPE_L2CACHE);
}
+ if (strcmp(type, "special") == 0) {
+ if (mindev != NULL)
+ *mindev = 1;
+ return (VDEV_TYPE_SPECIAL);
+ }
+
return (NULL);
}
/*
* Construct a syntactically valid vdev specification,
@@ -1195,13 +1202,14 @@
nvlist_t *
construct_spec(int argc, char **argv)
{
nvlist_t *nvroot, *nv, **top, **spares, **l2cache;
int t, toplevels, mindev, maxdev, nspares, nlogs, nl2cache;
+ int nspecial = 0;
const char *type;
- uint64_t is_log;
- boolean_t seen_logs;
+ boolean_t is_log, seen_logs;
+ boolean_t is_special, seen_special;
top = NULL;
toplevels = 0;
spares = NULL;
l2cache = NULL;
@@ -1208,10 +1216,12 @@
nspares = 0;
nlogs = 0;
nl2cache = 0;
is_log = B_FALSE;
seen_logs = B_FALSE;
+ is_special = B_FALSE;
+ seen_special = B_FALSE;
while (argc > 0) {
nv = NULL;
/*
@@ -1229,10 +1239,11 @@
"specification: 'spare' can be "
"specified only once\n"));
return (NULL);
}
is_log = B_FALSE;
+ is_special = B_FALSE;
}
if (strcmp(type, VDEV_TYPE_LOG) == 0) {
if (seen_logs) {
(void) fprintf(stderr,
@@ -1241,10 +1252,11 @@
"specified only once\n"));
return (NULL);
}
seen_logs = B_TRUE;
is_log = B_TRUE;
+ is_special = B_FALSE;
argc--;
argv++;
/*
* A log is not a real grouping device.
* We just set is_log and continue.
@@ -1259,12 +1271,33 @@
"specification: 'cache' can be "
"specified only once\n"));
return (NULL);
}
is_log = B_FALSE;
+ is_special = B_FALSE;
}
+ if (strcmp(type, VDEV_TYPE_SPECIAL) == 0) {
+ if (seen_special) {
+ (void) fprintf(stderr,
+ gettext("invalid vdev "
+ "specification: 'special' can be "
+ "specified only once\n"));
+ return (NULL);
+ }
+ seen_special = B_TRUE;
+ is_log = B_FALSE;
+ is_special = B_TRUE;
+ argc--;
+ argv++;
+ /*
+ * A special is not a real grouping device.
+ * We just set is_special and continue.
+ */
+ continue;
+ }
+
if (is_log) {
if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
(void) fprintf(stderr,
gettext("invalid vdev "
"specification: unsupported 'log' "
@@ -1272,20 +1305,32 @@
return (NULL);
}
nlogs++;
}
+ if (is_special) {
+ if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
+ (void) fprintf(stderr,
+ gettext("invalid vdev "
+ "specification: unsupported "
+ "'special' device: %s\n"), type);
+ return (NULL);
+ }
+ nspecial++;
+ }
+
for (c = 1; c < argc; c++) {
if (is_grouping(argv[c], NULL, NULL) != NULL)
break;
children++;
child = realloc(child,
children * sizeof (nvlist_t *));
if (child == NULL)
zpool_no_memory();
- if ((nv = make_leaf_vdev(argv[c], B_FALSE))
- == NULL)
+ if ((nv = make_leaf_vdev(argv[c],
+ (uint64_t)B_FALSE,
+ (uint64_t)B_FALSE)) == NULL)
return (NULL);
child[children - 1] = nv;
}
if (children < mindev) {
@@ -1317,11 +1362,15 @@
verify(nvlist_alloc(&nv, NV_UNIQUE_NAME,
0) == 0);
verify(nvlist_add_string(nv, ZPOOL_CONFIG_TYPE,
type) == 0);
verify(nvlist_add_uint64(nv,
- ZPOOL_CONFIG_IS_LOG, is_log) == 0);
+ ZPOOL_CONFIG_IS_LOG,
+ (uint64_t)is_log) == 0);
+ verify(nvlist_add_uint64(nv,
+ ZPOOL_CONFIG_IS_SPECIAL,
+ (uint64_t)is_special) == 0);
if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
verify(nvlist_add_uint64(nv,
ZPOOL_CONFIG_NPARITY,
mindev - 1) == 0);
}
@@ -1336,14 +1385,17 @@
} else {
/*
* We have a device. Pass off to make_leaf_vdev() to
* construct the appropriate nvlist describing the vdev.
*/
- if ((nv = make_leaf_vdev(argv[0], is_log)) == NULL)
+ if ((nv = make_leaf_vdev(argv[0], (uint64_t)is_log,
+ (uint64_t)is_special)) == NULL)
return (NULL);
if (is_log)
nlogs++;
+ if (is_special)
+ nspecial++;
argc--;
argv++;
}
toplevels++;
@@ -1357,10 +1409,16 @@
(void) fprintf(stderr, gettext("invalid vdev "
"specification: at least one toplevel vdev must be "
"specified\n"));
return (NULL);
}
+
+ if (seen_special && nspecial == 0) {
+ (void) fprintf(stderr, gettext("invalid vdev specification: "
+ "special requires at least 1 device\n"));
+ return (NULL);
+ }
if (seen_logs && nlogs == 0) {
(void) fprintf(stderr, gettext("invalid vdev specification: "
"log requires at least 1 device\n"));
return (NULL);