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