Print this page
1765 assert importing pool with number at start
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/zpool/zpool_main.c
+++ new/usr/src/cmd/zpool/zpool_main.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
25 25 * Copyright (c) 2012 by Delphix. All rights reserved.
26 26 * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
27 27 */
28 28
29 29 #include <assert.h>
30 30 #include <ctype.h>
31 31 #include <dirent.h>
32 32 #include <errno.h>
33 33 #include <fcntl.h>
34 34 #include <libgen.h>
35 35 #include <libintl.h>
36 36 #include <libuutil.h>
37 37 #include <locale.h>
38 38 #include <stdio.h>
39 39 #include <stdlib.h>
40 40 #include <string.h>
41 41 #include <strings.h>
42 42 #include <unistd.h>
43 43 #include <priv.h>
44 44 #include <pwd.h>
45 45 #include <zone.h>
46 46 #include <zfs_prop.h>
47 47 #include <sys/fs/zfs.h>
48 48 #include <sys/stat.h>
49 49
50 50 #include <libzfs.h>
51 51
52 52 #include "zpool_util.h"
53 53 #include "zfs_comutil.h"
54 54 #include "zfeature_common.h"
55 55
56 56 #include "statcommon.h"
57 57
58 58 static int zpool_do_create(int, char **);
59 59 static int zpool_do_destroy(int, char **);
60 60
61 61 static int zpool_do_add(int, char **);
62 62 static int zpool_do_remove(int, char **);
63 63
64 64 static int zpool_do_list(int, char **);
65 65 static int zpool_do_iostat(int, char **);
66 66 static int zpool_do_status(int, char **);
67 67
68 68 static int zpool_do_online(int, char **);
69 69 static int zpool_do_offline(int, char **);
70 70 static int zpool_do_clear(int, char **);
71 71 static int zpool_do_reopen(int, char **);
72 72
73 73 static int zpool_do_reguid(int, char **);
74 74
75 75 static int zpool_do_attach(int, char **);
76 76 static int zpool_do_detach(int, char **);
77 77 static int zpool_do_replace(int, char **);
78 78 static int zpool_do_split(int, char **);
79 79
80 80 static int zpool_do_scrub(int, char **);
81 81
82 82 static int zpool_do_import(int, char **);
83 83 static int zpool_do_export(int, char **);
84 84
85 85 static int zpool_do_upgrade(int, char **);
86 86
87 87 static int zpool_do_history(int, char **);
88 88
89 89 static int zpool_do_get(int, char **);
90 90 static int zpool_do_set(int, char **);
91 91
92 92 /*
93 93 * These libumem hooks provide a reasonable set of defaults for the allocator's
94 94 * debugging facilities.
95 95 */
96 96
97 97 #ifdef DEBUG
98 98 const char *
99 99 _umem_debug_init(void)
100 100 {
101 101 return ("default,verbose"); /* $UMEM_DEBUG setting */
102 102 }
103 103
104 104 const char *
105 105 _umem_logging_init(void)
106 106 {
107 107 return ("fail,contents"); /* $UMEM_LOGGING setting */
108 108 }
109 109 #endif
110 110
111 111 typedef enum {
112 112 HELP_ADD,
113 113 HELP_ATTACH,
114 114 HELP_CLEAR,
115 115 HELP_CREATE,
116 116 HELP_DESTROY,
117 117 HELP_DETACH,
118 118 HELP_EXPORT,
119 119 HELP_HISTORY,
120 120 HELP_IMPORT,
121 121 HELP_IOSTAT,
122 122 HELP_LIST,
123 123 HELP_OFFLINE,
124 124 HELP_ONLINE,
125 125 HELP_REPLACE,
126 126 HELP_REMOVE,
127 127 HELP_SCRUB,
128 128 HELP_STATUS,
129 129 HELP_UPGRADE,
130 130 HELP_GET,
131 131 HELP_SET,
132 132 HELP_SPLIT,
133 133 HELP_REGUID,
134 134 HELP_REOPEN
135 135 } zpool_help_t;
136 136
137 137
138 138 typedef struct zpool_command {
139 139 const char *name;
140 140 int (*func)(int, char **);
141 141 zpool_help_t usage;
142 142 } zpool_command_t;
143 143
144 144 /*
145 145 * Master command table. Each ZFS command has a name, associated function, and
146 146 * usage message. The usage messages need to be internationalized, so we have
147 147 * to have a function to return the usage message based on a command index.
148 148 *
149 149 * These commands are organized according to how they are displayed in the usage
150 150 * message. An empty command (one with a NULL name) indicates an empty line in
151 151 * the generic usage message.
152 152 */
153 153 static zpool_command_t command_table[] = {
154 154 { "create", zpool_do_create, HELP_CREATE },
155 155 { "destroy", zpool_do_destroy, HELP_DESTROY },
156 156 { NULL },
157 157 { "add", zpool_do_add, HELP_ADD },
158 158 { "remove", zpool_do_remove, HELP_REMOVE },
159 159 { NULL },
160 160 { "list", zpool_do_list, HELP_LIST },
161 161 { "iostat", zpool_do_iostat, HELP_IOSTAT },
162 162 { "status", zpool_do_status, HELP_STATUS },
163 163 { NULL },
164 164 { "online", zpool_do_online, HELP_ONLINE },
165 165 { "offline", zpool_do_offline, HELP_OFFLINE },
166 166 { "clear", zpool_do_clear, HELP_CLEAR },
167 167 { "reopen", zpool_do_reopen, HELP_REOPEN },
168 168 { NULL },
169 169 { "attach", zpool_do_attach, HELP_ATTACH },
170 170 { "detach", zpool_do_detach, HELP_DETACH },
171 171 { "replace", zpool_do_replace, HELP_REPLACE },
172 172 { "split", zpool_do_split, HELP_SPLIT },
173 173 { NULL },
174 174 { "scrub", zpool_do_scrub, HELP_SCRUB },
175 175 { NULL },
176 176 { "import", zpool_do_import, HELP_IMPORT },
177 177 { "export", zpool_do_export, HELP_EXPORT },
178 178 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
179 179 { "reguid", zpool_do_reguid, HELP_REGUID },
180 180 { NULL },
181 181 { "history", zpool_do_history, HELP_HISTORY },
182 182 { "get", zpool_do_get, HELP_GET },
183 183 { "set", zpool_do_set, HELP_SET },
184 184 };
185 185
186 186 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
187 187
188 188 static zpool_command_t *current_command;
189 189 static char history_str[HIS_MAX_RECORD_LEN];
190 190 static boolean_t log_history = B_TRUE;
191 191 static uint_t timestamp_fmt = NODATE;
192 192
193 193 static const char *
194 194 get_usage(zpool_help_t idx) {
195 195 switch (idx) {
196 196 case HELP_ADD:
197 197 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
198 198 case HELP_ATTACH:
199 199 return (gettext("\tattach [-f] <pool> <device> "
200 200 "<new-device>\n"));
201 201 case HELP_CLEAR:
202 202 return (gettext("\tclear [-nF] <pool> [device]\n"));
203 203 case HELP_CREATE:
204 204 return (gettext("\tcreate [-fnd] [-o property=value] ... \n"
205 205 "\t [-O file-system-property=value] ... \n"
206 206 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
207 207 case HELP_DESTROY:
208 208 return (gettext("\tdestroy [-f] <pool>\n"));
209 209 case HELP_DETACH:
210 210 return (gettext("\tdetach <pool> <device>\n"));
211 211 case HELP_EXPORT:
212 212 return (gettext("\texport [-f] <pool> ...\n"));
213 213 case HELP_HISTORY:
214 214 return (gettext("\thistory [-il] [<pool>] ...\n"));
215 215 case HELP_IMPORT:
216 216 return (gettext("\timport [-d dir] [-D]\n"
217 217 "\timport [-d dir | -c cachefile] [-F [-n]] <pool | id>\n"
218 218 "\timport [-o mntopts] [-o property=value] ... \n"
219 219 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
220 220 "[-R root] [-F [-n]] -a\n"
221 221 "\timport [-o mntopts] [-o property=value] ... \n"
222 222 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
223 223 "[-R root] [-F [-n]]\n"
224 224 "\t <pool | id> [newpool]\n"));
225 225 case HELP_IOSTAT:
226 226 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
227 227 "[count]]\n"));
228 228 case HELP_LIST:
229 229 return (gettext("\tlist [-H] [-o property[,...]] "
230 230 "[-T d|u] [pool] ... [interval [count]]\n"));
231 231 case HELP_OFFLINE:
232 232 return (gettext("\toffline [-t] <pool> <device> ...\n"));
233 233 case HELP_ONLINE:
234 234 return (gettext("\tonline <pool> <device> ...\n"));
235 235 case HELP_REPLACE:
236 236 return (gettext("\treplace [-f] <pool> <device> "
237 237 "[new-device]\n"));
238 238 case HELP_REMOVE:
239 239 return (gettext("\tremove <pool> <device> ...\n"));
240 240 case HELP_REOPEN:
241 241 return (gettext("\treopen <pool>\n"));
242 242 case HELP_SCRUB:
243 243 return (gettext("\tscrub [-s] <pool> ...\n"));
244 244 case HELP_STATUS:
245 245 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
246 246 "[count]]\n"));
247 247 case HELP_UPGRADE:
248 248 return (gettext("\tupgrade\n"
249 249 "\tupgrade -v\n"
250 250 "\tupgrade [-V version] <-a | pool ...>\n"));
251 251 case HELP_GET:
252 252 return (gettext("\tget <\"all\" | property[,...]> "
253 253 "<pool> ...\n"));
254 254 case HELP_SET:
255 255 return (gettext("\tset <property=value> <pool> \n"));
256 256 case HELP_SPLIT:
257 257 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
258 258 "\t [-o property=value] <pool> <newpool> "
259 259 "[<device> ...]\n"));
260 260 case HELP_REGUID:
261 261 return (gettext("\treguid <pool>\n"));
262 262 }
263 263
264 264 abort();
265 265 /* NOTREACHED */
266 266 }
267 267
268 268
269 269 /*
270 270 * Callback routine that will print out a pool property value.
271 271 */
272 272 static int
273 273 print_prop_cb(int prop, void *cb)
274 274 {
275 275 FILE *fp = cb;
276 276
277 277 (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop));
278 278
279 279 if (zpool_prop_readonly(prop))
280 280 (void) fprintf(fp, " NO ");
281 281 else
282 282 (void) fprintf(fp, " YES ");
283 283
284 284 if (zpool_prop_values(prop) == NULL)
285 285 (void) fprintf(fp, "-\n");
286 286 else
287 287 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
288 288
289 289 return (ZPROP_CONT);
290 290 }
291 291
292 292 /*
293 293 * Display usage message. If we're inside a command, display only the usage for
294 294 * that command. Otherwise, iterate over the entire command table and display
295 295 * a complete usage message.
296 296 */
297 297 void
298 298 usage(boolean_t requested)
299 299 {
300 300 FILE *fp = requested ? stdout : stderr;
301 301
302 302 if (current_command == NULL) {
303 303 int i;
304 304
305 305 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
306 306 (void) fprintf(fp,
307 307 gettext("where 'command' is one of the following:\n\n"));
308 308
309 309 for (i = 0; i < NCOMMAND; i++) {
310 310 if (command_table[i].name == NULL)
311 311 (void) fprintf(fp, "\n");
312 312 else
313 313 (void) fprintf(fp, "%s",
314 314 get_usage(command_table[i].usage));
315 315 }
316 316 } else {
317 317 (void) fprintf(fp, gettext("usage:\n"));
318 318 (void) fprintf(fp, "%s", get_usage(current_command->usage));
319 319 }
320 320
321 321 if (current_command != NULL &&
322 322 ((strcmp(current_command->name, "set") == 0) ||
323 323 (strcmp(current_command->name, "get") == 0) ||
324 324 (strcmp(current_command->name, "list") == 0))) {
325 325
326 326 (void) fprintf(fp,
327 327 gettext("\nthe following properties are supported:\n"));
328 328
329 329 (void) fprintf(fp, "\n\t%-15s %s %s\n\n",
330 330 "PROPERTY", "EDIT", "VALUES");
331 331
332 332 /* Iterate over all properties */
333 333 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
334 334 ZFS_TYPE_POOL);
335 335
336 336 (void) fprintf(fp, "\t%-15s ", "feature@...");
337 337 (void) fprintf(fp, "YES disabled | enabled | active\n");
338 338
339 339 (void) fprintf(fp, gettext("\nThe feature@ properties must be "
340 340 "appended with a feature name.\nSee zpool-features(5).\n"));
341 341 }
342 342
343 343 /*
344 344 * See comments at end of main().
345 345 */
346 346 if (getenv("ZFS_ABORT") != NULL) {
347 347 (void) printf("dumping core by request\n");
348 348 abort();
349 349 }
350 350
351 351 exit(requested ? 0 : 2);
352 352 }
353 353
354 354 void
355 355 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
356 356 boolean_t print_logs)
357 357 {
358 358 nvlist_t **child;
359 359 uint_t c, children;
360 360 char *vname;
361 361
362 362 if (name != NULL)
363 363 (void) printf("\t%*s%s\n", indent, "", name);
364 364
365 365 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
366 366 &child, &children) != 0)
367 367 return;
368 368
369 369 for (c = 0; c < children; c++) {
370 370 uint64_t is_log = B_FALSE;
371 371
372 372 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
373 373 &is_log);
374 374 if ((is_log && !print_logs) || (!is_log && print_logs))
375 375 continue;
376 376
377 377 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
378 378 print_vdev_tree(zhp, vname, child[c], indent + 2,
379 379 B_FALSE);
380 380 free(vname);
381 381 }
382 382 }
383 383
384 384 static boolean_t
385 385 prop_list_contains_feature(nvlist_t *proplist)
386 386 {
387 387 nvpair_t *nvp;
388 388 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
389 389 nvp = nvlist_next_nvpair(proplist, nvp)) {
390 390 if (zpool_prop_feature(nvpair_name(nvp)))
391 391 return (B_TRUE);
392 392 }
393 393 return (B_FALSE);
394 394 }
395 395
396 396 /*
397 397 * Add a property pair (name, string-value) into a property nvlist.
398 398 */
399 399 static int
400 400 add_prop_list(const char *propname, char *propval, nvlist_t **props,
401 401 boolean_t poolprop)
402 402 {
403 403 zpool_prop_t prop = ZPROP_INVAL;
404 404 zfs_prop_t fprop;
405 405 nvlist_t *proplist;
406 406 const char *normnm;
407 407 char *strval;
408 408
409 409 if (*props == NULL &&
410 410 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
411 411 (void) fprintf(stderr,
412 412 gettext("internal error: out of memory\n"));
413 413 return (1);
414 414 }
415 415
416 416 proplist = *props;
417 417
418 418 if (poolprop) {
419 419 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
420 420
421 421 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
422 422 !zpool_prop_feature(propname)) {
423 423 (void) fprintf(stderr, gettext("property '%s' is "
424 424 "not a valid pool property\n"), propname);
425 425 return (2);
426 426 }
427 427
428 428 /*
429 429 * feature@ properties and version should not be specified
430 430 * at the same time.
431 431 */
432 432 if ((prop == ZPROP_INVAL && zpool_prop_feature(propname) &&
433 433 nvlist_exists(proplist, vname)) ||
434 434 (prop == ZPOOL_PROP_VERSION &&
435 435 prop_list_contains_feature(proplist))) {
436 436 (void) fprintf(stderr, gettext("'feature@' and "
437 437 "'version' properties cannot be specified "
438 438 "together\n"));
439 439 return (2);
440 440 }
441 441
442 442
443 443 if (zpool_prop_feature(propname))
444 444 normnm = propname;
445 445 else
446 446 normnm = zpool_prop_to_name(prop);
447 447 } else {
448 448 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
449 449 normnm = zfs_prop_to_name(fprop);
450 450 } else {
451 451 normnm = propname;
452 452 }
453 453 }
454 454
455 455 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
456 456 prop != ZPOOL_PROP_CACHEFILE) {
457 457 (void) fprintf(stderr, gettext("property '%s' "
458 458 "specified multiple times\n"), propname);
459 459 return (2);
460 460 }
461 461
462 462 if (nvlist_add_string(proplist, normnm, propval) != 0) {
463 463 (void) fprintf(stderr, gettext("internal "
464 464 "error: out of memory\n"));
465 465 return (1);
466 466 }
467 467
468 468 return (0);
469 469 }
470 470
471 471 /*
472 472 * zpool add [-fn] <pool> <vdev> ...
473 473 *
474 474 * -f Force addition of devices, even if they appear in use
475 475 * -n Do not add the devices, but display the resulting layout if
476 476 * they were to be added.
477 477 *
478 478 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
479 479 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
480 480 * libzfs.
481 481 */
482 482 int
483 483 zpool_do_add(int argc, char **argv)
484 484 {
485 485 boolean_t force = B_FALSE;
486 486 boolean_t dryrun = B_FALSE;
487 487 int c;
488 488 nvlist_t *nvroot;
489 489 char *poolname;
490 490 int ret;
491 491 zpool_handle_t *zhp;
492 492 nvlist_t *config;
493 493
494 494 /* check options */
495 495 while ((c = getopt(argc, argv, "fn")) != -1) {
496 496 switch (c) {
497 497 case 'f':
498 498 force = B_TRUE;
499 499 break;
500 500 case 'n':
501 501 dryrun = B_TRUE;
502 502 break;
503 503 case '?':
504 504 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
505 505 optopt);
506 506 usage(B_FALSE);
507 507 }
508 508 }
509 509
510 510 argc -= optind;
511 511 argv += optind;
512 512
513 513 /* get pool name and check number of arguments */
514 514 if (argc < 1) {
515 515 (void) fprintf(stderr, gettext("missing pool name argument\n"));
516 516 usage(B_FALSE);
517 517 }
518 518 if (argc < 2) {
519 519 (void) fprintf(stderr, gettext("missing vdev specification\n"));
520 520 usage(B_FALSE);
521 521 }
522 522
523 523 poolname = argv[0];
524 524
525 525 argc--;
526 526 argv++;
527 527
528 528 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
529 529 return (1);
530 530
531 531 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
532 532 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
533 533 poolname);
534 534 zpool_close(zhp);
535 535 return (1);
536 536 }
537 537
538 538 /* pass off to get_vdev_spec for processing */
539 539 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
540 540 argc, argv);
541 541 if (nvroot == NULL) {
542 542 zpool_close(zhp);
543 543 return (1);
544 544 }
545 545
546 546 if (dryrun) {
547 547 nvlist_t *poolnvroot;
548 548
549 549 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
550 550 &poolnvroot) == 0);
551 551
552 552 (void) printf(gettext("would update '%s' to the following "
553 553 "configuration:\n"), zpool_get_name(zhp));
554 554
555 555 /* print original main pool and new tree */
556 556 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
557 557 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
558 558
559 559 /* Do the same for the logs */
560 560 if (num_logs(poolnvroot) > 0) {
561 561 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
562 562 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
563 563 } else if (num_logs(nvroot) > 0) {
564 564 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
565 565 }
566 566
567 567 ret = 0;
568 568 } else {
569 569 ret = (zpool_add(zhp, nvroot) != 0);
570 570 }
571 571
572 572 nvlist_free(nvroot);
573 573 zpool_close(zhp);
574 574
575 575 return (ret);
576 576 }
577 577
578 578 /*
579 579 * zpool remove <pool> <vdev> ...
580 580 *
581 581 * Removes the given vdev from the pool. Currently, this supports removing
582 582 * spares, cache, and log devices from the pool.
583 583 */
584 584 int
585 585 zpool_do_remove(int argc, char **argv)
586 586 {
587 587 char *poolname;
588 588 int i, ret = 0;
589 589 zpool_handle_t *zhp;
590 590
591 591 argc--;
592 592 argv++;
593 593
594 594 /* get pool name and check number of arguments */
595 595 if (argc < 1) {
596 596 (void) fprintf(stderr, gettext("missing pool name argument\n"));
597 597 usage(B_FALSE);
598 598 }
599 599 if (argc < 2) {
600 600 (void) fprintf(stderr, gettext("missing device\n"));
601 601 usage(B_FALSE);
602 602 }
603 603
604 604 poolname = argv[0];
605 605
606 606 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
607 607 return (1);
608 608
609 609 for (i = 1; i < argc; i++) {
610 610 if (zpool_vdev_remove(zhp, argv[i]) != 0)
611 611 ret = 1;
612 612 }
613 613
614 614 return (ret);
615 615 }
616 616
617 617 /*
618 618 * zpool create [-fnd] [-o property=value] ...
619 619 * [-O file-system-property=value] ...
620 620 * [-R root] [-m mountpoint] <pool> <dev> ...
621 621 *
622 622 * -f Force creation, even if devices appear in use
623 623 * -n Do not create the pool, but display the resulting layout if it
624 624 * were to be created.
625 625 * -R Create a pool under an alternate root
626 626 * -m Set default mountpoint for the root dataset. By default it's
627 627 * '/<pool>'
628 628 * -o Set property=value.
629 629 * -d Don't automatically enable all supported pool features
630 630 * (individual features can be enabled with -o).
631 631 * -O Set fsproperty=value in the pool's root file system
632 632 *
633 633 * Creates the named pool according to the given vdev specification. The
634 634 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
635 635 * we get the nvlist back from get_vdev_spec(), we either print out the contents
636 636 * (if '-n' was specified), or pass it to libzfs to do the creation.
637 637 */
638 638 int
639 639 zpool_do_create(int argc, char **argv)
640 640 {
641 641 boolean_t force = B_FALSE;
642 642 boolean_t dryrun = B_FALSE;
643 643 boolean_t enable_all_pool_feat = B_TRUE;
644 644 int c;
645 645 nvlist_t *nvroot = NULL;
646 646 char *poolname;
647 647 int ret = 1;
648 648 char *altroot = NULL;
649 649 char *mountpoint = NULL;
650 650 nvlist_t *fsprops = NULL;
651 651 nvlist_t *props = NULL;
652 652 char *propval;
653 653
654 654 /* check options */
655 655 while ((c = getopt(argc, argv, ":fndR:m:o:O:")) != -1) {
656 656 switch (c) {
657 657 case 'f':
658 658 force = B_TRUE;
659 659 break;
660 660 case 'n':
661 661 dryrun = B_TRUE;
662 662 break;
663 663 case 'd':
664 664 enable_all_pool_feat = B_FALSE;
665 665 break;
666 666 case 'R':
667 667 altroot = optarg;
668 668 if (add_prop_list(zpool_prop_to_name(
669 669 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
670 670 goto errout;
671 671 if (nvlist_lookup_string(props,
672 672 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
673 673 &propval) == 0)
674 674 break;
675 675 if (add_prop_list(zpool_prop_to_name(
676 676 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
677 677 goto errout;
678 678 break;
679 679 case 'm':
680 680 /* Equivalent to -O mountpoint=optarg */
681 681 mountpoint = optarg;
682 682 break;
683 683 case 'o':
684 684 if ((propval = strchr(optarg, '=')) == NULL) {
685 685 (void) fprintf(stderr, gettext("missing "
686 686 "'=' for -o option\n"));
687 687 goto errout;
688 688 }
689 689 *propval = '\0';
690 690 propval++;
691 691
692 692 if (add_prop_list(optarg, propval, &props, B_TRUE))
693 693 goto errout;
694 694
695 695 /*
696 696 * If the user is creating a pool that doesn't support
697 697 * feature flags, don't enable any features.
698 698 */
699 699 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
700 700 char *end;
701 701 u_longlong_t ver;
702 702
703 703 ver = strtoull(propval, &end, 10);
704 704 if (*end == '\0' &&
705 705 ver < SPA_VERSION_FEATURES) {
706 706 enable_all_pool_feat = B_FALSE;
707 707 }
708 708 }
709 709 break;
710 710 case 'O':
711 711 if ((propval = strchr(optarg, '=')) == NULL) {
712 712 (void) fprintf(stderr, gettext("missing "
713 713 "'=' for -O option\n"));
714 714 goto errout;
715 715 }
716 716 *propval = '\0';
717 717 propval++;
718 718
719 719 /*
720 720 * Mountpoints are checked and then added later.
721 721 * Uniquely among properties, they can be specified
722 722 * more than once, to avoid conflict with -m.
723 723 */
724 724 if (0 == strcmp(optarg,
725 725 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
726 726 mountpoint = propval;
727 727 } else if (add_prop_list(optarg, propval, &fsprops,
728 728 B_FALSE)) {
729 729 goto errout;
730 730 }
731 731 break;
732 732 case ':':
733 733 (void) fprintf(stderr, gettext("missing argument for "
734 734 "'%c' option\n"), optopt);
735 735 goto badusage;
736 736 case '?':
737 737 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
738 738 optopt);
739 739 goto badusage;
740 740 }
741 741 }
742 742
743 743 argc -= optind;
744 744 argv += optind;
745 745
746 746 /* get pool name and check number of arguments */
747 747 if (argc < 1) {
748 748 (void) fprintf(stderr, gettext("missing pool name argument\n"));
749 749 goto badusage;
750 750 }
751 751 if (argc < 2) {
752 752 (void) fprintf(stderr, gettext("missing vdev specification\n"));
753 753 goto badusage;
754 754 }
755 755
756 756 poolname = argv[0];
757 757
758 758 /*
759 759 * As a special case, check for use of '/' in the name, and direct the
760 760 * user to use 'zfs create' instead.
761 761 */
762 762 if (strchr(poolname, '/') != NULL) {
763 763 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
764 764 "character '/' in pool name\n"), poolname);
765 765 (void) fprintf(stderr, gettext("use 'zfs create' to "
766 766 "create a dataset\n"));
767 767 goto errout;
768 768 }
769 769
770 770 /* pass off to get_vdev_spec for bulk processing */
771 771 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
772 772 argc - 1, argv + 1);
773 773 if (nvroot == NULL)
774 774 goto errout;
775 775
776 776 /* make_root_vdev() allows 0 toplevel children if there are spares */
777 777 if (!zfs_allocatable_devs(nvroot)) {
778 778 (void) fprintf(stderr, gettext("invalid vdev "
779 779 "specification: at least one toplevel vdev must be "
780 780 "specified\n"));
781 781 goto errout;
782 782 }
783 783
784 784 if (altroot != NULL && altroot[0] != '/') {
785 785 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
786 786 "must be an absolute path\n"), altroot);
787 787 goto errout;
788 788 }
789 789
790 790 /*
791 791 * Check the validity of the mountpoint and direct the user to use the
792 792 * '-m' mountpoint option if it looks like its in use.
793 793 */
794 794 if (mountpoint == NULL ||
795 795 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
796 796 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
797 797 char buf[MAXPATHLEN];
798 798 DIR *dirp;
799 799
800 800 if (mountpoint && mountpoint[0] != '/') {
801 801 (void) fprintf(stderr, gettext("invalid mountpoint "
802 802 "'%s': must be an absolute path, 'legacy', or "
803 803 "'none'\n"), mountpoint);
804 804 goto errout;
805 805 }
806 806
807 807 if (mountpoint == NULL) {
808 808 if (altroot != NULL)
809 809 (void) snprintf(buf, sizeof (buf), "%s/%s",
810 810 altroot, poolname);
811 811 else
812 812 (void) snprintf(buf, sizeof (buf), "/%s",
813 813 poolname);
814 814 } else {
815 815 if (altroot != NULL)
816 816 (void) snprintf(buf, sizeof (buf), "%s%s",
817 817 altroot, mountpoint);
818 818 else
819 819 (void) snprintf(buf, sizeof (buf), "%s",
820 820 mountpoint);
821 821 }
822 822
823 823 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
824 824 (void) fprintf(stderr, gettext("mountpoint '%s' : "
825 825 "%s\n"), buf, strerror(errno));
826 826 (void) fprintf(stderr, gettext("use '-m' "
827 827 "option to provide a different default\n"));
828 828 goto errout;
829 829 } else if (dirp) {
830 830 int count = 0;
831 831
832 832 while (count < 3 && readdir(dirp) != NULL)
833 833 count++;
834 834 (void) closedir(dirp);
835 835
836 836 if (count > 2) {
837 837 (void) fprintf(stderr, gettext("mountpoint "
838 838 "'%s' exists and is not empty\n"), buf);
839 839 (void) fprintf(stderr, gettext("use '-m' "
840 840 "option to provide a "
841 841 "different default\n"));
842 842 goto errout;
843 843 }
844 844 }
845 845 }
846 846
847 847 /*
848 848 * Now that the mountpoint's validity has been checked, ensure that
849 849 * the property is set appropriately prior to creating the pool.
850 850 */
851 851 if (mountpoint != NULL) {
852 852 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
853 853 mountpoint, &fsprops, B_FALSE);
854 854 if (ret != 0)
855 855 goto errout;
856 856 }
857 857
858 858 ret = 1;
859 859 if (dryrun) {
860 860 /*
861 861 * For a dry run invocation, print out a basic message and run
862 862 * through all the vdevs in the list and print out in an
863 863 * appropriate hierarchy.
864 864 */
865 865 (void) printf(gettext("would create '%s' with the "
866 866 "following layout:\n\n"), poolname);
867 867
868 868 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
869 869 if (num_logs(nvroot) > 0)
870 870 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
871 871
872 872 ret = 0;
873 873 } else {
874 874 /*
875 875 * Hand off to libzfs.
876 876 */
877 877 if (enable_all_pool_feat) {
878 878 int i;
879 879 for (i = 0; i < SPA_FEATURES; i++) {
880 880 char propname[MAXPATHLEN];
881 881 zfeature_info_t *feat = &spa_feature_table[i];
882 882
883 883 (void) snprintf(propname, sizeof (propname),
884 884 "feature@%s", feat->fi_uname);
885 885
886 886 /*
887 887 * Skip feature if user specified it manually
888 888 * on the command line.
889 889 */
890 890 if (nvlist_exists(props, propname))
891 891 continue;
892 892
893 893 ret = add_prop_list(propname,
894 894 ZFS_FEATURE_ENABLED, &props, B_TRUE);
895 895 if (ret != 0)
896 896 goto errout;
897 897 }
898 898 }
899 899
900 900 ret = 1;
901 901 if (zpool_create(g_zfs, poolname,
902 902 nvroot, props, fsprops) == 0) {
903 903 zfs_handle_t *pool = zfs_open(g_zfs, poolname,
904 904 ZFS_TYPE_FILESYSTEM);
905 905 if (pool != NULL) {
906 906 if (zfs_mount(pool, NULL, 0) == 0)
907 907 ret = zfs_shareall(pool);
908 908 zfs_close(pool);
909 909 }
910 910 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
911 911 (void) fprintf(stderr, gettext("pool name may have "
912 912 "been omitted\n"));
913 913 }
914 914 }
915 915
916 916 errout:
917 917 nvlist_free(nvroot);
918 918 nvlist_free(fsprops);
919 919 nvlist_free(props);
920 920 return (ret);
921 921 badusage:
922 922 nvlist_free(fsprops);
923 923 nvlist_free(props);
924 924 usage(B_FALSE);
925 925 return (2);
926 926 }
927 927
928 928 /*
929 929 * zpool destroy <pool>
930 930 *
931 931 * -f Forcefully unmount any datasets
932 932 *
933 933 * Destroy the given pool. Automatically unmounts any datasets in the pool.
934 934 */
935 935 int
936 936 zpool_do_destroy(int argc, char **argv)
937 937 {
938 938 boolean_t force = B_FALSE;
939 939 int c;
940 940 char *pool;
941 941 zpool_handle_t *zhp;
942 942 int ret;
943 943
944 944 /* check options */
945 945 while ((c = getopt(argc, argv, "f")) != -1) {
946 946 switch (c) {
947 947 case 'f':
948 948 force = B_TRUE;
949 949 break;
950 950 case '?':
951 951 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
952 952 optopt);
953 953 usage(B_FALSE);
954 954 }
955 955 }
956 956
957 957 argc -= optind;
958 958 argv += optind;
959 959
960 960 /* check arguments */
961 961 if (argc < 1) {
962 962 (void) fprintf(stderr, gettext("missing pool argument\n"));
963 963 usage(B_FALSE);
964 964 }
965 965 if (argc > 1) {
966 966 (void) fprintf(stderr, gettext("too many arguments\n"));
967 967 usage(B_FALSE);
968 968 }
969 969
970 970 pool = argv[0];
971 971
972 972 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
973 973 /*
974 974 * As a special case, check for use of '/' in the name, and
975 975 * direct the user to use 'zfs destroy' instead.
976 976 */
977 977 if (strchr(pool, '/') != NULL)
978 978 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
979 979 "destroy a dataset\n"));
980 980 return (1);
981 981 }
982 982
983 983 if (zpool_disable_datasets(zhp, force) != 0) {
984 984 (void) fprintf(stderr, gettext("could not destroy '%s': "
985 985 "could not unmount datasets\n"), zpool_get_name(zhp));
986 986 return (1);
987 987 }
988 988
989 989 /* The history must be logged as part of the export */
990 990 log_history = B_FALSE;
991 991
992 992 ret = (zpool_destroy(zhp, history_str) != 0);
993 993
994 994 zpool_close(zhp);
995 995
996 996 return (ret);
997 997 }
998 998
999 999 /*
1000 1000 * zpool export [-f] <pool> ...
1001 1001 *
1002 1002 * -f Forcefully unmount datasets
1003 1003 *
1004 1004 * Export the given pools. By default, the command will attempt to cleanly
1005 1005 * unmount any active datasets within the pool. If the '-f' flag is specified,
1006 1006 * then the datasets will be forcefully unmounted.
1007 1007 */
1008 1008 int
1009 1009 zpool_do_export(int argc, char **argv)
1010 1010 {
1011 1011 boolean_t force = B_FALSE;
1012 1012 boolean_t hardforce = B_FALSE;
1013 1013 int c;
1014 1014 zpool_handle_t *zhp;
1015 1015 int ret;
1016 1016 int i;
1017 1017
1018 1018 /* check options */
1019 1019 while ((c = getopt(argc, argv, "fF")) != -1) {
1020 1020 switch (c) {
1021 1021 case 'f':
1022 1022 force = B_TRUE;
1023 1023 break;
1024 1024 case 'F':
1025 1025 hardforce = B_TRUE;
1026 1026 break;
1027 1027 case '?':
1028 1028 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1029 1029 optopt);
1030 1030 usage(B_FALSE);
1031 1031 }
1032 1032 }
1033 1033
1034 1034 argc -= optind;
1035 1035 argv += optind;
1036 1036
1037 1037 /* check arguments */
1038 1038 if (argc < 1) {
1039 1039 (void) fprintf(stderr, gettext("missing pool argument\n"));
1040 1040 usage(B_FALSE);
1041 1041 }
1042 1042
1043 1043 ret = 0;
1044 1044 for (i = 0; i < argc; i++) {
1045 1045 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1046 1046 ret = 1;
1047 1047 continue;
1048 1048 }
1049 1049
1050 1050 if (zpool_disable_datasets(zhp, force) != 0) {
1051 1051 ret = 1;
1052 1052 zpool_close(zhp);
1053 1053 continue;
1054 1054 }
1055 1055
1056 1056 /* The history must be logged as part of the export */
1057 1057 log_history = B_FALSE;
1058 1058
1059 1059 if (hardforce) {
1060 1060 if (zpool_export_force(zhp, history_str) != 0)
1061 1061 ret = 1;
1062 1062 } else if (zpool_export(zhp, force, history_str) != 0) {
1063 1063 ret = 1;
1064 1064 }
1065 1065
1066 1066 zpool_close(zhp);
1067 1067 }
1068 1068
1069 1069 return (ret);
1070 1070 }
1071 1071
1072 1072 /*
1073 1073 * Given a vdev configuration, determine the maximum width needed for the device
1074 1074 * name column.
1075 1075 */
1076 1076 static int
1077 1077 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1078 1078 {
1079 1079 char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1080 1080 nvlist_t **child;
1081 1081 uint_t c, children;
1082 1082 int ret;
1083 1083
1084 1084 if (strlen(name) + depth > max)
1085 1085 max = strlen(name) + depth;
1086 1086
1087 1087 free(name);
1088 1088
1089 1089 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1090 1090 &child, &children) == 0) {
1091 1091 for (c = 0; c < children; c++)
1092 1092 if ((ret = max_width(zhp, child[c], depth + 2,
1093 1093 max)) > max)
1094 1094 max = ret;
1095 1095 }
1096 1096
1097 1097 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1098 1098 &child, &children) == 0) {
1099 1099 for (c = 0; c < children; c++)
1100 1100 if ((ret = max_width(zhp, child[c], depth + 2,
1101 1101 max)) > max)
1102 1102 max = ret;
1103 1103 }
1104 1104
1105 1105 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1106 1106 &child, &children) == 0) {
1107 1107 for (c = 0; c < children; c++)
1108 1108 if ((ret = max_width(zhp, child[c], depth + 2,
1109 1109 max)) > max)
1110 1110 max = ret;
1111 1111 }
1112 1112
1113 1113
1114 1114 return (max);
1115 1115 }
1116 1116
1117 1117 typedef struct spare_cbdata {
1118 1118 uint64_t cb_guid;
1119 1119 zpool_handle_t *cb_zhp;
1120 1120 } spare_cbdata_t;
1121 1121
1122 1122 static boolean_t
1123 1123 find_vdev(nvlist_t *nv, uint64_t search)
1124 1124 {
1125 1125 uint64_t guid;
1126 1126 nvlist_t **child;
1127 1127 uint_t c, children;
1128 1128
1129 1129 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1130 1130 search == guid)
1131 1131 return (B_TRUE);
1132 1132
1133 1133 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1134 1134 &child, &children) == 0) {
1135 1135 for (c = 0; c < children; c++)
1136 1136 if (find_vdev(child[c], search))
1137 1137 return (B_TRUE);
1138 1138 }
1139 1139
1140 1140 return (B_FALSE);
1141 1141 }
1142 1142
1143 1143 static int
1144 1144 find_spare(zpool_handle_t *zhp, void *data)
1145 1145 {
1146 1146 spare_cbdata_t *cbp = data;
1147 1147 nvlist_t *config, *nvroot;
1148 1148
1149 1149 config = zpool_get_config(zhp, NULL);
1150 1150 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1151 1151 &nvroot) == 0);
1152 1152
1153 1153 if (find_vdev(nvroot, cbp->cb_guid)) {
1154 1154 cbp->cb_zhp = zhp;
1155 1155 return (1);
1156 1156 }
1157 1157
1158 1158 zpool_close(zhp);
1159 1159 return (0);
1160 1160 }
1161 1161
1162 1162 /*
1163 1163 * Print out configuration state as requested by status_callback.
1164 1164 */
1165 1165 void
1166 1166 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1167 1167 int namewidth, int depth, boolean_t isspare)
1168 1168 {
1169 1169 nvlist_t **child;
1170 1170 uint_t c, children;
1171 1171 pool_scan_stat_t *ps = NULL;
1172 1172 vdev_stat_t *vs;
1173 1173 char rbuf[6], wbuf[6], cbuf[6];
1174 1174 char *vname;
1175 1175 uint64_t notpresent;
1176 1176 spare_cbdata_t cb;
1177 1177 char *state;
1178 1178
1179 1179 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1180 1180 &child, &children) != 0)
1181 1181 children = 0;
1182 1182
1183 1183 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1184 1184 (uint64_t **)&vs, &c) == 0);
1185 1185
1186 1186 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1187 1187 if (isspare) {
1188 1188 /*
1189 1189 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1190 1190 * online drives.
1191 1191 */
1192 1192 if (vs->vs_aux == VDEV_AUX_SPARED)
1193 1193 state = "INUSE";
1194 1194 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1195 1195 state = "AVAIL";
1196 1196 }
1197 1197
1198 1198 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth,
1199 1199 name, state);
1200 1200
1201 1201 if (!isspare) {
1202 1202 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1203 1203 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1204 1204 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1205 1205 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1206 1206 }
1207 1207
1208 1208 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1209 1209 ¬present) == 0) {
1210 1210 char *path;
1211 1211 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
1212 1212 (void) printf(" was %s", path);
1213 1213 } else if (vs->vs_aux != 0) {
1214 1214 (void) printf(" ");
1215 1215
1216 1216 switch (vs->vs_aux) {
1217 1217 case VDEV_AUX_OPEN_FAILED:
1218 1218 (void) printf(gettext("cannot open"));
1219 1219 break;
1220 1220
1221 1221 case VDEV_AUX_BAD_GUID_SUM:
1222 1222 (void) printf(gettext("missing device"));
1223 1223 break;
1224 1224
1225 1225 case VDEV_AUX_NO_REPLICAS:
1226 1226 (void) printf(gettext("insufficient replicas"));
1227 1227 break;
1228 1228
1229 1229 case VDEV_AUX_VERSION_NEWER:
1230 1230 (void) printf(gettext("newer version"));
1231 1231 break;
1232 1232
1233 1233 case VDEV_AUX_UNSUP_FEAT:
1234 1234 (void) printf(gettext("unsupported feature(s)"));
1235 1235 break;
1236 1236
1237 1237 case VDEV_AUX_SPARED:
1238 1238 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1239 1239 &cb.cb_guid) == 0);
1240 1240 if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
1241 1241 if (strcmp(zpool_get_name(cb.cb_zhp),
1242 1242 zpool_get_name(zhp)) == 0)
1243 1243 (void) printf(gettext("currently in "
1244 1244 "use"));
1245 1245 else
1246 1246 (void) printf(gettext("in use by "
1247 1247 "pool '%s'"),
1248 1248 zpool_get_name(cb.cb_zhp));
1249 1249 zpool_close(cb.cb_zhp);
1250 1250 } else {
1251 1251 (void) printf(gettext("currently in use"));
1252 1252 }
1253 1253 break;
1254 1254
1255 1255 case VDEV_AUX_ERR_EXCEEDED:
1256 1256 (void) printf(gettext("too many errors"));
1257 1257 break;
1258 1258
1259 1259 case VDEV_AUX_IO_FAILURE:
1260 1260 (void) printf(gettext("experienced I/O failures"));
1261 1261 break;
1262 1262
1263 1263 case VDEV_AUX_BAD_LOG:
1264 1264 (void) printf(gettext("bad intent log"));
1265 1265 break;
1266 1266
1267 1267 case VDEV_AUX_EXTERNAL:
1268 1268 (void) printf(gettext("external device fault"));
1269 1269 break;
1270 1270
1271 1271 case VDEV_AUX_SPLIT_POOL:
1272 1272 (void) printf(gettext("split into new pool"));
1273 1273 break;
1274 1274
1275 1275 default:
1276 1276 (void) printf(gettext("corrupted data"));
1277 1277 break;
1278 1278 }
1279 1279 }
1280 1280
1281 1281 (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1282 1282 (uint64_t **)&ps, &c);
1283 1283
1284 1284 if (ps && ps->pss_state == DSS_SCANNING &&
1285 1285 vs->vs_scan_processed != 0 && children == 0) {
1286 1286 (void) printf(gettext(" (%s)"),
1287 1287 (ps->pss_func == POOL_SCAN_RESILVER) ?
1288 1288 "resilvering" : "repairing");
1289 1289 }
1290 1290
1291 1291 (void) printf("\n");
1292 1292
1293 1293 for (c = 0; c < children; c++) {
1294 1294 uint64_t islog = B_FALSE, ishole = B_FALSE;
1295 1295
1296 1296 /* Don't print logs or holes here */
1297 1297 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1298 1298 &islog);
1299 1299 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1300 1300 &ishole);
1301 1301 if (islog || ishole)
1302 1302 continue;
1303 1303 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1304 1304 print_status_config(zhp, vname, child[c],
1305 1305 namewidth, depth + 2, isspare);
1306 1306 free(vname);
1307 1307 }
1308 1308 }
1309 1309
1310 1310
1311 1311 /*
1312 1312 * Print the configuration of an exported pool. Iterate over all vdevs in the
1313 1313 * pool, printing out the name and status for each one.
1314 1314 */
1315 1315 void
1316 1316 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1317 1317 {
1318 1318 nvlist_t **child;
1319 1319 uint_t c, children;
1320 1320 vdev_stat_t *vs;
1321 1321 char *type, *vname;
1322 1322
1323 1323 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1324 1324 if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
1325 1325 strcmp(type, VDEV_TYPE_HOLE) == 0)
1326 1326 return;
1327 1327
1328 1328 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1329 1329 (uint64_t **)&vs, &c) == 0);
1330 1330
1331 1331 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1332 1332 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1333 1333
1334 1334 if (vs->vs_aux != 0) {
1335 1335 (void) printf(" ");
1336 1336
1337 1337 switch (vs->vs_aux) {
1338 1338 case VDEV_AUX_OPEN_FAILED:
1339 1339 (void) printf(gettext("cannot open"));
1340 1340 break;
1341 1341
1342 1342 case VDEV_AUX_BAD_GUID_SUM:
1343 1343 (void) printf(gettext("missing device"));
1344 1344 break;
1345 1345
1346 1346 case VDEV_AUX_NO_REPLICAS:
1347 1347 (void) printf(gettext("insufficient replicas"));
1348 1348 break;
1349 1349
1350 1350 case VDEV_AUX_VERSION_NEWER:
1351 1351 (void) printf(gettext("newer version"));
1352 1352 break;
1353 1353
1354 1354 case VDEV_AUX_UNSUP_FEAT:
1355 1355 (void) printf(gettext("unsupported feature(s)"));
1356 1356 break;
1357 1357
1358 1358 case VDEV_AUX_ERR_EXCEEDED:
1359 1359 (void) printf(gettext("too many errors"));
1360 1360 break;
1361 1361
1362 1362 default:
1363 1363 (void) printf(gettext("corrupted data"));
1364 1364 break;
1365 1365 }
1366 1366 }
1367 1367 (void) printf("\n");
1368 1368
1369 1369 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1370 1370 &child, &children) != 0)
1371 1371 return;
1372 1372
1373 1373 for (c = 0; c < children; c++) {
1374 1374 uint64_t is_log = B_FALSE;
1375 1375
1376 1376 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1377 1377 &is_log);
1378 1378 if (is_log)
1379 1379 continue;
1380 1380
1381 1381 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1382 1382 print_import_config(vname, child[c], namewidth, depth + 2);
1383 1383 free(vname);
1384 1384 }
1385 1385
1386 1386 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1387 1387 &child, &children) == 0) {
1388 1388 (void) printf(gettext("\tcache\n"));
1389 1389 for (c = 0; c < children; c++) {
1390 1390 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1391 1391 (void) printf("\t %s\n", vname);
1392 1392 free(vname);
1393 1393 }
1394 1394 }
1395 1395
1396 1396 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1397 1397 &child, &children) == 0) {
1398 1398 (void) printf(gettext("\tspares\n"));
1399 1399 for (c = 0; c < children; c++) {
1400 1400 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1401 1401 (void) printf("\t %s\n", vname);
1402 1402 free(vname);
1403 1403 }
1404 1404 }
1405 1405 }
1406 1406
1407 1407 /*
1408 1408 * Print log vdevs.
1409 1409 * Logs are recorded as top level vdevs in the main pool child array
1410 1410 * but with "is_log" set to 1. We use either print_status_config() or
1411 1411 * print_import_config() to print the top level logs then any log
1412 1412 * children (eg mirrored slogs) are printed recursively - which
1413 1413 * works because only the top level vdev is marked "is_log"
1414 1414 */
1415 1415 static void
1416 1416 print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose)
1417 1417 {
1418 1418 uint_t c, children;
1419 1419 nvlist_t **child;
1420 1420
1421 1421 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1422 1422 &children) != 0)
1423 1423 return;
1424 1424
1425 1425 (void) printf(gettext("\tlogs\n"));
1426 1426
1427 1427 for (c = 0; c < children; c++) {
1428 1428 uint64_t is_log = B_FALSE;
1429 1429 char *name;
1430 1430
1431 1431 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1432 1432 &is_log);
1433 1433 if (!is_log)
1434 1434 continue;
1435 1435 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1436 1436 if (verbose)
1437 1437 print_status_config(zhp, name, child[c], namewidth,
1438 1438 2, B_FALSE);
1439 1439 else
1440 1440 print_import_config(name, child[c], namewidth, 2);
1441 1441 free(name);
1442 1442 }
1443 1443 }
1444 1444
1445 1445 /*
1446 1446 * Display the status for the given pool.
1447 1447 */
1448 1448 static void
1449 1449 show_import(nvlist_t *config)
1450 1450 {
1451 1451 uint64_t pool_state;
1452 1452 vdev_stat_t *vs;
1453 1453 char *name;
1454 1454 uint64_t guid;
1455 1455 char *msgid;
1456 1456 nvlist_t *nvroot;
1457 1457 int reason;
1458 1458 const char *health;
1459 1459 uint_t vsc;
1460 1460 int namewidth;
1461 1461 char *comment;
1462 1462
1463 1463 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1464 1464 &name) == 0);
1465 1465 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1466 1466 &guid) == 0);
1467 1467 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1468 1468 &pool_state) == 0);
1469 1469 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1470 1470 &nvroot) == 0);
1471 1471
1472 1472 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
1473 1473 (uint64_t **)&vs, &vsc) == 0);
1474 1474 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1475 1475
1476 1476 reason = zpool_import_status(config, &msgid);
1477 1477
1478 1478 (void) printf(gettext(" pool: %s\n"), name);
1479 1479 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
1480 1480 (void) printf(gettext(" state: %s"), health);
1481 1481 if (pool_state == POOL_STATE_DESTROYED)
1482 1482 (void) printf(gettext(" (DESTROYED)"));
1483 1483 (void) printf("\n");
1484 1484
1485 1485 switch (reason) {
1486 1486 case ZPOOL_STATUS_MISSING_DEV_R:
1487 1487 case ZPOOL_STATUS_MISSING_DEV_NR:
1488 1488 case ZPOOL_STATUS_BAD_GUID_SUM:
1489 1489 (void) printf(gettext(" status: One or more devices are "
1490 1490 "missing from the system.\n"));
1491 1491 break;
1492 1492
1493 1493 case ZPOOL_STATUS_CORRUPT_LABEL_R:
1494 1494 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1495 1495 (void) printf(gettext(" status: One or more devices contains "
1496 1496 "corrupted data.\n"));
1497 1497 break;
1498 1498
1499 1499 case ZPOOL_STATUS_CORRUPT_DATA:
1500 1500 (void) printf(
1501 1501 gettext(" status: The pool data is corrupted.\n"));
1502 1502 break;
1503 1503
1504 1504 case ZPOOL_STATUS_OFFLINE_DEV:
1505 1505 (void) printf(gettext(" status: One or more devices "
1506 1506 "are offlined.\n"));
1507 1507 break;
1508 1508
1509 1509 case ZPOOL_STATUS_CORRUPT_POOL:
1510 1510 (void) printf(gettext(" status: The pool metadata is "
1511 1511 "corrupted.\n"));
1512 1512 break;
1513 1513
1514 1514 case ZPOOL_STATUS_VERSION_OLDER:
1515 1515 (void) printf(gettext(" status: The pool is formatted using a "
1516 1516 "legacy on-disk version.\n"));
1517 1517 break;
1518 1518
1519 1519 case ZPOOL_STATUS_VERSION_NEWER:
1520 1520 (void) printf(gettext(" status: The pool is formatted using an "
1521 1521 "incompatible version.\n"));
1522 1522 break;
1523 1523
1524 1524 case ZPOOL_STATUS_FEAT_DISABLED:
1525 1525 (void) printf(gettext(" status: Some supported features are "
1526 1526 "not enabled on the pool.\n"));
1527 1527 break;
1528 1528
1529 1529 case ZPOOL_STATUS_UNSUP_FEAT_READ:
1530 1530 (void) printf(gettext("status: The pool uses the following "
1531 1531 "feature(s) not supported on this sytem:\n"));
1532 1532 zpool_print_unsup_feat(config);
1533 1533 break;
1534 1534
1535 1535 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1536 1536 (void) printf(gettext("status: The pool can only be accessed "
1537 1537 "in read-only mode on this system. It\n\tcannot be "
1538 1538 "accessed in read-write mode because it uses the "
1539 1539 "following\n\tfeature(s) not supported on this system:\n"));
1540 1540 zpool_print_unsup_feat(config);
1541 1541 break;
1542 1542
1543 1543 case ZPOOL_STATUS_HOSTID_MISMATCH:
1544 1544 (void) printf(gettext(" status: The pool was last accessed by "
1545 1545 "another system.\n"));
1546 1546 break;
1547 1547
1548 1548 case ZPOOL_STATUS_FAULTED_DEV_R:
1549 1549 case ZPOOL_STATUS_FAULTED_DEV_NR:
1550 1550 (void) printf(gettext(" status: One or more devices are "
1551 1551 "faulted.\n"));
1552 1552 break;
1553 1553
1554 1554 case ZPOOL_STATUS_BAD_LOG:
1555 1555 (void) printf(gettext(" status: An intent log record cannot be "
1556 1556 "read.\n"));
1557 1557 break;
1558 1558
1559 1559 case ZPOOL_STATUS_RESILVERING:
1560 1560 (void) printf(gettext(" status: One or more devices were being "
1561 1561 "resilvered.\n"));
1562 1562 break;
1563 1563
1564 1564 default:
1565 1565 /*
1566 1566 * No other status can be seen when importing pools.
1567 1567 */
1568 1568 assert(reason == ZPOOL_STATUS_OK);
1569 1569 }
1570 1570
1571 1571 /*
1572 1572 * Print out an action according to the overall state of the pool.
1573 1573 */
1574 1574 if (vs->vs_state == VDEV_STATE_HEALTHY) {
1575 1575 if (reason == ZPOOL_STATUS_VERSION_OLDER ||
1576 1576 reason == ZPOOL_STATUS_FEAT_DISABLED) {
1577 1577 (void) printf(gettext(" action: The pool can be "
1578 1578 "imported using its name or numeric identifier, "
1579 1579 "though\n\tsome features will not be available "
1580 1580 "without an explicit 'zpool upgrade'.\n"));
1581 1581 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
1582 1582 (void) printf(gettext(" action: The pool can be "
1583 1583 "imported using its name or numeric "
1584 1584 "identifier and\n\tthe '-f' flag.\n"));
1585 1585 } else {
1586 1586 (void) printf(gettext(" action: The pool can be "
1587 1587 "imported using its name or numeric "
1588 1588 "identifier.\n"));
1589 1589 }
1590 1590 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1591 1591 (void) printf(gettext(" action: The pool can be imported "
1592 1592 "despite missing or damaged devices. The\n\tfault "
1593 1593 "tolerance of the pool may be compromised if imported.\n"));
1594 1594 } else {
1595 1595 switch (reason) {
1596 1596 case ZPOOL_STATUS_VERSION_NEWER:
1597 1597 (void) printf(gettext(" action: The pool cannot be "
1598 1598 "imported. Access the pool on a system running "
1599 1599 "newer\n\tsoftware, or recreate the pool from "
1600 1600 "backup.\n"));
1601 1601 break;
1602 1602 case ZPOOL_STATUS_UNSUP_FEAT_READ:
1603 1603 (void) printf(gettext("action: The pool cannot be "
1604 1604 "imported. Access the pool on a system that "
1605 1605 "supports\n\tthe required feature(s), or recreate "
1606 1606 "the pool from backup.\n"));
1607 1607 break;
1608 1608 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1609 1609 (void) printf(gettext("action: The pool cannot be "
1610 1610 "imported in read-write mode. Import the pool "
1611 1611 "with\n"
1612 1612 "\t\"-o readonly=on\", access the pool on a system "
1613 1613 "that supports the\n\trequired feature(s), or "
1614 1614 "recreate the pool from backup.\n"));
1615 1615 break;
1616 1616 case ZPOOL_STATUS_MISSING_DEV_R:
1617 1617 case ZPOOL_STATUS_MISSING_DEV_NR:
1618 1618 case ZPOOL_STATUS_BAD_GUID_SUM:
1619 1619 (void) printf(gettext(" action: The pool cannot be "
1620 1620 "imported. Attach the missing\n\tdevices and try "
1621 1621 "again.\n"));
1622 1622 break;
1623 1623 default:
1624 1624 (void) printf(gettext(" action: The pool cannot be "
1625 1625 "imported due to damaged devices or data.\n"));
1626 1626 }
1627 1627 }
1628 1628
1629 1629 /* Print the comment attached to the pool. */
1630 1630 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
1631 1631 (void) printf(gettext("comment: %s\n"), comment);
1632 1632
1633 1633 /*
1634 1634 * If the state is "closed" or "can't open", and the aux state
1635 1635 * is "corrupt data":
1636 1636 */
1637 1637 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1638 1638 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1639 1639 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1640 1640 if (pool_state == POOL_STATE_DESTROYED)
1641 1641 (void) printf(gettext("\tThe pool was destroyed, "
1642 1642 "but can be imported using the '-Df' flags.\n"));
1643 1643 else if (pool_state != POOL_STATE_EXPORTED)
1644 1644 (void) printf(gettext("\tThe pool may be active on "
1645 1645 "another system, but can be imported using\n\t"
1646 1646 "the '-f' flag.\n"));
1647 1647 }
1648 1648
1649 1649 if (msgid != NULL)
1650 1650 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
1651 1651 msgid);
1652 1652
1653 1653 (void) printf(gettext(" config:\n\n"));
1654 1654
1655 1655 namewidth = max_width(NULL, nvroot, 0, 0);
1656 1656 if (namewidth < 10)
1657 1657 namewidth = 10;
1658 1658
1659 1659 print_import_config(name, nvroot, namewidth, 0);
1660 1660 if (num_logs(nvroot) > 0)
1661 1661 print_logs(NULL, nvroot, namewidth, B_FALSE);
1662 1662
1663 1663 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1664 1664 (void) printf(gettext("\n\tAdditional devices are known to "
1665 1665 "be part of this pool, though their\n\texact "
1666 1666 "configuration cannot be determined.\n"));
1667 1667 }
1668 1668 }
1669 1669
1670 1670 /*
1671 1671 * Perform the import for the given configuration. This passes the heavy
1672 1672 * lifting off to zpool_import_props(), and then mounts the datasets contained
1673 1673 * within the pool.
1674 1674 */
1675 1675 static int
1676 1676 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1677 1677 nvlist_t *props, int flags)
1678 1678 {
1679 1679 zpool_handle_t *zhp;
1680 1680 char *name;
1681 1681 uint64_t state;
1682 1682 uint64_t version;
1683 1683
1684 1684 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1685 1685 &name) == 0);
1686 1686
1687 1687 verify(nvlist_lookup_uint64(config,
1688 1688 ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1689 1689 verify(nvlist_lookup_uint64(config,
1690 1690 ZPOOL_CONFIG_VERSION, &version) == 0);
1691 1691 if (!SPA_VERSION_IS_SUPPORTED(version)) {
1692 1692 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1693 1693 "is formatted using an unsupported ZFS version\n"), name);
1694 1694 return (1);
1695 1695 } else if (state != POOL_STATE_EXPORTED &&
1696 1696 !(flags & ZFS_IMPORT_ANY_HOST)) {
1697 1697 uint64_t hostid;
1698 1698
1699 1699 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
1700 1700 &hostid) == 0) {
1701 1701 if ((unsigned long)hostid != gethostid()) {
1702 1702 char *hostname;
1703 1703 uint64_t timestamp;
1704 1704 time_t t;
1705 1705
1706 1706 verify(nvlist_lookup_string(config,
1707 1707 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
1708 1708 verify(nvlist_lookup_uint64(config,
1709 1709 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0);
1710 1710 t = timestamp;
1711 1711 (void) fprintf(stderr, gettext("cannot import "
1712 1712 "'%s': pool may be in use from other "
1713 1713 "system, it was last accessed by %s "
1714 1714 "(hostid: 0x%lx) on %s"), name, hostname,
1715 1715 (unsigned long)hostid,
1716 1716 asctime(localtime(&t)));
1717 1717 (void) fprintf(stderr, gettext("use '-f' to "
1718 1718 "import anyway\n"));
1719 1719 return (1);
1720 1720 }
1721 1721 } else {
1722 1722 (void) fprintf(stderr, gettext("cannot import '%s': "
1723 1723 "pool may be in use from other system\n"), name);
1724 1724 (void) fprintf(stderr, gettext("use '-f' to import "
1725 1725 "anyway\n"));
1726 1726 return (1);
1727 1727 }
1728 1728 }
1729 1729
1730 1730 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
1731 1731 return (1);
1732 1732
1733 1733 if (newname != NULL)
1734 1734 name = (char *)newname;
1735 1735
1736 1736 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
1737 1737 return (1);
1738 1738
1739 1739 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
1740 1740 !(flags & ZFS_IMPORT_ONLY) &&
1741 1741 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
1742 1742 zpool_close(zhp);
1743 1743 return (1);
1744 1744 }
1745 1745
1746 1746 zpool_close(zhp);
1747 1747 return (0);
1748 1748 }
1749 1749
1750 1750 /*
1751 1751 * zpool import [-d dir] [-D]
1752 1752 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1753 1753 * [-d dir | -c cachefile] [-f] -a
1754 1754 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1755 1755 * [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
1756 1756 *
1757 1757 * -c Read pool information from a cachefile instead of searching
1758 1758 * devices.
1759 1759 *
1760 1760 * -d Scan in a specific directory, other than /dev/dsk. More than
1761 1761 * one directory can be specified using multiple '-d' options.
1762 1762 *
1763 1763 * -D Scan for previously destroyed pools or import all or only
1764 1764 * specified destroyed pools.
1765 1765 *
1766 1766 * -R Temporarily import the pool, with all mountpoints relative to
1767 1767 * the given root. The pool will remain exported when the machine
1768 1768 * is rebooted.
1769 1769 *
1770 1770 * -V Import even in the presence of faulted vdevs. This is an
1771 1771 * intentionally undocumented option for testing purposes, and
1772 1772 * treats the pool configuration as complete, leaving any bad
1773 1773 * vdevs in the FAULTED state. In other words, it does verbatim
1774 1774 * import.
1775 1775 *
1776 1776 * -f Force import, even if it appears that the pool is active.
1777 1777 *
1778 1778 * -F Attempt rewind if necessary.
1779 1779 *
1780 1780 * -n See if rewind would work, but don't actually rewind.
1781 1781 *
1782 1782 * -N Import the pool but don't mount datasets.
1783 1783 *
1784 1784 * -T Specify a starting txg to use for import. This option is
1785 1785 * intentionally undocumented option for testing purposes.
1786 1786 *
1787 1787 * -a Import all pools found.
1788 1788 *
1789 1789 * -o Set property=value and/or temporary mount options (without '=').
1790 1790 *
1791 1791 * The import command scans for pools to import, and import pools based on pool
1792 1792 * name and GUID. The pool can also be renamed as part of the import process.
1793 1793 */
1794 1794 int
1795 1795 zpool_do_import(int argc, char **argv)
1796 1796 {
1797 1797 char **searchdirs = NULL;
1798 1798 int nsearch = 0;
1799 1799 int c;
1800 1800 int err = 0;
1801 1801 nvlist_t *pools = NULL;
1802 1802 boolean_t do_all = B_FALSE;
1803 1803 boolean_t do_destroyed = B_FALSE;
1804 1804 char *mntopts = NULL;
1805 1805 nvpair_t *elem;
1806 1806 nvlist_t *config;
1807 1807 uint64_t searchguid = 0;
1808 1808 char *searchname = NULL;
1809 1809 char *propval;
1810 1810 nvlist_t *found_config;
1811 1811 nvlist_t *policy = NULL;
1812 1812 nvlist_t *props = NULL;
1813 1813 boolean_t first;
1814 1814 int flags = ZFS_IMPORT_NORMAL;
1815 1815 uint32_t rewind_policy = ZPOOL_NO_REWIND;
1816 1816 boolean_t dryrun = B_FALSE;
1817 1817 boolean_t do_rewind = B_FALSE;
1818 1818 boolean_t xtreme_rewind = B_FALSE;
1819 1819 uint64_t pool_state, txg = -1ULL;
1820 1820 char *cachefile = NULL;
1821 1821 importargs_t idata = { 0 };
1822 1822 char *endptr;
1823 1823
1824 1824 /* check options */
1825 1825 while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:rR:T:VX")) != -1) {
1826 1826 switch (c) {
1827 1827 case 'a':
1828 1828 do_all = B_TRUE;
1829 1829 break;
1830 1830 case 'c':
1831 1831 cachefile = optarg;
1832 1832 break;
1833 1833 case 'd':
1834 1834 if (searchdirs == NULL) {
1835 1835 searchdirs = safe_malloc(sizeof (char *));
1836 1836 } else {
1837 1837 char **tmp = safe_malloc((nsearch + 1) *
1838 1838 sizeof (char *));
1839 1839 bcopy(searchdirs, tmp, nsearch *
1840 1840 sizeof (char *));
1841 1841 free(searchdirs);
1842 1842 searchdirs = tmp;
1843 1843 }
1844 1844 searchdirs[nsearch++] = optarg;
1845 1845 break;
1846 1846 case 'D':
1847 1847 do_destroyed = B_TRUE;
1848 1848 break;
1849 1849 case 'f':
1850 1850 flags |= ZFS_IMPORT_ANY_HOST;
1851 1851 break;
1852 1852 case 'F':
1853 1853 do_rewind = B_TRUE;
1854 1854 break;
1855 1855 case 'm':
1856 1856 flags |= ZFS_IMPORT_MISSING_LOG;
1857 1857 break;
1858 1858 case 'n':
1859 1859 dryrun = B_TRUE;
1860 1860 break;
1861 1861 case 'N':
1862 1862 flags |= ZFS_IMPORT_ONLY;
1863 1863 break;
1864 1864 case 'o':
1865 1865 if ((propval = strchr(optarg, '=')) != NULL) {
1866 1866 *propval = '\0';
1867 1867 propval++;
1868 1868 if (add_prop_list(optarg, propval,
1869 1869 &props, B_TRUE))
1870 1870 goto error;
1871 1871 } else {
1872 1872 mntopts = optarg;
1873 1873 }
1874 1874 break;
1875 1875 case 'R':
1876 1876 if (add_prop_list(zpool_prop_to_name(
1877 1877 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
1878 1878 goto error;
1879 1879 if (nvlist_lookup_string(props,
1880 1880 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
1881 1881 &propval) == 0)
1882 1882 break;
1883 1883 if (add_prop_list(zpool_prop_to_name(
1884 1884 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1885 1885 goto error;
1886 1886 break;
1887 1887 case 'T':
1888 1888 errno = 0;
1889 1889 txg = strtoull(optarg, &endptr, 10);
1890 1890 if (errno != 0 || *endptr != '\0') {
1891 1891 (void) fprintf(stderr,
1892 1892 gettext("invalid txg value\n"));
1893 1893 usage(B_FALSE);
1894 1894 }
1895 1895 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
1896 1896 break;
1897 1897 case 'V':
1898 1898 flags |= ZFS_IMPORT_VERBATIM;
1899 1899 break;
1900 1900 case 'X':
1901 1901 xtreme_rewind = B_TRUE;
1902 1902 break;
1903 1903 case ':':
1904 1904 (void) fprintf(stderr, gettext("missing argument for "
1905 1905 "'%c' option\n"), optopt);
1906 1906 usage(B_FALSE);
1907 1907 break;
1908 1908 case '?':
1909 1909 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1910 1910 optopt);
1911 1911 usage(B_FALSE);
1912 1912 }
1913 1913 }
1914 1914
1915 1915 argc -= optind;
1916 1916 argv += optind;
1917 1917
1918 1918 if (cachefile && nsearch != 0) {
1919 1919 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
1920 1920 usage(B_FALSE);
1921 1921 }
1922 1922
1923 1923 if ((dryrun || xtreme_rewind) && !do_rewind) {
1924 1924 (void) fprintf(stderr,
1925 1925 gettext("-n or -X only meaningful with -F\n"));
1926 1926 usage(B_FALSE);
1927 1927 }
1928 1928 if (dryrun)
1929 1929 rewind_policy = ZPOOL_TRY_REWIND;
1930 1930 else if (do_rewind)
1931 1931 rewind_policy = ZPOOL_DO_REWIND;
1932 1932 if (xtreme_rewind)
1933 1933 rewind_policy |= ZPOOL_EXTREME_REWIND;
1934 1934
1935 1935 /* In the future, we can capture further policy and include it here */
1936 1936 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
1937 1937 nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 ||
1938 1938 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
1939 1939 goto error;
1940 1940
1941 1941 if (searchdirs == NULL) {
1942 1942 searchdirs = safe_malloc(sizeof (char *));
1943 1943 searchdirs[0] = "/dev/dsk";
1944 1944 nsearch = 1;
1945 1945 }
1946 1946
1947 1947 /* check argument count */
1948 1948 if (do_all) {
1949 1949 if (argc != 0) {
1950 1950 (void) fprintf(stderr, gettext("too many arguments\n"));
1951 1951 usage(B_FALSE);
1952 1952 }
1953 1953 } else {
1954 1954 if (argc > 2) {
1955 1955 (void) fprintf(stderr, gettext("too many arguments\n"));
1956 1956 usage(B_FALSE);
1957 1957 }
1958 1958
1959 1959 /*
1960 1960 * Check for the SYS_CONFIG privilege. We do this explicitly
1961 1961 * here because otherwise any attempt to discover pools will
1962 1962 * silently fail.
1963 1963 */
1964 1964 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
1965 1965 (void) fprintf(stderr, gettext("cannot "
1966 1966 "discover pools: permission denied\n"));
1967 1967 free(searchdirs);
1968 1968 nvlist_free(policy);
1969 1969 return (1);
1970 1970 }
1971 1971 }
1972 1972
1973 1973 /*
1974 1974 * Depending on the arguments given, we do one of the following:
1975 1975 *
1976 1976 * <none> Iterate through all pools and display information about
1977 1977 * each one.
1978 1978 *
1979 1979 * -a Iterate through all pools and try to import each one.
1980 1980 *
↓ open down ↓ |
1980 lines elided |
↑ open up ↑ |
1981 1981 * <id> Find the pool that corresponds to the given GUID/pool
1982 1982 * name and import that one.
1983 1983 *
1984 1984 * -D Above options applies only to destroyed pools.
1985 1985 */
1986 1986 if (argc != 0) {
1987 1987 char *endptr;
1988 1988
1989 1989 errno = 0;
1990 1990 searchguid = strtoull(argv[0], &endptr, 10);
1991 - if (errno != 0 || *endptr != '\0')
1991 + if (errno != 0 || *endptr != '\0') {
1992 1992 searchname = argv[0];
1993 + searchguid = 0;
1994 + }
1993 1995 found_config = NULL;
1994 1996
1995 1997 /*
1996 1998 * User specified a name or guid. Ensure it's unique.
1997 1999 */
1998 2000 idata.unique = B_TRUE;
1999 2001 }
2000 2002
2001 2003
2002 2004 idata.path = searchdirs;
2003 2005 idata.paths = nsearch;
2004 2006 idata.poolname = searchname;
2005 2007 idata.guid = searchguid;
2006 2008 idata.cachefile = cachefile;
2007 2009
2008 2010 pools = zpool_search_import(g_zfs, &idata);
2009 2011
2010 2012 if (pools != NULL && idata.exists &&
2011 2013 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2012 2014 (void) fprintf(stderr, gettext("cannot import '%s': "
2013 2015 "a pool with that name already exists\n"),
2014 2016 argv[0]);
2015 2017 (void) fprintf(stderr, gettext("use the form '%s "
2016 2018 "<pool | id> <newpool>' to give it a new name\n"),
2017 2019 "zpool import");
2018 2020 err = 1;
2019 2021 } else if (pools == NULL && idata.exists) {
2020 2022 (void) fprintf(stderr, gettext("cannot import '%s': "
2021 2023 "a pool with that name is already created/imported,\n"),
2022 2024 argv[0]);
2023 2025 (void) fprintf(stderr, gettext("and no additional pools "
2024 2026 "with that name were found\n"));
2025 2027 err = 1;
2026 2028 } else if (pools == NULL) {
2027 2029 if (argc != 0) {
2028 2030 (void) fprintf(stderr, gettext("cannot import '%s': "
2029 2031 "no such pool available\n"), argv[0]);
2030 2032 }
2031 2033 err = 1;
2032 2034 }
2033 2035
2034 2036 if (err == 1) {
2035 2037 free(searchdirs);
2036 2038 nvlist_free(policy);
2037 2039 return (1);
2038 2040 }
2039 2041
2040 2042 /*
2041 2043 * At this point we have a list of import candidate configs. Even if
2042 2044 * we were searching by pool name or guid, we still need to
2043 2045 * post-process the list to deal with pool state and possible
2044 2046 * duplicate names.
2045 2047 */
2046 2048 err = 0;
2047 2049 elem = NULL;
2048 2050 first = B_TRUE;
2049 2051 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2050 2052
2051 2053 verify(nvpair_value_nvlist(elem, &config) == 0);
2052 2054
2053 2055 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2054 2056 &pool_state) == 0);
2055 2057 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2056 2058 continue;
2057 2059 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2058 2060 continue;
2059 2061
2060 2062 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
2061 2063 policy) == 0);
2062 2064
2063 2065 if (argc == 0) {
2064 2066 if (first)
2065 2067 first = B_FALSE;
2066 2068 else if (!do_all)
2067 2069 (void) printf("\n");
2068 2070
2069 2071 if (do_all) {
2070 2072 err |= do_import(config, NULL, mntopts,
2071 2073 props, flags);
2072 2074 } else {
2073 2075 show_import(config);
2074 2076 }
2075 2077 } else if (searchname != NULL) {
2076 2078 char *name;
2077 2079
2078 2080 /*
2079 2081 * We are searching for a pool based on name.
2080 2082 */
2081 2083 verify(nvlist_lookup_string(config,
2082 2084 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2083 2085
2084 2086 if (strcmp(name, searchname) == 0) {
2085 2087 if (found_config != NULL) {
2086 2088 (void) fprintf(stderr, gettext(
2087 2089 "cannot import '%s': more than "
2088 2090 "one matching pool\n"), searchname);
2089 2091 (void) fprintf(stderr, gettext(
2090 2092 "import by numeric ID instead\n"));
2091 2093 err = B_TRUE;
2092 2094 }
2093 2095 found_config = config;
2094 2096 }
2095 2097 } else {
2096 2098 uint64_t guid;
2097 2099
2098 2100 /*
2099 2101 * Search for a pool by guid.
2100 2102 */
2101 2103 verify(nvlist_lookup_uint64(config,
2102 2104 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2103 2105
2104 2106 if (guid == searchguid)
2105 2107 found_config = config;
2106 2108 }
2107 2109 }
2108 2110
2109 2111 /*
2110 2112 * If we were searching for a specific pool, verify that we found a
2111 2113 * pool, and then do the import.
2112 2114 */
2113 2115 if (argc != 0 && err == 0) {
2114 2116 if (found_config == NULL) {
2115 2117 (void) fprintf(stderr, gettext("cannot import '%s': "
2116 2118 "no such pool available\n"), argv[0]);
2117 2119 err = B_TRUE;
2118 2120 } else {
2119 2121 err |= do_import(found_config, argc == 1 ? NULL :
2120 2122 argv[1], mntopts, props, flags);
2121 2123 }
2122 2124 }
2123 2125
2124 2126 /*
2125 2127 * If we were just looking for pools, report an error if none were
2126 2128 * found.
2127 2129 */
2128 2130 if (argc == 0 && first)
2129 2131 (void) fprintf(stderr,
2130 2132 gettext("no pools available to import\n"));
2131 2133
2132 2134 error:
2133 2135 nvlist_free(props);
2134 2136 nvlist_free(pools);
2135 2137 nvlist_free(policy);
2136 2138 free(searchdirs);
2137 2139
2138 2140 return (err ? 1 : 0);
2139 2141 }
2140 2142
2141 2143 typedef struct iostat_cbdata {
2142 2144 boolean_t cb_verbose;
2143 2145 int cb_namewidth;
2144 2146 int cb_iteration;
2145 2147 zpool_list_t *cb_list;
2146 2148 } iostat_cbdata_t;
2147 2149
2148 2150 static void
2149 2151 print_iostat_separator(iostat_cbdata_t *cb)
2150 2152 {
2151 2153 int i = 0;
2152 2154
2153 2155 for (i = 0; i < cb->cb_namewidth; i++)
2154 2156 (void) printf("-");
2155 2157 (void) printf(" ----- ----- ----- ----- ----- -----\n");
2156 2158 }
2157 2159
2158 2160 static void
2159 2161 print_iostat_header(iostat_cbdata_t *cb)
2160 2162 {
2161 2163 (void) printf("%*s capacity operations bandwidth\n",
2162 2164 cb->cb_namewidth, "");
2163 2165 (void) printf("%-*s alloc free read write read write\n",
2164 2166 cb->cb_namewidth, "pool");
2165 2167 print_iostat_separator(cb);
2166 2168 }
2167 2169
2168 2170 /*
2169 2171 * Display a single statistic.
2170 2172 */
2171 2173 static void
2172 2174 print_one_stat(uint64_t value)
2173 2175 {
2174 2176 char buf[64];
2175 2177
2176 2178 zfs_nicenum(value, buf, sizeof (buf));
2177 2179 (void) printf(" %5s", buf);
2178 2180 }
2179 2181
2180 2182 /*
2181 2183 * Print out all the statistics for the given vdev. This can either be the
2182 2184 * toplevel configuration, or called recursively. If 'name' is NULL, then this
2183 2185 * is a verbose output, and we don't want to display the toplevel pool stats.
2184 2186 */
2185 2187 void
2186 2188 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2187 2189 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2188 2190 {
2189 2191 nvlist_t **oldchild, **newchild;
2190 2192 uint_t c, children;
2191 2193 vdev_stat_t *oldvs, *newvs;
2192 2194 vdev_stat_t zerovs = { 0 };
2193 2195 uint64_t tdelta;
2194 2196 double scale;
2195 2197 char *vname;
2196 2198
2197 2199 if (oldnv != NULL) {
2198 2200 verify(nvlist_lookup_uint64_array(oldnv,
2199 2201 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2200 2202 } else {
2201 2203 oldvs = &zerovs;
2202 2204 }
2203 2205
2204 2206 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2205 2207 (uint64_t **)&newvs, &c) == 0);
2206 2208
2207 2209 if (strlen(name) + depth > cb->cb_namewidth)
2208 2210 (void) printf("%*s%s", depth, "", name);
2209 2211 else
2210 2212 (void) printf("%*s%s%*s", depth, "", name,
2211 2213 (int)(cb->cb_namewidth - strlen(name) - depth), "");
2212 2214
2213 2215 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2214 2216
2215 2217 if (tdelta == 0)
2216 2218 scale = 1.0;
2217 2219 else
2218 2220 scale = (double)NANOSEC / tdelta;
2219 2221
2220 2222 /* only toplevel vdevs have capacity stats */
2221 2223 if (newvs->vs_space == 0) {
2222 2224 (void) printf(" - -");
2223 2225 } else {
2224 2226 print_one_stat(newvs->vs_alloc);
2225 2227 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2226 2228 }
2227 2229
2228 2230 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2229 2231 oldvs->vs_ops[ZIO_TYPE_READ])));
2230 2232
2231 2233 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2232 2234 oldvs->vs_ops[ZIO_TYPE_WRITE])));
2233 2235
2234 2236 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2235 2237 oldvs->vs_bytes[ZIO_TYPE_READ])));
2236 2238
2237 2239 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2238 2240 oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2239 2241
2240 2242 (void) printf("\n");
2241 2243
2242 2244 if (!cb->cb_verbose)
2243 2245 return;
2244 2246
2245 2247 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2246 2248 &newchild, &children) != 0)
2247 2249 return;
2248 2250
2249 2251 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2250 2252 &oldchild, &c) != 0)
2251 2253 return;
2252 2254
2253 2255 for (c = 0; c < children; c++) {
2254 2256 uint64_t ishole = B_FALSE, islog = B_FALSE;
2255 2257
2256 2258 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2257 2259 &ishole);
2258 2260
2259 2261 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2260 2262 &islog);
2261 2263
2262 2264 if (ishole || islog)
2263 2265 continue;
2264 2266
2265 2267 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2266 2268 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2267 2269 newchild[c], cb, depth + 2);
2268 2270 free(vname);
2269 2271 }
2270 2272
2271 2273 /*
2272 2274 * Log device section
2273 2275 */
2274 2276
2275 2277 if (num_logs(newnv) > 0) {
2276 2278 (void) printf("%-*s - - - - - "
2277 2279 "-\n", cb->cb_namewidth, "logs");
2278 2280
2279 2281 for (c = 0; c < children; c++) {
2280 2282 uint64_t islog = B_FALSE;
2281 2283 (void) nvlist_lookup_uint64(newchild[c],
2282 2284 ZPOOL_CONFIG_IS_LOG, &islog);
2283 2285
2284 2286 if (islog) {
2285 2287 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2286 2288 B_FALSE);
2287 2289 print_vdev_stats(zhp, vname, oldnv ?
2288 2290 oldchild[c] : NULL, newchild[c],
2289 2291 cb, depth + 2);
2290 2292 free(vname);
2291 2293 }
2292 2294 }
2293 2295
2294 2296 }
2295 2297
2296 2298 /*
2297 2299 * Include level 2 ARC devices in iostat output
2298 2300 */
2299 2301 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2300 2302 &newchild, &children) != 0)
2301 2303 return;
2302 2304
2303 2305 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2304 2306 &oldchild, &c) != 0)
2305 2307 return;
2306 2308
2307 2309 if (children > 0) {
2308 2310 (void) printf("%-*s - - - - - "
2309 2311 "-\n", cb->cb_namewidth, "cache");
2310 2312 for (c = 0; c < children; c++) {
2311 2313 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2312 2314 B_FALSE);
2313 2315 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2314 2316 newchild[c], cb, depth + 2);
2315 2317 free(vname);
2316 2318 }
2317 2319 }
2318 2320 }
2319 2321
2320 2322 static int
2321 2323 refresh_iostat(zpool_handle_t *zhp, void *data)
2322 2324 {
2323 2325 iostat_cbdata_t *cb = data;
2324 2326 boolean_t missing;
2325 2327
2326 2328 /*
2327 2329 * If the pool has disappeared, remove it from the list and continue.
2328 2330 */
2329 2331 if (zpool_refresh_stats(zhp, &missing) != 0)
2330 2332 return (-1);
2331 2333
2332 2334 if (missing)
2333 2335 pool_list_remove(cb->cb_list, zhp);
2334 2336
2335 2337 return (0);
2336 2338 }
2337 2339
2338 2340 /*
2339 2341 * Callback to print out the iostats for the given pool.
2340 2342 */
2341 2343 int
2342 2344 print_iostat(zpool_handle_t *zhp, void *data)
2343 2345 {
2344 2346 iostat_cbdata_t *cb = data;
2345 2347 nvlist_t *oldconfig, *newconfig;
2346 2348 nvlist_t *oldnvroot, *newnvroot;
2347 2349
2348 2350 newconfig = zpool_get_config(zhp, &oldconfig);
2349 2351
2350 2352 if (cb->cb_iteration == 1)
2351 2353 oldconfig = NULL;
2352 2354
2353 2355 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
2354 2356 &newnvroot) == 0);
2355 2357
2356 2358 if (oldconfig == NULL)
2357 2359 oldnvroot = NULL;
2358 2360 else
2359 2361 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
2360 2362 &oldnvroot) == 0);
2361 2363
2362 2364 /*
2363 2365 * Print out the statistics for the pool.
2364 2366 */
2365 2367 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
2366 2368
2367 2369 if (cb->cb_verbose)
2368 2370 print_iostat_separator(cb);
2369 2371
2370 2372 return (0);
2371 2373 }
2372 2374
2373 2375 int
2374 2376 get_namewidth(zpool_handle_t *zhp, void *data)
2375 2377 {
2376 2378 iostat_cbdata_t *cb = data;
2377 2379 nvlist_t *config, *nvroot;
2378 2380
2379 2381 if ((config = zpool_get_config(zhp, NULL)) != NULL) {
2380 2382 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2381 2383 &nvroot) == 0);
2382 2384 if (!cb->cb_verbose)
2383 2385 cb->cb_namewidth = strlen(zpool_get_name(zhp));
2384 2386 else
2385 2387 cb->cb_namewidth = max_width(zhp, nvroot, 0,
2386 2388 cb->cb_namewidth);
2387 2389 }
2388 2390
2389 2391 /*
2390 2392 * The width must fall into the range [10,38]. The upper limit is the
2391 2393 * maximum we can have and still fit in 80 columns.
2392 2394 */
2393 2395 if (cb->cb_namewidth < 10)
2394 2396 cb->cb_namewidth = 10;
2395 2397 if (cb->cb_namewidth > 38)
2396 2398 cb->cb_namewidth = 38;
2397 2399
2398 2400 return (0);
2399 2401 }
2400 2402
2401 2403 /*
2402 2404 * Parse the input string, get the 'interval' and 'count' value if there is one.
2403 2405 */
2404 2406 static void
2405 2407 get_interval_count(int *argcp, char **argv, unsigned long *iv,
2406 2408 unsigned long *cnt)
2407 2409 {
2408 2410 unsigned long interval = 0, count = 0;
2409 2411 int argc = *argcp, errno;
2410 2412
2411 2413 /*
2412 2414 * Determine if the last argument is an integer or a pool name
2413 2415 */
2414 2416 if (argc > 0 && isdigit(argv[argc - 1][0])) {
2415 2417 char *end;
2416 2418
2417 2419 errno = 0;
2418 2420 interval = strtoul(argv[argc - 1], &end, 10);
2419 2421
2420 2422 if (*end == '\0' && errno == 0) {
2421 2423 if (interval == 0) {
2422 2424 (void) fprintf(stderr, gettext("interval "
2423 2425 "cannot be zero\n"));
2424 2426 usage(B_FALSE);
2425 2427 }
2426 2428 /*
2427 2429 * Ignore the last parameter
2428 2430 */
2429 2431 argc--;
2430 2432 } else {
2431 2433 /*
2432 2434 * If this is not a valid number, just plow on. The
2433 2435 * user will get a more informative error message later
2434 2436 * on.
2435 2437 */
2436 2438 interval = 0;
2437 2439 }
2438 2440 }
2439 2441
2440 2442 /*
2441 2443 * If the last argument is also an integer, then we have both a count
2442 2444 * and an interval.
2443 2445 */
2444 2446 if (argc > 0 && isdigit(argv[argc - 1][0])) {
2445 2447 char *end;
2446 2448
2447 2449 errno = 0;
2448 2450 count = interval;
2449 2451 interval = strtoul(argv[argc - 1], &end, 10);
2450 2452
2451 2453 if (*end == '\0' && errno == 0) {
2452 2454 if (interval == 0) {
2453 2455 (void) fprintf(stderr, gettext("interval "
2454 2456 "cannot be zero\n"));
2455 2457 usage(B_FALSE);
2456 2458 }
2457 2459
2458 2460 /*
2459 2461 * Ignore the last parameter
2460 2462 */
2461 2463 argc--;
2462 2464 } else {
2463 2465 interval = 0;
2464 2466 }
2465 2467 }
2466 2468
2467 2469 *iv = interval;
2468 2470 *cnt = count;
2469 2471 *argcp = argc;
2470 2472 }
2471 2473
2472 2474 static void
2473 2475 get_timestamp_arg(char c)
2474 2476 {
2475 2477 if (c == 'u')
2476 2478 timestamp_fmt = UDATE;
2477 2479 else if (c == 'd')
2478 2480 timestamp_fmt = DDATE;
2479 2481 else
2480 2482 usage(B_FALSE);
2481 2483 }
2482 2484
2483 2485 /*
2484 2486 * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
2485 2487 *
2486 2488 * -v Display statistics for individual vdevs
2487 2489 * -T Display a timestamp in date(1) or Unix format
2488 2490 *
2489 2491 * This command can be tricky because we want to be able to deal with pool
2490 2492 * creation/destruction as well as vdev configuration changes. The bulk of this
2491 2493 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
2492 2494 * on pool_list_update() to detect the addition of new pools. Configuration
2493 2495 * changes are all handled within libzfs.
2494 2496 */
2495 2497 int
2496 2498 zpool_do_iostat(int argc, char **argv)
2497 2499 {
2498 2500 int c;
2499 2501 int ret;
2500 2502 int npools;
2501 2503 unsigned long interval = 0, count = 0;
2502 2504 zpool_list_t *list;
2503 2505 boolean_t verbose = B_FALSE;
2504 2506 iostat_cbdata_t cb;
2505 2507
2506 2508 /* check options */
2507 2509 while ((c = getopt(argc, argv, "T:v")) != -1) {
2508 2510 switch (c) {
2509 2511 case 'T':
2510 2512 get_timestamp_arg(*optarg);
2511 2513 break;
2512 2514 case 'v':
2513 2515 verbose = B_TRUE;
2514 2516 break;
2515 2517 case '?':
2516 2518 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2517 2519 optopt);
2518 2520 usage(B_FALSE);
2519 2521 }
2520 2522 }
2521 2523
2522 2524 argc -= optind;
2523 2525 argv += optind;
2524 2526
2525 2527 get_interval_count(&argc, argv, &interval, &count);
2526 2528
2527 2529 /*
2528 2530 * Construct the list of all interesting pools.
2529 2531 */
2530 2532 ret = 0;
2531 2533 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
2532 2534 return (1);
2533 2535
2534 2536 if (pool_list_count(list) == 0 && argc != 0) {
2535 2537 pool_list_free(list);
2536 2538 return (1);
2537 2539 }
2538 2540
2539 2541 if (pool_list_count(list) == 0 && interval == 0) {
2540 2542 pool_list_free(list);
2541 2543 (void) fprintf(stderr, gettext("no pools available\n"));
2542 2544 return (1);
2543 2545 }
2544 2546
2545 2547 /*
2546 2548 * Enter the main iostat loop.
2547 2549 */
2548 2550 cb.cb_list = list;
2549 2551 cb.cb_verbose = verbose;
2550 2552 cb.cb_iteration = 0;
2551 2553 cb.cb_namewidth = 0;
2552 2554
2553 2555 for (;;) {
2554 2556 pool_list_update(list);
2555 2557
2556 2558 if ((npools = pool_list_count(list)) == 0)
2557 2559 break;
2558 2560
2559 2561 /*
2560 2562 * Refresh all statistics. This is done as an explicit step
2561 2563 * before calculating the maximum name width, so that any
2562 2564 * configuration changes are properly accounted for.
2563 2565 */
2564 2566 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
2565 2567
2566 2568 /*
2567 2569 * Iterate over all pools to determine the maximum width
2568 2570 * for the pool / device name column across all pools.
2569 2571 */
2570 2572 cb.cb_namewidth = 0;
2571 2573 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2572 2574
2573 2575 if (timestamp_fmt != NODATE)
2574 2576 print_timestamp(timestamp_fmt);
2575 2577
2576 2578 /*
2577 2579 * If it's the first time, or verbose mode, print the header.
2578 2580 */
2579 2581 if (++cb.cb_iteration == 1 || verbose)
2580 2582 print_iostat_header(&cb);
2581 2583
2582 2584 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
2583 2585
2584 2586 /*
2585 2587 * If there's more than one pool, and we're not in verbose mode
2586 2588 * (which prints a separator for us), then print a separator.
2587 2589 */
2588 2590 if (npools > 1 && !verbose)
2589 2591 print_iostat_separator(&cb);
2590 2592
2591 2593 if (verbose)
2592 2594 (void) printf("\n");
2593 2595
2594 2596 /*
2595 2597 * Flush the output so that redirection to a file isn't buffered
2596 2598 * indefinitely.
2597 2599 */
2598 2600 (void) fflush(stdout);
2599 2601
2600 2602 if (interval == 0)
2601 2603 break;
2602 2604
2603 2605 if (count != 0 && --count == 0)
2604 2606 break;
2605 2607
2606 2608 (void) sleep(interval);
2607 2609 }
2608 2610
2609 2611 pool_list_free(list);
2610 2612
2611 2613 return (ret);
2612 2614 }
2613 2615
2614 2616 typedef struct list_cbdata {
2615 2617 boolean_t cb_verbose;
2616 2618 int cb_namewidth;
2617 2619 boolean_t cb_scripted;
2618 2620 zprop_list_t *cb_proplist;
2619 2621 } list_cbdata_t;
2620 2622
2621 2623 /*
2622 2624 * Given a list of columns to display, output appropriate headers for each one.
2623 2625 */
2624 2626 static void
2625 2627 print_header(list_cbdata_t *cb)
2626 2628 {
2627 2629 zprop_list_t *pl = cb->cb_proplist;
2628 2630 char headerbuf[ZPOOL_MAXPROPLEN];
2629 2631 const char *header;
2630 2632 boolean_t first = B_TRUE;
2631 2633 boolean_t right_justify;
2632 2634 size_t width = 0;
2633 2635
2634 2636 for (; pl != NULL; pl = pl->pl_next) {
2635 2637 width = pl->pl_width;
2636 2638 if (first && cb->cb_verbose) {
2637 2639 /*
2638 2640 * Reset the width to accommodate the verbose listing
2639 2641 * of devices.
2640 2642 */
2641 2643 width = cb->cb_namewidth;
2642 2644 }
2643 2645
2644 2646 if (!first)
2645 2647 (void) printf(" ");
2646 2648 else
2647 2649 first = B_FALSE;
2648 2650
2649 2651 right_justify = B_FALSE;
2650 2652 if (pl->pl_prop != ZPROP_INVAL) {
2651 2653 header = zpool_prop_column_name(pl->pl_prop);
2652 2654 right_justify = zpool_prop_align_right(pl->pl_prop);
2653 2655 } else {
2654 2656 int i;
2655 2657
2656 2658 for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
2657 2659 headerbuf[i] = toupper(pl->pl_user_prop[i]);
2658 2660 headerbuf[i] = '\0';
2659 2661 header = headerbuf;
2660 2662 }
2661 2663
2662 2664 if (pl->pl_next == NULL && !right_justify)
2663 2665 (void) printf("%s", header);
2664 2666 else if (right_justify)
2665 2667 (void) printf("%*s", width, header);
2666 2668 else
2667 2669 (void) printf("%-*s", width, header);
2668 2670
2669 2671 }
2670 2672
2671 2673 (void) printf("\n");
2672 2674 }
2673 2675
2674 2676 /*
2675 2677 * Given a pool and a list of properties, print out all the properties according
2676 2678 * to the described layout.
2677 2679 */
2678 2680 static void
2679 2681 print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
2680 2682 {
2681 2683 zprop_list_t *pl = cb->cb_proplist;
2682 2684 boolean_t first = B_TRUE;
2683 2685 char property[ZPOOL_MAXPROPLEN];
2684 2686 char *propstr;
2685 2687 boolean_t right_justify;
2686 2688 size_t width;
2687 2689
2688 2690 for (; pl != NULL; pl = pl->pl_next) {
2689 2691
2690 2692 width = pl->pl_width;
2691 2693 if (first && cb->cb_verbose) {
2692 2694 /*
2693 2695 * Reset the width to accommodate the verbose listing
2694 2696 * of devices.
2695 2697 */
2696 2698 width = cb->cb_namewidth;
2697 2699 }
2698 2700
2699 2701 if (!first) {
2700 2702 if (cb->cb_scripted)
2701 2703 (void) printf("\t");
2702 2704 else
2703 2705 (void) printf(" ");
2704 2706 } else {
2705 2707 first = B_FALSE;
2706 2708 }
2707 2709
2708 2710 right_justify = B_FALSE;
2709 2711 if (pl->pl_prop != ZPROP_INVAL) {
2710 2712 if (pl->pl_prop == ZPOOL_PROP_EXPANDSZ &&
2711 2713 zpool_get_prop_int(zhp, pl->pl_prop, NULL) == 0)
2712 2714 propstr = "-";
2713 2715 else if (zpool_get_prop(zhp, pl->pl_prop, property,
2714 2716 sizeof (property), NULL) != 0)
2715 2717 propstr = "-";
2716 2718 else
2717 2719 propstr = property;
2718 2720
2719 2721 right_justify = zpool_prop_align_right(pl->pl_prop);
2720 2722 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
2721 2723 zpool_prop_unsupported(pl->pl_user_prop)) &&
2722 2724 zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
2723 2725 sizeof (property)) == 0) {
2724 2726 propstr = property;
2725 2727 } else {
2726 2728 propstr = "-";
2727 2729 }
2728 2730
2729 2731
2730 2732 /*
2731 2733 * If this is being called in scripted mode, or if this is the
2732 2734 * last column and it is left-justified, don't include a width
2733 2735 * format specifier.
2734 2736 */
2735 2737 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
2736 2738 (void) printf("%s", propstr);
2737 2739 else if (right_justify)
2738 2740 (void) printf("%*s", width, propstr);
2739 2741 else
2740 2742 (void) printf("%-*s", width, propstr);
2741 2743 }
2742 2744
2743 2745 (void) printf("\n");
2744 2746 }
2745 2747
2746 2748 static void
2747 2749 print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted)
2748 2750 {
2749 2751 char propval[64];
2750 2752 boolean_t fixed;
2751 2753 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
2752 2754
2753 2755 zfs_nicenum(value, propval, sizeof (propval));
2754 2756
2755 2757 if (prop == ZPOOL_PROP_EXPANDSZ && value == 0)
2756 2758 (void) strlcpy(propval, "-", sizeof (propval));
2757 2759
2758 2760 if (scripted)
2759 2761 (void) printf("\t%s", propval);
2760 2762 else
2761 2763 (void) printf(" %*s", width, propval);
2762 2764 }
2763 2765
2764 2766 void
2765 2767 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
2766 2768 list_cbdata_t *cb, int depth)
2767 2769 {
2768 2770 nvlist_t **child;
2769 2771 vdev_stat_t *vs;
2770 2772 uint_t c, children;
2771 2773 char *vname;
2772 2774 boolean_t scripted = cb->cb_scripted;
2773 2775
2774 2776 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
2775 2777 (uint64_t **)&vs, &c) == 0);
2776 2778
2777 2779 if (name != NULL) {
2778 2780 if (scripted)
2779 2781 (void) printf("\t%s", name);
2780 2782 else if (strlen(name) + depth > cb->cb_namewidth)
2781 2783 (void) printf("%*s%s", depth, "", name);
2782 2784 else
2783 2785 (void) printf("%*s%s%*s", depth, "", name,
2784 2786 (int)(cb->cb_namewidth - strlen(name) - depth), "");
2785 2787
2786 2788 /* only toplevel vdevs have capacity stats */
2787 2789 if (vs->vs_space == 0) {
2788 2790 if (scripted)
2789 2791 (void) printf("\t-\t-\t-");
2790 2792 else
2791 2793 (void) printf(" - - -");
2792 2794 } else {
2793 2795 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space,
2794 2796 scripted);
2795 2797 print_one_column(ZPOOL_PROP_CAPACITY, vs->vs_alloc,
2796 2798 scripted);
2797 2799 print_one_column(ZPOOL_PROP_FREE,
2798 2800 vs->vs_space - vs->vs_alloc, scripted);
2799 2801 }
2800 2802 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize,
2801 2803 scripted);
2802 2804 (void) printf("\n");
2803 2805 }
2804 2806
2805 2807 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2806 2808 &child, &children) != 0)
2807 2809 return;
2808 2810
2809 2811 for (c = 0; c < children; c++) {
2810 2812 uint64_t ishole = B_FALSE;
2811 2813
2812 2814 if (nvlist_lookup_uint64(child[c],
2813 2815 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
2814 2816 continue;
2815 2817
2816 2818 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
2817 2819 print_list_stats(zhp, vname, child[c], cb, depth + 2);
2818 2820 free(vname);
2819 2821 }
2820 2822
2821 2823 /*
2822 2824 * Include level 2 ARC devices in iostat output
2823 2825 */
2824 2826 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
2825 2827 &child, &children) != 0)
2826 2828 return;
2827 2829
2828 2830 if (children > 0) {
2829 2831 (void) printf("%-*s - - - - - "
2830 2832 "-\n", cb->cb_namewidth, "cache");
2831 2833 for (c = 0; c < children; c++) {
2832 2834 vname = zpool_vdev_name(g_zfs, zhp, child[c],
2833 2835 B_FALSE);
2834 2836 print_list_stats(zhp, vname, child[c], cb, depth + 2);
2835 2837 free(vname);
2836 2838 }
2837 2839 }
2838 2840 }
2839 2841
2840 2842
2841 2843 /*
2842 2844 * Generic callback function to list a pool.
2843 2845 */
2844 2846 int
2845 2847 list_callback(zpool_handle_t *zhp, void *data)
2846 2848 {
2847 2849 list_cbdata_t *cbp = data;
2848 2850 nvlist_t *config;
2849 2851 nvlist_t *nvroot;
2850 2852
2851 2853 config = zpool_get_config(zhp, NULL);
2852 2854
2853 2855 print_pool(zhp, cbp);
2854 2856 if (!cbp->cb_verbose)
2855 2857 return (0);
2856 2858
2857 2859 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2858 2860 &nvroot) == 0);
2859 2861 print_list_stats(zhp, NULL, nvroot, cbp, 0);
2860 2862
2861 2863 return (0);
2862 2864 }
2863 2865
2864 2866 /*
2865 2867 * zpool list [-H] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
2866 2868 *
2867 2869 * -H Scripted mode. Don't display headers, and separate properties
2868 2870 * by a single tab.
2869 2871 * -o List of properties to display. Defaults to
2870 2872 * "name,size,allocated,free,capacity,health,altroot"
2871 2873 * -T Display a timestamp in date(1) or Unix format
2872 2874 *
2873 2875 * List all pools in the system, whether or not they're healthy. Output space
2874 2876 * statistics for each one, as well as health status summary.
2875 2877 */
2876 2878 int
2877 2879 zpool_do_list(int argc, char **argv)
2878 2880 {
2879 2881 int c;
2880 2882 int ret;
2881 2883 list_cbdata_t cb = { 0 };
2882 2884 static char default_props[] =
2883 2885 "name,size,allocated,free,expandsize,capacity,dedupratio,"
2884 2886 "health,altroot";
2885 2887 char *props = default_props;
2886 2888 unsigned long interval = 0, count = 0;
2887 2889 zpool_list_t *list;
2888 2890 boolean_t first = B_TRUE;
2889 2891
2890 2892 /* check options */
2891 2893 while ((c = getopt(argc, argv, ":Ho:T:v")) != -1) {
2892 2894 switch (c) {
2893 2895 case 'H':
2894 2896 cb.cb_scripted = B_TRUE;
2895 2897 break;
2896 2898 case 'o':
2897 2899 props = optarg;
2898 2900 break;
2899 2901 case 'T':
2900 2902 get_timestamp_arg(*optarg);
2901 2903 break;
2902 2904 case 'v':
2903 2905 cb.cb_verbose = B_TRUE;
2904 2906 break;
2905 2907 case ':':
2906 2908 (void) fprintf(stderr, gettext("missing argument for "
2907 2909 "'%c' option\n"), optopt);
2908 2910 usage(B_FALSE);
2909 2911 break;
2910 2912 case '?':
2911 2913 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2912 2914 optopt);
2913 2915 usage(B_FALSE);
2914 2916 }
2915 2917 }
2916 2918
2917 2919 argc -= optind;
2918 2920 argv += optind;
2919 2921
2920 2922 get_interval_count(&argc, argv, &interval, &count);
2921 2923
2922 2924 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
2923 2925 usage(B_FALSE);
2924 2926
2925 2927 if ((list = pool_list_get(argc, argv, &cb.cb_proplist, &ret)) == NULL)
2926 2928 return (1);
2927 2929
2928 2930 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
2929 2931 (void) printf(gettext("no pools available\n"));
2930 2932 zprop_free_list(cb.cb_proplist);
2931 2933 return (0);
2932 2934 }
2933 2935
2934 2936 for (;;) {
2935 2937 pool_list_update(list);
2936 2938
2937 2939 if (pool_list_count(list) == 0)
2938 2940 break;
2939 2941
2940 2942 cb.cb_namewidth = 0;
2941 2943 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2942 2944
2943 2945 if (timestamp_fmt != NODATE)
2944 2946 print_timestamp(timestamp_fmt);
2945 2947
2946 2948 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
2947 2949 print_header(&cb);
2948 2950 first = B_FALSE;
2949 2951 }
2950 2952 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
2951 2953
2952 2954 if (interval == 0)
2953 2955 break;
2954 2956
2955 2957 if (count != 0 && --count == 0)
2956 2958 break;
2957 2959
2958 2960 (void) sleep(interval);
2959 2961 }
2960 2962
2961 2963 zprop_free_list(cb.cb_proplist);
2962 2964 return (ret);
2963 2965 }
2964 2966
2965 2967 static nvlist_t *
2966 2968 zpool_get_vdev_by_name(nvlist_t *nv, char *name)
2967 2969 {
2968 2970 nvlist_t **child;
2969 2971 uint_t c, children;
2970 2972 nvlist_t *match;
2971 2973 char *path;
2972 2974
2973 2975 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2974 2976 &child, &children) != 0) {
2975 2977 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2976 2978 if (strncmp(name, "/dev/dsk/", 9) == 0)
2977 2979 name += 9;
2978 2980 if (strncmp(path, "/dev/dsk/", 9) == 0)
2979 2981 path += 9;
2980 2982 if (strcmp(name, path) == 0)
2981 2983 return (nv);
2982 2984 return (NULL);
2983 2985 }
2984 2986
2985 2987 for (c = 0; c < children; c++)
2986 2988 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
2987 2989 return (match);
2988 2990
2989 2991 return (NULL);
2990 2992 }
2991 2993
2992 2994 static int
2993 2995 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
2994 2996 {
2995 2997 boolean_t force = B_FALSE;
2996 2998 int c;
2997 2999 nvlist_t *nvroot;
2998 3000 char *poolname, *old_disk, *new_disk;
2999 3001 zpool_handle_t *zhp;
3000 3002 int ret;
3001 3003
3002 3004 /* check options */
3003 3005 while ((c = getopt(argc, argv, "f")) != -1) {
3004 3006 switch (c) {
3005 3007 case 'f':
3006 3008 force = B_TRUE;
3007 3009 break;
3008 3010 case '?':
3009 3011 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3010 3012 optopt);
3011 3013 usage(B_FALSE);
3012 3014 }
3013 3015 }
3014 3016
3015 3017 argc -= optind;
3016 3018 argv += optind;
3017 3019
3018 3020 /* get pool name and check number of arguments */
3019 3021 if (argc < 1) {
3020 3022 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3021 3023 usage(B_FALSE);
3022 3024 }
3023 3025
3024 3026 poolname = argv[0];
3025 3027
3026 3028 if (argc < 2) {
3027 3029 (void) fprintf(stderr,
3028 3030 gettext("missing <device> specification\n"));
3029 3031 usage(B_FALSE);
3030 3032 }
3031 3033
3032 3034 old_disk = argv[1];
3033 3035
3034 3036 if (argc < 3) {
3035 3037 if (!replacing) {
3036 3038 (void) fprintf(stderr,
3037 3039 gettext("missing <new_device> specification\n"));
3038 3040 usage(B_FALSE);
3039 3041 }
3040 3042 new_disk = old_disk;
3041 3043 argc -= 1;
3042 3044 argv += 1;
3043 3045 } else {
3044 3046 new_disk = argv[2];
3045 3047 argc -= 2;
3046 3048 argv += 2;
3047 3049 }
3048 3050
3049 3051 if (argc > 1) {
3050 3052 (void) fprintf(stderr, gettext("too many arguments\n"));
3051 3053 usage(B_FALSE);
3052 3054 }
3053 3055
3054 3056 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3055 3057 return (1);
3056 3058
3057 3059 if (zpool_get_config(zhp, NULL) == NULL) {
3058 3060 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
3059 3061 poolname);
3060 3062 zpool_close(zhp);
3061 3063 return (1);
3062 3064 }
3063 3065
3064 3066 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
3065 3067 argc, argv);
3066 3068 if (nvroot == NULL) {
3067 3069 zpool_close(zhp);
3068 3070 return (1);
3069 3071 }
3070 3072
3071 3073 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
3072 3074
3073 3075 nvlist_free(nvroot);
3074 3076 zpool_close(zhp);
3075 3077
3076 3078 return (ret);
3077 3079 }
3078 3080
3079 3081 /*
3080 3082 * zpool replace [-f] <pool> <device> <new_device>
3081 3083 *
3082 3084 * -f Force attach, even if <new_device> appears to be in use.
3083 3085 *
3084 3086 * Replace <device> with <new_device>.
3085 3087 */
3086 3088 /* ARGSUSED */
3087 3089 int
3088 3090 zpool_do_replace(int argc, char **argv)
3089 3091 {
3090 3092 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
3091 3093 }
3092 3094
3093 3095 /*
3094 3096 * zpool attach [-f] <pool> <device> <new_device>
3095 3097 *
3096 3098 * -f Force attach, even if <new_device> appears to be in use.
3097 3099 *
3098 3100 * Attach <new_device> to the mirror containing <device>. If <device> is not
3099 3101 * part of a mirror, then <device> will be transformed into a mirror of
3100 3102 * <device> and <new_device>. In either case, <new_device> will begin life
3101 3103 * with a DTL of [0, now], and will immediately begin to resilver itself.
3102 3104 */
3103 3105 int
3104 3106 zpool_do_attach(int argc, char **argv)
3105 3107 {
3106 3108 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
3107 3109 }
3108 3110
3109 3111 /*
3110 3112 * zpool detach [-f] <pool> <device>
3111 3113 *
3112 3114 * -f Force detach of <device>, even if DTLs argue against it
3113 3115 * (not supported yet)
3114 3116 *
3115 3117 * Detach a device from a mirror. The operation will be refused if <device>
3116 3118 * is the last device in the mirror, or if the DTLs indicate that this device
3117 3119 * has the only valid copy of some data.
3118 3120 */
3119 3121 /* ARGSUSED */
3120 3122 int
3121 3123 zpool_do_detach(int argc, char **argv)
3122 3124 {
3123 3125 int c;
3124 3126 char *poolname, *path;
3125 3127 zpool_handle_t *zhp;
3126 3128 int ret;
3127 3129
3128 3130 /* check options */
3129 3131 while ((c = getopt(argc, argv, "f")) != -1) {
3130 3132 switch (c) {
3131 3133 case 'f':
3132 3134 case '?':
3133 3135 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3134 3136 optopt);
3135 3137 usage(B_FALSE);
3136 3138 }
3137 3139 }
3138 3140
3139 3141 argc -= optind;
3140 3142 argv += optind;
3141 3143
3142 3144 /* get pool name and check number of arguments */
3143 3145 if (argc < 1) {
3144 3146 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3145 3147 usage(B_FALSE);
3146 3148 }
3147 3149
3148 3150 if (argc < 2) {
3149 3151 (void) fprintf(stderr,
3150 3152 gettext("missing <device> specification\n"));
3151 3153 usage(B_FALSE);
3152 3154 }
3153 3155
3154 3156 poolname = argv[0];
3155 3157 path = argv[1];
3156 3158
3157 3159 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3158 3160 return (1);
3159 3161
3160 3162 ret = zpool_vdev_detach(zhp, path);
3161 3163
3162 3164 zpool_close(zhp);
3163 3165
3164 3166 return (ret);
3165 3167 }
3166 3168
3167 3169 /*
3168 3170 * zpool split [-n] [-o prop=val] ...
3169 3171 * [-o mntopt] ...
3170 3172 * [-R altroot] <pool> <newpool> [<device> ...]
3171 3173 *
3172 3174 * -n Do not split the pool, but display the resulting layout if
3173 3175 * it were to be split.
3174 3176 * -o Set property=value, or set mount options.
3175 3177 * -R Mount the split-off pool under an alternate root.
3176 3178 *
3177 3179 * Splits the named pool and gives it the new pool name. Devices to be split
3178 3180 * off may be listed, provided that no more than one device is specified
3179 3181 * per top-level vdev mirror. The newly split pool is left in an exported
3180 3182 * state unless -R is specified.
3181 3183 *
3182 3184 * Restrictions: the top-level of the pool pool must only be made up of
3183 3185 * mirrors; all devices in the pool must be healthy; no device may be
3184 3186 * undergoing a resilvering operation.
3185 3187 */
3186 3188 int
3187 3189 zpool_do_split(int argc, char **argv)
3188 3190 {
3189 3191 char *srcpool, *newpool, *propval;
3190 3192 char *mntopts = NULL;
3191 3193 splitflags_t flags;
3192 3194 int c, ret = 0;
3193 3195 zpool_handle_t *zhp;
3194 3196 nvlist_t *config, *props = NULL;
3195 3197
3196 3198 flags.dryrun = B_FALSE;
3197 3199 flags.import = B_FALSE;
3198 3200
3199 3201 /* check options */
3200 3202 while ((c = getopt(argc, argv, ":R:no:")) != -1) {
3201 3203 switch (c) {
3202 3204 case 'R':
3203 3205 flags.import = B_TRUE;
3204 3206 if (add_prop_list(
3205 3207 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
3206 3208 &props, B_TRUE) != 0) {
3207 3209 if (props)
3208 3210 nvlist_free(props);
3209 3211 usage(B_FALSE);
3210 3212 }
3211 3213 break;
3212 3214 case 'n':
3213 3215 flags.dryrun = B_TRUE;
3214 3216 break;
3215 3217 case 'o':
3216 3218 if ((propval = strchr(optarg, '=')) != NULL) {
3217 3219 *propval = '\0';
3218 3220 propval++;
3219 3221 if (add_prop_list(optarg, propval,
3220 3222 &props, B_TRUE) != 0) {
3221 3223 if (props)
3222 3224 nvlist_free(props);
3223 3225 usage(B_FALSE);
3224 3226 }
3225 3227 } else {
3226 3228 mntopts = optarg;
3227 3229 }
3228 3230 break;
3229 3231 case ':':
3230 3232 (void) fprintf(stderr, gettext("missing argument for "
3231 3233 "'%c' option\n"), optopt);
3232 3234 usage(B_FALSE);
3233 3235 break;
3234 3236 case '?':
3235 3237 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3236 3238 optopt);
3237 3239 usage(B_FALSE);
3238 3240 break;
3239 3241 }
3240 3242 }
3241 3243
3242 3244 if (!flags.import && mntopts != NULL) {
3243 3245 (void) fprintf(stderr, gettext("setting mntopts is only "
3244 3246 "valid when importing the pool\n"));
3245 3247 usage(B_FALSE);
3246 3248 }
3247 3249
3248 3250 argc -= optind;
3249 3251 argv += optind;
3250 3252
3251 3253 if (argc < 1) {
3252 3254 (void) fprintf(stderr, gettext("Missing pool name\n"));
3253 3255 usage(B_FALSE);
3254 3256 }
3255 3257 if (argc < 2) {
3256 3258 (void) fprintf(stderr, gettext("Missing new pool name\n"));
3257 3259 usage(B_FALSE);
3258 3260 }
3259 3261
3260 3262 srcpool = argv[0];
3261 3263 newpool = argv[1];
3262 3264
3263 3265 argc -= 2;
3264 3266 argv += 2;
3265 3267
3266 3268 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
3267 3269 return (1);
3268 3270
3269 3271 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
3270 3272 if (config == NULL) {
3271 3273 ret = 1;
3272 3274 } else {
3273 3275 if (flags.dryrun) {
3274 3276 (void) printf(gettext("would create '%s' with the "
3275 3277 "following layout:\n\n"), newpool);
3276 3278 print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
3277 3279 }
3278 3280 nvlist_free(config);
3279 3281 }
3280 3282
3281 3283 zpool_close(zhp);
3282 3284
3283 3285 if (ret != 0 || flags.dryrun || !flags.import)
3284 3286 return (ret);
3285 3287
3286 3288 /*
3287 3289 * The split was successful. Now we need to open the new
3288 3290 * pool and import it.
3289 3291 */
3290 3292 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
3291 3293 return (1);
3292 3294 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
3293 3295 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
3294 3296 ret = 1;
3295 3297 (void) fprintf(stderr, gettext("Split was successful, but "
3296 3298 "the datasets could not all be mounted\n"));
3297 3299 (void) fprintf(stderr, gettext("Try doing '%s' with a "
3298 3300 "different altroot\n"), "zpool import");
3299 3301 }
3300 3302 zpool_close(zhp);
3301 3303
3302 3304 return (ret);
3303 3305 }
3304 3306
3305 3307
3306 3308
3307 3309 /*
3308 3310 * zpool online <pool> <device> ...
3309 3311 */
3310 3312 int
3311 3313 zpool_do_online(int argc, char **argv)
3312 3314 {
3313 3315 int c, i;
3314 3316 char *poolname;
3315 3317 zpool_handle_t *zhp;
3316 3318 int ret = 0;
3317 3319 vdev_state_t newstate;
3318 3320 int flags = 0;
3319 3321
3320 3322 /* check options */
3321 3323 while ((c = getopt(argc, argv, "et")) != -1) {
3322 3324 switch (c) {
3323 3325 case 'e':
3324 3326 flags |= ZFS_ONLINE_EXPAND;
3325 3327 break;
3326 3328 case 't':
3327 3329 case '?':
3328 3330 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3329 3331 optopt);
3330 3332 usage(B_FALSE);
3331 3333 }
3332 3334 }
3333 3335
3334 3336 argc -= optind;
3335 3337 argv += optind;
3336 3338
3337 3339 /* get pool name and check number of arguments */
3338 3340 if (argc < 1) {
3339 3341 (void) fprintf(stderr, gettext("missing pool name\n"));
3340 3342 usage(B_FALSE);
3341 3343 }
3342 3344 if (argc < 2) {
3343 3345 (void) fprintf(stderr, gettext("missing device name\n"));
3344 3346 usage(B_FALSE);
3345 3347 }
3346 3348
3347 3349 poolname = argv[0];
3348 3350
3349 3351 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3350 3352 return (1);
3351 3353
3352 3354 for (i = 1; i < argc; i++) {
3353 3355 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
3354 3356 if (newstate != VDEV_STATE_HEALTHY) {
3355 3357 (void) printf(gettext("warning: device '%s' "
3356 3358 "onlined, but remains in faulted state\n"),
3357 3359 argv[i]);
3358 3360 if (newstate == VDEV_STATE_FAULTED)
3359 3361 (void) printf(gettext("use 'zpool "
3360 3362 "clear' to restore a faulted "
3361 3363 "device\n"));
3362 3364 else
3363 3365 (void) printf(gettext("use 'zpool "
3364 3366 "replace' to replace devices "
3365 3367 "that are no longer present\n"));
3366 3368 }
3367 3369 } else {
3368 3370 ret = 1;
3369 3371 }
3370 3372 }
3371 3373
3372 3374 zpool_close(zhp);
3373 3375
3374 3376 return (ret);
3375 3377 }
3376 3378
3377 3379 /*
3378 3380 * zpool offline [-ft] <pool> <device> ...
3379 3381 *
3380 3382 * -f Force the device into the offline state, even if doing
3381 3383 * so would appear to compromise pool availability.
3382 3384 * (not supported yet)
3383 3385 *
3384 3386 * -t Only take the device off-line temporarily. The offline
3385 3387 * state will not be persistent across reboots.
3386 3388 */
3387 3389 /* ARGSUSED */
3388 3390 int
3389 3391 zpool_do_offline(int argc, char **argv)
3390 3392 {
3391 3393 int c, i;
3392 3394 char *poolname;
3393 3395 zpool_handle_t *zhp;
3394 3396 int ret = 0;
3395 3397 boolean_t istmp = B_FALSE;
3396 3398
3397 3399 /* check options */
3398 3400 while ((c = getopt(argc, argv, "ft")) != -1) {
3399 3401 switch (c) {
3400 3402 case 't':
3401 3403 istmp = B_TRUE;
3402 3404 break;
3403 3405 case 'f':
3404 3406 case '?':
3405 3407 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3406 3408 optopt);
3407 3409 usage(B_FALSE);
3408 3410 }
3409 3411 }
3410 3412
3411 3413 argc -= optind;
3412 3414 argv += optind;
3413 3415
3414 3416 /* get pool name and check number of arguments */
3415 3417 if (argc < 1) {
3416 3418 (void) fprintf(stderr, gettext("missing pool name\n"));
3417 3419 usage(B_FALSE);
3418 3420 }
3419 3421 if (argc < 2) {
3420 3422 (void) fprintf(stderr, gettext("missing device name\n"));
3421 3423 usage(B_FALSE);
3422 3424 }
3423 3425
3424 3426 poolname = argv[0];
3425 3427
3426 3428 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3427 3429 return (1);
3428 3430
3429 3431 for (i = 1; i < argc; i++) {
3430 3432 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
3431 3433 ret = 1;
3432 3434 }
3433 3435
3434 3436 zpool_close(zhp);
3435 3437
3436 3438 return (ret);
3437 3439 }
3438 3440
3439 3441 /*
3440 3442 * zpool clear <pool> [device]
3441 3443 *
3442 3444 * Clear all errors associated with a pool or a particular device.
3443 3445 */
3444 3446 int
3445 3447 zpool_do_clear(int argc, char **argv)
3446 3448 {
3447 3449 int c;
3448 3450 int ret = 0;
3449 3451 boolean_t dryrun = B_FALSE;
3450 3452 boolean_t do_rewind = B_FALSE;
3451 3453 boolean_t xtreme_rewind = B_FALSE;
3452 3454 uint32_t rewind_policy = ZPOOL_NO_REWIND;
3453 3455 nvlist_t *policy = NULL;
3454 3456 zpool_handle_t *zhp;
3455 3457 char *pool, *device;
3456 3458
3457 3459 /* check options */
3458 3460 while ((c = getopt(argc, argv, "FnX")) != -1) {
3459 3461 switch (c) {
3460 3462 case 'F':
3461 3463 do_rewind = B_TRUE;
3462 3464 break;
3463 3465 case 'n':
3464 3466 dryrun = B_TRUE;
3465 3467 break;
3466 3468 case 'X':
3467 3469 xtreme_rewind = B_TRUE;
3468 3470 break;
3469 3471 case '?':
3470 3472 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3471 3473 optopt);
3472 3474 usage(B_FALSE);
3473 3475 }
3474 3476 }
3475 3477
3476 3478 argc -= optind;
3477 3479 argv += optind;
3478 3480
3479 3481 if (argc < 1) {
3480 3482 (void) fprintf(stderr, gettext("missing pool name\n"));
3481 3483 usage(B_FALSE);
3482 3484 }
3483 3485
3484 3486 if (argc > 2) {
3485 3487 (void) fprintf(stderr, gettext("too many arguments\n"));
3486 3488 usage(B_FALSE);
3487 3489 }
3488 3490
3489 3491 if ((dryrun || xtreme_rewind) && !do_rewind) {
3490 3492 (void) fprintf(stderr,
3491 3493 gettext("-n or -X only meaningful with -F\n"));
3492 3494 usage(B_FALSE);
3493 3495 }
3494 3496 if (dryrun)
3495 3497 rewind_policy = ZPOOL_TRY_REWIND;
3496 3498 else if (do_rewind)
3497 3499 rewind_policy = ZPOOL_DO_REWIND;
3498 3500 if (xtreme_rewind)
3499 3501 rewind_policy |= ZPOOL_EXTREME_REWIND;
3500 3502
3501 3503 /* In future, further rewind policy choices can be passed along here */
3502 3504 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
3503 3505 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
3504 3506 return (1);
3505 3507
3506 3508 pool = argv[0];
3507 3509 device = argc == 2 ? argv[1] : NULL;
3508 3510
3509 3511 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
3510 3512 nvlist_free(policy);
3511 3513 return (1);
3512 3514 }
3513 3515
3514 3516 if (zpool_clear(zhp, device, policy) != 0)
3515 3517 ret = 1;
3516 3518
3517 3519 zpool_close(zhp);
3518 3520
3519 3521 nvlist_free(policy);
3520 3522
3521 3523 return (ret);
3522 3524 }
3523 3525
3524 3526 /*
3525 3527 * zpool reguid <pool>
3526 3528 */
3527 3529 int
3528 3530 zpool_do_reguid(int argc, char **argv)
3529 3531 {
3530 3532 int c;
3531 3533 char *poolname;
3532 3534 zpool_handle_t *zhp;
3533 3535 int ret = 0;
3534 3536
3535 3537 /* check options */
3536 3538 while ((c = getopt(argc, argv, "")) != -1) {
3537 3539 switch (c) {
3538 3540 case '?':
3539 3541 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3540 3542 optopt);
3541 3543 usage(B_FALSE);
3542 3544 }
3543 3545 }
3544 3546
3545 3547 argc -= optind;
3546 3548 argv += optind;
3547 3549
3548 3550 /* get pool name and check number of arguments */
3549 3551 if (argc < 1) {
3550 3552 (void) fprintf(stderr, gettext("missing pool name\n"));
3551 3553 usage(B_FALSE);
3552 3554 }
3553 3555
3554 3556 if (argc > 1) {
3555 3557 (void) fprintf(stderr, gettext("too many arguments\n"));
3556 3558 usage(B_FALSE);
3557 3559 }
3558 3560
3559 3561 poolname = argv[0];
3560 3562 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3561 3563 return (1);
3562 3564
3563 3565 ret = zpool_reguid(zhp);
3564 3566
3565 3567 zpool_close(zhp);
3566 3568 return (ret);
3567 3569 }
3568 3570
3569 3571
3570 3572 /*
3571 3573 * zpool reopen <pool>
3572 3574 *
3573 3575 * Reopen the pool so that the kernel can update the sizes of all vdevs.
3574 3576 */
3575 3577 int
3576 3578 zpool_do_reopen(int argc, char **argv)
3577 3579 {
3578 3580 int c;
3579 3581 int ret = 0;
3580 3582 zpool_handle_t *zhp;
3581 3583 char *pool;
3582 3584
3583 3585 /* check options */
3584 3586 while ((c = getopt(argc, argv, "")) != -1) {
3585 3587 switch (c) {
3586 3588 case '?':
3587 3589 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3588 3590 optopt);
3589 3591 usage(B_FALSE);
3590 3592 }
3591 3593 }
3592 3594
3593 3595 argc--;
3594 3596 argv++;
3595 3597
3596 3598 if (argc < 1) {
3597 3599 (void) fprintf(stderr, gettext("missing pool name\n"));
3598 3600 usage(B_FALSE);
3599 3601 }
3600 3602
3601 3603 if (argc > 1) {
3602 3604 (void) fprintf(stderr, gettext("too many arguments\n"));
3603 3605 usage(B_FALSE);
3604 3606 }
3605 3607
3606 3608 pool = argv[0];
3607 3609 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
3608 3610 return (1);
3609 3611
3610 3612 ret = zpool_reopen(zhp);
3611 3613 zpool_close(zhp);
3612 3614 return (ret);
3613 3615 }
3614 3616
3615 3617 typedef struct scrub_cbdata {
3616 3618 int cb_type;
3617 3619 int cb_argc;
3618 3620 char **cb_argv;
3619 3621 } scrub_cbdata_t;
3620 3622
3621 3623 int
3622 3624 scrub_callback(zpool_handle_t *zhp, void *data)
3623 3625 {
3624 3626 scrub_cbdata_t *cb = data;
3625 3627 int err;
3626 3628
3627 3629 /*
3628 3630 * Ignore faulted pools.
3629 3631 */
3630 3632 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
3631 3633 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
3632 3634 "currently unavailable\n"), zpool_get_name(zhp));
3633 3635 return (1);
3634 3636 }
3635 3637
3636 3638 err = zpool_scan(zhp, cb->cb_type);
3637 3639
3638 3640 return (err != 0);
3639 3641 }
3640 3642
3641 3643 /*
3642 3644 * zpool scrub [-s] <pool> ...
3643 3645 *
3644 3646 * -s Stop. Stops any in-progress scrub.
3645 3647 */
3646 3648 int
3647 3649 zpool_do_scrub(int argc, char **argv)
3648 3650 {
3649 3651 int c;
3650 3652 scrub_cbdata_t cb;
3651 3653
3652 3654 cb.cb_type = POOL_SCAN_SCRUB;
3653 3655
3654 3656 /* check options */
3655 3657 while ((c = getopt(argc, argv, "s")) != -1) {
3656 3658 switch (c) {
3657 3659 case 's':
3658 3660 cb.cb_type = POOL_SCAN_NONE;
3659 3661 break;
3660 3662 case '?':
3661 3663 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3662 3664 optopt);
3663 3665 usage(B_FALSE);
3664 3666 }
3665 3667 }
3666 3668
3667 3669 cb.cb_argc = argc;
3668 3670 cb.cb_argv = argv;
3669 3671 argc -= optind;
3670 3672 argv += optind;
3671 3673
3672 3674 if (argc < 1) {
3673 3675 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3674 3676 usage(B_FALSE);
3675 3677 }
3676 3678
3677 3679 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
3678 3680 }
3679 3681
3680 3682 typedef struct status_cbdata {
3681 3683 int cb_count;
3682 3684 boolean_t cb_allpools;
3683 3685 boolean_t cb_verbose;
3684 3686 boolean_t cb_explain;
3685 3687 boolean_t cb_first;
3686 3688 boolean_t cb_dedup_stats;
3687 3689 } status_cbdata_t;
3688 3690
3689 3691 /*
3690 3692 * Print out detailed scrub status.
3691 3693 */
3692 3694 void
3693 3695 print_scan_status(pool_scan_stat_t *ps)
3694 3696 {
3695 3697 time_t start, end;
3696 3698 uint64_t elapsed, mins_left, hours_left;
3697 3699 uint64_t pass_exam, examined, total;
3698 3700 uint_t rate;
3699 3701 double fraction_done;
3700 3702 char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
3701 3703
3702 3704 (void) printf(gettext(" scan: "));
3703 3705
3704 3706 /* If there's never been a scan, there's not much to say. */
3705 3707 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
3706 3708 ps->pss_func >= POOL_SCAN_FUNCS) {
3707 3709 (void) printf(gettext("none requested\n"));
3708 3710 return;
3709 3711 }
3710 3712
3711 3713 start = ps->pss_start_time;
3712 3714 end = ps->pss_end_time;
3713 3715 zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
3714 3716
3715 3717 assert(ps->pss_func == POOL_SCAN_SCRUB ||
3716 3718 ps->pss_func == POOL_SCAN_RESILVER);
3717 3719 /*
3718 3720 * Scan is finished or canceled.
3719 3721 */
3720 3722 if (ps->pss_state == DSS_FINISHED) {
3721 3723 uint64_t minutes_taken = (end - start) / 60;
3722 3724 char *fmt;
3723 3725
3724 3726 if (ps->pss_func == POOL_SCAN_SCRUB) {
3725 3727 fmt = gettext("scrub repaired %s in %lluh%um with "
3726 3728 "%llu errors on %s");
3727 3729 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
3728 3730 fmt = gettext("resilvered %s in %lluh%um with "
3729 3731 "%llu errors on %s");
3730 3732 }
3731 3733 /* LINTED */
3732 3734 (void) printf(fmt, processed_buf,
3733 3735 (u_longlong_t)(minutes_taken / 60),
3734 3736 (uint_t)(minutes_taken % 60),
3735 3737 (u_longlong_t)ps->pss_errors,
3736 3738 ctime((time_t *)&end));
3737 3739 return;
3738 3740 } else if (ps->pss_state == DSS_CANCELED) {
3739 3741 if (ps->pss_func == POOL_SCAN_SCRUB) {
3740 3742 (void) printf(gettext("scrub canceled on %s"),
3741 3743 ctime(&end));
3742 3744 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
3743 3745 (void) printf(gettext("resilver canceled on %s"),
3744 3746 ctime(&end));
3745 3747 }
3746 3748 return;
3747 3749 }
3748 3750
3749 3751 assert(ps->pss_state == DSS_SCANNING);
3750 3752
3751 3753 /*
3752 3754 * Scan is in progress.
3753 3755 */
3754 3756 if (ps->pss_func == POOL_SCAN_SCRUB) {
3755 3757 (void) printf(gettext("scrub in progress since %s"),
3756 3758 ctime(&start));
3757 3759 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
3758 3760 (void) printf(gettext("resilver in progress since %s"),
3759 3761 ctime(&start));
3760 3762 }
3761 3763
3762 3764 examined = ps->pss_examined ? ps->pss_examined : 1;
3763 3765 total = ps->pss_to_examine;
3764 3766 fraction_done = (double)examined / total;
3765 3767
3766 3768 /* elapsed time for this pass */
3767 3769 elapsed = time(NULL) - ps->pss_pass_start;
3768 3770 elapsed = elapsed ? elapsed : 1;
3769 3771 pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
3770 3772 rate = pass_exam / elapsed;
3771 3773 rate = rate ? rate : 1;
3772 3774 mins_left = ((total - examined) / rate) / 60;
3773 3775 hours_left = mins_left / 60;
3774 3776
3775 3777 zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
3776 3778 zfs_nicenum(total, total_buf, sizeof (total_buf));
3777 3779 zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
3778 3780
3779 3781 /*
3780 3782 * do not print estimated time if hours_left is more than 30 days
3781 3783 */
3782 3784 (void) printf(gettext(" %s scanned out of %s at %s/s"),
3783 3785 examined_buf, total_buf, rate_buf);
3784 3786 if (hours_left < (30 * 24)) {
3785 3787 (void) printf(gettext(", %lluh%um to go\n"),
3786 3788 (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
3787 3789 } else {
3788 3790 (void) printf(gettext(
3789 3791 ", (scan is slow, no estimated time)\n"));
3790 3792 }
3791 3793
3792 3794 if (ps->pss_func == POOL_SCAN_RESILVER) {
3793 3795 (void) printf(gettext(" %s resilvered, %.2f%% done\n"),
3794 3796 processed_buf, 100 * fraction_done);
3795 3797 } else if (ps->pss_func == POOL_SCAN_SCRUB) {
3796 3798 (void) printf(gettext(" %s repaired, %.2f%% done\n"),
3797 3799 processed_buf, 100 * fraction_done);
3798 3800 }
3799 3801 }
3800 3802
3801 3803 static void
3802 3804 print_error_log(zpool_handle_t *zhp)
3803 3805 {
3804 3806 nvlist_t *nverrlist = NULL;
3805 3807 nvpair_t *elem;
3806 3808 char *pathname;
3807 3809 size_t len = MAXPATHLEN * 2;
3808 3810
3809 3811 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
3810 3812 (void) printf("errors: List of errors unavailable "
3811 3813 "(insufficient privileges)\n");
3812 3814 return;
3813 3815 }
3814 3816
3815 3817 (void) printf("errors: Permanent errors have been "
3816 3818 "detected in the following files:\n\n");
3817 3819
3818 3820 pathname = safe_malloc(len);
3819 3821 elem = NULL;
3820 3822 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
3821 3823 nvlist_t *nv;
3822 3824 uint64_t dsobj, obj;
3823 3825
3824 3826 verify(nvpair_value_nvlist(elem, &nv) == 0);
3825 3827 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
3826 3828 &dsobj) == 0);
3827 3829 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
3828 3830 &obj) == 0);
3829 3831 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
3830 3832 (void) printf("%7s %s\n", "", pathname);
3831 3833 }
3832 3834 free(pathname);
3833 3835 nvlist_free(nverrlist);
3834 3836 }
3835 3837
3836 3838 static void
3837 3839 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
3838 3840 int namewidth)
3839 3841 {
3840 3842 uint_t i;
3841 3843 char *name;
3842 3844
3843 3845 if (nspares == 0)
3844 3846 return;
3845 3847
3846 3848 (void) printf(gettext("\tspares\n"));
3847 3849
3848 3850 for (i = 0; i < nspares; i++) {
3849 3851 name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
3850 3852 print_status_config(zhp, name, spares[i],
3851 3853 namewidth, 2, B_TRUE);
3852 3854 free(name);
3853 3855 }
3854 3856 }
3855 3857
3856 3858 static void
3857 3859 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
3858 3860 int namewidth)
3859 3861 {
3860 3862 uint_t i;
3861 3863 char *name;
3862 3864
3863 3865 if (nl2cache == 0)
3864 3866 return;
3865 3867
3866 3868 (void) printf(gettext("\tcache\n"));
3867 3869
3868 3870 for (i = 0; i < nl2cache; i++) {
3869 3871 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
3870 3872 print_status_config(zhp, name, l2cache[i],
3871 3873 namewidth, 2, B_FALSE);
3872 3874 free(name);
3873 3875 }
3874 3876 }
3875 3877
3876 3878 static void
3877 3879 print_dedup_stats(nvlist_t *config)
3878 3880 {
3879 3881 ddt_histogram_t *ddh;
3880 3882 ddt_stat_t *dds;
3881 3883 ddt_object_t *ddo;
3882 3884 uint_t c;
3883 3885
3884 3886 /*
3885 3887 * If the pool was faulted then we may not have been able to
3886 3888 * obtain the config. Otherwise, if we have anything in the dedup
3887 3889 * table continue processing the stats.
3888 3890 */
3889 3891 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
3890 3892 (uint64_t **)&ddo, &c) != 0)
3891 3893 return;
3892 3894
3893 3895 (void) printf("\n");
3894 3896 (void) printf(gettext(" dedup: "));
3895 3897 if (ddo->ddo_count == 0) {
3896 3898 (void) printf(gettext("no DDT entries\n"));
3897 3899 return;
3898 3900 }
3899 3901
3900 3902 (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
3901 3903 (u_longlong_t)ddo->ddo_count,
3902 3904 (u_longlong_t)ddo->ddo_dspace,
3903 3905 (u_longlong_t)ddo->ddo_mspace);
3904 3906
3905 3907 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
3906 3908 (uint64_t **)&dds, &c) == 0);
3907 3909 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
3908 3910 (uint64_t **)&ddh, &c) == 0);
3909 3911 zpool_dump_ddt(dds, ddh);
3910 3912 }
3911 3913
3912 3914 /*
3913 3915 * Display a summary of pool status. Displays a summary such as:
3914 3916 *
3915 3917 * pool: tank
3916 3918 * status: DEGRADED
3917 3919 * reason: One or more devices ...
3918 3920 * see: http://illumos.org/msg/ZFS-xxxx-01
3919 3921 * config:
3920 3922 * mirror DEGRADED
3921 3923 * c1t0d0 OK
3922 3924 * c2t0d0 UNAVAIL
3923 3925 *
3924 3926 * When given the '-v' option, we print out the complete config. If the '-e'
3925 3927 * option is specified, then we print out error rate information as well.
3926 3928 */
3927 3929 int
3928 3930 status_callback(zpool_handle_t *zhp, void *data)
3929 3931 {
3930 3932 status_cbdata_t *cbp = data;
3931 3933 nvlist_t *config, *nvroot;
3932 3934 char *msgid;
3933 3935 int reason;
3934 3936 const char *health;
3935 3937 uint_t c;
3936 3938 vdev_stat_t *vs;
3937 3939
3938 3940 config = zpool_get_config(zhp, NULL);
3939 3941 reason = zpool_get_status(zhp, &msgid);
3940 3942
3941 3943 cbp->cb_count++;
3942 3944
3943 3945 /*
3944 3946 * If we were given 'zpool status -x', only report those pools with
3945 3947 * problems.
3946 3948 */
3947 3949 if (cbp->cb_explain &&
3948 3950 (reason == ZPOOL_STATUS_OK ||
3949 3951 reason == ZPOOL_STATUS_VERSION_OLDER ||
3950 3952 reason == ZPOOL_STATUS_FEAT_DISABLED)) {
3951 3953 if (!cbp->cb_allpools) {
3952 3954 (void) printf(gettext("pool '%s' is healthy\n"),
3953 3955 zpool_get_name(zhp));
3954 3956 if (cbp->cb_first)
3955 3957 cbp->cb_first = B_FALSE;
3956 3958 }
3957 3959 return (0);
3958 3960 }
3959 3961
3960 3962 if (cbp->cb_first)
3961 3963 cbp->cb_first = B_FALSE;
3962 3964 else
3963 3965 (void) printf("\n");
3964 3966
3965 3967 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3966 3968 &nvroot) == 0);
3967 3969 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
3968 3970 (uint64_t **)&vs, &c) == 0);
3969 3971 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
3970 3972
3971 3973 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
3972 3974 (void) printf(gettext(" state: %s\n"), health);
3973 3975
3974 3976 switch (reason) {
3975 3977 case ZPOOL_STATUS_MISSING_DEV_R:
3976 3978 (void) printf(gettext("status: One or more devices could not "
3977 3979 "be opened. Sufficient replicas exist for\n\tthe pool to "
3978 3980 "continue functioning in a degraded state.\n"));
3979 3981 (void) printf(gettext("action: Attach the missing device and "
3980 3982 "online it using 'zpool online'.\n"));
3981 3983 break;
3982 3984
3983 3985 case ZPOOL_STATUS_MISSING_DEV_NR:
3984 3986 (void) printf(gettext("status: One or more devices could not "
3985 3987 "be opened. There are insufficient\n\treplicas for the "
3986 3988 "pool to continue functioning.\n"));
3987 3989 (void) printf(gettext("action: Attach the missing device and "
3988 3990 "online it using 'zpool online'.\n"));
3989 3991 break;
3990 3992
3991 3993 case ZPOOL_STATUS_CORRUPT_LABEL_R:
3992 3994 (void) printf(gettext("status: One or more devices could not "
3993 3995 "be used because the label is missing or\n\tinvalid. "
3994 3996 "Sufficient replicas exist for the pool to continue\n\t"
3995 3997 "functioning in a degraded state.\n"));
3996 3998 (void) printf(gettext("action: Replace the device using "
3997 3999 "'zpool replace'.\n"));
3998 4000 break;
3999 4001
4000 4002 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
4001 4003 (void) printf(gettext("status: One or more devices could not "
4002 4004 "be used because the label is missing \n\tor invalid. "
4003 4005 "There are insufficient replicas for the pool to "
4004 4006 "continue\n\tfunctioning.\n"));
4005 4007 zpool_explain_recover(zpool_get_handle(zhp),
4006 4008 zpool_get_name(zhp), reason, config);
4007 4009 break;
4008 4010
4009 4011 case ZPOOL_STATUS_FAILING_DEV:
4010 4012 (void) printf(gettext("status: One or more devices has "
4011 4013 "experienced an unrecoverable error. An\n\tattempt was "
4012 4014 "made to correct the error. Applications are "
4013 4015 "unaffected.\n"));
4014 4016 (void) printf(gettext("action: Determine if the device needs "
4015 4017 "to be replaced, and clear the errors\n\tusing "
4016 4018 "'zpool clear' or replace the device with 'zpool "
4017 4019 "replace'.\n"));
4018 4020 break;
4019 4021
4020 4022 case ZPOOL_STATUS_OFFLINE_DEV:
4021 4023 (void) printf(gettext("status: One or more devices has "
4022 4024 "been taken offline by the administrator.\n\tSufficient "
4023 4025 "replicas exist for the pool to continue functioning in "
4024 4026 "a\n\tdegraded state.\n"));
4025 4027 (void) printf(gettext("action: Online the device using "
4026 4028 "'zpool online' or replace the device with\n\t'zpool "
4027 4029 "replace'.\n"));
4028 4030 break;
4029 4031
4030 4032 case ZPOOL_STATUS_REMOVED_DEV:
4031 4033 (void) printf(gettext("status: One or more devices has "
4032 4034 "been removed by the administrator.\n\tSufficient "
4033 4035 "replicas exist for the pool to continue functioning in "
4034 4036 "a\n\tdegraded state.\n"));
4035 4037 (void) printf(gettext("action: Online the device using "
4036 4038 "'zpool online' or replace the device with\n\t'zpool "
4037 4039 "replace'.\n"));
4038 4040 break;
4039 4041
4040 4042 case ZPOOL_STATUS_RESILVERING:
4041 4043 (void) printf(gettext("status: One or more devices is "
4042 4044 "currently being resilvered. The pool will\n\tcontinue "
4043 4045 "to function, possibly in a degraded state.\n"));
4044 4046 (void) printf(gettext("action: Wait for the resilver to "
4045 4047 "complete.\n"));
4046 4048 break;
4047 4049
4048 4050 case ZPOOL_STATUS_CORRUPT_DATA:
4049 4051 (void) printf(gettext("status: One or more devices has "
4050 4052 "experienced an error resulting in data\n\tcorruption. "
4051 4053 "Applications may be affected.\n"));
4052 4054 (void) printf(gettext("action: Restore the file in question "
4053 4055 "if possible. Otherwise restore the\n\tentire pool from "
4054 4056 "backup.\n"));
4055 4057 break;
4056 4058
4057 4059 case ZPOOL_STATUS_CORRUPT_POOL:
4058 4060 (void) printf(gettext("status: The pool metadata is corrupted "
4059 4061 "and the pool cannot be opened.\n"));
4060 4062 zpool_explain_recover(zpool_get_handle(zhp),
4061 4063 zpool_get_name(zhp), reason, config);
4062 4064 break;
4063 4065
4064 4066 case ZPOOL_STATUS_VERSION_OLDER:
4065 4067 (void) printf(gettext("status: The pool is formatted using a "
4066 4068 "legacy on-disk format. The pool can\n\tstill be used, "
4067 4069 "but some features are unavailable.\n"));
4068 4070 (void) printf(gettext("action: Upgrade the pool using 'zpool "
4069 4071 "upgrade'. Once this is done, the\n\tpool will no longer "
4070 4072 "be accessible on software that does not support feature\n"
4071 4073 "\tflags.\n"));
4072 4074 break;
4073 4075
4074 4076 case ZPOOL_STATUS_VERSION_NEWER:
4075 4077 (void) printf(gettext("status: The pool has been upgraded to a "
4076 4078 "newer, incompatible on-disk version.\n\tThe pool cannot "
4077 4079 "be accessed on this system.\n"));
4078 4080 (void) printf(gettext("action: Access the pool from a system "
4079 4081 "running more recent software, or\n\trestore the pool from "
4080 4082 "backup.\n"));
4081 4083 break;
4082 4084
4083 4085 case ZPOOL_STATUS_FEAT_DISABLED:
4084 4086 (void) printf(gettext("status: Some supported features are not "
4085 4087 "enabled on the pool. The pool can\n\tstill be used, but "
4086 4088 "some features are unavailable.\n"));
4087 4089 (void) printf(gettext("action: Enable all features using "
4088 4090 "'zpool upgrade'. Once this is done,\n\tthe pool may no "
4089 4091 "longer be accessible by software that does not support\n\t"
4090 4092 "the features. See zpool-features(5) for details.\n"));
4091 4093 break;
4092 4094
4093 4095 case ZPOOL_STATUS_UNSUP_FEAT_READ:
4094 4096 (void) printf(gettext("status: The pool cannot be accessed on "
4095 4097 "this system because it uses the\n\tfollowing feature(s) "
4096 4098 "not supported on this system:\n"));
4097 4099 zpool_print_unsup_feat(config);
4098 4100 (void) printf("\n");
4099 4101 (void) printf(gettext("action: Access the pool from a system "
4100 4102 "that supports the required feature(s),\n\tor restore the "
4101 4103 "pool from backup.\n"));
4102 4104 break;
4103 4105
4104 4106 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
4105 4107 (void) printf(gettext("status: The pool can only be accessed "
4106 4108 "in read-only mode on this system. It\n\tcannot be "
4107 4109 "accessed in read-write mode because it uses the "
4108 4110 "following\n\tfeature(s) not supported on this system:\n"));
4109 4111 zpool_print_unsup_feat(config);
4110 4112 (void) printf("\n");
4111 4113 (void) printf(gettext("action: The pool cannot be accessed in "
4112 4114 "read-write mode. Import the pool with\n"
4113 4115 "\t\"-o readonly=on\", access the pool from a system that "
4114 4116 "supports the\n\trequired feature(s), or restore the "
4115 4117 "pool from backup.\n"));
4116 4118 break;
4117 4119
4118 4120 case ZPOOL_STATUS_FAULTED_DEV_R:
4119 4121 (void) printf(gettext("status: One or more devices are "
4120 4122 "faulted in response to persistent errors.\n\tSufficient "
4121 4123 "replicas exist for the pool to continue functioning "
4122 4124 "in a\n\tdegraded state.\n"));
4123 4125 (void) printf(gettext("action: Replace the faulted device, "
4124 4126 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
4125 4127 break;
4126 4128
4127 4129 case ZPOOL_STATUS_FAULTED_DEV_NR:
4128 4130 (void) printf(gettext("status: One or more devices are "
4129 4131 "faulted in response to persistent errors. There are "
4130 4132 "insufficient replicas for the pool to\n\tcontinue "
4131 4133 "functioning.\n"));
4132 4134 (void) printf(gettext("action: Destroy and re-create the pool "
4133 4135 "from a backup source. Manually marking the device\n"
4134 4136 "\trepaired using 'zpool clear' may allow some data "
4135 4137 "to be recovered.\n"));
4136 4138 break;
4137 4139
4138 4140 case ZPOOL_STATUS_IO_FAILURE_WAIT:
4139 4141 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
4140 4142 (void) printf(gettext("status: One or more devices are "
4141 4143 "faulted in response to IO failures.\n"));
4142 4144 (void) printf(gettext("action: Make sure the affected devices "
4143 4145 "are connected, then run 'zpool clear'.\n"));
4144 4146 break;
4145 4147
4146 4148 case ZPOOL_STATUS_BAD_LOG:
4147 4149 (void) printf(gettext("status: An intent log record "
4148 4150 "could not be read.\n"
4149 4151 "\tWaiting for adminstrator intervention to fix the "
4150 4152 "faulted pool.\n"));
4151 4153 (void) printf(gettext("action: Either restore the affected "
4152 4154 "device(s) and run 'zpool online',\n"
4153 4155 "\tor ignore the intent log records by running "
4154 4156 "'zpool clear'.\n"));
4155 4157 break;
4156 4158
4157 4159 default:
4158 4160 /*
4159 4161 * The remaining errors can't actually be generated, yet.
4160 4162 */
4161 4163 assert(reason == ZPOOL_STATUS_OK);
4162 4164 }
4163 4165
4164 4166 if (msgid != NULL)
4165 4167 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
4166 4168 msgid);
4167 4169
4168 4170 if (config != NULL) {
4169 4171 int namewidth;
4170 4172 uint64_t nerr;
4171 4173 nvlist_t **spares, **l2cache;
4172 4174 uint_t nspares, nl2cache;
4173 4175 pool_scan_stat_t *ps = NULL;
4174 4176
4175 4177 (void) nvlist_lookup_uint64_array(nvroot,
4176 4178 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4177 4179 print_scan_status(ps);
4178 4180
4179 4181 namewidth = max_width(zhp, nvroot, 0, 0);
4180 4182 if (namewidth < 10)
4181 4183 namewidth = 10;
4182 4184
4183 4185 (void) printf(gettext("config:\n\n"));
4184 4186 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth,
4185 4187 "NAME", "STATE", "READ", "WRITE", "CKSUM");
4186 4188 print_status_config(zhp, zpool_get_name(zhp), nvroot,
4187 4189 namewidth, 0, B_FALSE);
4188 4190
4189 4191 if (num_logs(nvroot) > 0)
4190 4192 print_logs(zhp, nvroot, namewidth, B_TRUE);
4191 4193 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
4192 4194 &l2cache, &nl2cache) == 0)
4193 4195 print_l2cache(zhp, l2cache, nl2cache, namewidth);
4194 4196
4195 4197 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
4196 4198 &spares, &nspares) == 0)
4197 4199 print_spares(zhp, spares, nspares, namewidth);
4198 4200
4199 4201 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
4200 4202 &nerr) == 0) {
4201 4203 nvlist_t *nverrlist = NULL;
4202 4204
4203 4205 /*
4204 4206 * If the approximate error count is small, get a
4205 4207 * precise count by fetching the entire log and
4206 4208 * uniquifying the results.
4207 4209 */
4208 4210 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
4209 4211 zpool_get_errlog(zhp, &nverrlist) == 0) {
4210 4212 nvpair_t *elem;
4211 4213
4212 4214 elem = NULL;
4213 4215 nerr = 0;
4214 4216 while ((elem = nvlist_next_nvpair(nverrlist,
4215 4217 elem)) != NULL) {
4216 4218 nerr++;
4217 4219 }
4218 4220 }
4219 4221 nvlist_free(nverrlist);
4220 4222
4221 4223 (void) printf("\n");
4222 4224
4223 4225 if (nerr == 0)
4224 4226 (void) printf(gettext("errors: No known data "
4225 4227 "errors\n"));
4226 4228 else if (!cbp->cb_verbose)
4227 4229 (void) printf(gettext("errors: %llu data "
4228 4230 "errors, use '-v' for a list\n"),
4229 4231 (u_longlong_t)nerr);
4230 4232 else
4231 4233 print_error_log(zhp);
4232 4234 }
4233 4235
4234 4236 if (cbp->cb_dedup_stats)
4235 4237 print_dedup_stats(config);
4236 4238 } else {
4237 4239 (void) printf(gettext("config: The configuration cannot be "
4238 4240 "determined.\n"));
4239 4241 }
4240 4242
4241 4243 return (0);
4242 4244 }
4243 4245
4244 4246 /*
4245 4247 * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
4246 4248 *
4247 4249 * -v Display complete error logs
4248 4250 * -x Display only pools with potential problems
4249 4251 * -D Display dedup status (undocumented)
4250 4252 * -T Display a timestamp in date(1) or Unix format
4251 4253 *
4252 4254 * Describes the health status of all pools or some subset.
4253 4255 */
4254 4256 int
4255 4257 zpool_do_status(int argc, char **argv)
4256 4258 {
4257 4259 int c;
4258 4260 int ret;
4259 4261 unsigned long interval = 0, count = 0;
4260 4262 status_cbdata_t cb = { 0 };
4261 4263
4262 4264 /* check options */
4263 4265 while ((c = getopt(argc, argv, "vxDT:")) != -1) {
4264 4266 switch (c) {
4265 4267 case 'v':
4266 4268 cb.cb_verbose = B_TRUE;
4267 4269 break;
4268 4270 case 'x':
4269 4271 cb.cb_explain = B_TRUE;
4270 4272 break;
4271 4273 case 'D':
4272 4274 cb.cb_dedup_stats = B_TRUE;
4273 4275 break;
4274 4276 case 'T':
4275 4277 get_timestamp_arg(*optarg);
4276 4278 break;
4277 4279 case '?':
4278 4280 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4279 4281 optopt);
4280 4282 usage(B_FALSE);
4281 4283 }
4282 4284 }
4283 4285
4284 4286 argc -= optind;
4285 4287 argv += optind;
4286 4288
4287 4289 get_interval_count(&argc, argv, &interval, &count);
4288 4290
4289 4291 if (argc == 0)
4290 4292 cb.cb_allpools = B_TRUE;
4291 4293
4292 4294 cb.cb_first = B_TRUE;
4293 4295
4294 4296 for (;;) {
4295 4297 if (timestamp_fmt != NODATE)
4296 4298 print_timestamp(timestamp_fmt);
4297 4299
4298 4300 ret = for_each_pool(argc, argv, B_TRUE, NULL,
4299 4301 status_callback, &cb);
4300 4302
4301 4303 if (argc == 0 && cb.cb_count == 0)
4302 4304 (void) printf(gettext("no pools available\n"));
4303 4305 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
4304 4306 (void) printf(gettext("all pools are healthy\n"));
4305 4307
4306 4308 if (ret != 0)
4307 4309 return (ret);
4308 4310
4309 4311 if (interval == 0)
4310 4312 break;
4311 4313
4312 4314 if (count != 0 && --count == 0)
4313 4315 break;
4314 4316
4315 4317 (void) sleep(interval);
4316 4318 }
4317 4319
4318 4320 return (0);
4319 4321 }
4320 4322
4321 4323 typedef struct upgrade_cbdata {
4322 4324 int cb_first;
4323 4325 int cb_argc;
4324 4326 uint64_t cb_version;
4325 4327 char **cb_argv;
4326 4328 } upgrade_cbdata_t;
4327 4329
4328 4330 static int
4329 4331 upgrade_version(zpool_handle_t *zhp, uint64_t version)
4330 4332 {
4331 4333 int ret;
4332 4334 nvlist_t *config;
4333 4335 uint64_t oldversion;
4334 4336
4335 4337 config = zpool_get_config(zhp, NULL);
4336 4338 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4337 4339 &oldversion) == 0);
4338 4340
4339 4341 assert(SPA_VERSION_IS_SUPPORTED(oldversion));
4340 4342 assert(oldversion < version);
4341 4343
4342 4344 ret = zpool_upgrade(zhp, version);
4343 4345 if (ret != 0)
4344 4346 return (ret);
4345 4347
4346 4348 if (version >= SPA_VERSION_FEATURES) {
4347 4349 (void) printf(gettext("Successfully upgraded "
4348 4350 "'%s' from version %llu to feature flags.\n"),
4349 4351 zpool_get_name(zhp), oldversion);
4350 4352 } else {
4351 4353 (void) printf(gettext("Successfully upgraded "
4352 4354 "'%s' from version %llu to version %llu.\n"),
4353 4355 zpool_get_name(zhp), oldversion, version);
4354 4356 }
4355 4357
4356 4358 return (0);
4357 4359 }
4358 4360
4359 4361 static int
4360 4362 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
4361 4363 {
4362 4364 int i, ret, count;
4363 4365 boolean_t firstff = B_TRUE;
4364 4366 nvlist_t *enabled = zpool_get_features(zhp);
4365 4367
4366 4368 count = 0;
4367 4369 for (i = 0; i < SPA_FEATURES; i++) {
4368 4370 const char *fname = spa_feature_table[i].fi_uname;
4369 4371 const char *fguid = spa_feature_table[i].fi_guid;
4370 4372 if (!nvlist_exists(enabled, fguid)) {
4371 4373 char *propname;
4372 4374 verify(-1 != asprintf(&propname, "feature@%s", fname));
4373 4375 ret = zpool_set_prop(zhp, propname,
4374 4376 ZFS_FEATURE_ENABLED);
4375 4377 if (ret != 0) {
4376 4378 free(propname);
4377 4379 return (ret);
4378 4380 }
4379 4381 count++;
4380 4382
4381 4383 if (firstff) {
4382 4384 (void) printf(gettext("Enabled the "
4383 4385 "following features on '%s':\n"),
4384 4386 zpool_get_name(zhp));
4385 4387 firstff = B_FALSE;
4386 4388 }
4387 4389 (void) printf(gettext(" %s\n"), fname);
4388 4390 free(propname);
4389 4391 }
4390 4392 }
4391 4393
4392 4394 if (countp != NULL)
4393 4395 *countp = count;
4394 4396 return (0);
4395 4397 }
4396 4398
4397 4399 static int
4398 4400 upgrade_cb(zpool_handle_t *zhp, void *arg)
4399 4401 {
4400 4402 upgrade_cbdata_t *cbp = arg;
4401 4403 nvlist_t *config;
4402 4404 uint64_t version;
4403 4405 boolean_t printnl = B_FALSE;
4404 4406 int ret;
4405 4407
4406 4408 config = zpool_get_config(zhp, NULL);
4407 4409 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4408 4410 &version) == 0);
4409 4411
4410 4412 assert(SPA_VERSION_IS_SUPPORTED(version));
4411 4413
4412 4414 if (version < cbp->cb_version) {
4413 4415 cbp->cb_first = B_FALSE;
4414 4416 ret = upgrade_version(zhp, cbp->cb_version);
4415 4417 if (ret != 0)
4416 4418 return (ret);
4417 4419 printnl = B_TRUE;
4418 4420
4419 4421 /*
4420 4422 * If they did "zpool upgrade -a", then we could
4421 4423 * be doing ioctls to different pools. We need
4422 4424 * to log this history once to each pool, and bypass
4423 4425 * the normal history logging that happens in main().
4424 4426 */
4425 4427 (void) zpool_log_history(g_zfs, history_str);
4426 4428 log_history = B_FALSE;
4427 4429 }
4428 4430
4429 4431 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
4430 4432 int count;
4431 4433 ret = upgrade_enable_all(zhp, &count);
4432 4434 if (ret != 0)
4433 4435 return (ret);
4434 4436
4435 4437 if (count > 0) {
4436 4438 cbp->cb_first = B_FALSE;
4437 4439 printnl = B_TRUE;
4438 4440 }
4439 4441 }
4440 4442
4441 4443 if (printnl) {
4442 4444 (void) printf(gettext("\n"));
4443 4445 }
4444 4446
4445 4447 return (0);
4446 4448 }
4447 4449
4448 4450 static int
4449 4451 upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
4450 4452 {
4451 4453 upgrade_cbdata_t *cbp = arg;
4452 4454 nvlist_t *config;
4453 4455 uint64_t version;
4454 4456
4455 4457 config = zpool_get_config(zhp, NULL);
4456 4458 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4457 4459 &version) == 0);
4458 4460
4459 4461 assert(SPA_VERSION_IS_SUPPORTED(version));
4460 4462
4461 4463 if (version < SPA_VERSION_FEATURES) {
4462 4464 if (cbp->cb_first) {
4463 4465 (void) printf(gettext("The following pools are "
4464 4466 "formatted with legacy version numbers and can\n"
4465 4467 "be upgraded to use feature flags. After "
4466 4468 "being upgraded, these pools\nwill no "
4467 4469 "longer be accessible by software that does not "
4468 4470 "support feature\nflags.\n\n"));
4469 4471 (void) printf(gettext("VER POOL\n"));
4470 4472 (void) printf(gettext("--- ------------\n"));
4471 4473 cbp->cb_first = B_FALSE;
4472 4474 }
4473 4475
4474 4476 (void) printf("%2llu %s\n", (u_longlong_t)version,
4475 4477 zpool_get_name(zhp));
4476 4478 }
4477 4479
4478 4480 return (0);
4479 4481 }
4480 4482
4481 4483 static int
4482 4484 upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
4483 4485 {
4484 4486 upgrade_cbdata_t *cbp = arg;
4485 4487 nvlist_t *config;
4486 4488 uint64_t version;
4487 4489
4488 4490 config = zpool_get_config(zhp, NULL);
4489 4491 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4490 4492 &version) == 0);
4491 4493
4492 4494 if (version >= SPA_VERSION_FEATURES) {
4493 4495 int i;
4494 4496 boolean_t poolfirst = B_TRUE;
4495 4497 nvlist_t *enabled = zpool_get_features(zhp);
4496 4498
4497 4499 for (i = 0; i < SPA_FEATURES; i++) {
4498 4500 const char *fguid = spa_feature_table[i].fi_guid;
4499 4501 const char *fname = spa_feature_table[i].fi_uname;
4500 4502 if (!nvlist_exists(enabled, fguid)) {
4501 4503 if (cbp->cb_first) {
4502 4504 (void) printf(gettext("\nSome "
4503 4505 "supported features are not "
4504 4506 "enabled on the following pools. "
4505 4507 "Once a\nfeature is enabled the "
4506 4508 "pool may become incompatible with "
4507 4509 "software\nthat does not support "
4508 4510 "the feature. See "
4509 4511 "zpool-features(5) for "
4510 4512 "details.\n\n"));
4511 4513 (void) printf(gettext("POOL "
4512 4514 "FEATURE\n"));
4513 4515 (void) printf(gettext("------"
4514 4516 "---------\n"));
4515 4517 cbp->cb_first = B_FALSE;
4516 4518 }
4517 4519
4518 4520 if (poolfirst) {
4519 4521 (void) printf(gettext("%s\n"),
4520 4522 zpool_get_name(zhp));
4521 4523 poolfirst = B_FALSE;
4522 4524 }
4523 4525
4524 4526 (void) printf(gettext(" %s\n"), fname);
4525 4527 }
4526 4528 }
4527 4529 }
4528 4530
4529 4531 return (0);
4530 4532 }
4531 4533
4532 4534 /* ARGSUSED */
4533 4535 static int
4534 4536 upgrade_one(zpool_handle_t *zhp, void *data)
4535 4537 {
4536 4538 boolean_t printnl = B_FALSE;
4537 4539 upgrade_cbdata_t *cbp = data;
4538 4540 uint64_t cur_version;
4539 4541 int ret;
4540 4542
4541 4543 if (strcmp("log", zpool_get_name(zhp)) == 0) {
4542 4544 (void) printf(gettext("'log' is now a reserved word\n"
4543 4545 "Pool 'log' must be renamed using export and import"
4544 4546 " to upgrade.\n"));
4545 4547 return (1);
4546 4548 }
4547 4549
4548 4550 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
4549 4551 if (cur_version > cbp->cb_version) {
4550 4552 (void) printf(gettext("Pool '%s' is already formatted "
4551 4553 "using more current version '%llu'.\n\n"),
4552 4554 zpool_get_name(zhp), cur_version);
4553 4555 return (0);
4554 4556 }
4555 4557
4556 4558 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
4557 4559 (void) printf(gettext("Pool '%s' is already formatted "
4558 4560 "using version %llu.\n\n"), zpool_get_name(zhp),
4559 4561 cbp->cb_version);
4560 4562 return (0);
4561 4563 }
4562 4564
4563 4565 if (cur_version != cbp->cb_version) {
4564 4566 printnl = B_TRUE;
4565 4567 ret = upgrade_version(zhp, cbp->cb_version);
4566 4568 if (ret != 0)
4567 4569 return (ret);
4568 4570 }
4569 4571
4570 4572 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
4571 4573 int count = 0;
4572 4574 ret = upgrade_enable_all(zhp, &count);
4573 4575 if (ret != 0)
4574 4576 return (ret);
4575 4577
4576 4578 if (count != 0) {
4577 4579 printnl = B_TRUE;
4578 4580 } else if (cur_version == SPA_VERSION) {
4579 4581 (void) printf(gettext("Pool '%s' already has all "
4580 4582 "supported features enabled.\n"),
4581 4583 zpool_get_name(zhp));
4582 4584 }
4583 4585 }
4584 4586
4585 4587 if (printnl) {
4586 4588 (void) printf(gettext("\n"));
4587 4589 }
4588 4590
4589 4591 return (0);
4590 4592 }
4591 4593
4592 4594 /*
4593 4595 * zpool upgrade
4594 4596 * zpool upgrade -v
4595 4597 * zpool upgrade [-V version] <-a | pool ...>
4596 4598 *
4597 4599 * With no arguments, display downrev'd ZFS pool available for upgrade.
4598 4600 * Individual pools can be upgraded by specifying the pool, and '-a' will
4599 4601 * upgrade all pools.
4600 4602 */
4601 4603 int
4602 4604 zpool_do_upgrade(int argc, char **argv)
4603 4605 {
4604 4606 int c;
4605 4607 upgrade_cbdata_t cb = { 0 };
4606 4608 int ret = 0;
4607 4609 boolean_t showversions = B_FALSE;
4608 4610 boolean_t upgradeall = B_FALSE;
4609 4611 char *end;
4610 4612
4611 4613
4612 4614 /* check options */
4613 4615 while ((c = getopt(argc, argv, ":avV:")) != -1) {
4614 4616 switch (c) {
4615 4617 case 'a':
4616 4618 upgradeall = B_TRUE;
4617 4619 break;
4618 4620 case 'v':
4619 4621 showversions = B_TRUE;
4620 4622 break;
4621 4623 case 'V':
4622 4624 cb.cb_version = strtoll(optarg, &end, 10);
4623 4625 if (*end != '\0' ||
4624 4626 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
4625 4627 (void) fprintf(stderr,
4626 4628 gettext("invalid version '%s'\n"), optarg);
4627 4629 usage(B_FALSE);
4628 4630 }
4629 4631 break;
4630 4632 case ':':
4631 4633 (void) fprintf(stderr, gettext("missing argument for "
4632 4634 "'%c' option\n"), optopt);
4633 4635 usage(B_FALSE);
4634 4636 break;
4635 4637 case '?':
4636 4638 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4637 4639 optopt);
4638 4640 usage(B_FALSE);
4639 4641 }
4640 4642 }
4641 4643
4642 4644 cb.cb_argc = argc;
4643 4645 cb.cb_argv = argv;
4644 4646 argc -= optind;
4645 4647 argv += optind;
4646 4648
4647 4649 if (cb.cb_version == 0) {
4648 4650 cb.cb_version = SPA_VERSION;
4649 4651 } else if (!upgradeall && argc == 0) {
4650 4652 (void) fprintf(stderr, gettext("-V option is "
4651 4653 "incompatible with other arguments\n"));
4652 4654 usage(B_FALSE);
4653 4655 }
4654 4656
4655 4657 if (showversions) {
4656 4658 if (upgradeall || argc != 0) {
4657 4659 (void) fprintf(stderr, gettext("-v option is "
4658 4660 "incompatible with other arguments\n"));
4659 4661 usage(B_FALSE);
4660 4662 }
4661 4663 } else if (upgradeall) {
4662 4664 if (argc != 0) {
4663 4665 (void) fprintf(stderr, gettext("-a option should not "
4664 4666 "be used along with a pool name\n"));
4665 4667 usage(B_FALSE);
4666 4668 }
4667 4669 }
4668 4670
4669 4671 (void) printf(gettext("This system supports ZFS pool feature "
4670 4672 "flags.\n\n"));
4671 4673 if (showversions) {
4672 4674 int i;
4673 4675
4674 4676 (void) printf(gettext("The following features are "
4675 4677 "supported:\n\n"));
4676 4678 (void) printf(gettext("FEAT DESCRIPTION\n"));
4677 4679 (void) printf("----------------------------------------------"
4678 4680 "---------------\n");
4679 4681 for (i = 0; i < SPA_FEATURES; i++) {
4680 4682 zfeature_info_t *fi = &spa_feature_table[i];
4681 4683 const char *ro = fi->fi_can_readonly ?
4682 4684 " (read-only compatible)" : "";
4683 4685
4684 4686 (void) printf("%-37s%s\n", fi->fi_uname, ro);
4685 4687 (void) printf(" %s\n", fi->fi_desc);
4686 4688 }
4687 4689 (void) printf("\n");
4688 4690
4689 4691 (void) printf(gettext("The following legacy versions are also "
4690 4692 "supported:\n\n"));
4691 4693 (void) printf(gettext("VER DESCRIPTION\n"));
4692 4694 (void) printf("--- -----------------------------------------"
4693 4695 "---------------\n");
4694 4696 (void) printf(gettext(" 1 Initial ZFS version\n"));
4695 4697 (void) printf(gettext(" 2 Ditto blocks "
4696 4698 "(replicated metadata)\n"));
4697 4699 (void) printf(gettext(" 3 Hot spares and double parity "
4698 4700 "RAID-Z\n"));
4699 4701 (void) printf(gettext(" 4 zpool history\n"));
4700 4702 (void) printf(gettext(" 5 Compression using the gzip "
4701 4703 "algorithm\n"));
4702 4704 (void) printf(gettext(" 6 bootfs pool property\n"));
4703 4705 (void) printf(gettext(" 7 Separate intent log devices\n"));
4704 4706 (void) printf(gettext(" 8 Delegated administration\n"));
4705 4707 (void) printf(gettext(" 9 refquota and refreservation "
4706 4708 "properties\n"));
4707 4709 (void) printf(gettext(" 10 Cache devices\n"));
4708 4710 (void) printf(gettext(" 11 Improved scrub performance\n"));
4709 4711 (void) printf(gettext(" 12 Snapshot properties\n"));
4710 4712 (void) printf(gettext(" 13 snapused property\n"));
4711 4713 (void) printf(gettext(" 14 passthrough-x aclinherit\n"));
4712 4714 (void) printf(gettext(" 15 user/group space accounting\n"));
4713 4715 (void) printf(gettext(" 16 stmf property support\n"));
4714 4716 (void) printf(gettext(" 17 Triple-parity RAID-Z\n"));
4715 4717 (void) printf(gettext(" 18 Snapshot user holds\n"));
4716 4718 (void) printf(gettext(" 19 Log device removal\n"));
4717 4719 (void) printf(gettext(" 20 Compression using zle "
4718 4720 "(zero-length encoding)\n"));
4719 4721 (void) printf(gettext(" 21 Deduplication\n"));
4720 4722 (void) printf(gettext(" 22 Received properties\n"));
4721 4723 (void) printf(gettext(" 23 Slim ZIL\n"));
4722 4724 (void) printf(gettext(" 24 System attributes\n"));
4723 4725 (void) printf(gettext(" 25 Improved scrub stats\n"));
4724 4726 (void) printf(gettext(" 26 Improved snapshot deletion "
4725 4727 "performance\n"));
4726 4728 (void) printf(gettext(" 27 Improved snapshot creation "
4727 4729 "performance\n"));
4728 4730 (void) printf(gettext(" 28 Multiple vdev replacements\n"));
4729 4731 (void) printf(gettext("\nFor more information on a particular "
4730 4732 "version, including supported releases,\n"));
4731 4733 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
4732 4734 } else if (argc == 0 && upgradeall) {
4733 4735 cb.cb_first = B_TRUE;
4734 4736 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
4735 4737 if (ret == 0 && cb.cb_first) {
4736 4738 if (cb.cb_version == SPA_VERSION) {
4737 4739 (void) printf(gettext("All pools are already "
4738 4740 "formatted using feature flags.\n\n"));
4739 4741 (void) printf(gettext("Every feature flags "
4740 4742 "pool already has all supported features "
4741 4743 "enabled.\n"));
4742 4744 } else {
4743 4745 (void) printf(gettext("All pools are already "
4744 4746 "formatted with version %llu or higher.\n"),
4745 4747 cb.cb_version);
4746 4748 }
4747 4749 }
4748 4750 } else if (argc == 0) {
4749 4751 cb.cb_first = B_TRUE;
4750 4752 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
4751 4753 assert(ret == 0);
4752 4754
4753 4755 if (cb.cb_first) {
4754 4756 (void) printf(gettext("All pools are formatted "
4755 4757 "using feature flags.\n\n"));
4756 4758 } else {
4757 4759 (void) printf(gettext("\nUse 'zpool upgrade -v' "
4758 4760 "for a list of available legacy versions.\n"));
4759 4761 }
4760 4762
4761 4763 cb.cb_first = B_TRUE;
4762 4764 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
4763 4765 assert(ret == 0);
4764 4766
4765 4767 if (cb.cb_first) {
4766 4768 (void) printf(gettext("Every feature flags pool has "
4767 4769 "all supported features enabled.\n"));
4768 4770 } else {
4769 4771 (void) printf(gettext("\n"));
4770 4772 }
4771 4773 } else {
4772 4774 ret = for_each_pool(argc, argv, B_FALSE, NULL,
4773 4775 upgrade_one, &cb);
4774 4776 }
4775 4777
4776 4778 return (ret);
4777 4779 }
4778 4780
4779 4781 typedef struct hist_cbdata {
4780 4782 boolean_t first;
4781 4783 boolean_t longfmt;
4782 4784 boolean_t internal;
4783 4785 } hist_cbdata_t;
4784 4786
4785 4787 /*
4786 4788 * Print out the command history for a specific pool.
4787 4789 */
4788 4790 static int
4789 4791 get_history_one(zpool_handle_t *zhp, void *data)
4790 4792 {
4791 4793 nvlist_t *nvhis;
4792 4794 nvlist_t **records;
4793 4795 uint_t numrecords;
4794 4796 int ret, i;
4795 4797 hist_cbdata_t *cb = (hist_cbdata_t *)data;
4796 4798
4797 4799 cb->first = B_FALSE;
4798 4800
4799 4801 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
4800 4802
4801 4803 if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
4802 4804 return (ret);
4803 4805
4804 4806 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
4805 4807 &records, &numrecords) == 0);
4806 4808 for (i = 0; i < numrecords; i++) {
4807 4809 nvlist_t *rec = records[i];
4808 4810 char tbuf[30] = "";
4809 4811
4810 4812 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
4811 4813 time_t tsec;
4812 4814 struct tm t;
4813 4815
4814 4816 tsec = fnvlist_lookup_uint64(records[i],
4815 4817 ZPOOL_HIST_TIME);
4816 4818 (void) localtime_r(&tsec, &t);
4817 4819 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
4818 4820 }
4819 4821
4820 4822 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
4821 4823 (void) printf("%s %s", tbuf,
4822 4824 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
4823 4825 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
4824 4826 int ievent =
4825 4827 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
4826 4828 if (!cb->internal)
4827 4829 continue;
4828 4830 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
4829 4831 (void) printf("%s unrecognized record:\n",
4830 4832 tbuf);
4831 4833 dump_nvlist(rec, 4);
4832 4834 continue;
4833 4835 }
4834 4836 (void) printf("%s [internal %s txg:%lld] %s", tbuf,
4835 4837 zfs_history_event_names[ievent],
4836 4838 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
4837 4839 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
4838 4840 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
4839 4841 if (!cb->internal)
4840 4842 continue;
4841 4843 (void) printf("%s [txg:%lld] %s", tbuf,
4842 4844 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
4843 4845 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
4844 4846 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
4845 4847 (void) printf(" %s (%llu)",
4846 4848 fnvlist_lookup_string(rec,
4847 4849 ZPOOL_HIST_DSNAME),
4848 4850 fnvlist_lookup_uint64(rec,
4849 4851 ZPOOL_HIST_DSID));
4850 4852 }
4851 4853 (void) printf(" %s", fnvlist_lookup_string(rec,
4852 4854 ZPOOL_HIST_INT_STR));
4853 4855 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
4854 4856 if (!cb->internal)
4855 4857 continue;
4856 4858 (void) printf("%s ioctl %s\n", tbuf,
4857 4859 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
4858 4860 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
4859 4861 (void) printf(" input:\n");
4860 4862 dump_nvlist(fnvlist_lookup_nvlist(rec,
4861 4863 ZPOOL_HIST_INPUT_NVL), 8);
4862 4864 }
4863 4865 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
4864 4866 (void) printf(" output:\n");
4865 4867 dump_nvlist(fnvlist_lookup_nvlist(rec,
4866 4868 ZPOOL_HIST_OUTPUT_NVL), 8);
4867 4869 }
4868 4870 } else {
4869 4871 if (!cb->internal)
4870 4872 continue;
4871 4873 (void) printf("%s unrecognized record:\n", tbuf);
4872 4874 dump_nvlist(rec, 4);
4873 4875 }
4874 4876
4875 4877 if (!cb->longfmt) {
4876 4878 (void) printf("\n");
4877 4879 continue;
4878 4880 }
4879 4881 (void) printf(" [");
4880 4882 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
4881 4883 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
4882 4884 struct passwd *pwd = getpwuid(who);
4883 4885 (void) printf("user %d ", (int)who);
4884 4886 if (pwd != NULL)
4885 4887 (void) printf("(%s) ", pwd->pw_name);
4886 4888 }
4887 4889 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
4888 4890 (void) printf("on %s",
4889 4891 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
4890 4892 }
4891 4893 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
4892 4894 (void) printf(":%s",
4893 4895 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
4894 4896 }
4895 4897 (void) printf("]");
4896 4898 (void) printf("\n");
4897 4899 }
4898 4900 (void) printf("\n");
4899 4901 nvlist_free(nvhis);
4900 4902
4901 4903 return (ret);
4902 4904 }
4903 4905
4904 4906 /*
4905 4907 * zpool history <pool>
4906 4908 *
4907 4909 * Displays the history of commands that modified pools.
4908 4910 */
4909 4911 int
4910 4912 zpool_do_history(int argc, char **argv)
4911 4913 {
4912 4914 hist_cbdata_t cbdata = { 0 };
4913 4915 int ret;
4914 4916 int c;
4915 4917
4916 4918 cbdata.first = B_TRUE;
4917 4919 /* check options */
4918 4920 while ((c = getopt(argc, argv, "li")) != -1) {
4919 4921 switch (c) {
4920 4922 case 'l':
4921 4923 cbdata.longfmt = B_TRUE;
4922 4924 break;
4923 4925 case 'i':
4924 4926 cbdata.internal = B_TRUE;
4925 4927 break;
4926 4928 case '?':
4927 4929 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4928 4930 optopt);
4929 4931 usage(B_FALSE);
4930 4932 }
4931 4933 }
4932 4934 argc -= optind;
4933 4935 argv += optind;
4934 4936
4935 4937 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
4936 4938 &cbdata);
4937 4939
4938 4940 if (argc == 0 && cbdata.first == B_TRUE) {
4939 4941 (void) printf(gettext("no pools available\n"));
4940 4942 return (0);
4941 4943 }
4942 4944
4943 4945 return (ret);
4944 4946 }
4945 4947
4946 4948 static int
4947 4949 get_callback(zpool_handle_t *zhp, void *data)
4948 4950 {
4949 4951 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
4950 4952 char value[MAXNAMELEN];
4951 4953 zprop_source_t srctype;
4952 4954 zprop_list_t *pl;
4953 4955
4954 4956 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
4955 4957
4956 4958 /*
4957 4959 * Skip the special fake placeholder. This will also skip
4958 4960 * over the name property when 'all' is specified.
4959 4961 */
4960 4962 if (pl->pl_prop == ZPOOL_PROP_NAME &&
4961 4963 pl == cbp->cb_proplist)
4962 4964 continue;
4963 4965
4964 4966 if (pl->pl_prop == ZPROP_INVAL &&
4965 4967 (zpool_prop_feature(pl->pl_user_prop) ||
4966 4968 zpool_prop_unsupported(pl->pl_user_prop))) {
4967 4969 srctype = ZPROP_SRC_LOCAL;
4968 4970
4969 4971 if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
4970 4972 value, sizeof (value)) == 0) {
4971 4973 zprop_print_one_property(zpool_get_name(zhp),
4972 4974 cbp, pl->pl_user_prop, value, srctype,
4973 4975 NULL, NULL);
4974 4976 }
4975 4977 } else {
4976 4978 if (zpool_get_prop(zhp, pl->pl_prop, value,
4977 4979 sizeof (value), &srctype) != 0)
4978 4980 continue;
4979 4981
4980 4982 zprop_print_one_property(zpool_get_name(zhp), cbp,
4981 4983 zpool_prop_to_name(pl->pl_prop), value, srctype,
4982 4984 NULL, NULL);
4983 4985 }
4984 4986 }
4985 4987 return (0);
4986 4988 }
4987 4989
4988 4990 int
4989 4991 zpool_do_get(int argc, char **argv)
4990 4992 {
4991 4993 zprop_get_cbdata_t cb = { 0 };
4992 4994 zprop_list_t fake_name = { 0 };
4993 4995 int ret;
4994 4996
4995 4997 if (argc < 2) {
4996 4998 (void) fprintf(stderr, gettext("missing property "
4997 4999 "argument\n"));
4998 5000 usage(B_FALSE);
4999 5001 }
5000 5002
5001 5003 cb.cb_first = B_TRUE;
5002 5004 cb.cb_sources = ZPROP_SRC_ALL;
5003 5005 cb.cb_columns[0] = GET_COL_NAME;
5004 5006 cb.cb_columns[1] = GET_COL_PROPERTY;
5005 5007 cb.cb_columns[2] = GET_COL_VALUE;
5006 5008 cb.cb_columns[3] = GET_COL_SOURCE;
5007 5009 cb.cb_type = ZFS_TYPE_POOL;
5008 5010
5009 5011 if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist,
5010 5012 ZFS_TYPE_POOL) != 0)
5011 5013 usage(B_FALSE);
5012 5014
5013 5015 if (cb.cb_proplist != NULL) {
5014 5016 fake_name.pl_prop = ZPOOL_PROP_NAME;
5015 5017 fake_name.pl_width = strlen(gettext("NAME"));
5016 5018 fake_name.pl_next = cb.cb_proplist;
5017 5019 cb.cb_proplist = &fake_name;
5018 5020 }
5019 5021
5020 5022 ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist,
5021 5023 get_callback, &cb);
5022 5024
5023 5025 if (cb.cb_proplist == &fake_name)
5024 5026 zprop_free_list(fake_name.pl_next);
5025 5027 else
5026 5028 zprop_free_list(cb.cb_proplist);
5027 5029
5028 5030 return (ret);
5029 5031 }
5030 5032
5031 5033 typedef struct set_cbdata {
5032 5034 char *cb_propname;
5033 5035 char *cb_value;
5034 5036 boolean_t cb_any_successful;
5035 5037 } set_cbdata_t;
5036 5038
5037 5039 int
5038 5040 set_callback(zpool_handle_t *zhp, void *data)
5039 5041 {
5040 5042 int error;
5041 5043 set_cbdata_t *cb = (set_cbdata_t *)data;
5042 5044
5043 5045 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
5044 5046
5045 5047 if (!error)
5046 5048 cb->cb_any_successful = B_TRUE;
5047 5049
5048 5050 return (error);
5049 5051 }
5050 5052
5051 5053 int
5052 5054 zpool_do_set(int argc, char **argv)
5053 5055 {
5054 5056 set_cbdata_t cb = { 0 };
5055 5057 int error;
5056 5058
5057 5059 if (argc > 1 && argv[1][0] == '-') {
5058 5060 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5059 5061 argv[1][1]);
5060 5062 usage(B_FALSE);
5061 5063 }
5062 5064
5063 5065 if (argc < 2) {
5064 5066 (void) fprintf(stderr, gettext("missing property=value "
5065 5067 "argument\n"));
5066 5068 usage(B_FALSE);
5067 5069 }
5068 5070
5069 5071 if (argc < 3) {
5070 5072 (void) fprintf(stderr, gettext("missing pool name\n"));
5071 5073 usage(B_FALSE);
5072 5074 }
5073 5075
5074 5076 if (argc > 3) {
5075 5077 (void) fprintf(stderr, gettext("too many pool names\n"));
5076 5078 usage(B_FALSE);
5077 5079 }
5078 5080
5079 5081 cb.cb_propname = argv[1];
5080 5082 cb.cb_value = strchr(cb.cb_propname, '=');
5081 5083 if (cb.cb_value == NULL) {
5082 5084 (void) fprintf(stderr, gettext("missing value in "
5083 5085 "property=value argument\n"));
5084 5086 usage(B_FALSE);
5085 5087 }
5086 5088
5087 5089 *(cb.cb_value) = '\0';
5088 5090 cb.cb_value++;
5089 5091
5090 5092 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
5091 5093 set_callback, &cb);
5092 5094
5093 5095 return (error);
5094 5096 }
5095 5097
5096 5098 static int
5097 5099 find_command_idx(char *command, int *idx)
5098 5100 {
5099 5101 int i;
5100 5102
5101 5103 for (i = 0; i < NCOMMAND; i++) {
5102 5104 if (command_table[i].name == NULL)
5103 5105 continue;
5104 5106
5105 5107 if (strcmp(command, command_table[i].name) == 0) {
5106 5108 *idx = i;
5107 5109 return (0);
5108 5110 }
5109 5111 }
5110 5112 return (1);
5111 5113 }
5112 5114
5113 5115 int
5114 5116 main(int argc, char **argv)
5115 5117 {
5116 5118 int ret;
5117 5119 int i;
5118 5120 char *cmdname;
5119 5121
5120 5122 (void) setlocale(LC_ALL, "");
5121 5123 (void) textdomain(TEXT_DOMAIN);
5122 5124
5123 5125 if ((g_zfs = libzfs_init()) == NULL) {
5124 5126 (void) fprintf(stderr, gettext("internal error: failed to "
5125 5127 "initialize ZFS library\n"));
5126 5128 return (1);
5127 5129 }
5128 5130
5129 5131 libzfs_print_on_error(g_zfs, B_TRUE);
5130 5132
5131 5133 opterr = 0;
5132 5134
5133 5135 /*
5134 5136 * Make sure the user has specified some command.
5135 5137 */
5136 5138 if (argc < 2) {
5137 5139 (void) fprintf(stderr, gettext("missing command\n"));
5138 5140 usage(B_FALSE);
5139 5141 }
5140 5142
5141 5143 cmdname = argv[1];
5142 5144
5143 5145 /*
5144 5146 * Special case '-?'
5145 5147 */
5146 5148 if (strcmp(cmdname, "-?") == 0)
5147 5149 usage(B_TRUE);
5148 5150
5149 5151 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
5150 5152
5151 5153 /*
5152 5154 * Run the appropriate command.
5153 5155 */
5154 5156 if (find_command_idx(cmdname, &i) == 0) {
5155 5157 current_command = &command_table[i];
5156 5158 ret = command_table[i].func(argc - 1, argv + 1);
5157 5159 } else if (strchr(cmdname, '=')) {
5158 5160 verify(find_command_idx("set", &i) == 0);
5159 5161 current_command = &command_table[i];
5160 5162 ret = command_table[i].func(argc, argv);
5161 5163 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
5162 5164 /*
5163 5165 * 'freeze' is a vile debugging abomination, so we treat
5164 5166 * it as such.
5165 5167 */
5166 5168 char buf[16384];
5167 5169 int fd = open(ZFS_DEV, O_RDWR);
5168 5170 (void) strcpy((void *)buf, argv[2]);
5169 5171 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
5170 5172 } else {
5171 5173 (void) fprintf(stderr, gettext("unrecognized "
5172 5174 "command '%s'\n"), cmdname);
5173 5175 usage(B_FALSE);
5174 5176 }
5175 5177
5176 5178 if (ret == 0 && log_history)
5177 5179 (void) zpool_log_history(g_zfs, history_str);
5178 5180
5179 5181 libzfs_fini(g_zfs);
5180 5182
5181 5183 /*
5182 5184 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
5183 5185 * for the purposes of running ::findleaks.
5184 5186 */
5185 5187 if (getenv("ZFS_ABORT") != NULL) {
5186 5188 (void) printf("dumping core by request\n");
5187 5189 abort();
5188 5190 }
5189 5191
5190 5192 return (ret);
5191 5193 }
↓ open down ↓ |
3189 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX