4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
25 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
26 */
27
28 /*
29 * Functions to convert between a list of vdevs and an nvlist representing the
30 * configuration. Each entry in the list can be one of:
31 *
32 * Device vdevs
33 * disk=(path=..., devid=...)
34 * file=(path=...)
35 *
36 * Group vdevs
37 * raidz[1|2]=(...)
38 * mirror=(...)
39 *
40 * Hot spares
41 *
42 * While the underlying implementation supports it, group vdevs cannot contain
43 * other group vdevs. All userland verification of devices is contained within
370 return (B_FALSE);
371 if (efi_alloc_and_init(fd, EFI_NUMPAR, &label) != 0) {
372 (void) close(fd);
373 return (B_FALSE);
374 }
375 efi_free(label);
376 (void) close(fd);
377 return (B_TRUE);
378 }
379
380 /*
381 * Create a leaf vdev. Determine if this is a file or a device. If it's a
382 * device, fill in the device id to make a complete nvlist. Valid forms for a
383 * leaf vdev are:
384 *
385 * /dev/dsk/xxx Complete disk path
386 * /xxx Full path to file
387 * xxx Shorthand for /dev/dsk/xxx
388 */
389 static nvlist_t *
390 make_leaf_vdev(const char *arg, uint64_t is_log)
391 {
392 char path[MAXPATHLEN];
393 struct stat64 statbuf;
394 nvlist_t *vdev = NULL;
395 char *type = NULL;
396 boolean_t wholedisk = B_FALSE;
397
398 /*
399 * Determine what type of vdev this is, and put the full path into
400 * 'path'. We detect whether this is a device of file afterwards by
401 * checking the st_mode of the file.
402 */
403 if (arg[0] == '/') {
404 /*
405 * Complete device or file path. Exact type is determined by
406 * examining the file descriptor afterwards.
407 */
408 wholedisk = is_whole_disk(arg);
409 if (!wholedisk && (stat64(arg, &statbuf) != 0)) {
410 (void) fprintf(stderr,
454 */
455 if (wholedisk || S_ISBLK(statbuf.st_mode)) {
456 type = VDEV_TYPE_DISK;
457 } else if (S_ISREG(statbuf.st_mode)) {
458 type = VDEV_TYPE_FILE;
459 } else {
460 (void) fprintf(stderr, gettext("cannot use '%s': must be a "
461 "block device or regular file\n"), path);
462 return (NULL);
463 }
464
465 /*
466 * Finally, we have the complete device or file, and we know that it is
467 * acceptable to use. Construct the nvlist to describe this vdev. All
468 * vdevs have a 'path' element, and devices also have a 'devid' element.
469 */
470 verify(nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) == 0);
471 verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0);
472 verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0);
473 verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_LOG, is_log) == 0);
474 if (strcmp(type, VDEV_TYPE_DISK) == 0)
475 verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
476 (uint64_t)wholedisk) == 0);
477
478 /*
479 * For a whole disk, defer getting its devid until after labeling it.
480 */
481 if (S_ISBLK(statbuf.st_mode) && !wholedisk) {
482 /*
483 * Get the devid for the device.
484 */
485 int fd;
486 ddi_devid_t devid;
487 char *minor = NULL, *devid_str = NULL;
488
489 if ((fd = open(path, O_RDONLY)) < 0) {
490 (void) fprintf(stderr, gettext("cannot open '%s': "
491 "%s\n"), path, strerror(errno));
492 nvlist_free(vdev);
493 return (NULL);
611 * bother doing it again.
612 */
613 type = NULL;
614 dontreport = 0;
615 vdev_size = -1ULL;
616 for (c = 0; c < children; c++) {
617 nvlist_t *cnv = child[c];
618 char *path;
619 struct stat64 statbuf;
620 uint64_t size = -1ULL;
621 char *childtype;
622 int fd, err;
623
624 rep.zprl_children++;
625
626 verify(nvlist_lookup_string(cnv,
627 ZPOOL_CONFIG_TYPE, &childtype) == 0);
628
629 /*
630 * If this is a replacing or spare vdev, then
631 * get the real first child of the vdev: do this
632 * in a loop because replacing and spare vdevs
633 * can be nested.
634 */
635 while (strcmp(childtype,
636 VDEV_TYPE_REPLACING) == 0 ||
637 strcmp(childtype, VDEV_TYPE_SPARE) == 0) {
638 nvlist_t **rchild;
639 uint_t rchildren;
640
641 verify(nvlist_lookup_nvlist_array(cnv,
642 ZPOOL_CONFIG_CHILDREN, &rchild,
643 &rchildren) == 0);
644 assert(rchildren == 2);
645 cnv = rchild[0];
646
647 verify(nvlist_lookup_string(cnv,
648 ZPOOL_CONFIG_TYPE,
649 &childtype) == 0);
650 }
651
652 verify(nvlist_lookup_string(cnv,
653 ZPOOL_CONFIG_PATH, &path) == 0);
654
655 /*
1166 }
1167
1168 if (strcmp(type, "spare") == 0) {
1169 if (mindev != NULL)
1170 *mindev = 1;
1171 return (VDEV_TYPE_SPARE);
1172 }
1173
1174 if (strcmp(type, "log") == 0) {
1175 if (mindev != NULL)
1176 *mindev = 1;
1177 return (VDEV_TYPE_LOG);
1178 }
1179
1180 if (strcmp(type, "cache") == 0) {
1181 if (mindev != NULL)
1182 *mindev = 1;
1183 return (VDEV_TYPE_L2CACHE);
1184 }
1185
1186 return (NULL);
1187 }
1188
1189 /*
1190 * Construct a syntactically valid vdev specification,
1191 * and ensure that all devices and files exist and can be opened.
1192 * Note: we don't bother freeing anything in the error paths
1193 * because the program is just going to exit anyway.
1194 */
1195 nvlist_t *
1196 construct_spec(int argc, char **argv)
1197 {
1198 nvlist_t *nvroot, *nv, **top, **spares, **l2cache;
1199 int t, toplevels, mindev, maxdev, nspares, nlogs, nl2cache;
1200 const char *type;
1201 uint64_t is_log;
1202 boolean_t seen_logs;
1203
1204 top = NULL;
1205 toplevels = 0;
1206 spares = NULL;
1207 l2cache = NULL;
1208 nspares = 0;
1209 nlogs = 0;
1210 nl2cache = 0;
1211 is_log = B_FALSE;
1212 seen_logs = B_FALSE;
1213
1214 while (argc > 0) {
1215 nv = NULL;
1216
1217 /*
1218 * If it's a mirror or raidz, the subsequent arguments are
1219 * its leaves -- until we encounter the next mirror or raidz.
1220 */
1221 if ((type = is_grouping(argv[0], &mindev, &maxdev)) != NULL) {
1222 nvlist_t **child = NULL;
1223 int c, children = 0;
1224
1225 if (strcmp(type, VDEV_TYPE_SPARE) == 0) {
1226 if (spares != NULL) {
1227 (void) fprintf(stderr,
1228 gettext("invalid vdev "
1229 "specification: 'spare' can be "
1230 "specified only once\n"));
1231 return (NULL);
1232 }
1233 is_log = B_FALSE;
1234 }
1235
1236 if (strcmp(type, VDEV_TYPE_LOG) == 0) {
1237 if (seen_logs) {
1238 (void) fprintf(stderr,
1239 gettext("invalid vdev "
1240 "specification: 'log' can be "
1241 "specified only once\n"));
1242 return (NULL);
1243 }
1244 seen_logs = B_TRUE;
1245 is_log = B_TRUE;
1246 argc--;
1247 argv++;
1248 /*
1249 * A log is not a real grouping device.
1250 * We just set is_log and continue.
1251 */
1252 continue;
1253 }
1254
1255 if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) {
1256 if (l2cache != NULL) {
1257 (void) fprintf(stderr,
1258 gettext("invalid vdev "
1259 "specification: 'cache' can be "
1260 "specified only once\n"));
1261 return (NULL);
1262 }
1263 is_log = B_FALSE;
1264 }
1265
1266 if (is_log) {
1267 if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
1268 (void) fprintf(stderr,
1269 gettext("invalid vdev "
1270 "specification: unsupported 'log' "
1271 "device: %s\n"), type);
1272 return (NULL);
1273 }
1274 nlogs++;
1275 }
1276
1277 for (c = 1; c < argc; c++) {
1278 if (is_grouping(argv[c], NULL, NULL) != NULL)
1279 break;
1280 children++;
1281 child = realloc(child,
1282 children * sizeof (nvlist_t *));
1283 if (child == NULL)
1284 zpool_no_memory();
1285 if ((nv = make_leaf_vdev(argv[c], B_FALSE))
1286 == NULL)
1287 return (NULL);
1288 child[children - 1] = nv;
1289 }
1290
1291 if (children < mindev) {
1292 (void) fprintf(stderr, gettext("invalid vdev "
1293 "specification: %s requires at least %d "
1294 "devices\n"), argv[0], mindev);
1295 return (NULL);
1296 }
1297
1298 if (children > maxdev) {
1299 (void) fprintf(stderr, gettext("invalid vdev "
1300 "specification: %s supports no more than "
1301 "%d devices\n"), argv[0], maxdev);
1302 return (NULL);
1303 }
1304
1305 argc -= c;
1306 argv += c;
1307
1308 if (strcmp(type, VDEV_TYPE_SPARE) == 0) {
1309 spares = child;
1310 nspares = children;
1311 continue;
1312 } else if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) {
1313 l2cache = child;
1314 nl2cache = children;
1315 continue;
1316 } else {
1317 verify(nvlist_alloc(&nv, NV_UNIQUE_NAME,
1318 0) == 0);
1319 verify(nvlist_add_string(nv, ZPOOL_CONFIG_TYPE,
1320 type) == 0);
1321 verify(nvlist_add_uint64(nv,
1322 ZPOOL_CONFIG_IS_LOG, is_log) == 0);
1323 if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
1324 verify(nvlist_add_uint64(nv,
1325 ZPOOL_CONFIG_NPARITY,
1326 mindev - 1) == 0);
1327 }
1328 verify(nvlist_add_nvlist_array(nv,
1329 ZPOOL_CONFIG_CHILDREN, child,
1330 children) == 0);
1331
1332 for (c = 0; c < children; c++)
1333 nvlist_free(child[c]);
1334 free(child);
1335 }
1336 } else {
1337 /*
1338 * We have a device. Pass off to make_leaf_vdev() to
1339 * construct the appropriate nvlist describing the vdev.
1340 */
1341 if ((nv = make_leaf_vdev(argv[0], is_log)) == NULL)
1342 return (NULL);
1343 if (is_log)
1344 nlogs++;
1345 argc--;
1346 argv++;
1347 }
1348
1349 toplevels++;
1350 top = realloc(top, toplevels * sizeof (nvlist_t *));
1351 if (top == NULL)
1352 zpool_no_memory();
1353 top[toplevels - 1] = nv;
1354 }
1355
1356 if (toplevels == 0 && nspares == 0 && nl2cache == 0) {
1357 (void) fprintf(stderr, gettext("invalid vdev "
1358 "specification: at least one toplevel vdev must be "
1359 "specified\n"));
1360 return (NULL);
1361 }
1362
1363 if (seen_logs && nlogs == 0) {
1364 (void) fprintf(stderr, gettext("invalid vdev specification: "
1365 "log requires at least 1 device\n"));
1366 return (NULL);
1367 }
1368
1369 /*
1370 * Finally, create nvroot and add all top-level vdevs to it.
1371 */
1372 verify(nvlist_alloc(&nvroot, NV_UNIQUE_NAME, 0) == 0);
1373 verify(nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE,
1374 VDEV_TYPE_ROOT) == 0);
1375 verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
1376 top, toplevels) == 0);
1377 if (nspares != 0)
1378 verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
1379 spares, nspares) == 0);
1380 if (nl2cache != 0)
1381 verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25 * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
26 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
27 */
28
29 /*
30 * Functions to convert between a list of vdevs and an nvlist representing the
31 * configuration. Each entry in the list can be one of:
32 *
33 * Device vdevs
34 * disk=(path=..., devid=...)
35 * file=(path=...)
36 *
37 * Group vdevs
38 * raidz[1|2]=(...)
39 * mirror=(...)
40 *
41 * Hot spares
42 *
43 * While the underlying implementation supports it, group vdevs cannot contain
44 * other group vdevs. All userland verification of devices is contained within
371 return (B_FALSE);
372 if (efi_alloc_and_init(fd, EFI_NUMPAR, &label) != 0) {
373 (void) close(fd);
374 return (B_FALSE);
375 }
376 efi_free(label);
377 (void) close(fd);
378 return (B_TRUE);
379 }
380
381 /*
382 * Create a leaf vdev. Determine if this is a file or a device. If it's a
383 * device, fill in the device id to make a complete nvlist. Valid forms for a
384 * leaf vdev are:
385 *
386 * /dev/dsk/xxx Complete disk path
387 * /xxx Full path to file
388 * xxx Shorthand for /dev/dsk/xxx
389 */
390 static nvlist_t *
391 make_leaf_vdev(const char *arg, uint64_t is_log, uint64_t is_special)
392 {
393 char path[MAXPATHLEN];
394 struct stat64 statbuf;
395 nvlist_t *vdev = NULL;
396 char *type = NULL;
397 boolean_t wholedisk = B_FALSE;
398
399 /*
400 * Determine what type of vdev this is, and put the full path into
401 * 'path'. We detect whether this is a device of file afterwards by
402 * checking the st_mode of the file.
403 */
404 if (arg[0] == '/') {
405 /*
406 * Complete device or file path. Exact type is determined by
407 * examining the file descriptor afterwards.
408 */
409 wholedisk = is_whole_disk(arg);
410 if (!wholedisk && (stat64(arg, &statbuf) != 0)) {
411 (void) fprintf(stderr,
455 */
456 if (wholedisk || S_ISBLK(statbuf.st_mode)) {
457 type = VDEV_TYPE_DISK;
458 } else if (S_ISREG(statbuf.st_mode)) {
459 type = VDEV_TYPE_FILE;
460 } else {
461 (void) fprintf(stderr, gettext("cannot use '%s': must be a "
462 "block device or regular file\n"), path);
463 return (NULL);
464 }
465
466 /*
467 * Finally, we have the complete device or file, and we know that it is
468 * acceptable to use. Construct the nvlist to describe this vdev. All
469 * vdevs have a 'path' element, and devices also have a 'devid' element.
470 */
471 verify(nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) == 0);
472 verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0);
473 verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0);
474 verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_LOG, is_log) == 0);
475 verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_SPECIAL,
476 is_special) == 0);
477 if (strcmp(type, VDEV_TYPE_DISK) == 0)
478 verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
479 (uint64_t)wholedisk) == 0);
480
481 /*
482 * For a whole disk, defer getting its devid until after labeling it.
483 */
484 if (S_ISBLK(statbuf.st_mode) && !wholedisk) {
485 /*
486 * Get the devid for the device.
487 */
488 int fd;
489 ddi_devid_t devid;
490 char *minor = NULL, *devid_str = NULL;
491
492 if ((fd = open(path, O_RDONLY)) < 0) {
493 (void) fprintf(stderr, gettext("cannot open '%s': "
494 "%s\n"), path, strerror(errno));
495 nvlist_free(vdev);
496 return (NULL);
614 * bother doing it again.
615 */
616 type = NULL;
617 dontreport = 0;
618 vdev_size = -1ULL;
619 for (c = 0; c < children; c++) {
620 nvlist_t *cnv = child[c];
621 char *path;
622 struct stat64 statbuf;
623 uint64_t size = -1ULL;
624 char *childtype;
625 int fd, err;
626
627 rep.zprl_children++;
628
629 verify(nvlist_lookup_string(cnv,
630 ZPOOL_CONFIG_TYPE, &childtype) == 0);
631
632 /*
633 * If this is a replacing or spare vdev, then
634 * get the real first child of the vdev.
635 */
636 if (strcmp(childtype,
637 VDEV_TYPE_REPLACING) == 0 ||
638 strcmp(childtype, VDEV_TYPE_SPARE) == 0) {
639 nvlist_t **rchild;
640 uint_t rchildren;
641
642 verify(nvlist_lookup_nvlist_array(cnv,
643 ZPOOL_CONFIG_CHILDREN, &rchild,
644 &rchildren) == 0);
645 assert(rchildren == 2);
646 cnv = rchild[0];
647
648 verify(nvlist_lookup_string(cnv,
649 ZPOOL_CONFIG_TYPE,
650 &childtype) == 0);
651 }
652
653 verify(nvlist_lookup_string(cnv,
654 ZPOOL_CONFIG_PATH, &path) == 0);
655
656 /*
1167 }
1168
1169 if (strcmp(type, "spare") == 0) {
1170 if (mindev != NULL)
1171 *mindev = 1;
1172 return (VDEV_TYPE_SPARE);
1173 }
1174
1175 if (strcmp(type, "log") == 0) {
1176 if (mindev != NULL)
1177 *mindev = 1;
1178 return (VDEV_TYPE_LOG);
1179 }
1180
1181 if (strcmp(type, "cache") == 0) {
1182 if (mindev != NULL)
1183 *mindev = 1;
1184 return (VDEV_TYPE_L2CACHE);
1185 }
1186
1187 if (strcmp(type, "special") == 0) {
1188 if (mindev != NULL)
1189 *mindev = 1;
1190 return (VDEV_TYPE_SPECIAL);
1191 }
1192
1193 return (NULL);
1194 }
1195
1196 /*
1197 * Construct a syntactically valid vdev specification,
1198 * and ensure that all devices and files exist and can be opened.
1199 * Note: we don't bother freeing anything in the error paths
1200 * because the program is just going to exit anyway.
1201 */
1202 nvlist_t *
1203 construct_spec(int argc, char **argv)
1204 {
1205 nvlist_t *nvroot, *nv, **top, **spares, **l2cache;
1206 int t, toplevels, mindev, maxdev, nspares, nlogs, nl2cache;
1207 int nspecial = 0;
1208 const char *type;
1209 boolean_t is_log, seen_logs;
1210 boolean_t is_special, seen_special;
1211
1212 top = NULL;
1213 toplevels = 0;
1214 spares = NULL;
1215 l2cache = NULL;
1216 nspares = 0;
1217 nlogs = 0;
1218 nl2cache = 0;
1219 is_log = B_FALSE;
1220 seen_logs = B_FALSE;
1221 is_special = B_FALSE;
1222 seen_special = B_FALSE;
1223
1224 while (argc > 0) {
1225 nv = NULL;
1226
1227 /*
1228 * If it's a mirror or raidz, the subsequent arguments are
1229 * its leaves -- until we encounter the next mirror or raidz.
1230 */
1231 if ((type = is_grouping(argv[0], &mindev, &maxdev)) != NULL) {
1232 nvlist_t **child = NULL;
1233 int c, children = 0;
1234
1235 if (strcmp(type, VDEV_TYPE_SPARE) == 0) {
1236 if (spares != NULL) {
1237 (void) fprintf(stderr,
1238 gettext("invalid vdev "
1239 "specification: 'spare' can be "
1240 "specified only once\n"));
1241 return (NULL);
1242 }
1243 is_log = B_FALSE;
1244 is_special = B_FALSE;
1245 }
1246
1247 if (strcmp(type, VDEV_TYPE_LOG) == 0) {
1248 if (seen_logs) {
1249 (void) fprintf(stderr,
1250 gettext("invalid vdev "
1251 "specification: 'log' can be "
1252 "specified only once\n"));
1253 return (NULL);
1254 }
1255 seen_logs = B_TRUE;
1256 is_log = B_TRUE;
1257 is_special = B_FALSE;
1258 argc--;
1259 argv++;
1260 /*
1261 * A log is not a real grouping device.
1262 * We just set is_log and continue.
1263 */
1264 continue;
1265 }
1266
1267 if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) {
1268 if (l2cache != NULL) {
1269 (void) fprintf(stderr,
1270 gettext("invalid vdev "
1271 "specification: 'cache' can be "
1272 "specified only once\n"));
1273 return (NULL);
1274 }
1275 is_log = B_FALSE;
1276 is_special = B_FALSE;
1277 }
1278
1279 if (strcmp(type, VDEV_TYPE_SPECIAL) == 0) {
1280 if (seen_special) {
1281 (void) fprintf(stderr,
1282 gettext("invalid vdev "
1283 "specification: 'special' can be "
1284 "specified only once\n"));
1285 return (NULL);
1286 }
1287 seen_special = B_TRUE;
1288 is_log = B_FALSE;
1289 is_special = B_TRUE;
1290 argc--;
1291 argv++;
1292 /*
1293 * A special is not a real grouping device.
1294 * We just set is_special and continue.
1295 */
1296 continue;
1297 }
1298
1299 if (is_log) {
1300 if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
1301 (void) fprintf(stderr,
1302 gettext("invalid vdev "
1303 "specification: unsupported 'log' "
1304 "device: %s\n"), type);
1305 return (NULL);
1306 }
1307 nlogs++;
1308 }
1309
1310 if (is_special) {
1311 if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
1312 (void) fprintf(stderr,
1313 gettext("invalid vdev "
1314 "specification: unsupported "
1315 "'special' device: %s\n"), type);
1316 return (NULL);
1317 }
1318 nspecial++;
1319 }
1320
1321 for (c = 1; c < argc; c++) {
1322 if (is_grouping(argv[c], NULL, NULL) != NULL)
1323 break;
1324 children++;
1325 child = realloc(child,
1326 children * sizeof (nvlist_t *));
1327 if (child == NULL)
1328 zpool_no_memory();
1329 if ((nv = make_leaf_vdev(argv[c],
1330 (uint64_t)B_FALSE,
1331 (uint64_t)B_FALSE)) == NULL)
1332 return (NULL);
1333 child[children - 1] = nv;
1334 }
1335
1336 if (children < mindev) {
1337 (void) fprintf(stderr, gettext("invalid vdev "
1338 "specification: %s requires at least %d "
1339 "devices\n"), argv[0], mindev);
1340 return (NULL);
1341 }
1342
1343 if (children > maxdev) {
1344 (void) fprintf(stderr, gettext("invalid vdev "
1345 "specification: %s supports no more than "
1346 "%d devices\n"), argv[0], maxdev);
1347 return (NULL);
1348 }
1349
1350 argc -= c;
1351 argv += c;
1352
1353 if (strcmp(type, VDEV_TYPE_SPARE) == 0) {
1354 spares = child;
1355 nspares = children;
1356 continue;
1357 } else if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) {
1358 l2cache = child;
1359 nl2cache = children;
1360 continue;
1361 } else {
1362 verify(nvlist_alloc(&nv, NV_UNIQUE_NAME,
1363 0) == 0);
1364 verify(nvlist_add_string(nv, ZPOOL_CONFIG_TYPE,
1365 type) == 0);
1366 verify(nvlist_add_uint64(nv,
1367 ZPOOL_CONFIG_IS_LOG,
1368 (uint64_t)is_log) == 0);
1369 verify(nvlist_add_uint64(nv,
1370 ZPOOL_CONFIG_IS_SPECIAL,
1371 (uint64_t)is_special) == 0);
1372 if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
1373 verify(nvlist_add_uint64(nv,
1374 ZPOOL_CONFIG_NPARITY,
1375 mindev - 1) == 0);
1376 }
1377 verify(nvlist_add_nvlist_array(nv,
1378 ZPOOL_CONFIG_CHILDREN, child,
1379 children) == 0);
1380
1381 for (c = 0; c < children; c++)
1382 nvlist_free(child[c]);
1383 free(child);
1384 }
1385 } else {
1386 /*
1387 * We have a device. Pass off to make_leaf_vdev() to
1388 * construct the appropriate nvlist describing the vdev.
1389 */
1390 if ((nv = make_leaf_vdev(argv[0], (uint64_t)is_log,
1391 (uint64_t)is_special)) == NULL)
1392 return (NULL);
1393 if (is_log)
1394 nlogs++;
1395 if (is_special)
1396 nspecial++;
1397 argc--;
1398 argv++;
1399 }
1400
1401 toplevels++;
1402 top = realloc(top, toplevels * sizeof (nvlist_t *));
1403 if (top == NULL)
1404 zpool_no_memory();
1405 top[toplevels - 1] = nv;
1406 }
1407
1408 if (toplevels == 0 && nspares == 0 && nl2cache == 0) {
1409 (void) fprintf(stderr, gettext("invalid vdev "
1410 "specification: at least one toplevel vdev must be "
1411 "specified\n"));
1412 return (NULL);
1413 }
1414
1415 if (seen_special && nspecial == 0) {
1416 (void) fprintf(stderr, gettext("invalid vdev specification: "
1417 "special requires at least 1 device\n"));
1418 return (NULL);
1419 }
1420
1421 if (seen_logs && nlogs == 0) {
1422 (void) fprintf(stderr, gettext("invalid vdev specification: "
1423 "log requires at least 1 device\n"));
1424 return (NULL);
1425 }
1426
1427 /*
1428 * Finally, create nvroot and add all top-level vdevs to it.
1429 */
1430 verify(nvlist_alloc(&nvroot, NV_UNIQUE_NAME, 0) == 0);
1431 verify(nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE,
1432 VDEV_TYPE_ROOT) == 0);
1433 verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
1434 top, toplevels) == 0);
1435 if (nspares != 0)
1436 verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
1437 spares, nspares) == 0);
1438 if (nl2cache != 0)
1439 verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
|