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) 2011, 2018 by Delphix. All rights reserved.
25 * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
26 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
27 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
28 * Copyright 2016 Nexenta Systems, Inc.
29 * Copyright (c) 2017 Datto Inc.
30 */
31
32 #include <assert.h>
33 #include <ctype.h>
34 #include <dirent.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <libgen.h>
38 #include <libintl.h>
39 #include <libuutil.h>
40 #include <locale.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <strings.h>
45 #include <unistd.h>
46 #include <priv.h>
47 #include <pwd.h>
48 #include <zone.h>
49 #include <zfs_prop.h>
50 #include <sys/fs/zfs.h>
51 #include <sys/stat.h>
52
53 #include <libzfs.h>
54
55 #include "zpool_util.h"
56 #include "zfs_comutil.h"
57 #include "zfeature_common.h"
58
59 #include "statcommon.h"
60
61 static int zpool_do_create(int, char **);
62 static int zpool_do_destroy(int, char **);
63
64 static int zpool_do_add(int, char **);
65 static int zpool_do_remove(int, char **);
66 static int zpool_do_labelclear(int, char **);
67
68 static int zpool_do_list(int, char **);
69 static int zpool_do_iostat(int, char **);
70 static int zpool_do_status(int, char **);
71
72 static int zpool_do_online(int, char **);
73 static int zpool_do_offline(int, char **);
74 static int zpool_do_clear(int, char **);
75 static int zpool_do_reopen(int, char **);
76
77 static int zpool_do_reguid(int, char **);
78
79 static int zpool_do_attach(int, char **);
80 static int zpool_do_detach(int, char **);
81 static int zpool_do_replace(int, char **);
82 static int zpool_do_split(int, char **);
83
84 static int zpool_do_scrub(int, char **);
85
86 static int zpool_do_import(int, char **);
87 static int zpool_do_export(int, char **);
88
89 static int zpool_do_upgrade(int, char **);
90
91 static int zpool_do_history(int, char **);
92
93 static int zpool_do_get(int, char **);
94 static int zpool_do_set(int, char **);
95
96 /*
97 * These libumem hooks provide a reasonable set of defaults for the allocator's
98 * debugging facilities.
99 */
100
101 #ifdef DEBUG
102 const char *
103 _umem_debug_init(void)
104 {
105 return ("default,verbose"); /* $UMEM_DEBUG setting */
106 }
107
108 const char *
109 _umem_logging_init(void)
110 {
111 return ("fail,contents"); /* $UMEM_LOGGING setting */
112 }
113 #endif
114
115 typedef enum {
116 HELP_ADD,
117 HELP_ATTACH,
118 HELP_CLEAR,
119 HELP_CREATE,
120 HELP_DESTROY,
121 HELP_DETACH,
122 HELP_EXPORT,
123 HELP_HISTORY,
124 HELP_IMPORT,
125 HELP_IOSTAT,
126 HELP_LABELCLEAR,
127 HELP_LIST,
128 HELP_OFFLINE,
129 HELP_ONLINE,
130 HELP_REPLACE,
131 HELP_REMOVE,
132 HELP_SCRUB,
133 HELP_STATUS,
134 HELP_UPGRADE,
135 HELP_GET,
136 HELP_SET,
137 HELP_SPLIT,
138 HELP_REGUID,
139 HELP_REOPEN
140 } zpool_help_t;
141
142
143 typedef struct zpool_command {
144 const char *name;
145 int (*func)(int, char **);
146 zpool_help_t usage;
147 } zpool_command_t;
148
149 /*
150 * Master command table. Each ZFS command has a name, associated function, and
151 * usage message. The usage messages need to be internationalized, so we have
152 * to have a function to return the usage message based on a command index.
153 *
154 * These commands are organized according to how they are displayed in the usage
155 * message. An empty command (one with a NULL name) indicates an empty line in
156 * the generic usage message.
157 */
158 static zpool_command_t command_table[] = {
159 { "create", zpool_do_create, HELP_CREATE },
163 { "remove", zpool_do_remove, HELP_REMOVE },
164 { NULL },
165 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR },
166 { NULL },
167 { "list", zpool_do_list, HELP_LIST },
168 { "iostat", zpool_do_iostat, HELP_IOSTAT },
169 { "status", zpool_do_status, HELP_STATUS },
170 { NULL },
171 { "online", zpool_do_online, HELP_ONLINE },
172 { "offline", zpool_do_offline, HELP_OFFLINE },
173 { "clear", zpool_do_clear, HELP_CLEAR },
174 { "reopen", zpool_do_reopen, HELP_REOPEN },
175 { NULL },
176 { "attach", zpool_do_attach, HELP_ATTACH },
177 { "detach", zpool_do_detach, HELP_DETACH },
178 { "replace", zpool_do_replace, HELP_REPLACE },
179 { "split", zpool_do_split, HELP_SPLIT },
180 { NULL },
181 { "scrub", zpool_do_scrub, HELP_SCRUB },
182 { NULL },
183 { "import", zpool_do_import, HELP_IMPORT },
184 { "export", zpool_do_export, HELP_EXPORT },
185 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
186 { "reguid", zpool_do_reguid, HELP_REGUID },
187 { NULL },
188 { "history", zpool_do_history, HELP_HISTORY },
189 { "get", zpool_do_get, HELP_GET },
190 { "set", zpool_do_set, HELP_SET },
191 };
192
193 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
194
195 static zpool_command_t *current_command;
196 static char history_str[HIS_MAX_RECORD_LEN];
197 static boolean_t log_history = B_TRUE;
198 static uint_t timestamp_fmt = NODATE;
199
200 static const char *
201 get_usage(zpool_help_t idx)
202 {
203 switch (idx) {
204 case HELP_ADD:
205 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
206 case HELP_ATTACH:
207 return (gettext("\tattach [-f] <pool> <device> "
208 "<new-device>\n"));
209 case HELP_CLEAR:
210 return (gettext("\tclear [-nF] <pool> [device]\n"));
211 case HELP_CREATE:
212 return (gettext("\tcreate [-fnd] [-B] "
213 "[-o property=value] ... \n"
214 "\t [-O file-system-property=value] ... \n"
215 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
216 case HELP_DESTROY:
217 return (gettext("\tdestroy [-f] <pool>\n"));
218 case HELP_DETACH:
219 return (gettext("\tdetach <pool> <device>\n"));
220 case HELP_EXPORT:
221 return (gettext("\texport [-f] <pool> ...\n"));
222 case HELP_HISTORY:
223 return (gettext("\thistory [-il] [<pool>] ...\n"));
224 case HELP_IMPORT:
225 return (gettext("\timport [-d dir] [-D]\n"
226 "\timport [-d dir | -c cachefile] [-F [-n]] <pool | id>\n"
227 "\timport [-o mntopts] [-o property=value] ... \n"
228 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
229 "[-R root] [-F [-n]] -a\n"
230 "\timport [-o mntopts] [-o property=value] ... \n"
231 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
232 "[-R root] [-F [-n]]\n"
233 "\t <pool | id> [newpool]\n"));
234 case HELP_IOSTAT:
235 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
236 "[count]]\n"));
237 case HELP_LABELCLEAR:
238 return (gettext("\tlabelclear [-f] <vdev>\n"));
239 case HELP_LIST:
240 return (gettext("\tlist [-Hp] [-o property[,...]] "
241 "[-T d|u] [pool] ... [interval [count]]\n"));
242 case HELP_OFFLINE:
243 return (gettext("\toffline [-t] <pool> <device> ...\n"));
244 case HELP_ONLINE:
245 return (gettext("\tonline <pool> <device> ...\n"));
246 case HELP_REPLACE:
247 return (gettext("\treplace [-f] <pool> <device> "
248 "[new-device]\n"));
249 case HELP_REMOVE:
250 return (gettext("\tremove [-nps] <pool> <device> ...\n"));
251 case HELP_REOPEN:
252 return (gettext("\treopen <pool>\n"));
253 case HELP_SCRUB:
254 return (gettext("\tscrub [-s | -p] <pool> ...\n"));
255 case HELP_STATUS:
256 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
257 "[count]]\n"));
258 case HELP_UPGRADE:
259 return (gettext("\tupgrade\n"
260 "\tupgrade -v\n"
261 "\tupgrade [-V version] <-a | pool ...>\n"));
262 case HELP_GET:
263 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
264 "<\"all\" | property[,...]> <pool> ...\n"));
265 case HELP_SET:
266 return (gettext("\tset <property=value> <pool> \n"));
267 case HELP_SPLIT:
268 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
269 "\t [-o property=value] <pool> <newpool> "
270 "[<device> ...]\n"));
271 case HELP_REGUID:
272 return (gettext("\treguid <pool>\n"));
273 }
274
275 abort();
276 /* NOTREACHED */
277 }
278
279
280 /*
281 * Callback routine that will print out a pool property value.
282 */
283 static int
284 print_prop_cb(int prop, void *cb)
285 {
286 FILE *fp = cb;
287
288 (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop));
289
290 if (zpool_prop_readonly(prop))
291 (void) fprintf(fp, " NO ");
292 else
293 (void) fprintf(fp, " YES ");
294
295 if (zpool_prop_values(prop) == NULL)
296 (void) fprintf(fp, "-\n");
297 else
298 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
299
394
395 static boolean_t
396 prop_list_contains_feature(nvlist_t *proplist)
397 {
398 nvpair_t *nvp;
399 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
400 nvp = nvlist_next_nvpair(proplist, nvp)) {
401 if (zpool_prop_feature(nvpair_name(nvp)))
402 return (B_TRUE);
403 }
404 return (B_FALSE);
405 }
406
407 /*
408 * Add a property pair (name, string-value) into a property nvlist.
409 */
410 static int
411 add_prop_list(const char *propname, char *propval, nvlist_t **props,
412 boolean_t poolprop)
413 {
414 zpool_prop_t prop = ZPOOL_PROP_INVAL;
415 zfs_prop_t fprop;
416 nvlist_t *proplist;
417 const char *normnm;
418 char *strval;
419
420 if (*props == NULL &&
421 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
422 (void) fprintf(stderr,
423 gettext("internal error: out of memory\n"));
424 return (1);
425 }
426
427 proplist = *props;
428
429 if (poolprop) {
430 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
431
432 if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL &&
433 !zpool_prop_feature(propname)) {
434 (void) fprintf(stderr, gettext("property '%s' is "
435 "not a valid pool property\n"), propname);
436 return (2);
437 }
438
439 /*
440 * feature@ properties and version should not be specified
441 * at the same time.
442 */
443 if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
444 nvlist_exists(proplist, vname)) ||
445 (prop == ZPOOL_PROP_VERSION &&
446 prop_list_contains_feature(proplist))) {
447 (void) fprintf(stderr, gettext("'feature@' and "
448 "'version' properties cannot be specified "
449 "together\n"));
450 return (2);
451 }
452
453
454 if (zpool_prop_feature(propname))
455 normnm = propname;
456 else
457 normnm = zpool_prop_to_name(prop);
458 } else {
459 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
460 normnm = zfs_prop_to_name(fprop);
461 } else {
462 normnm = propname;
463 }
464 }
465
466 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
467 prop != ZPOOL_PROP_CACHEFILE) {
468 (void) fprintf(stderr, gettext("property '%s' "
469 "specified multiple times\n"), propname);
470 return (2);
471 }
472
473 if (nvlist_add_string(proplist, normnm, propval) != 0) {
474 (void) fprintf(stderr, gettext("internal "
475 "error: out of memory\n"));
476 return (1);
477 }
478
479 return (0);
480 }
481
482 /*
483 * zpool add [-fn] <pool> <vdev> ...
484 *
485 * -f Force addition of devices, even if they appear in use
486 * -n Do not add the devices, but display the resulting layout if
487 * they were to be added.
488 *
489 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
490 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
491 * libzfs.
492 */
493 int
494 zpool_do_add(int argc, char **argv)
495 {
496 boolean_t force = B_FALSE;
497 boolean_t dryrun = B_FALSE;
498 int c;
499 nvlist_t *nvroot;
500 char *poolname;
501 zpool_boot_label_t boot_type;
502 uint64_t boot_size;
580 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
581 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
582 } else if (num_logs(nvroot) > 0) {
583 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
584 }
585
586 ret = 0;
587 } else {
588 ret = (zpool_add(zhp, nvroot) != 0);
589 }
590
591 nvlist_free(nvroot);
592 zpool_close(zhp);
593
594 return (ret);
595 }
596
597 /*
598 * zpool remove <pool> <vdev> ...
599 *
600 * Removes the given vdev from the pool.
601 */
602 int
603 zpool_do_remove(int argc, char **argv)
604 {
605 char *poolname;
606 int i, ret = 0;
607 zpool_handle_t *zhp;
608 boolean_t stop = B_FALSE;
609 boolean_t noop = B_FALSE;
610 boolean_t parsable = B_FALSE;
611 char c;
612
613 /* check options */
614 while ((c = getopt(argc, argv, "nps")) != -1) {
615 switch (c) {
616 case 'n':
617 noop = B_TRUE;
618 break;
619 case 'p':
620 parsable = B_TRUE;
621 break;
622 case 's':
623 stop = B_TRUE;
624 break;
625 case '?':
626 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
627 optopt);
628 usage(B_FALSE);
629 }
630 }
631
632 argc -= optind;
633 argv += optind;
634
635 /* get pool name and check number of arguments */
636 if (argc < 1) {
637 (void) fprintf(stderr, gettext("missing pool name argument\n"));
638 usage(B_FALSE);
639 }
640
641 poolname = argv[0];
642
643 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
644 return (1);
645
646 if (stop && noop) {
647 (void) fprintf(stderr, gettext("stop request ignored\n"));
648 return (0);
649 }
650
651 if (stop) {
652 if (argc > 1) {
653 (void) fprintf(stderr, gettext("too many arguments\n"));
654 usage(B_FALSE);
655 }
656 if (zpool_vdev_remove_cancel(zhp) != 0)
657 ret = 1;
658 } else {
659 if (argc < 2) {
660 (void) fprintf(stderr, gettext("missing device\n"));
661 usage(B_FALSE);
662 }
663
664 for (i = 1; i < argc; i++) {
665 if (noop) {
666 uint64_t size;
667
668 if (zpool_vdev_indirect_size(zhp, argv[i],
669 &size) != 0) {
670 ret = 1;
671 break;
672 }
673 if (parsable) {
674 (void) printf("%s %llu\n",
675 argv[i], size);
676 } else {
677 char valstr[32];
678 zfs_nicenum(size, valstr,
679 sizeof (valstr));
680 (void) printf("Memory that will be "
681 "used after removing %s: %s\n",
682 argv[i], valstr);
683 }
684 } else {
685 if (zpool_vdev_remove(zhp, argv[i]) != 0)
686 ret = 1;
687 }
688 }
689 }
690
691 return (ret);
692 }
693
694 /*
695 * zpool labelclear [-f] <vdev>
696 *
697 * -f Force clearing the label for the vdevs which are members of
698 * the exported or foreign pools.
699 *
700 * Verifies that the vdev is not active and zeros out the label information
701 * on the device.
702 */
703 int
704 zpool_do_labelclear(int argc, char **argv)
705 {
706 char vdev[MAXPATHLEN];
707 char *name = NULL;
708 struct stat st;
709 int c, fd, ret = 0;
1247 usage(B_FALSE);
1248 }
1249 if (argc > 1) {
1250 (void) fprintf(stderr, gettext("too many arguments\n"));
1251 usage(B_FALSE);
1252 }
1253
1254 pool = argv[0];
1255
1256 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1257 /*
1258 * As a special case, check for use of '/' in the name, and
1259 * direct the user to use 'zfs destroy' instead.
1260 */
1261 if (strchr(pool, '/') != NULL)
1262 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1263 "destroy a dataset\n"));
1264 return (1);
1265 }
1266
1267 if (zpool_disable_datasets(zhp, force) != 0) {
1268 (void) fprintf(stderr, gettext("could not destroy '%s': "
1269 "could not unmount datasets\n"), zpool_get_name(zhp));
1270 return (1);
1271 }
1272
1273 /* The history must be logged as part of the export */
1274 log_history = B_FALSE;
1275
1276 ret = (zpool_destroy(zhp, history_str) != 0);
1277
1278 zpool_close(zhp);
1279
1280 return (ret);
1281 }
1282
1283 /*
1284 * zpool export [-f] <pool> ...
1285 *
1286 * -f Forcefully unmount datasets
1287 *
1288 * Export the given pools. By default, the command will attempt to cleanly
1289 * unmount any active datasets within the pool. If the '-f' flag is specified,
1290 * then the datasets will be forcefully unmounted.
1291 */
1292 int
1293 zpool_do_export(int argc, char **argv)
1294 {
1295 boolean_t force = B_FALSE;
1296 boolean_t hardforce = B_FALSE;
1297 int c;
1298 zpool_handle_t *zhp;
1299 int ret;
1300 int i;
1301
1302 /* check options */
1303 while ((c = getopt(argc, argv, "fF")) != -1) {
1304 switch (c) {
1305 case 'f':
1306 force = B_TRUE;
1307 break;
1308 case 'F':
1309 hardforce = B_TRUE;
1310 break;
1311 case '?':
1312 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1313 optopt);
1314 usage(B_FALSE);
1315 }
1316 }
1317
1318 argc -= optind;
1319 argv += optind;
1320
1321 /* check arguments */
1322 if (argc < 1) {
1323 (void) fprintf(stderr, gettext("missing pool argument\n"));
1324 usage(B_FALSE);
1325 }
1326
1327 ret = 0;
1328 for (i = 0; i < argc; i++) {
1329 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1330 ret = 1;
1331 continue;
1332 }
1333
1334 if (zpool_disable_datasets(zhp, force) != 0) {
1335 ret = 1;
1336 zpool_close(zhp);
1337 continue;
1338 }
1339
1340 /* The history must be logged as part of the export */
1341 log_history = B_FALSE;
1342
1343 if (hardforce) {
1344 if (zpool_export_force(zhp, history_str) != 0)
1345 ret = 1;
1346 } else if (zpool_export(zhp, force, history_str) != 0) {
1347 ret = 1;
1348 }
1349
1350 zpool_close(zhp);
1351 }
1352
1353 return (ret);
1354 }
1355
1356 /*
1357 * Given a vdev configuration, determine the maximum width needed for the device
1358 * name column.
1359 */
1360 static int
1361 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1362 {
1363 char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1364 nvlist_t **child;
1365 uint_t c, children;
1366 int ret;
1442 zpool_close(zhp);
1443 return (0);
1444 }
1445
1446 /*
1447 * Print out configuration state as requested by status_callback.
1448 */
1449 void
1450 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1451 int namewidth, int depth, boolean_t isspare)
1452 {
1453 nvlist_t **child;
1454 uint_t c, children;
1455 pool_scan_stat_t *ps = NULL;
1456 vdev_stat_t *vs;
1457 char rbuf[6], wbuf[6], cbuf[6];
1458 char *vname;
1459 uint64_t notpresent;
1460 spare_cbdata_t cb;
1461 const char *state;
1462 char *type;
1463
1464 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1465 &child, &children) != 0)
1466 children = 0;
1467
1468 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1469 (uint64_t **)&vs, &c) == 0);
1470
1471 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1472
1473 if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
1474 return;
1475
1476 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1477 if (isspare) {
1478 /*
1479 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1480 * online drives.
1481 */
1482 if (vs->vs_aux == VDEV_AUX_SPARED)
1483 state = "INUSE";
1484 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1485 state = "AVAIL";
1486 }
1487
1488 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth,
1489 name, state);
1490
1491 if (!isspare) {
1492 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1493 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1494 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1495 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1545 case VDEV_AUX_ERR_EXCEEDED:
1546 (void) printf(gettext("too many errors"));
1547 break;
1548
1549 case VDEV_AUX_IO_FAILURE:
1550 (void) printf(gettext("experienced I/O failures"));
1551 break;
1552
1553 case VDEV_AUX_BAD_LOG:
1554 (void) printf(gettext("bad intent log"));
1555 break;
1556
1557 case VDEV_AUX_EXTERNAL:
1558 (void) printf(gettext("external device fault"));
1559 break;
1560
1561 case VDEV_AUX_SPLIT_POOL:
1562 (void) printf(gettext("split into new pool"));
1563 break;
1564
1565 case VDEV_AUX_CHILDREN_OFFLINE:
1566 (void) printf(gettext("all children offline"));
1567 break;
1568
1569 default:
1570 (void) printf(gettext("corrupted data"));
1571 break;
1572 }
1573 }
1574
1575 (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1576 (uint64_t **)&ps, &c);
1577
1578 if (ps && ps->pss_state == DSS_SCANNING &&
1579 vs->vs_scan_processed != 0 && children == 0) {
1580 (void) printf(gettext(" (%s)"),
1581 (ps->pss_func == POOL_SCAN_RESILVER) ?
1582 "resilvering" : "repairing");
1583 }
1584
1585 (void) printf("\n");
1586
1587 for (c = 0; c < children; c++) {
1588 uint64_t islog = B_FALSE, ishole = B_FALSE;
1589
1590 /* Don't print logs or holes here */
1591 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1592 &islog);
1593 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1594 &ishole);
1595 if (islog || ishole)
1596 continue;
1597 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1598 print_status_config(zhp, vname, child[c],
1599 namewidth, depth + 2, isspare);
1600 free(vname);
1601 }
1602 }
1603
1604
1605 /*
1606 * Print the configuration of an exported pool. Iterate over all vdevs in the
1607 * pool, printing out the name and status for each one.
1608 */
1609 void
1610 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1611 {
1612 nvlist_t **child;
1613 uint_t c, children;
1614 vdev_stat_t *vs;
1615 char *type, *vname;
1636 case VDEV_AUX_BAD_GUID_SUM:
1637 (void) printf(gettext("missing device"));
1638 break;
1639
1640 case VDEV_AUX_NO_REPLICAS:
1641 (void) printf(gettext("insufficient replicas"));
1642 break;
1643
1644 case VDEV_AUX_VERSION_NEWER:
1645 (void) printf(gettext("newer version"));
1646 break;
1647
1648 case VDEV_AUX_UNSUP_FEAT:
1649 (void) printf(gettext("unsupported feature(s)"));
1650 break;
1651
1652 case VDEV_AUX_ERR_EXCEEDED:
1653 (void) printf(gettext("too many errors"));
1654 break;
1655
1656 case VDEV_AUX_CHILDREN_OFFLINE:
1657 (void) printf(gettext("all children offline"));
1658 break;
1659
1660 default:
1661 (void) printf(gettext("corrupted data"));
1662 break;
1663 }
1664 }
1665 (void) printf("\n");
1666
1667 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1668 &child, &children) != 0)
1669 return;
1670
1671 for (c = 0; c < children; c++) {
1672 uint64_t is_log = B_FALSE;
1673
1674 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1675 &is_log);
1676 if (is_log)
1677 continue;
1678
1679 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1680 print_import_config(vname, child[c], namewidth, depth + 2);
1681 free(vname);
1682 }
1683
1684 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1685 &child, &children) == 0) {
1686 (void) printf(gettext("\tcache\n"));
1687 for (c = 0; c < children; c++) {
1688 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1689 (void) printf("\t %s\n", vname);
1690 free(vname);
1691 }
1692 }
1693
1694 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1695 &child, &children) == 0) {
1696 (void) printf(gettext("\tspares\n"));
1724
1725 for (c = 0; c < children; c++) {
1726 uint64_t is_log = B_FALSE;
1727 char *name;
1728
1729 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1730 &is_log);
1731 if (!is_log)
1732 continue;
1733 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1734 if (verbose)
1735 print_status_config(zhp, name, child[c], namewidth,
1736 2, B_FALSE);
1737 else
1738 print_import_config(name, child[c], namewidth, 2);
1739 free(name);
1740 }
1741 }
1742
1743 /*
1744 * Display the status for the given pool.
1745 */
1746 static void
1747 show_import(nvlist_t *config)
1748 {
1749 uint64_t pool_state;
1750 vdev_stat_t *vs;
1751 char *name;
1752 uint64_t guid;
1753 char *msgid;
1754 nvlist_t *nvroot;
1755 int reason;
1756 const char *health;
1757 uint_t vsc;
1758 int namewidth;
1759 char *comment;
1760
1761 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1762 &name) == 0);
1763 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1938 if (pool_state == POOL_STATE_DESTROYED)
1939 (void) printf(gettext("\tThe pool was destroyed, "
1940 "but can be imported using the '-Df' flags.\n"));
1941 else if (pool_state != POOL_STATE_EXPORTED)
1942 (void) printf(gettext("\tThe pool may be active on "
1943 "another system, but can be imported using\n\t"
1944 "the '-f' flag.\n"));
1945 }
1946
1947 if (msgid != NULL)
1948 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
1949 msgid);
1950
1951 (void) printf(gettext(" config:\n\n"));
1952
1953 namewidth = max_width(NULL, nvroot, 0, 0);
1954 if (namewidth < 10)
1955 namewidth = 10;
1956
1957 print_import_config(name, nvroot, namewidth, 0);
1958 if (num_logs(nvroot) > 0)
1959 print_logs(NULL, nvroot, namewidth, B_FALSE);
1960
1961 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1962 (void) printf(gettext("\n\tAdditional devices are known to "
1963 "be part of this pool, though their\n\texact "
1964 "configuration cannot be determined.\n"));
1965 }
1966 }
1967
1968 /*
1969 * Perform the import for the given configuration. This passes the heavy
1970 * lifting off to zpool_import_props(), and then mounts the datasets contained
1971 * within the pool.
1972 */
1973 static int
1974 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1975 nvlist_t *props, int flags)
1976 {
1977 zpool_handle_t *zhp;
1978 char *name;
1979 uint64_t state;
1980 uint64_t version;
1981
1982 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1983 &name) == 0);
1984
1985 verify(nvlist_lookup_uint64(config,
1986 ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1987 verify(nvlist_lookup_uint64(config,
1988 ZPOOL_CONFIG_VERSION, &version) == 0);
1989 if (!SPA_VERSION_IS_SUPPORTED(version)) {
1990 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1991 "is formatted using an unsupported ZFS version\n"), name);
1992 return (1);
1993 } else if (state != POOL_STATE_EXPORTED &&
1994 !(flags & ZFS_IMPORT_ANY_HOST)) {
1995 uint64_t hostid;
2019 } else {
2020 (void) fprintf(stderr, gettext("cannot import '%s': "
2021 "pool may be in use from other system\n"), name);
2022 (void) fprintf(stderr, gettext("use '-f' to import "
2023 "anyway\n"));
2024 return (1);
2025 }
2026 }
2027
2028 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2029 return (1);
2030
2031 if (newname != NULL)
2032 name = (char *)newname;
2033
2034 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2035 return (1);
2036
2037 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2038 !(flags & ZFS_IMPORT_ONLY) &&
2039 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
2040 zpool_close(zhp);
2041 return (1);
2042 }
2043
2044 zpool_close(zhp);
2045 return (0);
2046 }
2047
2048 /*
2049 * zpool import [-d dir] [-D]
2050 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2051 * [-d dir | -c cachefile] [-f] -a
2052 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2053 * [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
2054 *
2055 * -c Read pool information from a cachefile instead of searching
2056 * devices.
2057 *
2058 * -d Scan in a specific directory, other than /dev/dsk. More than
2059 * one directory can be specified using multiple '-d' options.
2060 *
2061 * -D Scan for previously destroyed pools or import all or only
2062 * specified destroyed pools.
2063 *
2064 * -R Temporarily import the pool, with all mountpoints relative to
2065 * the given root. The pool will remain exported when the machine
2066 * is rebooted.
2067 *
2068 * -V Import even in the presence of faulted vdevs. This is an
2069 * intentionally undocumented option for testing purposes, and
2070 * treats the pool configuration as complete, leaving any bad
2071 * vdevs in the FAULTED state. In other words, it does verbatim
2072 * import.
2073 *
2074 * -f Force import, even if it appears that the pool is active.
2075 *
2076 * -F Attempt rewind if necessary.
2077 *
2078 * -n See if rewind would work, but don't actually rewind.
2079 *
2080 * -N Import the pool but don't mount datasets.
2081 *
2082 * -T Specify a starting txg to use for import. This option is
2083 * intentionally undocumented option for testing purposes.
2084 *
2085 * -a Import all pools found.
2086 *
2087 * -o Set property=value and/or temporary mount options (without '=').
2088 *
2089 * The import command scans for pools to import, and import pools based on pool
2090 * name and GUID. The pool can also be renamed as part of the import process.
2091 */
2092 int
2093 zpool_do_import(int argc, char **argv)
2094 {
2095 char **searchdirs = NULL;
2096 int nsearch = 0;
2097 int c;
2098 int err = 0;
2099 nvlist_t *pools = NULL;
2100 boolean_t do_all = B_FALSE;
2101 boolean_t do_destroyed = B_FALSE;
2102 char *mntopts = NULL;
2103 nvpair_t *elem;
2104 nvlist_t *config;
2105 uint64_t searchguid = 0;
2106 char *searchname = NULL;
2107 char *propval;
2108 nvlist_t *found_config;
2109 nvlist_t *policy = NULL;
2110 nvlist_t *props = NULL;
2111 boolean_t first;
2112 int flags = ZFS_IMPORT_NORMAL;
2113 uint32_t rewind_policy = ZPOOL_NO_REWIND;
2114 boolean_t dryrun = B_FALSE;
2115 boolean_t do_rewind = B_FALSE;
2116 boolean_t xtreme_rewind = B_FALSE;
2117 uint64_t pool_state, txg = -1ULL;
2118 char *cachefile = NULL;
2119 importargs_t idata = { 0 };
2120 char *endptr;
2121
2122 /* check options */
2123 while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:rR:T:VX")) != -1) {
2124 switch (c) {
2125 case 'a':
2126 do_all = B_TRUE;
2127 break;
2128 case 'c':
2129 cachefile = optarg;
2130 break;
2131 case 'd':
2132 if (searchdirs == NULL) {
2133 searchdirs = safe_malloc(sizeof (char *));
2134 } else {
2135 char **tmp = safe_malloc((nsearch + 1) *
2136 sizeof (char *));
2137 bcopy(searchdirs, tmp, nsearch *
2138 sizeof (char *));
2139 free(searchdirs);
2140 searchdirs = tmp;
2141 }
2142 searchdirs[nsearch++] = optarg;
2143 break;
2165 propval++;
2166 if (add_prop_list(optarg, propval,
2167 &props, B_TRUE))
2168 goto error;
2169 } else {
2170 mntopts = optarg;
2171 }
2172 break;
2173 case 'R':
2174 if (add_prop_list(zpool_prop_to_name(
2175 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2176 goto error;
2177 if (nvlist_lookup_string(props,
2178 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
2179 &propval) == 0)
2180 break;
2181 if (add_prop_list(zpool_prop_to_name(
2182 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2183 goto error;
2184 break;
2185 case 'T':
2186 errno = 0;
2187 txg = strtoull(optarg, &endptr, 0);
2188 if (errno != 0 || *endptr != '\0') {
2189 (void) fprintf(stderr,
2190 gettext("invalid txg value\n"));
2191 usage(B_FALSE);
2192 }
2193 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2194 break;
2195 case 'V':
2196 flags |= ZFS_IMPORT_VERBATIM;
2197 break;
2198 case 'X':
2199 xtreme_rewind = B_TRUE;
2200 break;
2201 case ':':
2202 (void) fprintf(stderr, gettext("missing argument for "
2203 "'%c' option\n"), optopt);
2204 usage(B_FALSE);
2287 errno = 0;
2288 searchguid = strtoull(argv[0], &endptr, 10);
2289 if (errno != 0 || *endptr != '\0') {
2290 searchname = argv[0];
2291 searchguid = 0;
2292 }
2293 found_config = NULL;
2294
2295 /*
2296 * User specified a name or guid. Ensure it's unique.
2297 */
2298 idata.unique = B_TRUE;
2299 }
2300
2301
2302 idata.path = searchdirs;
2303 idata.paths = nsearch;
2304 idata.poolname = searchname;
2305 idata.guid = searchguid;
2306 idata.cachefile = cachefile;
2307 idata.policy = policy;
2308
2309 pools = zpool_search_import(g_zfs, &idata);
2310
2311 if (pools != NULL && idata.exists &&
2312 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2313 (void) fprintf(stderr, gettext("cannot import '%s': "
2314 "a pool with that name already exists\n"),
2315 argv[0]);
2316 (void) fprintf(stderr, gettext("use the form '%s "
2317 "<pool | id> <newpool>' to give it a new name\n"),
2318 "zpool import");
2319 err = 1;
2320 } else if (pools == NULL && idata.exists) {
2321 (void) fprintf(stderr, gettext("cannot import '%s': "
2322 "a pool with that name is already created/imported,\n"),
2323 argv[0]);
2324 (void) fprintf(stderr, gettext("and no additional pools "
2325 "with that name were found\n"));
2326 err = 1;
2327 } else if (pools == NULL) {
2352 verify(nvpair_value_nvlist(elem, &config) == 0);
2353
2354 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2355 &pool_state) == 0);
2356 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2357 continue;
2358 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2359 continue;
2360
2361 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2362 policy) == 0);
2363
2364 if (argc == 0) {
2365 if (first)
2366 first = B_FALSE;
2367 else if (!do_all)
2368 (void) printf("\n");
2369
2370 if (do_all) {
2371 err |= do_import(config, NULL, mntopts,
2372 props, flags);
2373 } else {
2374 show_import(config);
2375 }
2376 } else if (searchname != NULL) {
2377 char *name;
2378
2379 /*
2380 * We are searching for a pool based on name.
2381 */
2382 verify(nvlist_lookup_string(config,
2383 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2384
2385 if (strcmp(name, searchname) == 0) {
2386 if (found_config != NULL) {
2387 (void) fprintf(stderr, gettext(
2388 "cannot import '%s': more than "
2389 "one matching pool\n"), searchname);
2390 (void) fprintf(stderr, gettext(
2391 "import by numeric ID instead\n"));
2392 err = B_TRUE;
2401 */
2402 verify(nvlist_lookup_uint64(config,
2403 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2404
2405 if (guid == searchguid)
2406 found_config = config;
2407 }
2408 }
2409
2410 /*
2411 * If we were searching for a specific pool, verify that we found a
2412 * pool, and then do the import.
2413 */
2414 if (argc != 0 && err == 0) {
2415 if (found_config == NULL) {
2416 (void) fprintf(stderr, gettext("cannot import '%s': "
2417 "no such pool available\n"), argv[0]);
2418 err = B_TRUE;
2419 } else {
2420 err |= do_import(found_config, argc == 1 ? NULL :
2421 argv[1], mntopts, props, flags);
2422 }
2423 }
2424
2425 /*
2426 * If we were just looking for pools, report an error if none were
2427 * found.
2428 */
2429 if (argc == 0 && first)
2430 (void) fprintf(stderr,
2431 gettext("no pools available to import\n"));
2432
2433 error:
2434 nvlist_free(props);
2435 nvlist_free(pools);
2436 nvlist_free(policy);
2437 free(searchdirs);
2438
2439 return (err ? 1 : 0);
2440 }
2441
2442 typedef struct iostat_cbdata {
2443 boolean_t cb_verbose;
2444 int cb_namewidth;
2445 int cb_iteration;
2446 zpool_list_t *cb_list;
2447 } iostat_cbdata_t;
2448
2449 static void
2450 print_iostat_separator(iostat_cbdata_t *cb)
2451 {
2452 int i = 0;
2453
2454 for (i = 0; i < cb->cb_namewidth; i++)
2455 (void) printf("-");
2456 (void) printf(" ----- ----- ----- ----- ----- -----\n");
2457 }
2458
2459 static void
2460 print_iostat_header(iostat_cbdata_t *cb)
2461 {
2462 (void) printf("%*s capacity operations bandwidth\n",
2463 cb->cb_namewidth, "");
2464 (void) printf("%-*s alloc free read write read write\n",
2465 cb->cb_namewidth, "pool");
2466 print_iostat_separator(cb);
2467 }
2468
2469 /*
2470 * Display a single statistic.
2471 */
2472 static void
2473 print_one_stat(uint64_t value)
2474 {
2475 char buf[64];
2476
2477 zfs_nicenum(value, buf, sizeof (buf));
2478 (void) printf(" %5s", buf);
2479 }
2480
2481 /*
2482 * Print out all the statistics for the given vdev. This can either be the
2483 * toplevel configuration, or called recursively. If 'name' is NULL, then this
2484 * is a verbose output, and we don't want to display the toplevel pool stats.
2485 */
2486 void
2487 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2488 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2489 {
2490 nvlist_t **oldchild, **newchild;
2491 uint_t c, children;
2492 vdev_stat_t *oldvs, *newvs;
2493 vdev_stat_t zerovs = { 0 };
2494 uint64_t tdelta;
2495 double scale;
2496 char *vname;
2497
2498 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
2499 return;
2500
2501 if (oldnv != NULL) {
2502 verify(nvlist_lookup_uint64_array(oldnv,
2503 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2504 } else {
2505 oldvs = &zerovs;
2506 }
2507
2508 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2509 (uint64_t **)&newvs, &c) == 0);
2510
2511 if (strlen(name) + depth > cb->cb_namewidth)
2512 (void) printf("%*s%s", depth, "", name);
2513 else
2514 (void) printf("%*s%s%*s", depth, "", name,
2515 (int)(cb->cb_namewidth - strlen(name) - depth), "");
2516
2517 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2518
2519 if (tdelta == 0)
2520 scale = 1.0;
2524 /* only toplevel vdevs have capacity stats */
2525 if (newvs->vs_space == 0) {
2526 (void) printf(" - -");
2527 } else {
2528 print_one_stat(newvs->vs_alloc);
2529 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2530 }
2531
2532 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2533 oldvs->vs_ops[ZIO_TYPE_READ])));
2534
2535 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2536 oldvs->vs_ops[ZIO_TYPE_WRITE])));
2537
2538 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2539 oldvs->vs_bytes[ZIO_TYPE_READ])));
2540
2541 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2542 oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2543
2544 (void) printf("\n");
2545
2546 if (!cb->cb_verbose)
2547 return;
2548
2549 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2550 &newchild, &children) != 0)
2551 return;
2552
2553 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2554 &oldchild, &c) != 0)
2555 return;
2556
2557 for (c = 0; c < children; c++) {
2558 uint64_t ishole = B_FALSE, islog = B_FALSE;
2559
2560 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2561 &ishole);
2562
2563 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2564 &islog);
2565
2566 if (ishole || islog)
2567 continue;
2568
2569 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2570 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2571 newchild[c], cb, depth + 2);
2572 free(vname);
2573 }
2574
2575 /*
2576 * Log device section
2577 */
2578
2579 if (num_logs(newnv) > 0) {
2580 (void) printf("%-*s - - - - - "
2581 "-\n", cb->cb_namewidth, "logs");
2582
2583 for (c = 0; c < children; c++) {
2584 uint64_t islog = B_FALSE;
2585 (void) nvlist_lookup_uint64(newchild[c],
2586 ZPOOL_CONFIG_IS_LOG, &islog);
2587
2588 if (islog) {
2589 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2590 B_FALSE);
2591 print_vdev_stats(zhp, vname, oldnv ?
2592 oldchild[c] : NULL, newchild[c],
2593 cb, depth + 2);
2594 free(vname);
2595 }
2596 }
2597
2598 }
2599
2600 /*
2601 * Include level 2 ARC devices in iostat output
2602 */
2603 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2604 &newchild, &children) != 0)
2605 return;
2606
2607 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2608 &oldchild, &c) != 0)
2609 return;
2610
2611 if (children > 0) {
2612 (void) printf("%-*s - - - - - "
2613 "-\n", cb->cb_namewidth, "cache");
2614 for (c = 0; c < children; c++) {
2615 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2616 B_FALSE);
2617 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2618 newchild[c], cb, depth + 2);
3087 void
3088 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3089 list_cbdata_t *cb, int depth)
3090 {
3091 nvlist_t **child;
3092 vdev_stat_t *vs;
3093 uint_t c, children;
3094 char *vname;
3095 boolean_t scripted = cb->cb_scripted;
3096 uint64_t islog = B_FALSE;
3097 boolean_t haslog = B_FALSE;
3098 char *dashes = "%-*s - - - - - -\n";
3099
3100 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3101 (uint64_t **)&vs, &c) == 0);
3102
3103 if (name != NULL) {
3104 boolean_t toplevel = (vs->vs_space != 0);
3105 uint64_t cap;
3106
3107 if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
3108 return;
3109
3110 if (scripted)
3111 (void) printf("\t%s", name);
3112 else if (strlen(name) + depth > cb->cb_namewidth)
3113 (void) printf("%*s%s", depth, "", name);
3114 else
3115 (void) printf("%*s%s%*s", depth, "", name,
3116 (int)(cb->cb_namewidth - strlen(name) - depth), "");
3117
3118 /*
3119 * Print the properties for the individual vdevs. Some
3120 * properties are only applicable to toplevel vdevs. The
3121 * 'toplevel' boolean value is passed to the print_one_column()
3122 * to indicate that the value is valid.
3123 */
3124 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3125 toplevel);
3126 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3127 toplevel);
3128 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3129 scripted, toplevel);
3221 }
3222
3223 /*
3224 * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3225 *
3226 * -H Scripted mode. Don't display headers, and separate properties
3227 * by a single tab.
3228 * -o List of properties to display. Defaults to
3229 * "name,size,allocated,free,expandsize,fragmentation,capacity,"
3230 * "dedupratio,health,altroot"
3231 * -p Diplay values in parsable (exact) format.
3232 * -T Display a timestamp in date(1) or Unix format
3233 *
3234 * List all pools in the system, whether or not they're healthy. Output space
3235 * statistics for each one, as well as health status summary.
3236 */
3237 int
3238 zpool_do_list(int argc, char **argv)
3239 {
3240 int c;
3241 int ret;
3242 list_cbdata_t cb = { 0 };
3243 static char default_props[] =
3244 "name,size,allocated,free,expandsize,fragmentation,capacity,"
3245 "dedupratio,health,altroot";
3246 char *props = default_props;
3247 unsigned long interval = 0, count = 0;
3248 zpool_list_t *list;
3249 boolean_t first = B_TRUE;
3250
3251 /* check options */
3252 while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3253 switch (c) {
3254 case 'H':
3255 cb.cb_scripted = B_TRUE;
3256 break;
3257 case 'o':
3258 props = optarg;
3259 break;
3260 case 'p':
3261 cb.cb_literal = B_TRUE;
3965 int
3966 scrub_callback(zpool_handle_t *zhp, void *data)
3967 {
3968 scrub_cbdata_t *cb = data;
3969 int err;
3970
3971 /*
3972 * Ignore faulted pools.
3973 */
3974 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
3975 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
3976 "currently unavailable\n"), zpool_get_name(zhp));
3977 return (1);
3978 }
3979
3980 err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
3981
3982 return (err != 0);
3983 }
3984
3985 /*
3986 * zpool scrub [-s | -p] <pool> ...
3987 *
3988 * -s Stop. Stops any in-progress scrub.
3989 * -p Pause. Pause in-progress scrub.
3990 */
3991 int
3992 zpool_do_scrub(int argc, char **argv)
3993 {
3994 int c;
3995 scrub_cbdata_t cb;
3996
3997 cb.cb_type = POOL_SCAN_SCRUB;
3998 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
3999
4000 /* check options */
4001 while ((c = getopt(argc, argv, "sp")) != -1) {
4002 switch (c) {
4003 case 's':
4004 cb.cb_type = POOL_SCAN_NONE;
4005 break;
4006 case 'p':
4007 cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4008 break;
4009 case '?':
4010 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4011 optopt);
4012 usage(B_FALSE);
4013 }
4014 }
4015
4016 if (cb.cb_type == POOL_SCAN_NONE &&
4017 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4018 (void) fprintf(stderr, gettext("invalid option combination: "
4019 "-s and -p are mutually exclusive\n"));
4020 usage(B_FALSE);
4021 }
4022
4023 cb.cb_argc = argc;
4024 cb.cb_argv = argv;
4025 argc -= optind;
4026 argv += optind;
4027
4028 if (argc < 1) {
4029 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4030 usage(B_FALSE);
4031 }
4032
4033 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4034 }
4035
4036 typedef struct status_cbdata {
4037 int cb_count;
4038 boolean_t cb_allpools;
4039 boolean_t cb_verbose;
4040 boolean_t cb_explain;
4041 boolean_t cb_first;
4042 boolean_t cb_dedup_stats;
4043 } status_cbdata_t;
4044
4045 /*
4046 * Print out detailed scrub status.
4047 */
4048 static void
4049 print_scan_status(pool_scan_stat_t *ps)
4050 {
4051 time_t start, end, pause;
4052 uint64_t elapsed, mins_left, hours_left;
4053 uint64_t pass_exam, examined, total;
4054 uint_t rate;
4055 double fraction_done;
4056 char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4057
4058 (void) printf(gettext(" scan: "));
4059
4060 /* If there's never been a scan, there's not much to say. */
4061 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4062 ps->pss_func >= POOL_SCAN_FUNCS) {
4063 (void) printf(gettext("none requested\n"));
4064 return;
4065 }
4066
4067 start = ps->pss_start_time;
4068 end = ps->pss_end_time;
4069 pause = ps->pss_pass_scrub_pause;
4070 zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4071
4072 assert(ps->pss_func == POOL_SCAN_SCRUB ||
4073 ps->pss_func == POOL_SCAN_RESILVER);
4074 /*
4075 * Scan is finished or canceled.
4076 */
4077 if (ps->pss_state == DSS_FINISHED) {
4078 uint64_t minutes_taken = (end - start) / 60;
4079 char *fmt = NULL;
4080
4081 if (ps->pss_func == POOL_SCAN_SCRUB) {
4082 fmt = gettext("scrub repaired %s in %lluh%um with "
4083 "%llu errors on %s");
4084 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4085 fmt = gettext("resilvered %s in %lluh%um with "
4086 "%llu errors on %s");
4087 }
4088 /* LINTED */
4089 (void) printf(fmt, processed_buf,
4090 (u_longlong_t)(minutes_taken / 60),
4091 (uint_t)(minutes_taken % 60),
4092 (u_longlong_t)ps->pss_errors,
4093 ctime((time_t *)&end));
4094 return;
4095 } else if (ps->pss_state == DSS_CANCELED) {
4096 if (ps->pss_func == POOL_SCAN_SCRUB) {
4097 (void) printf(gettext("scrub canceled on %s"),
4098 ctime(&end));
4099 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4100 (void) printf(gettext("resilver canceled on %s"),
4101 ctime(&end));
4102 }
4103 return;
4104 }
4105
4106 assert(ps->pss_state == DSS_SCANNING);
4107
4108 /*
4109 * Scan is in progress.
4110 */
4111 if (ps->pss_func == POOL_SCAN_SCRUB) {
4112 if (pause == 0) {
4113 (void) printf(gettext("scrub in progress since %s"),
4114 ctime(&start));
4115 } else {
4116 char buf[32];
4117 struct tm *p = localtime(&pause);
4118 (void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p);
4119 (void) printf(gettext("scrub paused since %s\n"), buf);
4120 (void) printf(gettext("\tscrub started on %s"),
4121 ctime(&start));
4122 }
4123 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4124 (void) printf(gettext("resilver in progress since %s"),
4125 ctime(&start));
4126 }
4127
4128 examined = ps->pss_examined ? ps->pss_examined : 1;
4129 total = ps->pss_to_examine;
4130 fraction_done = (double)examined / total;
4131
4132 /* elapsed time for this pass */
4133 elapsed = time(NULL) - ps->pss_pass_start;
4134 elapsed -= ps->pss_pass_scrub_spent_paused;
4135 elapsed = elapsed ? elapsed : 1;
4136 pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
4137 rate = pass_exam / elapsed;
4138 rate = rate ? rate : 1;
4139 mins_left = ((total - examined) / rate) / 60;
4140 hours_left = mins_left / 60;
4141
4142 zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
4143 zfs_nicenum(total, total_buf, sizeof (total_buf));
4144
4145 /*
4146 * do not print estimated time if hours_left is more than 30 days
4147 * or we have a paused scrub
4148 */
4149 if (pause == 0) {
4150 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4151 (void) printf(gettext("\t%s scanned out of %s at %s/s"),
4152 examined_buf, total_buf, rate_buf);
4153 if (hours_left < (30 * 24)) {
4154 (void) printf(gettext(", %lluh%um to go\n"),
4155 (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4156 } else {
4157 (void) printf(gettext(
4158 ", (scan is slow, no estimated time)\n"));
4159 }
4160 } else {
4161 (void) printf(gettext("\t%s scanned out of %s\n"),
4162 examined_buf, total_buf);
4163 }
4164
4165 if (ps->pss_func == POOL_SCAN_RESILVER) {
4166 (void) printf(gettext(" %s resilvered, %.2f%% done\n"),
4167 processed_buf, 100 * fraction_done);
4168 } else if (ps->pss_func == POOL_SCAN_SCRUB) {
4169 (void) printf(gettext(" %s repaired, %.2f%% done\n"),
4170 processed_buf, 100 * fraction_done);
4171 }
4172 }
4173
4174 /*
4175 * Print out detailed removal status.
4176 */
4177 static void
4178 print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
4179 {
4180 char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4181 time_t start, end;
4182 nvlist_t *config, *nvroot;
4183 nvlist_t **child;
4184 uint_t children;
4185 char *vdev_name;
4186
4187 if (prs == NULL || prs->prs_state == DSS_NONE)
4188 return;
4189
4190 /*
4191 * Determine name of vdev.
4192 */
4193 config = zpool_get_config(zhp, NULL);
4194 nvroot = fnvlist_lookup_nvlist(config,
4195 ZPOOL_CONFIG_VDEV_TREE);
4196 verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4197 &child, &children) == 0);
4198 assert(prs->prs_removing_vdev < children);
4199 vdev_name = zpool_vdev_name(g_zfs, zhp,
4200 child[prs->prs_removing_vdev], B_TRUE);
4201
4202 (void) printf(gettext("remove: "));
4203
4204 start = prs->prs_start_time;
4205 end = prs->prs_end_time;
4206 zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
4207
4208 /*
4209 * Removal is finished or canceled.
4210 */
4211 if (prs->prs_state == DSS_FINISHED) {
4212 uint64_t minutes_taken = (end - start) / 60;
4213
4214 (void) printf(gettext("Removal of vdev %llu copied %s "
4215 "in %lluh%um, completed on %s"),
4216 (longlong_t)prs->prs_removing_vdev,
4217 copied_buf,
4218 (u_longlong_t)(minutes_taken / 60),
4219 (uint_t)(minutes_taken % 60),
4220 ctime((time_t *)&end));
4221 } else if (prs->prs_state == DSS_CANCELED) {
4222 (void) printf(gettext("Removal of %s canceled on %s"),
4223 vdev_name, ctime(&end));
4224 } else {
4225 uint64_t copied, total, elapsed, mins_left, hours_left;
4226 double fraction_done;
4227 uint_t rate;
4228
4229 assert(prs->prs_state == DSS_SCANNING);
4230
4231 /*
4232 * Removal is in progress.
4233 */
4234 (void) printf(gettext(
4235 "Evacuation of %s in progress since %s"),
4236 vdev_name, ctime(&start));
4237
4238 copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
4239 total = prs->prs_to_copy;
4240 fraction_done = (double)copied / total;
4241
4242 /* elapsed time for this pass */
4243 elapsed = time(NULL) - prs->prs_start_time;
4244 elapsed = elapsed > 0 ? elapsed : 1;
4245 rate = copied / elapsed;
4246 rate = rate > 0 ? rate : 1;
4247 mins_left = ((total - copied) / rate) / 60;
4248 hours_left = mins_left / 60;
4249
4250 zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
4251 zfs_nicenum(total, total_buf, sizeof (total_buf));
4252 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4253
4254 /*
4255 * do not print estimated time if hours_left is more than
4256 * 30 days
4257 */
4258 (void) printf(gettext(" %s copied out of %s at %s/s, "
4259 "%.2f%% done"),
4260 examined_buf, total_buf, rate_buf, 100 * fraction_done);
4261 if (hours_left < (30 * 24)) {
4262 (void) printf(gettext(", %lluh%um to go\n"),
4263 (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4264 } else {
4265 (void) printf(gettext(
4266 ", (copy is slow, no estimated time)\n"));
4267 }
4268 }
4269
4270 if (prs->prs_mapping_memory > 0) {
4271 char mem_buf[7];
4272 zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
4273 (void) printf(gettext(" %s memory used for "
4274 "removed device mappings\n"),
4275 mem_buf);
4276 }
4277 }
4278
4279 static void
4280 print_error_log(zpool_handle_t *zhp)
4281 {
4282 nvlist_t *nverrlist = NULL;
4283 nvpair_t *elem;
4284 char *pathname;
4285 size_t len = MAXPATHLEN * 2;
4286
4287 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
4288 (void) printf("errors: List of errors unavailable "
4289 "(insufficient privileges)\n");
4290 return;
4291 }
4292
4293 (void) printf("errors: Permanent errors have been "
4294 "detected in the following files:\n\n");
4295
4371 (void) printf("\n");
4372 (void) printf(gettext(" dedup: "));
4373 if (ddo->ddo_count == 0) {
4374 (void) printf(gettext("no DDT entries\n"));
4375 return;
4376 }
4377
4378 (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4379 (u_longlong_t)ddo->ddo_count,
4380 (u_longlong_t)ddo->ddo_dspace,
4381 (u_longlong_t)ddo->ddo_mspace);
4382
4383 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4384 (uint64_t **)&dds, &c) == 0);
4385 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4386 (uint64_t **)&ddh, &c) == 0);
4387 zpool_dump_ddt(dds, ddh);
4388 }
4389
4390 /*
4391 * Display a summary of pool status. Displays a summary such as:
4392 *
4393 * pool: tank
4394 * status: DEGRADED
4395 * reason: One or more devices ...
4396 * see: http://illumos.org/msg/ZFS-xxxx-01
4397 * config:
4398 * mirror DEGRADED
4399 * c1t0d0 OK
4400 * c2t0d0 UNAVAIL
4401 *
4402 * When given the '-v' option, we print out the complete config. If the '-e'
4403 * option is specified, then we print out error rate information as well.
4404 */
4405 int
4406 status_callback(zpool_handle_t *zhp, void *data)
4407 {
4408 status_cbdata_t *cbp = data;
4409 nvlist_t *config, *nvroot;
4410 char *msgid;
4423 * problems.
4424 */
4425 if (cbp->cb_explain &&
4426 (reason == ZPOOL_STATUS_OK ||
4427 reason == ZPOOL_STATUS_VERSION_OLDER ||
4428 reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4429 if (!cbp->cb_allpools) {
4430 (void) printf(gettext("pool '%s' is healthy\n"),
4431 zpool_get_name(zhp));
4432 if (cbp->cb_first)
4433 cbp->cb_first = B_FALSE;
4434 }
4435 return (0);
4436 }
4437
4438 if (cbp->cb_first)
4439 cbp->cb_first = B_FALSE;
4440 else
4441 (void) printf("\n");
4442
4443 nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4444 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4445 (uint64_t **)&vs, &c) == 0);
4446 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4447
4448 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
4449 (void) printf(gettext(" state: %s\n"), health);
4450
4451 switch (reason) {
4452 case ZPOOL_STATUS_MISSING_DEV_R:
4453 (void) printf(gettext("status: One or more devices could not "
4454 "be opened. Sufficient replicas exist for\n\tthe pool to "
4455 "continue functioning in a degraded state.\n"));
4456 (void) printf(gettext("action: Attach the missing device and "
4457 "online it using 'zpool online'.\n"));
4458 break;
4459
4460 case ZPOOL_STATUS_MISSING_DEV_NR:
4461 (void) printf(gettext("status: One or more devices could not "
4462 "be opened. There are insufficient\n\treplicas for the "
4463 "pool to continue functioning.\n"));
4631 "'zpool clear'.\n"));
4632 break;
4633
4634 default:
4635 /*
4636 * The remaining errors can't actually be generated, yet.
4637 */
4638 assert(reason == ZPOOL_STATUS_OK);
4639 }
4640
4641 if (msgid != NULL)
4642 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
4643 msgid);
4644
4645 if (config != NULL) {
4646 int namewidth;
4647 uint64_t nerr;
4648 nvlist_t **spares, **l2cache;
4649 uint_t nspares, nl2cache;
4650 pool_scan_stat_t *ps = NULL;
4651 pool_removal_stat_t *prs = NULL;
4652
4653 (void) nvlist_lookup_uint64_array(nvroot,
4654 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4655 print_scan_status(ps);
4656
4657 (void) nvlist_lookup_uint64_array(nvroot,
4658 ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
4659 print_removal_status(zhp, prs);
4660
4661 namewidth = max_width(zhp, nvroot, 0, 0);
4662 if (namewidth < 10)
4663 namewidth = 10;
4664
4665 (void) printf(gettext("config:\n\n"));
4666 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth,
4667 "NAME", "STATE", "READ", "WRITE", "CKSUM");
4668 print_status_config(zhp, zpool_get_name(zhp), nvroot,
4669 namewidth, 0, B_FALSE);
4670
4671 if (num_logs(nvroot) > 0)
4672 print_logs(zhp, nvroot, namewidth, B_TRUE);
4673 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
4674 &l2cache, &nl2cache) == 0)
4675 print_l2cache(zhp, l2cache, nl2cache, namewidth);
4676
4677 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
4678 &spares, &nspares) == 0)
4679 print_spares(zhp, spares, nspares, namewidth);
4680
4681 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
4682 &nerr) == 0) {
4683 nvlist_t *nverrlist = NULL;
4684
4685 /*
4686 * If the approximate error count is small, get a
4687 * precise count by fetching the entire log and
4688 * uniquifying the results.
4689 */
4690 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
4830 "'%s' from version %llu to feature flags.\n"),
4831 zpool_get_name(zhp), oldversion);
4832 } else {
4833 (void) printf(gettext("Successfully upgraded "
4834 "'%s' from version %llu to version %llu.\n"),
4835 zpool_get_name(zhp), oldversion, version);
4836 }
4837
4838 return (0);
4839 }
4840
4841 static int
4842 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
4843 {
4844 int i, ret, count;
4845 boolean_t firstff = B_TRUE;
4846 nvlist_t *enabled = zpool_get_features(zhp);
4847
4848 count = 0;
4849 for (i = 0; i < SPA_FEATURES; i++) {
4850 const char *fname = spa_feature_table[i].fi_uname;
4851 const char *fguid = spa_feature_table[i].fi_guid;
4852 if (!nvlist_exists(enabled, fguid)) {
4853 char *propname;
4854 verify(-1 != asprintf(&propname, "feature@%s", fname));
4855 ret = zpool_set_prop(zhp, propname,
4856 ZFS_FEATURE_ENABLED);
4857 if (ret != 0) {
4858 free(propname);
4859 return (ret);
4860 }
4861 count++;
4862
4863 if (firstff) {
4864 (void) printf(gettext("Enabled the "
4865 "following features on '%s':\n"),
4866 zpool_get_name(zhp));
4867 firstff = B_FALSE;
4868 }
4869 (void) printf(gettext(" %s\n"), fname);
4870 free(propname);
4871 }
4872 }
4873
5591
5592 if (cb.cb_proplist != NULL) {
5593 fake_name.pl_prop = ZPOOL_PROP_NAME;
5594 fake_name.pl_width = strlen(gettext("NAME"));
5595 fake_name.pl_next = cb.cb_proplist;
5596 cb.cb_proplist = &fake_name;
5597 }
5598
5599 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
5600 get_callback, &cb);
5601
5602 if (cb.cb_proplist == &fake_name)
5603 zprop_free_list(fake_name.pl_next);
5604 else
5605 zprop_free_list(cb.cb_proplist);
5606
5607 return (ret);
5608 }
5609
5610 typedef struct set_cbdata {
5611 char *cb_propname;
5612 char *cb_value;
5613 boolean_t cb_any_successful;
5614 } set_cbdata_t;
5615
5616 int
5617 set_callback(zpool_handle_t *zhp, void *data)
5618 {
5619 int error;
5620 set_cbdata_t *cb = (set_cbdata_t *)data;
5621
5622 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
5623
5624 if (!error)
5625 cb->cb_any_successful = B_TRUE;
5626
5627 return (error);
5628 }
5629
5630 int
5631 zpool_do_set(int argc, char **argv)
5632 {
5633 set_cbdata_t cb = { 0 };
5634 int error;
5635
5636 if (argc > 1 && argv[1][0] == '-') {
5637 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5638 argv[1][1]);
5639 usage(B_FALSE);
5640 }
5641
5642 if (argc < 2) {
5643 (void) fprintf(stderr, gettext("missing property=value "
5644 "argument\n"));
5645 usage(B_FALSE);
5646 }
5647
5648 if (argc < 3) {
5649 (void) fprintf(stderr, gettext("missing pool name\n"));
5650 usage(B_FALSE);
5651 }
5652
5653 if (argc > 3) {
5654 (void) fprintf(stderr, gettext("too many pool names\n"));
5655 usage(B_FALSE);
5656 }
5657
5658 cb.cb_propname = argv[1];
5659 cb.cb_value = strchr(cb.cb_propname, '=');
5660 if (cb.cb_value == NULL) {
5661 (void) fprintf(stderr, gettext("missing value in "
5662 "property=value argument\n"));
5663 usage(B_FALSE);
5664 }
5665
5666 *(cb.cb_value) = '\0';
5667 cb.cb_value++;
5668
5669 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
5670 set_callback, &cb);
5671
5672 return (error);
5673 }
5674
5675 static int
5676 find_command_idx(char *command, int *idx)
5677 {
5678 int i;
5679
5680 for (i = 0; i < NCOMMAND; i++) {
5681 if (command_table[i].name == NULL)
5682 continue;
5683
5684 if (strcmp(command, command_table[i].name) == 0) {
5685 *idx = i;
5686 return (0);
5687 }
5688 }
5689 return (1);
5690 }
5691
5692 int
5693 main(int argc, char **argv)
5694 {
5695 int ret = 0;
5709
5710 opterr = 0;
5711
5712 /*
5713 * Make sure the user has specified some command.
5714 */
5715 if (argc < 2) {
5716 (void) fprintf(stderr, gettext("missing command\n"));
5717 usage(B_FALSE);
5718 }
5719
5720 cmdname = argv[1];
5721
5722 /*
5723 * Special case '-?'
5724 */
5725 if (strcmp(cmdname, "-?") == 0)
5726 usage(B_TRUE);
5727
5728 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
5729
5730 /*
5731 * Run the appropriate command.
5732 */
5733 if (find_command_idx(cmdname, &i) == 0) {
5734 current_command = &command_table[i];
5735 ret = command_table[i].func(argc - 1, argv + 1);
5736 } else if (strchr(cmdname, '=')) {
5737 verify(find_command_idx("set", &i) == 0);
5738 current_command = &command_table[i];
5739 ret = command_table[i].func(argc, argv);
5740 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
5741 /*
5742 * 'freeze' is a vile debugging abomination, so we treat
5743 * it as such.
5744 */
5745 char buf[16384];
5746 int fd = open(ZFS_DEV, O_RDWR);
5747 (void) strcpy((void *)buf, argv[2]);
5748 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
|
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) 2011, 2016 by Delphix. All rights reserved.
25 * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
26 * Copyright (c) 2013 by Delphix. All rights reserved.
27 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
28 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
29 * Copyright 2016 Nexenta Systems, Inc.
30 * Copyright (c) 2017 Datto Inc.
31 */
32
33 #include <assert.h>
34 #include <ctype.h>
35 #include <dirent.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <libgen.h>
39 #include <libintl.h>
40 #include <libuutil.h>
41 #include <locale.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <strings.h>
46 #include <unistd.h>
47 #include <priv.h>
48 #include <pwd.h>
49 #include <zone.h>
50 #include <zfs_prop.h>
51 #include <sys/fs/zfs.h>
52 #include <sys/stat.h>
53
54 #include <libzfs.h>
55
56 #include "zpool_util.h"
57 #include "zfs_comutil.h"
58 #include "zfeature_common.h"
59
60 #include "statcommon.h"
61
62 #ifndef MAX
63 #define MAX(x, y) ((x) > (y) ? (x) : (y))
64 #endif /* MAX */
65
66 static int zpool_do_create(int, char **);
67 static int zpool_do_destroy(int, char **);
68
69 static int zpool_do_add(int, char **);
70 static int zpool_do_remove(int, char **);
71 static int zpool_do_labelclear(int, char **);
72
73 static int zpool_do_list(int, char **);
74 static int zpool_do_iostat(int, char **);
75 static int zpool_do_status(int, char **);
76
77 static int zpool_do_online(int, char **);
78 static int zpool_do_offline(int, char **);
79 static int zpool_do_clear(int, char **);
80 static int zpool_do_reopen(int, char **);
81
82 static int zpool_do_reguid(int, char **);
83
84 static int zpool_do_attach(int, char **);
85 static int zpool_do_detach(int, char **);
86 static int zpool_do_replace(int, char **);
87 static int zpool_do_split(int, char **);
88
89 static int zpool_do_scrub(int, char **);
90 static int zpool_do_trim(int, char **);
91
92 static int zpool_do_import(int, char **);
93 static int zpool_do_export(int, char **);
94
95 static int zpool_do_upgrade(int, char **);
96
97 static int zpool_do_history(int, char **);
98
99 static int zpool_do_get(int, char **);
100 static int zpool_do_set(int, char **);
101
102 static int zpool_do_vdev_get(int, char **);
103 static int zpool_do_vdev_set(int, char **);
104
105 static int zpool_do_cos_alloc(int, char **);
106 static int zpool_do_cos_free(int, char **);
107 static int zpool_do_cos_list(int, char **);
108 static int zpool_do_cos_get(int, char **);
109 static int zpool_do_cos_set(int, char **);
110
111 static boolean_t nexenta_meta_enable();
112
113 /*
114 * These libumem hooks provide a reasonable set of defaults for the allocator's
115 * debugging facilities.
116 */
117
118 #ifdef DEBUG
119 const char *
120 _umem_debug_init(void)
121 {
122 return ("default,verbose"); /* $UMEM_DEBUG setting */
123 }
124
125 const char *
126 _umem_logging_init(void)
127 {
128 return ("fail,contents"); /* $UMEM_LOGGING setting */
129 }
130 #endif
131
132 typedef enum {
133 HELP_ADD,
134 HELP_ATTACH,
135 HELP_CLEAR,
136 HELP_CREATE,
137 HELP_DESTROY,
138 HELP_DETACH,
139 HELP_EXPORT,
140 HELP_HISTORY,
141 HELP_IMPORT,
142 HELP_IOSTAT,
143 HELP_LABELCLEAR,
144 HELP_LIST,
145 HELP_OFFLINE,
146 HELP_ONLINE,
147 HELP_REPLACE,
148 HELP_REMOVE,
149 HELP_SCRUB,
150 HELP_TRIM,
151 HELP_STATUS,
152 HELP_UPGRADE,
153 HELP_GET,
154 HELP_SET,
155 HELP_SPLIT,
156 HELP_REGUID,
157 HELP_REOPEN,
158 HELP_VDEV_GET,
159 HELP_VDEV_SET,
160 HELP_COS_ALLOC,
161 HELP_COS_FREE,
162 HELP_COS_LIST,
163 HELP_COS_GET,
164 HELP_COS_SET
165 } zpool_help_t;
166
167
168 typedef struct zpool_command {
169 const char *name;
170 int (*func)(int, char **);
171 zpool_help_t usage;
172 } zpool_command_t;
173
174 /*
175 * Master command table. Each ZFS command has a name, associated function, and
176 * usage message. The usage messages need to be internationalized, so we have
177 * to have a function to return the usage message based on a command index.
178 *
179 * These commands are organized according to how they are displayed in the usage
180 * message. An empty command (one with a NULL name) indicates an empty line in
181 * the generic usage message.
182 */
183 static zpool_command_t command_table[] = {
184 { "create", zpool_do_create, HELP_CREATE },
188 { "remove", zpool_do_remove, HELP_REMOVE },
189 { NULL },
190 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR },
191 { NULL },
192 { "list", zpool_do_list, HELP_LIST },
193 { "iostat", zpool_do_iostat, HELP_IOSTAT },
194 { "status", zpool_do_status, HELP_STATUS },
195 { NULL },
196 { "online", zpool_do_online, HELP_ONLINE },
197 { "offline", zpool_do_offline, HELP_OFFLINE },
198 { "clear", zpool_do_clear, HELP_CLEAR },
199 { "reopen", zpool_do_reopen, HELP_REOPEN },
200 { NULL },
201 { "attach", zpool_do_attach, HELP_ATTACH },
202 { "detach", zpool_do_detach, HELP_DETACH },
203 { "replace", zpool_do_replace, HELP_REPLACE },
204 { "split", zpool_do_split, HELP_SPLIT },
205 { NULL },
206 { "scrub", zpool_do_scrub, HELP_SCRUB },
207 { NULL },
208 { "trim", zpool_do_trim, HELP_TRIM },
209 { NULL },
210 { "import", zpool_do_import, HELP_IMPORT },
211 { "export", zpool_do_export, HELP_EXPORT },
212 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
213 { "reguid", zpool_do_reguid, HELP_REGUID },
214 { NULL },
215 { "history", zpool_do_history, HELP_HISTORY },
216 { "get", zpool_do_get, HELP_GET },
217 { "set", zpool_do_set, HELP_SET },
218 { "vdev-get", zpool_do_vdev_get, HELP_VDEV_GET },
219 { "vdev-set", zpool_do_vdev_set, HELP_VDEV_SET },
220 { "cos-alloc", zpool_do_cos_alloc, HELP_COS_ALLOC },
221 { "cos-free", zpool_do_cos_free, HELP_COS_FREE },
222 { "cos-list", zpool_do_cos_list, HELP_COS_LIST },
223 { "cos-get", zpool_do_cos_get, HELP_COS_GET },
224 { "cos-set", zpool_do_cos_set, HELP_COS_SET }
225 };
226
227 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
228
229 static zpool_command_t *current_command;
230 static char history_str[HIS_MAX_RECORD_LEN];
231 static boolean_t log_history = B_TRUE;
232 static uint_t timestamp_fmt = NODATE;
233
234 static const char *
235 get_usage(zpool_help_t idx)
236 {
237 switch (idx) {
238 case HELP_ADD:
239 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
240 case HELP_ATTACH:
241 return (gettext("\tattach [-f] <pool> <device> "
242 "<new-device>\n"));
243 case HELP_CLEAR:
244 return (gettext("\tclear [-nF] <pool> [device]\n"));
245 case HELP_CREATE:
246 return (gettext("\tcreate [-fnd] [-B] "
247 "[-o property=value] ... \n"
248 "\t [-O file-system-property=value] ... \n"
249 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
250 case HELP_DESTROY:
251 return (gettext("\tdestroy [-f] <pool>\n"));
252 case HELP_DETACH:
253 return (gettext("\tdetach <pool> <device>\n"));
254 case HELP_EXPORT:
255 return (gettext("\texport [-f] <pool> ...\n"));
256 case HELP_HISTORY:
257 return (gettext("\thistory [-il] [<pool>] ...\n"));
258 case HELP_IMPORT:
259 return (gettext("\timport [-d dir] [-D] [-t num]\n"
260 "\timport [-d dir | -c cachefile] [-F [-n]] <pool | id>\n"
261 "\timport [-o mntopts] [-o property=value] ... \n"
262 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
263 "[-R root] [-F [-n]] [-t num] -a\n"
264 "\timport [-o mntopts] [-o property=value] ... \n"
265 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
266 "[-R root] [-F [-n]]\n"
267 "\t <pool | id> [newpool]\n"));
268 case HELP_IOSTAT:
269 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
270 "[count]]\n"));
271 case HELP_LABELCLEAR:
272 return (gettext("\tlabelclear [-f] <vdev>\n"));
273 case HELP_LIST:
274 return (gettext("\tlist [-Hp] [-o property[,...]] "
275 "[-T d|u] [pool] ... [interval [count]]\n"));
276 case HELP_OFFLINE:
277 return (gettext("\toffline [-t] <pool> <device> ...\n"));
278 case HELP_ONLINE:
279 return (gettext("\tonline <pool> <device> ...\n"));
280 case HELP_REPLACE:
281 return (gettext("\treplace [-f] <pool> <device> "
282 "[new-device]\n"));
283 case HELP_REMOVE:
284 return (gettext("\tremove <pool> <device> ...\n"));
285 case HELP_REOPEN:
286 return (gettext("\treopen <pool>\n"));
287 case HELP_SCRUB:
288 return (gettext("\tscrub [-m|-M|-p|-s] <pool> ...\n"));
289 case HELP_TRIM:
290 return (gettext("\ttrim [-s|-r <rate>] <pool> ...\n"));
291 case HELP_STATUS:
292 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
293 "[count]]\n"));
294 case HELP_UPGRADE:
295 return (gettext("\tupgrade\n"
296 "\tupgrade -v\n"
297 "\tupgrade [-V version] <-a | pool ...>\n"));
298 case HELP_GET:
299 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
300 "<\"all\" | property[,...]> <pool> ...\n"));
301 case HELP_SET:
302 return (gettext("\tset <property=value> <pool> \n"));
303 case HELP_SPLIT:
304 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
305 "\t [-o property=value] <pool> <newpool> "
306 "[<device> ...]\n"));
307 case HELP_REGUID:
308 return (gettext("\treguid <pool>\n"));
309 case HELP_VDEV_GET:
310 return (gettext("\tvdev-get <property | all> <pool> "
311 "<vdev name | GUID>\n"));
312 case HELP_VDEV_SET:
313 return (gettext("\tvdev-set <property=value> <pool> "
314 "<vdev name | GUID>\n"));
315 case HELP_COS_ALLOC:
316 return (gettext("\tcos-alloc <pool> <cos name | GUID>\n"));
317 case HELP_COS_FREE:
318 return (gettext("\tcos-free [-f] <pool> <cos name | GUID>\n"));
319 case HELP_COS_LIST:
320 return (gettext("\tcos-list <pool>\n"));
321 case HELP_COS_GET:
322 return (gettext("\tcos-get <property | all> <pool>"
323 "<cos name | GUID>\n"));
324 case HELP_COS_SET:
325 return (gettext("\tcos-set <property=value> <pool>"
326 "<cos name | GUID>\n"));
327 }
328
329 abort();
330 /* NOTREACHED */
331 }
332 /*
333 * Check if additional ZFS meta features are enabled.
334 */
335 static boolean_t
336 nexenta_meta_enable()
337 {
338 if (getenv("nexenta_meta_enable") == NULL) {
339 (void) fprintf(stderr, gettext("feature not enabled\n"));
340 (void) fprintf(stderr,
341 gettext("set nexenta_meta_enable to access\n"));
342 return (B_FALSE);
343 }
344 return (B_TRUE);
345 }
346
347 /*
348 * Callback routine that will print out a pool property value.
349 */
350 static int
351 print_prop_cb(int prop, void *cb)
352 {
353 FILE *fp = cb;
354
355 (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop));
356
357 if (zpool_prop_readonly(prop))
358 (void) fprintf(fp, " NO ");
359 else
360 (void) fprintf(fp, " YES ");
361
362 if (zpool_prop_values(prop) == NULL)
363 (void) fprintf(fp, "-\n");
364 else
365 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
366
461
462 static boolean_t
463 prop_list_contains_feature(nvlist_t *proplist)
464 {
465 nvpair_t *nvp;
466 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
467 nvp = nvlist_next_nvpair(proplist, nvp)) {
468 if (zpool_prop_feature(nvpair_name(nvp)))
469 return (B_TRUE);
470 }
471 return (B_FALSE);
472 }
473
474 /*
475 * Add a property pair (name, string-value) into a property nvlist.
476 */
477 static int
478 add_prop_list(const char *propname, char *propval, nvlist_t **props,
479 boolean_t poolprop)
480 {
481 zpool_prop_t prop = ZPROP_INVAL;
482 zfs_prop_t fprop;
483 nvlist_t *proplist;
484 const char *normnm;
485 char *strval;
486
487 if (*props == NULL &&
488 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
489 (void) fprintf(stderr,
490 gettext("internal error: out of memory\n"));
491 return (1);
492 }
493
494 proplist = *props;
495
496 if (poolprop) {
497 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
498
499 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
500 !zpool_prop_feature(propname)) {
501 (void) fprintf(stderr, gettext("property '%s' is "
502 "not a valid pool property\n"), propname);
503 return (2);
504 }
505
506 /*
507 * feature@ properties and version should not be specified
508 * at the same time.
509 */
510 if ((prop == ZPROP_INVAL && zpool_prop_feature(propname) &&
511 nvlist_exists(proplist, vname)) ||
512 (prop == ZPOOL_PROP_VERSION &&
513 prop_list_contains_feature(proplist))) {
514 (void) fprintf(stderr, gettext("'feature@' and "
515 "'version' properties cannot be specified "
516 "together\n"));
517 return (2);
518 }
519
520
521 if (zpool_prop_feature(propname))
522 normnm = propname;
523 else
524 normnm = zpool_prop_to_name(prop);
525 } else {
526 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
527 normnm = zfs_prop_to_name(fprop);
528 } else {
529 normnm = propname;
530 }
531 }
532
533 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
534 prop != ZPOOL_PROP_CACHEFILE) {
535 (void) fprintf(stderr, gettext("property '%s' "
536 "specified multiple times\n"), propname);
537 return (2);
538 }
539
540 if (nvlist_add_string(proplist, normnm, propval) != 0) {
541 (void) fprintf(stderr, gettext("internal "
542 "error: out of memory\n"));
543 return (1);
544 }
545
546 return (0);
547 }
548
549 /*
550 * Add a property pair (name, string-value) into a vdev property nvlist.
551 */
552 static int
553 add_vdev_prop_list(const char *propname, char *propval, nvlist_t **props)
554 {
555 vdev_prop_t prop = ZPROP_INVAL;
556 nvlist_t *proplist;
557 const char *normnm;
558
559 if (*props == NULL && nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
560 (void) fprintf(stderr,
561 gettext("internal error: out of memory\n"));
562 return (1);
563 }
564
565 proplist = *props;
566 if ((prop = vdev_name_to_prop(propname)) == ZPROP_INVAL) {
567 (void) fprintf(stderr, gettext("property '%s' is "
568 "not a valid vdev property\n"), propname);
569 return (2);
570 }
571 normnm = vdev_prop_to_name(prop);
572
573 if (nvlist_add_string(proplist, normnm, propval) != 0) {
574 (void) fprintf(stderr, gettext("internal "
575 "error: out of memory\n"));
576 return (1);
577 }
578
579 return (0);
580 }
581
582 /*
583 * Add a property pair (name, string-value) into a cos property nvlist.
584 */
585 static int
586 add_cos_prop_list(const char *propname, char *propval, nvlist_t **props)
587 {
588 cos_prop_t prop = ZPROP_INVAL;
589 nvlist_t *proplist;
590 const char *normnm;
591
592 if (*props == NULL && nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
593 (void) fprintf(stderr,
594 gettext("internal error: out of memory\n"));
595 return (1);
596 }
597
598 proplist = *props;
599 if ((prop = cos_name_to_prop(propname)) == ZPROP_INVAL) {
600 (void) fprintf(stderr, gettext("property '%s' is "
601 "not a valid cos property\n"), propname);
602 return (2);
603 }
604 normnm = cos_prop_to_name(prop);
605
606 if (nvlist_add_string(proplist, normnm, propval) != 0) {
607 (void) fprintf(stderr, gettext("internal "
608 "error: out of memory\n"));
609 return (1);
610 }
611
612 return (0);
613 }
614
615 /*
616 * zpool add [-fn] <pool> <vdev> ...
617 *
618 * -f Force addition of devices, even if they appear in use
619 * -n Do not add the devices, but display the resulting layout if
620 * they were to be added.
621 *
622 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
623 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
624 * libzfs.
625 */
626 int
627 zpool_do_add(int argc, char **argv)
628 {
629 boolean_t force = B_FALSE;
630 boolean_t dryrun = B_FALSE;
631 int c;
632 nvlist_t *nvroot;
633 char *poolname;
634 zpool_boot_label_t boot_type;
635 uint64_t boot_size;
713 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
714 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
715 } else if (num_logs(nvroot) > 0) {
716 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
717 }
718
719 ret = 0;
720 } else {
721 ret = (zpool_add(zhp, nvroot) != 0);
722 }
723
724 nvlist_free(nvroot);
725 zpool_close(zhp);
726
727 return (ret);
728 }
729
730 /*
731 * zpool remove <pool> <vdev> ...
732 *
733 * Removes the given vdev from the pool. Currently, this supports removing
734 * spares, cache, and log devices from the pool.
735 */
736 int
737 zpool_do_remove(int argc, char **argv)
738 {
739 char *poolname;
740 int i, ret = 0;
741 zpool_handle_t *zhp;
742
743 argc--;
744 argv++;
745
746 /* get pool name and check number of arguments */
747 if (argc < 1) {
748 (void) fprintf(stderr, gettext("missing pool name argument\n"));
749 usage(B_FALSE);
750 }
751 if (argc < 2) {
752 (void) fprintf(stderr, gettext("missing device\n"));
753 usage(B_FALSE);
754 }
755
756 poolname = argv[0];
757
758 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
759 return (1);
760
761 for (i = 1; i < argc; i++) {
762 if (zpool_vdev_remove(zhp, argv[i]) != 0)
763 ret = 1;
764 }
765
766 return (ret);
767 }
768
769 /*
770 * zpool labelclear [-f] <vdev>
771 *
772 * -f Force clearing the label for the vdevs which are members of
773 * the exported or foreign pools.
774 *
775 * Verifies that the vdev is not active and zeros out the label information
776 * on the device.
777 */
778 int
779 zpool_do_labelclear(int argc, char **argv)
780 {
781 char vdev[MAXPATHLEN];
782 char *name = NULL;
783 struct stat st;
784 int c, fd, ret = 0;
1322 usage(B_FALSE);
1323 }
1324 if (argc > 1) {
1325 (void) fprintf(stderr, gettext("too many arguments\n"));
1326 usage(B_FALSE);
1327 }
1328
1329 pool = argv[0];
1330
1331 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
1332 /*
1333 * As a special case, check for use of '/' in the name, and
1334 * direct the user to use 'zfs destroy' instead.
1335 */
1336 if (strchr(pool, '/') != NULL)
1337 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1338 "destroy a dataset\n"));
1339 return (1);
1340 }
1341
1342 ret = zfs_check_krrp(g_zfs, argv[0]);
1343 /*
1344 * ENOTSUP means that autosnaper doesn't handle this pool.
1345 */
1346 if (ret != ENOTSUP) {
1347 if (ret == ECHILD || ret == EBUSY || ret == EUSERS)
1348 ret = EBUSY;
1349
1350 if (ret) {
1351 (void) zpool_standard_error(g_zfs,
1352 ret, gettext("cannnot destroy pool because "
1353 "of krrp"));
1354 zpool_close(zhp);
1355 ret = 1;
1356 return (ret);
1357 }
1358 } else {
1359 ret = 0;
1360 }
1361
1362 if (zpool_disable_datasets(zhp, force) != 0) {
1363 (void) fprintf(stderr, gettext("could not destroy '%s': "
1364 "could not unmount datasets\n"), zpool_get_name(zhp));
1365 return (1);
1366 }
1367
1368 /* The history must be logged as part of the export */
1369 log_history = B_FALSE;
1370
1371 ret = (zpool_destroy(zhp, history_str) != 0);
1372
1373 zpool_close(zhp);
1374
1375 return (ret);
1376 }
1377
1378 /*
1379 * zpool export [-f] <pool> ...
1380 *
1381 * -f Forcefully unmount datasets
1382 *
1383 * Export the given pools. By default, the command will attempt to cleanly
1384 * unmount any active datasets within the pool. If the '-f' flag is specified,
1385 * then the datasets will be forcefully unmounted.
1386 */
1387 int
1388 zpool_do_export(int argc, char **argv)
1389 {
1390 boolean_t force = B_FALSE;
1391 boolean_t hardforce = B_FALSE;
1392 boolean_t saveconfig = B_FALSE;
1393 int c;
1394 int n_threads = sysconf(_SC_NPROCESSORS_ONLN) * 2;
1395 zpool_handle_t *zhp;
1396 int ret;
1397 int i;
1398
1399 /* check options */
1400 while ((c = getopt(argc, argv, ":fFct:")) != -1) {
1401 switch (c) {
1402 case 'f':
1403 force = B_TRUE;
1404 break;
1405 case 'F':
1406 hardforce = B_TRUE;
1407 break;
1408 case 'c':
1409 saveconfig = B_TRUE;
1410 break;
1411 case 't':
1412 n_threads = atoi(optarg);
1413 break;
1414 case '?':
1415 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1416 optopt);
1417 usage(B_FALSE);
1418 break;
1419 case ':':
1420 (void) fprintf(stderr, gettext("missing argument "
1421 "for option '%c'\n"), optopt);
1422 usage(B_FALSE);
1423 break;
1424 }
1425 }
1426
1427 argc -= optind;
1428 argv += optind;
1429
1430 /* check arguments */
1431 if (argc < 1) {
1432 (void) fprintf(stderr, gettext("missing pool argument\n"));
1433 usage(B_FALSE);
1434 }
1435
1436 ret = 0;
1437 for (i = 0; i < argc; i++) {
1438 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1439 ret = 1;
1440 continue;
1441 }
1442
1443 ret = zfs_check_krrp(g_zfs, argv[0]);
1444 /*
1445 * ENOTSUP means that autosnaper doesn't handle this pool.
1446 */
1447 if (ret != ENOTSUP) {
1448 if (ret == ECHILD || ret == EBUSY || ret == EUSERS)
1449 ret = EBUSY;
1450
1451 if (ret) {
1452 (void) zpool_standard_error(g_zfs,
1453 ret, gettext("cannnot export pool because "
1454 "of krrp"));
1455 zpool_close(zhp);
1456 ret = 1;
1457 continue;
1458 }
1459 } else {
1460 ret = 0;
1461 }
1462
1463 if (zpool_disable_datasets_ex(zhp, force, n_threads) != 0) {
1464 ret = 1;
1465 zpool_close(zhp);
1466 continue;
1467 }
1468
1469 /* The history must be logged as part of the export */
1470 log_history = B_FALSE;
1471
1472 if (hardforce) {
1473 if (zpool_export_force(zhp, saveconfig, history_str)
1474 != 0)
1475 ret = 1;
1476 } else if (zpool_export(zhp, force, saveconfig, history_str)
1477 != 0) {
1478 ret = 1;
1479 }
1480
1481 zpool_close(zhp);
1482 }
1483
1484 return (ret);
1485 }
1486
1487 /*
1488 * Given a vdev configuration, determine the maximum width needed for the device
1489 * name column.
1490 */
1491 static int
1492 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1493 {
1494 char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1495 nvlist_t **child;
1496 uint_t c, children;
1497 int ret;
1573 zpool_close(zhp);
1574 return (0);
1575 }
1576
1577 /*
1578 * Print out configuration state as requested by status_callback.
1579 */
1580 void
1581 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1582 int namewidth, int depth, boolean_t isspare)
1583 {
1584 nvlist_t **child;
1585 uint_t c, children;
1586 pool_scan_stat_t *ps = NULL;
1587 vdev_stat_t *vs;
1588 char rbuf[6], wbuf[6], cbuf[6];
1589 char *vname;
1590 uint64_t notpresent;
1591 spare_cbdata_t cb;
1592 const char *state;
1593
1594 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1595 &child, &children) != 0)
1596 children = 0;
1597
1598 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1599 (uint64_t **)&vs, &c) == 0);
1600
1601 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1602 if (isspare) {
1603 /*
1604 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1605 * online drives.
1606 */
1607 if (vs->vs_aux == VDEV_AUX_SPARED)
1608 state = "INUSE";
1609 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1610 state = "AVAIL";
1611 }
1612
1613 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth,
1614 name, state);
1615
1616 if (!isspare) {
1617 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1618 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1619 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1620 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1670 case VDEV_AUX_ERR_EXCEEDED:
1671 (void) printf(gettext("too many errors"));
1672 break;
1673
1674 case VDEV_AUX_IO_FAILURE:
1675 (void) printf(gettext("experienced I/O failures"));
1676 break;
1677
1678 case VDEV_AUX_BAD_LOG:
1679 (void) printf(gettext("bad intent log"));
1680 break;
1681
1682 case VDEV_AUX_EXTERNAL:
1683 (void) printf(gettext("external device fault"));
1684 break;
1685
1686 case VDEV_AUX_SPLIT_POOL:
1687 (void) printf(gettext("split into new pool"));
1688 break;
1689
1690 default:
1691 (void) printf(gettext("corrupted data"));
1692 break;
1693 }
1694 }
1695
1696 (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1697 (uint64_t **)&ps, &c);
1698
1699 if (ps != NULL && (ps->pss_state == DSS_SCANNING ||
1700 ps->pss_state == DSS_FINISHING) && vs->vs_scan_processed != 0 &&
1701 children == 0) {
1702 (void) printf(gettext(" (%s)"),
1703 (ps->pss_func == POOL_SCAN_RESILVER) ?
1704 "resilvering" : "repairing");
1705 }
1706
1707 (void) printf("\n");
1708
1709 for (c = 0; c < children; c++) {
1710 uint64_t islog = B_FALSE, ishole = B_FALSE, isspecial = B_FALSE;
1711
1712 /* Don't print logs or holes here */
1713 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1714 &islog);
1715 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1716 &ishole);
1717 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_SPECIAL,
1718 &isspecial);
1719 if (islog || ishole || isspecial)
1720 continue;
1721 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1722 print_status_config(zhp, vname, child[c],
1723 namewidth, depth + 2, isspare);
1724 free(vname);
1725 }
1726 }
1727
1728
1729 /*
1730 * Print the configuration of an exported pool. Iterate over all vdevs in the
1731 * pool, printing out the name and status for each one.
1732 */
1733 void
1734 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1735 {
1736 nvlist_t **child;
1737 uint_t c, children;
1738 vdev_stat_t *vs;
1739 char *type, *vname;
1760 case VDEV_AUX_BAD_GUID_SUM:
1761 (void) printf(gettext("missing device"));
1762 break;
1763
1764 case VDEV_AUX_NO_REPLICAS:
1765 (void) printf(gettext("insufficient replicas"));
1766 break;
1767
1768 case VDEV_AUX_VERSION_NEWER:
1769 (void) printf(gettext("newer version"));
1770 break;
1771
1772 case VDEV_AUX_UNSUP_FEAT:
1773 (void) printf(gettext("unsupported feature(s)"));
1774 break;
1775
1776 case VDEV_AUX_ERR_EXCEEDED:
1777 (void) printf(gettext("too many errors"));
1778 break;
1779
1780 default:
1781 (void) printf(gettext("corrupted data"));
1782 break;
1783 }
1784 }
1785 (void) printf("\n");
1786
1787 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1788 &child, &children) != 0)
1789 return;
1790
1791 for (c = 0; c < children; c++) {
1792 uint64_t is_log = B_FALSE, is_special = B_FALSE;
1793
1794 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1795 &is_log);
1796 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_SPECIAL,
1797 &is_special);
1798 if (is_log || is_special)
1799 continue;
1800
1801 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1802 print_import_config(vname, child[c], namewidth, depth + 2);
1803 free(vname);
1804 }
1805
1806 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1807 &child, &children) == 0) {
1808 (void) printf(gettext("\tcache\n"));
1809 for (c = 0; c < children; c++) {
1810 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1811 (void) printf("\t %s\n", vname);
1812 free(vname);
1813 }
1814 }
1815
1816 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1817 &child, &children) == 0) {
1818 (void) printf(gettext("\tspares\n"));
1846
1847 for (c = 0; c < children; c++) {
1848 uint64_t is_log = B_FALSE;
1849 char *name;
1850
1851 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1852 &is_log);
1853 if (!is_log)
1854 continue;
1855 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1856 if (verbose)
1857 print_status_config(zhp, name, child[c], namewidth,
1858 2, B_FALSE);
1859 else
1860 print_import_config(name, child[c], namewidth, 2);
1861 free(name);
1862 }
1863 }
1864
1865 /*
1866 * Print special vdevs.
1867 * Special vdevs are recorded as top level vdevs in the main pool child array
1868 * but with "is_special" set to 1. We use either print_status_config() or
1869 * print_import_config() to print the top level logs then any log
1870 * children (eg mirrored slogs) are printed recursively - which
1871 * works because only the top level vdev is marked "is_special"
1872 */
1873 static void
1874 print_special(zpool_handle_t *zhp, nvlist_t *nv, int namewidth,
1875 boolean_t verbose)
1876 {
1877 uint_t c, children;
1878 nvlist_t **child;
1879
1880 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1881 &children) != 0)
1882 return;
1883
1884 (void) printf(gettext("\tspecial\n"));
1885
1886 for (c = 0; c < children; c++) {
1887 uint64_t is_special = B_FALSE;
1888 char *name;
1889
1890 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_SPECIAL,
1891 &is_special);
1892 if (!is_special)
1893 continue;
1894 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1895 if (verbose)
1896 print_status_config(zhp, name, child[c], namewidth,
1897 2, B_FALSE);
1898 else
1899 print_import_config(name, child[c], namewidth, 2);
1900 free(name);
1901 }
1902 }
1903
1904 /*
1905 * Display the status for the given pool.
1906 */
1907 static void
1908 show_import(nvlist_t *config)
1909 {
1910 uint64_t pool_state;
1911 vdev_stat_t *vs;
1912 char *name;
1913 uint64_t guid;
1914 char *msgid;
1915 nvlist_t *nvroot;
1916 int reason;
1917 const char *health;
1918 uint_t vsc;
1919 int namewidth;
1920 char *comment;
1921
1922 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1923 &name) == 0);
1924 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
2099 if (pool_state == POOL_STATE_DESTROYED)
2100 (void) printf(gettext("\tThe pool was destroyed, "
2101 "but can be imported using the '-Df' flags.\n"));
2102 else if (pool_state != POOL_STATE_EXPORTED)
2103 (void) printf(gettext("\tThe pool may be active on "
2104 "another system, but can be imported using\n\t"
2105 "the '-f' flag.\n"));
2106 }
2107
2108 if (msgid != NULL)
2109 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
2110 msgid);
2111
2112 (void) printf(gettext(" config:\n\n"));
2113
2114 namewidth = max_width(NULL, nvroot, 0, 0);
2115 if (namewidth < 10)
2116 namewidth = 10;
2117
2118 print_import_config(name, nvroot, namewidth, 0);
2119 if (num_special(nvroot) > 0)
2120 print_special(NULL, nvroot, namewidth, B_FALSE);
2121
2122 if (num_logs(nvroot) > 0)
2123 print_logs(NULL, nvroot, namewidth, B_FALSE);
2124
2125 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
2126 (void) printf(gettext("\n\tAdditional devices are known to "
2127 "be part of this pool, though their\n\texact "
2128 "configuration cannot be determined.\n"));
2129 }
2130 }
2131
2132 /*
2133 * Perform the import for the given configuration. This passes the heavy
2134 * lifting off to zpool_import_props(), and then mounts the datasets contained
2135 * within the pool.
2136 */
2137 static int
2138 do_import(nvlist_t *config, const char *newname, const char *mntopts,
2139 nvlist_t *props, int flags, int n_threads)
2140 {
2141 zpool_handle_t *zhp;
2142 char *name;
2143 uint64_t state;
2144 uint64_t version;
2145
2146 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
2147 &name) == 0);
2148
2149 verify(nvlist_lookup_uint64(config,
2150 ZPOOL_CONFIG_POOL_STATE, &state) == 0);
2151 verify(nvlist_lookup_uint64(config,
2152 ZPOOL_CONFIG_VERSION, &version) == 0);
2153 if (!SPA_VERSION_IS_SUPPORTED(version)) {
2154 (void) fprintf(stderr, gettext("cannot import '%s': pool "
2155 "is formatted using an unsupported ZFS version\n"), name);
2156 return (1);
2157 } else if (state != POOL_STATE_EXPORTED &&
2158 !(flags & ZFS_IMPORT_ANY_HOST)) {
2159 uint64_t hostid;
2183 } else {
2184 (void) fprintf(stderr, gettext("cannot import '%s': "
2185 "pool may be in use from other system\n"), name);
2186 (void) fprintf(stderr, gettext("use '-f' to import "
2187 "anyway\n"));
2188 return (1);
2189 }
2190 }
2191
2192 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
2193 return (1);
2194
2195 if (newname != NULL)
2196 name = (char *)newname;
2197
2198 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2199 return (1);
2200
2201 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2202 !(flags & ZFS_IMPORT_ONLY) &&
2203 zpool_enable_datasets_ex(zhp, mntopts, 0, n_threads) != 0) {
2204 zpool_close(zhp);
2205 return (1);
2206 }
2207
2208 zpool_close(zhp);
2209 return (0);
2210 }
2211
2212 /*
2213 * zpool import [-d dir] [-D]
2214 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-t num]
2215 * [-d dir | -c cachefile] [-f] -a
2216 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-t num]
2217 * [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
2218 *
2219 * -c Read pool information from a cachefile instead of searching
2220 * devices.
2221 *
2222 * -d Scan in a specific directory, other than /dev/dsk. More than
2223 * one directory can be specified using multiple '-d' options.
2224 *
2225 * -D Scan for previously destroyed pools or import all or only
2226 * specified destroyed pools.
2227 *
2228 * -R Temporarily import the pool, with all mountpoints relative to
2229 * the given root. The pool will remain exported when the machine
2230 * is rebooted.
2231 *
2232 * -V Import even in the presence of faulted vdevs. This is an
2233 * intentionally undocumented option for testing purposes, and
2234 * treats the pool configuration as complete, leaving any bad
2235 * vdevs in the FAULTED state. In other words, it does verbatim
2236 * import.
2237 *
2238 * -f Force import, even if it appears that the pool is active.
2239 *
2240 * -F Attempt rewind if necessary.
2241 *
2242 * -n See if rewind would work, but don't actually rewind.
2243 *
2244 * -N Import the pool but don't mount datasets.
2245 *
2246 * -t Use up to num threads to mount datasets in parallel.
2247 *
2248 * -T Specify a starting txg to use for import. This option is
2249 * intentionally undocumented option for testing purposes.
2250 *
2251 * -a Import all pools found.
2252 *
2253 * -o Set property=value and/or temporary mount options (without '=').
2254 *
2255 * The import command scans for pools to import, and import pools based on pool
2256 * name and GUID. The pool can also be renamed as part of the import process.
2257 */
2258 int
2259 zpool_do_import(int argc, char **argv)
2260 {
2261 char **searchdirs = NULL;
2262 int nsearch = 0;
2263 int c;
2264 int err = 0;
2265 nvlist_t *pools = NULL;
2266 boolean_t do_all = B_FALSE;
2267 boolean_t do_destroyed = B_FALSE;
2268 char *mntopts = NULL;
2269 nvpair_t *elem;
2270 nvlist_t *config;
2271 uint64_t searchguid = 0;
2272 char *searchname = NULL;
2273 char *propval;
2274 nvlist_t *found_config;
2275 nvlist_t *policy = NULL;
2276 nvlist_t *props = NULL;
2277 boolean_t first;
2278 int flags = ZFS_IMPORT_NORMAL;
2279 uint32_t rewind_policy = ZPOOL_NO_REWIND;
2280 boolean_t dryrun = B_FALSE;
2281 boolean_t do_rewind = B_FALSE;
2282 boolean_t xtreme_rewind = B_FALSE;
2283 uint64_t pool_state, txg = -1ULL;
2284 char *cachefile = NULL;
2285 importargs_t idata = { 0 };
2286 unsigned long n_threads = sysconf(_SC_NPROCESSORS_ONLN) * 2;
2287 char *endptr;
2288
2289 /* check options */
2290 while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:rR:t:T:VX")) != -1) {
2291 switch (c) {
2292 case 'a':
2293 do_all = B_TRUE;
2294 break;
2295 case 'c':
2296 cachefile = optarg;
2297 break;
2298 case 'd':
2299 if (searchdirs == NULL) {
2300 searchdirs = safe_malloc(sizeof (char *));
2301 } else {
2302 char **tmp = safe_malloc((nsearch + 1) *
2303 sizeof (char *));
2304 bcopy(searchdirs, tmp, nsearch *
2305 sizeof (char *));
2306 free(searchdirs);
2307 searchdirs = tmp;
2308 }
2309 searchdirs[nsearch++] = optarg;
2310 break;
2332 propval++;
2333 if (add_prop_list(optarg, propval,
2334 &props, B_TRUE))
2335 goto error;
2336 } else {
2337 mntopts = optarg;
2338 }
2339 break;
2340 case 'R':
2341 if (add_prop_list(zpool_prop_to_name(
2342 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2343 goto error;
2344 if (nvlist_lookup_string(props,
2345 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
2346 &propval) == 0)
2347 break;
2348 if (add_prop_list(zpool_prop_to_name(
2349 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2350 goto error;
2351 break;
2352 case 't':
2353 errno = 0;
2354 n_threads = strtol(optarg, &endptr, 10);
2355 if (errno != 0 || *endptr != '\0') {
2356 (void) fprintf(stderr,
2357 gettext("invalid num value\n"));
2358 usage(B_FALSE);
2359 }
2360 break;
2361 case 'T':
2362 errno = 0;
2363 txg = strtoull(optarg, &endptr, 0);
2364 if (errno != 0 || *endptr != '\0') {
2365 (void) fprintf(stderr,
2366 gettext("invalid txg value\n"));
2367 usage(B_FALSE);
2368 }
2369 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2370 break;
2371 case 'V':
2372 flags |= ZFS_IMPORT_VERBATIM;
2373 break;
2374 case 'X':
2375 xtreme_rewind = B_TRUE;
2376 break;
2377 case ':':
2378 (void) fprintf(stderr, gettext("missing argument for "
2379 "'%c' option\n"), optopt);
2380 usage(B_FALSE);
2463 errno = 0;
2464 searchguid = strtoull(argv[0], &endptr, 10);
2465 if (errno != 0 || *endptr != '\0') {
2466 searchname = argv[0];
2467 searchguid = 0;
2468 }
2469 found_config = NULL;
2470
2471 /*
2472 * User specified a name or guid. Ensure it's unique.
2473 */
2474 idata.unique = B_TRUE;
2475 }
2476
2477
2478 idata.path = searchdirs;
2479 idata.paths = nsearch;
2480 idata.poolname = searchname;
2481 idata.guid = searchguid;
2482 idata.cachefile = cachefile;
2483
2484 pools = zpool_search_import(g_zfs, &idata);
2485
2486 if (pools != NULL && idata.exists &&
2487 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2488 (void) fprintf(stderr, gettext("cannot import '%s': "
2489 "a pool with that name already exists\n"),
2490 argv[0]);
2491 (void) fprintf(stderr, gettext("use the form '%s "
2492 "<pool | id> <newpool>' to give it a new name\n"),
2493 "zpool import");
2494 err = 1;
2495 } else if (pools == NULL && idata.exists) {
2496 (void) fprintf(stderr, gettext("cannot import '%s': "
2497 "a pool with that name is already created/imported,\n"),
2498 argv[0]);
2499 (void) fprintf(stderr, gettext("and no additional pools "
2500 "with that name were found\n"));
2501 err = 1;
2502 } else if (pools == NULL) {
2527 verify(nvpair_value_nvlist(elem, &config) == 0);
2528
2529 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2530 &pool_state) == 0);
2531 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2532 continue;
2533 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2534 continue;
2535
2536 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2537 policy) == 0);
2538
2539 if (argc == 0) {
2540 if (first)
2541 first = B_FALSE;
2542 else if (!do_all)
2543 (void) printf("\n");
2544
2545 if (do_all) {
2546 err |= do_import(config, NULL, mntopts,
2547 props, flags, n_threads);
2548 } else {
2549 show_import(config);
2550 }
2551 } else if (searchname != NULL) {
2552 char *name;
2553
2554 /*
2555 * We are searching for a pool based on name.
2556 */
2557 verify(nvlist_lookup_string(config,
2558 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2559
2560 if (strcmp(name, searchname) == 0) {
2561 if (found_config != NULL) {
2562 (void) fprintf(stderr, gettext(
2563 "cannot import '%s': more than "
2564 "one matching pool\n"), searchname);
2565 (void) fprintf(stderr, gettext(
2566 "import by numeric ID instead\n"));
2567 err = B_TRUE;
2576 */
2577 verify(nvlist_lookup_uint64(config,
2578 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2579
2580 if (guid == searchguid)
2581 found_config = config;
2582 }
2583 }
2584
2585 /*
2586 * If we were searching for a specific pool, verify that we found a
2587 * pool, and then do the import.
2588 */
2589 if (argc != 0 && err == 0) {
2590 if (found_config == NULL) {
2591 (void) fprintf(stderr, gettext("cannot import '%s': "
2592 "no such pool available\n"), argv[0]);
2593 err = B_TRUE;
2594 } else {
2595 err |= do_import(found_config, argc == 1 ? NULL :
2596 argv[1], mntopts, props, flags, n_threads);
2597 }
2598 }
2599
2600 /*
2601 * If we were just looking for pools, report an error if none were
2602 * found.
2603 */
2604 if (argc == 0 && first)
2605 (void) fprintf(stderr,
2606 gettext("no pools available to import\n"));
2607
2608 error:
2609 nvlist_free(props);
2610 nvlist_free(pools);
2611 nvlist_free(policy);
2612 free(searchdirs);
2613
2614 return (err ? 1 : 0);
2615 }
2616
2617 typedef struct iostat_cbdata {
2618 boolean_t cb_verbose;
2619 int cb_namewidth;
2620 int cb_iteration;
2621 zpool_list_t *cb_list;
2622 } iostat_cbdata_t;
2623
2624 static void
2625 print_iostat_separator(iostat_cbdata_t *cb)
2626 {
2627 int i = 0;
2628
2629 for (i = 0; i < cb->cb_namewidth; i++)
2630 (void) printf("-");
2631 (void) printf(" ----- ----- ----- ----- ----- ----- ----- "
2632 "-----\n");
2633 }
2634
2635 static void
2636 print_iostat_header(iostat_cbdata_t *cb)
2637 {
2638 (void) printf("%*s capacity operations bandwidth "
2639 "latency\n", cb->cb_namewidth, "");
2640 (void) printf("%-*s alloc free read write read write read "
2641 "write\n", cb->cb_namewidth, "pool");
2642 print_iostat_separator(cb);
2643 }
2644
2645 /*
2646 * Display a single statistic.
2647 */
2648 static void
2649 print_one_stat(uint64_t value)
2650 {
2651 char buf[64];
2652
2653 zfs_nicenum(value, buf, sizeof (buf));
2654 (void) printf(" %5s", buf);
2655 }
2656
2657 /*
2658 * Display latency statistic (extra care needed)
2659 */
2660 static void
2661 print_one_latency_stat(uint64_t iotime, uint64_t ops)
2662 {
2663 char buf[64];
2664 double value = 0.0; /* latency in milliseconds */
2665
2666 if (ops != 0) {
2667 value = (double)iotime;
2668 value /= (double)ops;
2669 value /= (double)(MICROSEC / MILLISEC);
2670 }
2671
2672 (void) sprintf(buf, "%.2f", value);
2673 (void) printf(" %5s", buf);
2674 }
2675
2676 /*
2677 * Print out all the statistics for the given vdev. This can either be the
2678 * toplevel configuration, or called recursively. If 'name' is NULL, then this
2679 * is a verbose output, and we don't want to display the toplevel pool stats.
2680 */
2681 void
2682 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2683 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2684 {
2685 nvlist_t **oldchild, **newchild;
2686 uint_t c, children;
2687 vdev_stat_t *oldvs, *newvs;
2688 vdev_stat_t zerovs = { 0 };
2689 uint64_t tdelta;
2690 double scale;
2691 char *vname;
2692
2693 if (oldnv != NULL) {
2694 verify(nvlist_lookup_uint64_array(oldnv,
2695 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2696 } else {
2697 oldvs = &zerovs;
2698 }
2699
2700 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2701 (uint64_t **)&newvs, &c) == 0);
2702
2703 if (strlen(name) + depth > cb->cb_namewidth)
2704 (void) printf("%*s%s", depth, "", name);
2705 else
2706 (void) printf("%*s%s%*s", depth, "", name,
2707 (int)(cb->cb_namewidth - strlen(name) - depth), "");
2708
2709 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2710
2711 if (tdelta == 0)
2712 scale = 1.0;
2716 /* only toplevel vdevs have capacity stats */
2717 if (newvs->vs_space == 0) {
2718 (void) printf(" - -");
2719 } else {
2720 print_one_stat(newvs->vs_alloc);
2721 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2722 }
2723
2724 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2725 oldvs->vs_ops[ZIO_TYPE_READ])));
2726
2727 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2728 oldvs->vs_ops[ZIO_TYPE_WRITE])));
2729
2730 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2731 oldvs->vs_bytes[ZIO_TYPE_READ])));
2732
2733 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2734 oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2735
2736 /*
2737 * No scale needed here since we are dividing in
2738 * print_one_latency_stat()
2739 */
2740
2741 print_one_latency_stat(
2742 newvs->vs_iotime[ZIO_TYPE_READ] - oldvs->vs_iotime[ZIO_TYPE_READ],
2743 newvs->vs_ops[ZIO_TYPE_READ] - oldvs->vs_ops[ZIO_TYPE_READ]);
2744
2745 print_one_latency_stat(
2746 newvs->vs_iotime[ZIO_TYPE_WRITE] - oldvs->vs_iotime[ZIO_TYPE_WRITE],
2747 newvs->vs_ops[ZIO_TYPE_WRITE] - oldvs->vs_ops[ZIO_TYPE_WRITE]);
2748
2749 (void) printf("\n");
2750
2751 if (!cb->cb_verbose)
2752 return;
2753
2754 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2755 &newchild, &children) != 0)
2756 return;
2757
2758 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2759 &oldchild, &c) != 0)
2760 return;
2761
2762 for (c = 0; c < children; c++) {
2763 uint64_t ishole = B_FALSE, islog = B_FALSE, isspec = B_FALSE;
2764
2765 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2766 &ishole);
2767
2768 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2769 &islog);
2770
2771 (void) nvlist_lookup_uint64(newchild[c],
2772 ZPOOL_CONFIG_IS_SPECIAL, &isspec);
2773
2774 if (ishole || islog || isspec)
2775 continue;
2776
2777 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2778 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2779 newchild[c], cb, depth + 2);
2780 free(vname);
2781 }
2782
2783 /*
2784 * Log device section
2785 */
2786
2787 if (num_logs(newnv) > 0) {
2788 (void) printf("%-*s - - - - - "
2789 "-\n", cb->cb_namewidth, "logs");
2790
2791 for (c = 0; c < children; c++) {
2792 uint64_t islog = B_FALSE;
2793 (void) nvlist_lookup_uint64(newchild[c],
2794 ZPOOL_CONFIG_IS_LOG, &islog);
2795
2796 if (islog) {
2797 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2798 B_FALSE);
2799 print_vdev_stats(zhp, vname, oldnv ?
2800 oldchild[c] : NULL, newchild[c],
2801 cb, depth + 2);
2802 free(vname);
2803 }
2804 }
2805 }
2806
2807 /*
2808 * Special device section
2809 */
2810
2811 if (num_special(newnv) > 0) {
2812 (void) printf("%-*s - - - - - "
2813 "-\n", cb->cb_namewidth, "special");
2814
2815 for (c = 0; c < children; c++) {
2816 uint64_t isspec = B_FALSE;
2817 (void) nvlist_lookup_uint64(newchild[c],
2818 ZPOOL_CONFIG_IS_SPECIAL, &isspec);
2819
2820 if (isspec) {
2821 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2822 B_FALSE);
2823 print_vdev_stats(zhp, vname, oldnv ?
2824 oldchild[c] : NULL, newchild[c],
2825 cb, depth + 2);
2826 free(vname);
2827 }
2828 }
2829 }
2830
2831 /*
2832 * Include level 2 ARC devices in iostat output
2833 */
2834 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2835 &newchild, &children) != 0)
2836 return;
2837
2838 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2839 &oldchild, &c) != 0)
2840 return;
2841
2842 if (children > 0) {
2843 (void) printf("%-*s - - - - - "
2844 "-\n", cb->cb_namewidth, "cache");
2845 for (c = 0; c < children; c++) {
2846 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2847 B_FALSE);
2848 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2849 newchild[c], cb, depth + 2);
3318 void
3319 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3320 list_cbdata_t *cb, int depth)
3321 {
3322 nvlist_t **child;
3323 vdev_stat_t *vs;
3324 uint_t c, children;
3325 char *vname;
3326 boolean_t scripted = cb->cb_scripted;
3327 uint64_t islog = B_FALSE;
3328 boolean_t haslog = B_FALSE;
3329 char *dashes = "%-*s - - - - - -\n";
3330
3331 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3332 (uint64_t **)&vs, &c) == 0);
3333
3334 if (name != NULL) {
3335 boolean_t toplevel = (vs->vs_space != 0);
3336 uint64_t cap;
3337
3338 if (scripted)
3339 (void) printf("\t%s", name);
3340 else if (strlen(name) + depth > cb->cb_namewidth)
3341 (void) printf("%*s%s", depth, "", name);
3342 else
3343 (void) printf("%*s%s%*s", depth, "", name,
3344 (int)(cb->cb_namewidth - strlen(name) - depth), "");
3345
3346 /*
3347 * Print the properties for the individual vdevs. Some
3348 * properties are only applicable to toplevel vdevs. The
3349 * 'toplevel' boolean value is passed to the print_one_column()
3350 * to indicate that the value is valid.
3351 */
3352 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3353 toplevel);
3354 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3355 toplevel);
3356 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3357 scripted, toplevel);
3449 }
3450
3451 /*
3452 * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3453 *
3454 * -H Scripted mode. Don't display headers, and separate properties
3455 * by a single tab.
3456 * -o List of properties to display. Defaults to
3457 * "name,size,allocated,free,expandsize,fragmentation,capacity,"
3458 * "dedupratio,health,altroot"
3459 * -p Diplay values in parsable (exact) format.
3460 * -T Display a timestamp in date(1) or Unix format
3461 *
3462 * List all pools in the system, whether or not they're healthy. Output space
3463 * statistics for each one, as well as health status summary.
3464 */
3465 int
3466 zpool_do_list(int argc, char **argv)
3467 {
3468 int c;
3469 int ret = 0;
3470 list_cbdata_t cb = { 0 };
3471 static char default_props[] =
3472 "name,size,allocated,free,expandsize,fragmentation,capacity,"
3473 "dedupratio,health,altroot";
3474 char *props = default_props;
3475 unsigned long interval = 0, count = 0;
3476 zpool_list_t *list;
3477 boolean_t first = B_TRUE;
3478
3479 /* check options */
3480 while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3481 switch (c) {
3482 case 'H':
3483 cb.cb_scripted = B_TRUE;
3484 break;
3485 case 'o':
3486 props = optarg;
3487 break;
3488 case 'p':
3489 cb.cb_literal = B_TRUE;
4193 int
4194 scrub_callback(zpool_handle_t *zhp, void *data)
4195 {
4196 scrub_cbdata_t *cb = data;
4197 int err;
4198
4199 /*
4200 * Ignore faulted pools.
4201 */
4202 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4203 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
4204 "currently unavailable\n"), zpool_get_name(zhp));
4205 return (1);
4206 }
4207
4208 err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
4209
4210 return (err != 0);
4211 }
4212
4213 typedef struct trim_cbdata {
4214 boolean_t cb_start;
4215 uint64_t cb_rate;
4216 } trim_cbdata_t;
4217
4218 int
4219 trim_callback(zpool_handle_t *zhp, void *data)
4220 {
4221 trim_cbdata_t *cb = data;
4222 int err;
4223
4224 /*
4225 * Ignore faulted pools.
4226 */
4227 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4228 (void) fprintf(stderr, gettext("cannot trim '%s': pool is "
4229 "currently unavailable\n"), zpool_get_name(zhp));
4230 return (1);
4231 }
4232
4233 err = zpool_trim(zhp, cb->cb_start, cb->cb_rate);
4234
4235 return (err != 0);
4236 }
4237
4238 /*
4239 * zpool scrub [-s | -p] <pool> ...
4240 *
4241 * -s Stop. Stops any in-progress scrub.
4242 * -p Pause. Pause in-progress scrub.
4243 */
4244 int
4245 zpool_do_scrub(int argc, char **argv)
4246 {
4247 int c;
4248 scrub_cbdata_t cb;
4249
4250 cb.cb_type = POOL_SCAN_SCRUB;
4251 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
4252
4253 /* check options */
4254 while ((c = getopt(argc, argv, "mMps")) != -1) {
4255 switch (c) {
4256 case 's':
4257 if (cb.cb_type != POOL_SCAN_SCRUB) {
4258 (void) fprintf(stderr,
4259 gettext("incompatible options\n"));
4260 usage(B_FALSE);
4261 } else
4262 cb.cb_type = POOL_SCAN_NONE;
4263 break;
4264 case 'M':
4265 if (cb.cb_type != POOL_SCAN_SCRUB) {
4266 (void) fprintf(stderr,
4267 gettext("incompatible options\n"));
4268 usage(B_FALSE);
4269 } else
4270 cb.cb_type = POOL_SCAN_MOS;
4271 break;
4272 case 'm':
4273 if (cb.cb_type != POOL_SCAN_SCRUB) {
4274 (void) fprintf(stderr,
4275 gettext("incompatible options\n"));
4276 usage(B_FALSE);
4277 } else
4278 cb.cb_type = POOL_SCAN_META;
4279 break;
4280 case 'p':
4281 cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4282 break;
4283 case '?':
4284 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4285 optopt);
4286 usage(B_FALSE);
4287 }
4288 }
4289
4290 if (cb.cb_type == POOL_SCAN_NONE &&
4291 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4292 (void) fprintf(stderr, gettext("invalid option combination: "
4293 "-s and -p are mutually exclusive\n"));
4294 usage(B_FALSE);
4295 }
4296
4297 cb.cb_argc = argc;
4298 cb.cb_argv = argv;
4299 argc -= optind;
4300 argv += optind;
4301
4302 if (argc < 1) {
4303 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4304 usage(B_FALSE);
4305 }
4306
4307 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4308 }
4309
4310 /*
4311 * zpool trim [-s|-r <rate>] <pool> ...
4312 *
4313 * -s Stop. Stops any in-progress trim.
4314 * -r <rate> Sets the TRIM rate.
4315 */
4316 int
4317 zpool_do_trim(int argc, char **argv)
4318 {
4319 int c;
4320 trim_cbdata_t cb;
4321
4322 cb.cb_start = B_TRUE;
4323 cb.cb_rate = 0;
4324
4325 /* check options */
4326 while ((c = getopt(argc, argv, "sr:")) != -1) {
4327 switch (c) {
4328 case 's':
4329 cb.cb_start = B_FALSE;
4330 break;
4331 case 'r':
4332 if (zfs_nicestrtonum(NULL, optarg, &cb.cb_rate) == -1) {
4333 (void) fprintf(stderr,
4334 gettext("invalid value for rate\n"));
4335 usage(B_FALSE);
4336 }
4337 break;
4338 case '?':
4339 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4340 optopt);
4341 usage(B_FALSE);
4342 }
4343 }
4344
4345 argc -= optind;
4346 argv += optind;
4347
4348 if (argc < 1) {
4349 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4350 usage(B_FALSE);
4351 }
4352
4353 return (for_each_pool(argc, argv, B_TRUE, NULL, trim_callback, &cb));
4354 }
4355
4356 typedef struct status_cbdata {
4357 int cb_count;
4358 boolean_t cb_allpools;
4359 boolean_t cb_verbose;
4360 boolean_t cb_explain;
4361 boolean_t cb_first;
4362 boolean_t cb_dedup_stats;
4363 } status_cbdata_t;
4364
4365 /*
4366 * Print out detailed scrub status.
4367 */
4368 void
4369 print_scan_status(pool_scan_stat_t *ps)
4370 {
4371 time_t start, end, pause;
4372 uint64_t elapsed, mins_left, hours_left;
4373 uint64_t examined, total;
4374 uint64_t rate, proc_rate;
4375 double fraction_done;
4376 char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7],
4377 issued_buf[7];
4378
4379 (void) printf(gettext(" scan: "));
4380
4381 /* If there's never been a scan, there's not much to say. */
4382 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4383 ps->pss_func >= POOL_SCAN_FUNCS) {
4384 (void) printf(gettext("none requested\n"));
4385 return;
4386 }
4387
4388 start = ps->pss_start_time;
4389 end = ps->pss_end_time;
4390 pause = ps->pss_pass_scrub_pause;
4391 zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4392
4393 assert(ps->pss_func == POOL_SCAN_SCRUB ||
4394 ps->pss_func == POOL_SCAN_RESILVER ||
4395 ps->pss_func == POOL_SCAN_MOS ||
4396 ps->pss_func == POOL_SCAN_META);
4397 /*
4398 * Scan is finished or canceled.
4399 */
4400 if (ps->pss_state == DSS_FINISHED) {
4401 uint64_t minutes_taken = (end - start) / 60;
4402 char *fmt = NULL;
4403
4404 if (ps->pss_func == POOL_SCAN_SCRUB) {
4405 fmt = gettext("scrub repaired %s in %lluh%um with "
4406 "%llu errors on %s");
4407 } else if (ps->pss_func == POOL_SCAN_MOS) {
4408 fmt = gettext("MOS scrub repaired %s in %lluh%um with "
4409 "%llu errors on %s");
4410 } else if (ps->pss_func == POOL_SCAN_META) {
4411 fmt = gettext("meta scrub repaired %s in %lluh%um with "
4412 "%llu errors on %s");
4413 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4414 fmt = gettext("resilvered %s in %lluh%um with "
4415 "%llu errors on %s");
4416 }
4417 /* LINTED */
4418 (void) printf(fmt, processed_buf,
4419 (u_longlong_t)(minutes_taken / 60),
4420 (uint_t)(minutes_taken % 60),
4421 (u_longlong_t)ps->pss_errors,
4422 ctime((time_t *)&end));
4423 return;
4424 } else if (ps->pss_state == DSS_CANCELED) {
4425 if (ps->pss_func == POOL_SCAN_SCRUB) {
4426 (void) printf(gettext("scrub canceled on %s"),
4427 ctime(&end));
4428 } else if (ps->pss_func == POOL_SCAN_MOS) {
4429 (void) printf(gettext("MOS scrub canceled on %s"),
4430 ctime(&end));
4431 } else if (ps->pss_func == POOL_SCAN_META) {
4432 (void) printf(gettext("meta scrub canceled on %s"),
4433 ctime(&end));
4434 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4435 (void) printf(gettext("resilver canceled on %s"),
4436 ctime(&end));
4437 }
4438 return;
4439 }
4440
4441 assert(ps->pss_state == DSS_SCANNING || ps->pss_state == DSS_FINISHING);
4442
4443 /*
4444 * Scan is in progress.
4445 */
4446 if (ps->pss_func == POOL_SCAN_SCRUB) {
4447 if (pause == 0) {
4448 (void) printf(gettext("scrub in progress since %s"),
4449 ctime(&start));
4450 } else {
4451 char buf[32];
4452 struct tm *p = localtime(&pause);
4453 (void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p);
4454 (void) printf(gettext("scrub paused since %s\n"), buf);
4455 (void) printf(gettext("\tscrub started on %s"),
4456 ctime(&start));
4457 }
4458 } else if (ps->pss_func == POOL_SCAN_MOS) {
4459 (void) printf(gettext("MOS scrub in progress since %s"),
4460 ctime(&start));
4461 } else if (ps->pss_func == POOL_SCAN_META) {
4462 (void) printf(gettext("meta scrub in progress since %s"),
4463 ctime(&start));
4464 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4465 (void) printf(gettext("resilver in progress since %s"),
4466 ctime(&start));
4467 }
4468
4469 examined = ps->pss_examined;
4470 total = ps->pss_to_examine;
4471 fraction_done = (double)ps->pss_issued / total;
4472
4473 /* elapsed time for this pass */
4474 elapsed = MAX(time(NULL) - ps->pss_start_time -
4475 ps->pss_pass_scrub_spent_paused, 1);
4476 if (ps->pss_func == POOL_SCAN_RESILVER) {
4477 rate = MAX(((ps->pss_issued + ps->pss_processed) / 2) /
4478 elapsed, 1);
4479 } else {
4480 rate = MAX(ps->pss_issued / elapsed, 1);
4481 }
4482 proc_rate = MAX(ps->pss_processed / elapsed, 1);
4483 if (ps->pss_func == POOL_SCAN_RESILVER)
4484 mins_left = ((total - ps->pss_issued) / proc_rate) / 60;
4485 else
4486 mins_left = ((total - ps->pss_issued) / rate) / 60;
4487 hours_left = mins_left / 60;
4488
4489 zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
4490 zfs_nicenum(ps->pss_issued, issued_buf, sizeof (issued_buf));
4491 zfs_nicenum(total, total_buf, sizeof (total_buf));
4492 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4493
4494 if (pause == 0) {
4495 (void) printf(gettext(" %s scanned, %s verified "
4496 "out of %s at %s/s, %.2f%% done\n"), examined_buf,
4497 issued_buf, total_buf, rate_buf, 100 * fraction_done);
4498 }
4499
4500 if (ps->pss_func == POOL_SCAN_RESILVER) {
4501 char proc_rate_buf[7];
4502 zfs_nicenum(proc_rate, proc_rate_buf,
4503 sizeof (proc_rate_buf));
4504 (void) printf(gettext(" %s resilvered at %s/s"),
4505 processed_buf, proc_rate_buf);
4506 } else if (ps->pss_func == POOL_SCAN_SCRUB ||
4507 ps->pss_func == POOL_SCAN_MOS ||
4508 ps->pss_func == POOL_SCAN_META) {
4509 (void) printf(gettext(" %s repaired"),
4510 processed_buf);
4511 }
4512
4513 /*
4514 * do not print estimated time if hours_left is more than 30 days
4515 * or we have a paused scrub
4516 */
4517 if (pause == 0) {
4518 if (hours_left < (30 * 24)) {
4519 (void) printf(gettext(", %lluh%um to go\n"),
4520 (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4521 } else {
4522 (void) printf(gettext(
4523 ", (scan is slow, no estimated time)\n"));
4524 }
4525 } else {
4526 (void) printf(gettext("\t%s scanned, %s verified out of %s\n"),
4527 examined_buf, issued_buf, total_buf);
4528 }
4529 }
4530
4531 static void
4532 print_trim_status(uint64_t trim_prog, uint64_t total_size, uint64_t rate,
4533 uint64_t start_time_u64, uint64_t end_time_u64)
4534 {
4535 time_t start_time = start_time_u64, end_time = end_time_u64;
4536 char *buf;
4537
4538 assert(trim_prog <= total_size);
4539 if (trim_prog != 0 && trim_prog != total_size) {
4540 buf = ctime(&start_time);
4541 buf[strlen(buf) - 1] = '\0'; /* strip trailing newline */
4542 if (rate != 0) {
4543 char rate_str[32];
4544 zfs_nicenum(rate, rate_str, sizeof (rate_str));
4545 (void) printf(" trim: %.02f%%\tstarted: %s\t"
4546 "(rate: %s/s)\n", (((double)trim_prog) /
4547 total_size) * 100, buf, rate_str);
4548 } else {
4549 (void) printf(" trim: %.02f%%\tstarted: %s\t"
4550 "(rate: max)\n", (((double)trim_prog) /
4551 total_size) * 100, buf);
4552 }
4553 } else {
4554 if (start_time != 0) {
4555 /*
4556 * Non-zero start time means we were run at some point
4557 * in the past.
4558 */
4559 if (end_time != 0) {
4560 /* Non-zero end time means we completed */
4561 time_t diff = end_time - start_time;
4562 int hrs, mins;
4563
4564 buf = ctime(&end_time);
4565 buf[strlen(buf) - 1] = '\0';
4566 hrs = diff / 3600;
4567 mins = (diff % 3600) / 60;
4568 (void) printf(gettext(" trim: completed on %s "
4569 "(after %dh%dm)\n"), buf, hrs, mins);
4570 } else {
4571 buf = ctime(&start_time);
4572 buf[strlen(buf) - 1] = '\0';
4573 /* Zero end time means we were interrupted */
4574 (void) printf(gettext(" trim: interrupted\t"
4575 "(started %s)\n"), buf);
4576 }
4577 } else {
4578 /* trim was never run */
4579 (void) printf(gettext(" trim: none requested\n"));
4580 }
4581 }
4582 }
4583
4584 static void
4585 print_error_log(zpool_handle_t *zhp)
4586 {
4587 nvlist_t *nverrlist = NULL;
4588 nvpair_t *elem;
4589 char *pathname;
4590 size_t len = MAXPATHLEN * 2;
4591
4592 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
4593 (void) printf("errors: List of errors unavailable "
4594 "(insufficient privileges)\n");
4595 return;
4596 }
4597
4598 (void) printf("errors: Permanent errors have been "
4599 "detected in the following files:\n\n");
4600
4676 (void) printf("\n");
4677 (void) printf(gettext(" dedup: "));
4678 if (ddo->ddo_count == 0) {
4679 (void) printf(gettext("no DDT entries\n"));
4680 return;
4681 }
4682
4683 (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4684 (u_longlong_t)ddo->ddo_count,
4685 (u_longlong_t)ddo->ddo_dspace,
4686 (u_longlong_t)ddo->ddo_mspace);
4687
4688 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4689 (uint64_t **)&dds, &c) == 0);
4690 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4691 (uint64_t **)&ddh, &c) == 0);
4692 zpool_dump_ddt(dds, ddh);
4693 }
4694
4695 /*
4696 * Calculates the total space available on log devices on the pool.
4697 * For whatever reason, this is not counted in the root vdev's space stats.
4698 */
4699 static uint64_t
4700 zpool_slog_space(nvlist_t *nvroot)
4701 {
4702 nvlist_t **newchild;
4703 uint_t c, children;
4704 uint64_t space = 0;
4705
4706 verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4707 &newchild, &children) == 0);
4708
4709 for (c = 0; c < children; c++) {
4710 uint64_t islog = B_FALSE;
4711 vdev_stat_t *vs;
4712 uint_t n;
4713 uint_t n_subchildren = 1;
4714 nvlist_t **subchild;
4715
4716 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
4717 &islog);
4718 if (!islog)
4719 continue;
4720 verify(nvlist_lookup_uint64_array(newchild[c],
4721 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &n) == 0);
4722
4723 /* vdev can be non-leaf, so multiply by number of children */
4724 (void) nvlist_lookup_nvlist_array(newchild[c],
4725 ZPOOL_CONFIG_CHILDREN, &subchild, &n_subchildren);
4726 space += n_subchildren * vs->vs_space;
4727 }
4728
4729 return (space);
4730 }
4731
4732 /*
4733 * Display a summary of pool status. Displays a summary such as:
4734 *
4735 * pool: tank
4736 * status: DEGRADED
4737 * reason: One or more devices ...
4738 * see: http://illumos.org/msg/ZFS-xxxx-01
4739 * config:
4740 * mirror DEGRADED
4741 * c1t0d0 OK
4742 * c2t0d0 UNAVAIL
4743 *
4744 * When given the '-v' option, we print out the complete config. If the '-e'
4745 * option is specified, then we print out error rate information as well.
4746 */
4747 int
4748 status_callback(zpool_handle_t *zhp, void *data)
4749 {
4750 status_cbdata_t *cbp = data;
4751 nvlist_t *config, *nvroot;
4752 char *msgid;
4765 * problems.
4766 */
4767 if (cbp->cb_explain &&
4768 (reason == ZPOOL_STATUS_OK ||
4769 reason == ZPOOL_STATUS_VERSION_OLDER ||
4770 reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4771 if (!cbp->cb_allpools) {
4772 (void) printf(gettext("pool '%s' is healthy\n"),
4773 zpool_get_name(zhp));
4774 if (cbp->cb_first)
4775 cbp->cb_first = B_FALSE;
4776 }
4777 return (0);
4778 }
4779
4780 if (cbp->cb_first)
4781 cbp->cb_first = B_FALSE;
4782 else
4783 (void) printf("\n");
4784
4785 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4786 &nvroot) == 0);
4787 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4788 (uint64_t **)&vs, &c) == 0);
4789 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4790
4791 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
4792 (void) printf(gettext(" state: %s\n"), health);
4793
4794 switch (reason) {
4795 case ZPOOL_STATUS_MISSING_DEV_R:
4796 (void) printf(gettext("status: One or more devices could not "
4797 "be opened. Sufficient replicas exist for\n\tthe pool to "
4798 "continue functioning in a degraded state.\n"));
4799 (void) printf(gettext("action: Attach the missing device and "
4800 "online it using 'zpool online'.\n"));
4801 break;
4802
4803 case ZPOOL_STATUS_MISSING_DEV_NR:
4804 (void) printf(gettext("status: One or more devices could not "
4805 "be opened. There are insufficient\n\treplicas for the "
4806 "pool to continue functioning.\n"));
4974 "'zpool clear'.\n"));
4975 break;
4976
4977 default:
4978 /*
4979 * The remaining errors can't actually be generated, yet.
4980 */
4981 assert(reason == ZPOOL_STATUS_OK);
4982 }
4983
4984 if (msgid != NULL)
4985 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
4986 msgid);
4987
4988 if (config != NULL) {
4989 int namewidth;
4990 uint64_t nerr;
4991 nvlist_t **spares, **l2cache;
4992 uint_t nspares, nl2cache;
4993 pool_scan_stat_t *ps = NULL;
4994 uint64_t trim_prog, trim_rate, trim_start_time, trim_stop_time;
4995
4996 (void) nvlist_lookup_uint64_array(nvroot,
4997 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4998 print_scan_status(ps);
4999
5000 /* Grab trim stats if the pool supports it */
5001 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_PROG,
5002 &trim_prog) == 0 &&
5003 nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_RATE,
5004 &trim_rate) == 0 &&
5005 nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_START_TIME,
5006 &trim_start_time) == 0 &&
5007 nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_STOP_TIME,
5008 &trim_stop_time) == 0) {
5009 /*
5010 * For whatever reason, root vdev_stats_t don't
5011 * include log devices.
5012 */
5013 print_trim_status(trim_prog, vs->vs_space +
5014 zpool_slog_space(nvroot), trim_rate,
5015 trim_start_time, trim_stop_time);
5016 }
5017
5018 namewidth = max_width(zhp, nvroot, 0, 0);
5019 if (namewidth < 10)
5020 namewidth = 10;
5021
5022 (void) printf(gettext("config:\n\n"));
5023 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth,
5024 "NAME", "STATE", "READ", "WRITE", "CKSUM");
5025 print_status_config(zhp, zpool_get_name(zhp), nvroot,
5026 namewidth, 0, B_FALSE);
5027
5028 if (num_special(nvroot) > 0)
5029 print_special(zhp, nvroot, namewidth, B_TRUE);
5030 if (num_logs(nvroot) > 0)
5031 print_logs(zhp, nvroot, namewidth, B_TRUE);
5032 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
5033 &l2cache, &nl2cache) == 0)
5034 print_l2cache(zhp, l2cache, nl2cache, namewidth);
5035
5036 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
5037 &spares, &nspares) == 0)
5038 print_spares(zhp, spares, nspares, namewidth);
5039
5040 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
5041 &nerr) == 0) {
5042 nvlist_t *nverrlist = NULL;
5043
5044 /*
5045 * If the approximate error count is small, get a
5046 * precise count by fetching the entire log and
5047 * uniquifying the results.
5048 */
5049 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
5189 "'%s' from version %llu to feature flags.\n"),
5190 zpool_get_name(zhp), oldversion);
5191 } else {
5192 (void) printf(gettext("Successfully upgraded "
5193 "'%s' from version %llu to version %llu.\n"),
5194 zpool_get_name(zhp), oldversion, version);
5195 }
5196
5197 return (0);
5198 }
5199
5200 static int
5201 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
5202 {
5203 int i, ret, count;
5204 boolean_t firstff = B_TRUE;
5205 nvlist_t *enabled = zpool_get_features(zhp);
5206
5207 count = 0;
5208 for (i = 0; i < SPA_FEATURES; i++) {
5209 zfeature_info_t *finfo = &spa_feature_table[i];
5210 const char *fname = finfo->fi_uname;
5211 const char *fguid = finfo->fi_guid;
5212 if (!nvlist_exists(enabled, fguid)) {
5213 char *propname;
5214
5215 /*
5216 * SPA_FEATURE_WBC can be enabled only
5217 * if 'special' vdev available
5218 */
5219 if (finfo->fi_feature == SPA_FEATURE_WBC)
5220 continue;
5221
5222 verify(-1 != asprintf(&propname, "feature@%s", fname));
5223 ret = zpool_set_prop(zhp, propname,
5224 ZFS_FEATURE_ENABLED);
5225 if (ret != 0) {
5226 free(propname);
5227 return (ret);
5228 }
5229 count++;
5230
5231 if (firstff) {
5232 (void) printf(gettext("Enabled the "
5233 "following features on '%s':\n"),
5234 zpool_get_name(zhp));
5235 firstff = B_FALSE;
5236 }
5237 (void) printf(gettext(" %s\n"), fname);
5238 free(propname);
5239 }
5240 }
5241
5959
5960 if (cb.cb_proplist != NULL) {
5961 fake_name.pl_prop = ZPOOL_PROP_NAME;
5962 fake_name.pl_width = strlen(gettext("NAME"));
5963 fake_name.pl_next = cb.cb_proplist;
5964 cb.cb_proplist = &fake_name;
5965 }
5966
5967 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
5968 get_callback, &cb);
5969
5970 if (cb.cb_proplist == &fake_name)
5971 zprop_free_list(fake_name.pl_next);
5972 else
5973 zprop_free_list(cb.cb_proplist);
5974
5975 return (ret);
5976 }
5977
5978 typedef struct set_cbdata {
5979 nvlist_t *cb_nvl;
5980 boolean_t cb_any_successful;
5981 } set_cbdata_t;
5982
5983 int
5984 set_callback(zpool_handle_t *zhp, void *data)
5985 {
5986 int error;
5987 set_cbdata_t *cb = (set_cbdata_t *)data;
5988
5989 error = zpool_set_proplist(zhp, cb->cb_nvl);
5990 if (!error)
5991 cb->cb_any_successful = B_TRUE;
5992
5993 return (error);
5994 }
5995
5996 static void
5997 parse_props(char *propname, nvlist_t **nvl, zfs_type_t prop_type)
5998 {
5999 char *propval;
6000 char *delim;
6001 int err;
6002
6003 do {
6004 delim = strchr(propname, ',');
6005 if (delim != NULL)
6006 *delim++ = '\0';
6007
6008 propval = strchr(propname, '=');
6009 if (propval == NULL) {
6010 (void) fprintf(stderr, gettext("missing value "
6011 "in property=value argument\n"));
6012 if (*nvl != NULL)
6013 nvlist_free(*nvl);
6014 usage(B_FALSE);
6015 }
6016 *propval++ = '\0';
6017 switch (prop_type) {
6018 case ZFS_TYPE_VDEV:
6019 err = add_vdev_prop_list(propname, propval, nvl);
6020 break;
6021 case ZFS_TYPE_COS:
6022 err = add_cos_prop_list(propname, propval, nvl);
6023 break;
6024 default:
6025 err = add_prop_list(propname, propval, nvl, B_TRUE);
6026 }
6027
6028 if (err) {
6029 if (*nvl != NULL)
6030 nvlist_free(*nvl);
6031 usage(B_FALSE);
6032 }
6033
6034 propname = delim;
6035 } while (delim != NULL);
6036 }
6037
6038 int
6039 zpool_do_set(int argc, char **argv)
6040 {
6041 set_cbdata_t cb = { 0 };
6042 int error;
6043
6044 if (argc > 1 && argv[1][0] == '-') {
6045 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6046 argv[1][1]);
6047 usage(B_FALSE);
6048 }
6049
6050 if (argc < 2) {
6051 (void) fprintf(stderr, gettext("missing property=value "
6052 "argument\n"));
6053 usage(B_FALSE);
6054 }
6055
6056 if (argc < 3) {
6057 (void) fprintf(stderr, gettext("missing pool name\n"));
6058 usage(B_FALSE);
6059 }
6060
6061 if (argc > 3) {
6062 (void) fprintf(stderr, gettext("too many pool names\n"));
6063 usage(B_FALSE);
6064 }
6065
6066 parse_props(argv[1], &cb.cb_nvl, ZFS_TYPE_POOL);
6067
6068 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
6069 set_callback, &cb);
6070
6071 return (error);
6072 }
6073
6074 typedef struct vdev_cbdata {
6075 char *vcb_vdev;
6076 nvlist_t *vcb_nvl; /* values */
6077 boolean_t vcb_any_successful;
6078 } vdev_cbdata_t;
6079
6080 typedef struct vdev_get_cbdata {
6081 zprop_get_cbdata_t vcb_zprop_get_cbdata;
6082 char *vcb_vdev;
6083 nvlist_t *vcb_nvl; /* values */
6084 boolean_t vcb_any_successful;
6085 } vdev_get_cbdata_t;
6086
6087 static int
6088 vdev_get_callback(zpool_handle_t *zhp, void *data)
6089 {
6090 int err;
6091 boolean_t l2cache, avail_space;
6092 vdev_get_cbdata_t *vcb = (vdev_get_cbdata_t *)data;
6093 zprop_get_cbdata_t *cb = &vcb->vcb_zprop_get_cbdata;
6094 char value[MAXNAMELEN];
6095 zprop_list_t *pl;
6096
6097 (void) zpool_find_vdev(zhp, vcb->vcb_vdev, &avail_space,
6098 &l2cache, NULL, NULL);
6099 for (pl = cb->cb_proplist; pl != NULL; pl = pl->pl_next) {
6100 if ((err = vdev_get_prop(zhp, vcb->vcb_vdev,
6101 pl->pl_prop, value, sizeof (value))) != 0)
6102 return (err);
6103
6104 /* don't show L2ARC prop for non L2ARC dev, can't set anyway */
6105 if (!l2cache && pl->pl_prop == VDEV_PROP_L2ADDDT)
6106 continue;
6107 vdev_print_one_property(zpool_get_name(zhp), vcb->vcb_vdev, cb,
6108 vdev_prop_to_name(pl->pl_prop), value);
6109 }
6110
6111 return (0);
6112 }
6113
6114
6115 int
6116 zpool_do_vdev_get(int argc, char **argv)
6117 {
6118 vdev_get_cbdata_t vcb = { 0 };
6119 zprop_get_cbdata_t *cb = &vcb.vcb_zprop_get_cbdata;
6120 int error;
6121
6122 if (argc > 1 && argv[1][0] == '-') {
6123 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6124 argv[1][1]);
6125 usage(B_FALSE);
6126 }
6127
6128 if (argc < 2) {
6129 (void) fprintf(stderr, gettext("missing property name\n"));
6130 usage(B_FALSE);
6131 }
6132
6133 if (argc < 3) {
6134 (void) fprintf(stderr, gettext("missing pool name\n"));
6135 usage(B_FALSE);
6136 }
6137
6138 if (argc < 4) {
6139 (void) fprintf(stderr,
6140 gettext("at least one vdev name or guid is required\n"));
6141 usage(B_FALSE);
6142 }
6143
6144 cb->cb_first = B_TRUE;
6145 cb->cb_sources = ZPROP_SRC_ALL;
6146 cb->cb_columns[0] = GET_COL_NAME;
6147 cb->cb_columns[1] = GET_COL_SOURCE;
6148 cb->cb_columns[2] = GET_COL_PROPERTY;
6149 cb->cb_columns[3] = GET_COL_VALUE;
6150 cb->cb_type = ZFS_TYPE_VDEV;
6151
6152 if (vdev_get_proplist(g_zfs, argv[1], &cb->cb_proplist) != 0)
6153 usage(B_FALSE);
6154
6155 vcb.vcb_vdev = argv[3];
6156 error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6157 vdev_get_callback, &vcb);
6158
6159 zprop_free_list(cb->cb_proplist);
6160
6161 return (error);
6162 }
6163
6164 int
6165 vdev_set_callback(zpool_handle_t *zhp, void *data)
6166 {
6167 int error;
6168 vdev_cbdata_t *cb = (vdev_cbdata_t *)data;
6169
6170 error = vdev_set_proplist(zhp, cb->vcb_vdev, cb->vcb_nvl);
6171 if (!error)
6172 cb->vcb_any_successful = B_TRUE;
6173
6174 return (error);
6175 }
6176
6177 int
6178 zpool_do_vdev_set(int argc, char **argv)
6179 {
6180 vdev_cbdata_t cb = { 0 };
6181 int error;
6182
6183 if (argc > 1 && argv[1][0] == '-') {
6184 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6185 argv[1][1]);
6186 usage(B_FALSE);
6187 }
6188
6189 if (argc < 2) {
6190 (void) fprintf(stderr, gettext("missing property=value "
6191 "argument\n"));
6192 usage(B_FALSE);
6193 }
6194
6195 if (argc < 3) {
6196 (void) fprintf(stderr, gettext("missing pool name\n"));
6197 usage(B_FALSE);
6198 }
6199
6200 if (argc < 4) {
6201 (void) fprintf(stderr,
6202 gettext("at least one vdev name or guid is required\n"));
6203 usage(B_FALSE);
6204 }
6205
6206 parse_props(argv[1], &cb.vcb_nvl, ZFS_TYPE_VDEV);
6207
6208 cb.vcb_vdev = argv[3];
6209 error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6210 vdev_set_callback, &cb);
6211
6212 return (error);
6213 }
6214
6215 typedef struct cos_af_cbdata {
6216 char *cb_cos;
6217 uint64_t cb_guid;
6218 boolean_t cb_alloc;
6219 boolean_t cb_any_successful;
6220 boolean_t cb_force;
6221 nvlist_t *cb_nvl;
6222 } cos_af_cbdata_t;
6223
6224 int
6225 cos_alloc_callback(zpool_handle_t *zhp, void *data)
6226 {
6227 int error;
6228 cos_af_cbdata_t *cb = (cos_af_cbdata_t *)data;
6229
6230 if (cb->cb_alloc)
6231 error = cos_alloc(zhp, cb->cb_cos, cb->cb_nvl);
6232 else
6233 error = cos_free(zhp, cb->cb_cos, cb->cb_guid, cb->cb_force);
6234 if (!error)
6235 cb->cb_any_successful = B_TRUE;
6236
6237 if (error == ENOTSUP) {
6238 (void) fprintf(stderr, gettext("operation failed: "
6239 "CoS feature is disabled.\n"));
6240 }
6241
6242 return (error);
6243 }
6244
6245 int
6246 zpool_do_cos_alloc(int argc, char **argv)
6247 {
6248 nvlist_t *nvl;
6249 cos_af_cbdata_t cb = { 0 };
6250 int error;
6251
6252 if (!nexenta_meta_enable())
6253 return (-1);
6254
6255 if (argc < 2) {
6256 (void) fprintf(stderr, gettext("missing pool name\n"));
6257 usage(B_FALSE);
6258 }
6259
6260 if (argc < 3) {
6261 (void) fprintf(stderr,
6262 gettext("at least one cos name or id is required\n"));
6263 usage(B_FALSE);
6264 }
6265
6266 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
6267 (void) fprintf(stderr,
6268 gettext("internal error: out of memory\n"));
6269 return (1);
6270 }
6271
6272 cb.cb_cos = argv[2];
6273 cb.cb_alloc = B_TRUE;
6274 cb.cb_nvl = nvl;
6275 error = for_each_pool(1, argv + 1, B_TRUE, NULL,
6276 cos_alloc_callback, &cb);
6277
6278 nvlist_free(nvl);
6279
6280 return (error);
6281 }
6282
6283 int
6284 zpool_do_cos_free(int argc, char **argv)
6285 {
6286 cos_af_cbdata_t cb = { 0 };
6287 char *endp;
6288 int error;
6289
6290 if (!nexenta_meta_enable())
6291 return (-1);
6292
6293 if (argc > 1 && strncmp(argv[1], "-f", sizeof ("-f")) == 0) {
6294 /* -f - force option */
6295 cb.cb_force = B_TRUE;
6296 argc--;
6297 argv++;
6298 }
6299
6300 if (argc < 2) {
6301 (void) fprintf(stderr, gettext("missing pool name\n"));
6302 usage(B_FALSE);
6303 }
6304
6305 if (argc < 3) {
6306 (void) fprintf(stderr,
6307 gettext("at least one cos name or id is required\n"));
6308 usage(B_FALSE);
6309 }
6310
6311 cb.cb_guid = strtoll(argv[2], &endp, 10);
6312 if (endp < argv[2] + strlen(argv[2])) {
6313 cb.cb_guid = 0;
6314 }
6315
6316 if (cb.cb_guid == 0)
6317 cb.cb_cos = argv[2];
6318 else
6319 cb.cb_cos = "";
6320
6321 error = for_each_pool(1, argv + 1, B_TRUE, NULL,
6322 cos_alloc_callback, &cb);
6323
6324 return (error);
6325 }
6326
6327
6328 static int
6329 cos_list_callback(zpool_handle_t *zhp, void *data)
6330 {
6331 int err, i;
6332 nvlist_t *nvl = (nvlist_t *)data;
6333 nvpair_t *nvp;
6334
6335 if ((err = cos_list(zhp, &nvl)) == 0) {
6336 (void) printf("%-*s %s\n", MAXCOSNAMELEN, gettext("COSNAME"),
6337 gettext("COSID"));
6338 for (i = 0, nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
6339 nvp = nvlist_next_nvpair(nvl, nvp), i++) {
6340 uint64_t cosid;
6341 char *cosname = nvpair_name(nvp);
6342 if (nvpair_value_uint64(nvp, &cosid) == 0)
6343 (void) printf("%-*s %llu\n", MAXCOSNAMELEN,
6344 cosname, cosid);
6345 }
6346
6347 if (!i)
6348 (void) printf("%s\n", gettext("<no classes found>"));
6349 }
6350 return (err);
6351 }
6352
6353 int
6354 zpool_do_cos_list(int argc, char **argv)
6355 {
6356 nvlist_t *nvl;
6357 int error;
6358
6359 if (!nexenta_meta_enable())
6360 return (-1);
6361
6362 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
6363 (void) fprintf(stderr,
6364 gettext("internal error: out of memory\n"));
6365 return (1);
6366 }
6367
6368 if (argc < 2) {
6369 (void) fprintf(stderr, gettext("missing pool name\n"));
6370 usage(B_FALSE);
6371 }
6372
6373 error = for_each_pool(1, argv+1, B_TRUE, NULL,
6374 cos_list_callback, nvl);
6375
6376 nvlist_free(nvl);
6377
6378 return (error);
6379
6380 }
6381
6382 typedef struct cos_cbdata {
6383 char *vcb_cos;
6384 nvlist_t *vcb_nvl; /* values */
6385 boolean_t vcb_any_successful;
6386 } cos_cbdata_t;
6387
6388 typedef struct cos_get_cbdata {
6389 zprop_get_cbdata_t vcb_zprop_get_cbdata;
6390 char *vcb_cos;
6391 nvlist_t *vcb_nvl; /* values */
6392 boolean_t vcb_any_successful;
6393 } cos_get_cbdata_t;
6394
6395 static int
6396 cos_get_callback(zpool_handle_t *zhp, void *data)
6397 {
6398 int err;
6399 cos_get_cbdata_t *vcb = (cos_get_cbdata_t *)data;
6400 zprop_get_cbdata_t *cb = &vcb->vcb_zprop_get_cbdata;
6401 char value[MAXNAMELEN];
6402 zprop_list_t *pl;
6403 nvlist_t *nvl = NULL;
6404
6405 for (pl = cb->cb_proplist; pl != NULL; pl = pl->pl_next) {
6406 if ((err = cos_get_prop(zhp, vcb->vcb_cos,
6407 pl->pl_prop, value, sizeof (value), &nvl)) != 0)
6408 return (err);
6409
6410 cos_print_one_property(zpool_get_name(zhp), vcb->vcb_cos, cb,
6411 cos_prop_to_name(pl->pl_prop), value);
6412 }
6413
6414 return (0);
6415 }
6416
6417
6418 int
6419 zpool_do_cos_get(int argc, char **argv)
6420 {
6421 cos_get_cbdata_t vcb = { 0 };
6422 zprop_get_cbdata_t *cb = &vcb.vcb_zprop_get_cbdata;
6423 int error;
6424
6425 if (!nexenta_meta_enable())
6426 return (-1);
6427
6428 if (argc > 1 && argv[1][0] == '-') {
6429 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6430 argv[1][1]);
6431 usage(B_FALSE);
6432 }
6433
6434 if (argc < 2) {
6435 (void) fprintf(stderr, gettext("missing property name\n"));
6436 usage(B_FALSE);
6437 }
6438
6439 if (argc < 3) {
6440 (void) fprintf(stderr, gettext("missing pool name\n"));
6441 usage(B_FALSE);
6442 }
6443
6444 if (argc < 4) {
6445 (void) fprintf(stderr,
6446 gettext("at least one cos name or guid is required\n"));
6447 usage(B_FALSE);
6448 }
6449
6450 cb->cb_first = B_TRUE;
6451 cb->cb_sources = ZPROP_SRC_ALL;
6452 cb->cb_columns[0] = GET_COL_NAME;
6453 cb->cb_columns[1] = GET_COL_SOURCE;
6454 cb->cb_columns[2] = GET_COL_PROPERTY;
6455 cb->cb_columns[3] = GET_COL_VALUE;
6456 cb->cb_type = ZFS_TYPE_COS;
6457
6458 if (cos_get_proplist(g_zfs, argv[1], &cb->cb_proplist) != 0)
6459 usage(B_FALSE);
6460
6461 vcb.vcb_cos = argv[3];
6462 error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6463 cos_get_callback, &vcb);
6464
6465 zprop_free_list(cb->cb_proplist);
6466
6467 return (error);
6468
6469 }
6470
6471 int
6472 cos_set_callback(zpool_handle_t *zhp, void *data)
6473 {
6474 int error;
6475 cos_cbdata_t *cb = (cos_cbdata_t *)data;
6476
6477 error = cos_set_proplist(zhp, cb->vcb_cos, cb->vcb_nvl);
6478 if (!error)
6479 cb->vcb_any_successful = B_TRUE;
6480
6481 return (error);
6482 }
6483
6484 int
6485 zpool_do_cos_set(int argc, char **argv)
6486 {
6487 cos_cbdata_t cb = { 0 };
6488 int error;
6489
6490 if (!nexenta_meta_enable())
6491 return (-1);
6492
6493 if (argc > 1 && argv[1][0] == '-') {
6494 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6495 argv[1][1]);
6496 usage(B_FALSE);
6497 }
6498
6499 if (argc < 2) {
6500 (void) fprintf(stderr, gettext("missing property=value "
6501 "argument\n"));
6502 usage(B_FALSE);
6503 }
6504
6505 if (argc < 3) {
6506 (void) fprintf(stderr, gettext("missing pool name\n"));
6507 usage(B_FALSE);
6508 }
6509
6510 if (argc < 4) {
6511 (void) fprintf(stderr,
6512 gettext("at least one cos name or id is required\n"));
6513 usage(B_FALSE);
6514 }
6515
6516 parse_props(argv[1], &cb.vcb_nvl, ZFS_TYPE_COS);
6517
6518 cb.vcb_cos = argv[3];
6519 error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6520 cos_set_callback, &cb);
6521
6522 return (error);
6523 }
6524
6525 static int
6526 find_command_idx(char *command, int *idx)
6527 {
6528 int i;
6529
6530 for (i = 0; i < NCOMMAND; i++) {
6531 if (command_table[i].name == NULL)
6532 continue;
6533
6534 if (strcmp(command, command_table[i].name) == 0) {
6535 *idx = i;
6536 return (0);
6537 }
6538 }
6539 return (1);
6540 }
6541
6542 int
6543 main(int argc, char **argv)
6544 {
6545 int ret = 0;
6559
6560 opterr = 0;
6561
6562 /*
6563 * Make sure the user has specified some command.
6564 */
6565 if (argc < 2) {
6566 (void) fprintf(stderr, gettext("missing command\n"));
6567 usage(B_FALSE);
6568 }
6569
6570 cmdname = argv[1];
6571
6572 /*
6573 * Special case '-?'
6574 */
6575 if (strcmp(cmdname, "-?") == 0)
6576 usage(B_TRUE);
6577
6578 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
6579 verify(zpool_stage_history(g_zfs, history_str) == 0);
6580
6581 /*
6582 * Run the appropriate command.
6583 */
6584 if (find_command_idx(cmdname, &i) == 0) {
6585 current_command = &command_table[i];
6586 ret = command_table[i].func(argc - 1, argv + 1);
6587 } else if (strchr(cmdname, '=')) {
6588 verify(find_command_idx("set", &i) == 0);
6589 current_command = &command_table[i];
6590 ret = command_table[i].func(argc, argv);
6591 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
6592 /*
6593 * 'freeze' is a vile debugging abomination, so we treat
6594 * it as such.
6595 */
6596 char buf[16384];
6597 int fd = open(ZFS_DEV, O_RDWR);
6598 (void) strcpy((void *)buf, argv[2]);
6599 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
|