Print this page
| 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 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 #include <assert.h>
28 28 #include <ctype.h>
29 29 #include <dirent.h>
30 30 #include <errno.h>
31 31 #include <fcntl.h>
32 32 #include <libgen.h>
33 33 #include <libintl.h>
34 34 #include <libuutil.h>
35 35 #include <locale.h>
36 36 #include <stdio.h>
37 37 #include <stdlib.h>
38 38 #include <string.h>
39 39 #include <strings.h>
40 40 #include <unistd.h>
41 41 #include <priv.h>
42 42 #include <pwd.h>
43 43 #include <zone.h>
44 44 #include <sys/fs/zfs.h>
45 45
46 46 #include <sys/stat.h>
47 47
48 48 #include <libzfs.h>
49 49
50 50 #include "zpool_util.h"
51 51 #include "zfs_comutil.h"
52 52
53 53 static int zpool_do_create(int, char **);
54 54 static int zpool_do_destroy(int, char **);
55 55
56 56 static int zpool_do_add(int, char **);
57 57 static int zpool_do_remove(int, char **);
58 58
59 59 static int zpool_do_list(int, char **);
60 60 static int zpool_do_iostat(int, char **);
61 61 static int zpool_do_status(int, char **);
62 62
63 63 static int zpool_do_online(int, char **);
64 64 static int zpool_do_offline(int, char **);
65 65 static int zpool_do_clear(int, char **);
66 66
67 67 static int zpool_do_attach(int, char **);
68 68 static int zpool_do_detach(int, char **);
69 69 static int zpool_do_replace(int, char **);
70 70
71 71 static int zpool_do_scrub(int, char **);
72 72
|
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
73 73 static int zpool_do_import(int, char **);
74 74 static int zpool_do_export(int, char **);
75 75
76 76 static int zpool_do_upgrade(int, char **);
77 77
78 78 static int zpool_do_history(int, char **);
79 79
80 80 static int zpool_do_get(int, char **);
81 81 static int zpool_do_set(int, char **);
82 82
83 +static int zpool_do_key(int, char **);
84 +
83 85 /*
84 86 * These libumem hooks provide a reasonable set of defaults for the allocator's
85 87 * debugging facilities.
86 88 */
87 89
88 90 #ifdef DEBUG
89 91 const char *
90 92 _umem_debug_init(void)
91 93 {
92 94 return ("default,verbose"); /* $UMEM_DEBUG setting */
93 95 }
94 96
95 97 const char *
96 98 _umem_logging_init(void)
97 99 {
98 100 return ("fail,contents"); /* $UMEM_LOGGING setting */
99 101 }
100 102 #endif
101 103
102 104 typedef enum {
103 105 HELP_ADD,
104 106 HELP_ATTACH,
105 107 HELP_CLEAR,
106 108 HELP_CREATE,
107 109 HELP_DESTROY,
108 110 HELP_DETACH,
109 111 HELP_EXPORT,
110 112 HELP_HISTORY,
111 113 HELP_IMPORT,
|
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
112 114 HELP_IOSTAT,
113 115 HELP_LIST,
114 116 HELP_OFFLINE,
115 117 HELP_ONLINE,
116 118 HELP_REPLACE,
117 119 HELP_REMOVE,
118 120 HELP_SCRUB,
119 121 HELP_STATUS,
120 122 HELP_UPGRADE,
121 123 HELP_GET,
122 - HELP_SET
124 + HELP_SET,
125 + HELP_KEY
123 126 } zpool_help_t;
124 127
125 128
126 129 typedef struct zpool_command {
127 130 const char *name;
128 131 int (*func)(int, char **);
129 132 zpool_help_t usage;
130 133 } zpool_command_t;
131 134
132 135 /*
133 136 * Master command table. Each ZFS command has a name, associated function, and
134 137 * usage message. The usage messages need to be internationalized, so we have
135 138 * to have a function to return the usage message based on a command index.
136 139 *
137 140 * These commands are organized according to how they are displayed in the usage
138 141 * message. An empty command (one with a NULL name) indicates an empty line in
139 142 * the generic usage message.
140 143 */
141 144 static zpool_command_t command_table[] = {
142 145 { "create", zpool_do_create, HELP_CREATE },
143 146 { "destroy", zpool_do_destroy, HELP_DESTROY },
144 147 { NULL },
145 148 { "add", zpool_do_add, HELP_ADD },
146 149 { "remove", zpool_do_remove, HELP_REMOVE },
147 150 { NULL },
148 151 { "list", zpool_do_list, HELP_LIST },
149 152 { "iostat", zpool_do_iostat, HELP_IOSTAT },
150 153 { "status", zpool_do_status, HELP_STATUS },
151 154 { NULL },
152 155 { "online", zpool_do_online, HELP_ONLINE },
153 156 { "offline", zpool_do_offline, HELP_OFFLINE },
154 157 { "clear", zpool_do_clear, HELP_CLEAR },
155 158 { NULL },
156 159 { "attach", zpool_do_attach, HELP_ATTACH },
157 160 { "detach", zpool_do_detach, HELP_DETACH },
158 161 { "replace", zpool_do_replace, HELP_REPLACE },
|
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
159 162 { NULL },
160 163 { "scrub", zpool_do_scrub, HELP_SCRUB },
161 164 { NULL },
162 165 { "import", zpool_do_import, HELP_IMPORT },
163 166 { "export", zpool_do_export, HELP_EXPORT },
164 167 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
165 168 { NULL },
166 169 { "history", zpool_do_history, HELP_HISTORY },
167 170 { "get", zpool_do_get, HELP_GET },
168 171 { "set", zpool_do_set, HELP_SET },
172 + { NULL },
173 + { "key", zpool_do_key, HELP_KEY },
169 174 };
170 175
171 176 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
172 177
173 178 zpool_command_t *current_command;
174 179 static char history_str[HIS_MAX_RECORD_LEN];
175 180
176 181 static const char *
177 182 get_usage(zpool_help_t idx) {
178 183 switch (idx) {
179 184 case HELP_ADD:
180 185 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
181 186 case HELP_ATTACH:
182 187 return (gettext("\tattach [-f] <pool> <device> "
183 188 "<new-device>\n"));
184 189 case HELP_CLEAR:
185 190 return (gettext("\tclear <pool> [device]\n"));
186 191 case HELP_CREATE:
187 192 return (gettext("\tcreate [-fn] [-o property=value] ... \n"
188 193 "\t [-O file-system-property=value] ... \n"
189 194 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
190 195 case HELP_DESTROY:
191 196 return (gettext("\tdestroy [-f] <pool>\n"));
192 197 case HELP_DETACH:
193 198 return (gettext("\tdetach <pool> <device>\n"));
194 199 case HELP_EXPORT:
195 200 return (gettext("\texport [-f] <pool> ...\n"));
196 201 case HELP_HISTORY:
197 202 return (gettext("\thistory [-il] [<pool>] ...\n"));
198 203 case HELP_IMPORT:
199 204 return (gettext("\timport [-d dir] [-D]\n"
200 205 "\timport [-o mntopts] [-o property=value] ... \n"
201 206 "\t [-d dir | -c cachefile] [-D] [-f] [-R root] -a\n"
202 207 "\timport [-o mntopts] [-o property=value] ... \n"
203 208 "\t [-d dir | -c cachefile] [-D] [-f] [-R root] "
204 209 "<pool | id> [newpool]\n"));
205 210 case HELP_IOSTAT:
206 211 return (gettext("\tiostat [-v] [pool] ... [interval "
207 212 "[count]]\n"));
208 213 case HELP_LIST:
209 214 return (gettext("\tlist [-H] [-o property[,...]] "
210 215 "[pool] ...\n"));
211 216 case HELP_OFFLINE:
212 217 return (gettext("\toffline [-t] <pool> <device> ...\n"));
213 218 case HELP_ONLINE:
214 219 return (gettext("\tonline <pool> <device> ...\n"));
215 220 case HELP_REPLACE:
216 221 return (gettext("\treplace [-f] <pool> <device> "
217 222 "[new-device]\n"));
218 223 case HELP_REMOVE:
219 224 return (gettext("\tremove <pool> <device> ...\n"));
220 225 case HELP_SCRUB:
221 226 return (gettext("\tscrub [-s] <pool> ...\n"));
222 227 case HELP_STATUS:
|
↓ open down ↓ |
44 lines elided |
↑ open up ↑ |
223 228 return (gettext("\tstatus [-vx] [pool] ...\n"));
224 229 case HELP_UPGRADE:
225 230 return (gettext("\tupgrade\n"
226 231 "\tupgrade -v\n"
227 232 "\tupgrade [-V version] <-a | pool ...>\n"));
228 233 case HELP_GET:
229 234 return (gettext("\tget <\"all\" | property[,...]> "
230 235 "<pool> ...\n"));
231 236 case HELP_SET:
232 237 return (gettext("\tset <property=value> <pool> \n"));
238 + case HELP_KEY:
239 + return (gettext("\tkey <-l | -u | -c [ -o <property=value>]> "
240 + "<-a | pool>\n"));
233 241 }
234 242
235 243 abort();
236 244 /* NOTREACHED */
237 245 }
238 246
239 247
240 248 /*
241 249 * Callback routine that will print out a pool property value.
242 250 */
243 251 static int
244 252 print_prop_cb(int prop, void *cb)
245 253 {
246 254 FILE *fp = cb;
247 255
248 256 (void) fprintf(fp, "\t%-13s ", zpool_prop_to_name(prop));
249 257
250 258 if (zpool_prop_readonly(prop))
251 259 (void) fprintf(fp, " NO ");
252 260 else
253 261 (void) fprintf(fp, " YES ");
254 262
255 263 if (zpool_prop_values(prop) == NULL)
256 264 (void) fprintf(fp, "-\n");
257 265 else
258 266 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
259 267
260 268 return (ZPROP_CONT);
261 269 }
262 270
263 271 /*
264 272 * Display usage message. If we're inside a command, display only the usage for
265 273 * that command. Otherwise, iterate over the entire command table and display
266 274 * a complete usage message.
267 275 */
268 276 void
269 277 usage(boolean_t requested)
270 278 {
271 279 FILE *fp = requested ? stdout : stderr;
272 280
273 281 if (current_command == NULL) {
274 282 int i;
275 283
276 284 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
277 285 (void) fprintf(fp,
278 286 gettext("where 'command' is one of the following:\n\n"));
279 287
280 288 for (i = 0; i < NCOMMAND; i++) {
281 289 if (command_table[i].name == NULL)
282 290 (void) fprintf(fp, "\n");
283 291 else
284 292 (void) fprintf(fp, "%s",
285 293 get_usage(command_table[i].usage));
286 294 }
287 295 } else {
288 296 (void) fprintf(fp, gettext("usage:\n"));
289 297 (void) fprintf(fp, "%s", get_usage(current_command->usage));
290 298 }
291 299
292 300 if (current_command != NULL &&
293 301 ((strcmp(current_command->name, "set") == 0) ||
294 302 (strcmp(current_command->name, "get") == 0) ||
295 303 (strcmp(current_command->name, "list") == 0))) {
296 304
297 305 (void) fprintf(fp,
298 306 gettext("\nthe following properties are supported:\n"));
299 307
300 308 (void) fprintf(fp, "\n\t%-13s %s %s\n\n",
301 309 "PROPERTY", "EDIT", "VALUES");
302 310
303 311 /* Iterate over all properties */
304 312 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
305 313 ZFS_TYPE_POOL);
306 314 }
307 315
308 316 /*
309 317 * See comments at end of main().
310 318 */
311 319 if (getenv("ZFS_ABORT") != NULL) {
312 320 (void) printf("dumping core by request\n");
313 321 abort();
314 322 }
315 323
316 324 exit(requested ? 0 : 2);
317 325 }
318 326
319 327 void
320 328 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
321 329 boolean_t print_logs)
322 330 {
323 331 nvlist_t **child;
324 332 uint_t c, children;
325 333 char *vname;
326 334
327 335 if (name != NULL)
328 336 (void) printf("\t%*s%s\n", indent, "", name);
329 337
330 338 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
331 339 &child, &children) != 0)
332 340 return;
333 341
334 342 for (c = 0; c < children; c++) {
335 343 uint64_t is_log = B_FALSE;
336 344
337 345 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
338 346 &is_log);
339 347 if ((is_log && !print_logs) || (!is_log && print_logs))
340 348 continue;
341 349
342 350 vname = zpool_vdev_name(g_zfs, zhp, child[c]);
343 351 print_vdev_tree(zhp, vname, child[c], indent + 2,
344 352 B_FALSE);
345 353 free(vname);
346 354 }
347 355 }
348 356
349 357 /*
350 358 * Add a property pair (name, string-value) into a property nvlist.
351 359 */
352 360 static int
353 361 add_prop_list(const char *propname, char *propval, nvlist_t **props,
354 362 boolean_t poolprop)
355 363 {
356 364 zpool_prop_t prop = ZPROP_INVAL;
357 365 zfs_prop_t fprop;
358 366 nvlist_t *proplist;
359 367 const char *normnm;
360 368 char *strval;
361 369
362 370 if (*props == NULL &&
363 371 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
364 372 (void) fprintf(stderr,
365 373 gettext("internal error: out of memory\n"));
366 374 return (1);
367 375 }
368 376
369 377 proplist = *props;
370 378
371 379 if (poolprop) {
372 380 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
373 381 (void) fprintf(stderr, gettext("property '%s' is "
374 382 "not a valid pool property\n"), propname);
375 383 return (2);
376 384 }
377 385 normnm = zpool_prop_to_name(prop);
378 386 } else {
379 387 if ((fprop = zfs_name_to_prop(propname)) == ZPROP_INVAL) {
380 388 (void) fprintf(stderr, gettext("property '%s' is "
381 389 "not a valid file system property\n"), propname);
382 390 return (2);
383 391 }
384 392 normnm = zfs_prop_to_name(fprop);
385 393 }
386 394
387 395 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
388 396 prop != ZPOOL_PROP_CACHEFILE) {
389 397 (void) fprintf(stderr, gettext("property '%s' "
390 398 "specified multiple times\n"), propname);
391 399 return (2);
392 400 }
393 401
394 402 if (nvlist_add_string(proplist, normnm, propval) != 0) {
395 403 (void) fprintf(stderr, gettext("internal "
396 404 "error: out of memory\n"));
397 405 return (1);
398 406 }
399 407
400 408 return (0);
401 409 }
402 410
403 411 /*
404 412 * zpool add [-fn] <pool> <vdev> ...
405 413 *
406 414 * -f Force addition of devices, even if they appear in use
407 415 * -n Do not add the devices, but display the resulting layout if
408 416 * they were to be added.
409 417 *
410 418 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
411 419 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
412 420 * libzfs.
413 421 */
414 422 int
415 423 zpool_do_add(int argc, char **argv)
416 424 {
417 425 boolean_t force = B_FALSE;
418 426 boolean_t dryrun = B_FALSE;
419 427 int c;
420 428 nvlist_t *nvroot;
421 429 char *poolname;
422 430 int ret;
423 431 zpool_handle_t *zhp;
424 432 nvlist_t *config;
425 433
426 434 /* check options */
427 435 while ((c = getopt(argc, argv, "fn")) != -1) {
428 436 switch (c) {
429 437 case 'f':
430 438 force = B_TRUE;
431 439 break;
432 440 case 'n':
433 441 dryrun = B_TRUE;
434 442 break;
435 443 case '?':
436 444 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
437 445 optopt);
438 446 usage(B_FALSE);
439 447 }
440 448 }
441 449
442 450 argc -= optind;
443 451 argv += optind;
444 452
445 453 /* get pool name and check number of arguments */
446 454 if (argc < 1) {
447 455 (void) fprintf(stderr, gettext("missing pool name argument\n"));
448 456 usage(B_FALSE);
449 457 }
450 458 if (argc < 2) {
451 459 (void) fprintf(stderr, gettext("missing vdev specification\n"));
452 460 usage(B_FALSE);
453 461 }
454 462
455 463 poolname = argv[0];
456 464
457 465 argc--;
458 466 argv++;
459 467
460 468 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
461 469 return (1);
462 470
463 471 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
464 472 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
465 473 poolname);
466 474 zpool_close(zhp);
467 475 return (1);
468 476 }
469 477
470 478 /* pass off to get_vdev_spec for processing */
471 479 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
472 480 argc, argv);
473 481 if (nvroot == NULL) {
474 482 zpool_close(zhp);
475 483 return (1);
476 484 }
477 485
478 486 if (dryrun) {
479 487 nvlist_t *poolnvroot;
480 488
481 489 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
482 490 &poolnvroot) == 0);
483 491
484 492 (void) printf(gettext("would update '%s' to the following "
485 493 "configuration:\n"), zpool_get_name(zhp));
486 494
487 495 /* print original main pool and new tree */
488 496 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
489 497 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
490 498
491 499 /* Do the same for the logs */
492 500 if (num_logs(poolnvroot) > 0) {
493 501 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
494 502 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
495 503 } else if (num_logs(nvroot) > 0) {
496 504 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
497 505 }
498 506
499 507 ret = 0;
500 508 } else {
501 509 ret = (zpool_add(zhp, nvroot) != 0);
502 510 }
503 511
504 512 nvlist_free(nvroot);
505 513 zpool_close(zhp);
506 514
507 515 return (ret);
508 516 }
509 517
510 518 /*
511 519 * zpool remove <pool> <vdev> ...
512 520 *
513 521 * Removes the given vdev from the pool. Currently, this only supports removing
514 522 * spares and cache devices from the pool. Eventually, we'll want to support
515 523 * removing leaf vdevs (as an alias for 'detach') as well as toplevel vdevs.
516 524 */
517 525 int
518 526 zpool_do_remove(int argc, char **argv)
519 527 {
520 528 char *poolname;
521 529 int i, ret = 0;
522 530 zpool_handle_t *zhp;
523 531
524 532 argc--;
525 533 argv++;
526 534
527 535 /* get pool name and check number of arguments */
528 536 if (argc < 1) {
529 537 (void) fprintf(stderr, gettext("missing pool name argument\n"));
530 538 usage(B_FALSE);
531 539 }
532 540 if (argc < 2) {
533 541 (void) fprintf(stderr, gettext("missing device\n"));
534 542 usage(B_FALSE);
535 543 }
536 544
537 545 poolname = argv[0];
538 546
539 547 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
540 548 return (1);
541 549
542 550 for (i = 1; i < argc; i++) {
543 551 if (zpool_vdev_remove(zhp, argv[i]) != 0)
544 552 ret = 1;
545 553 }
546 554
547 555 return (ret);
548 556 }
549 557
550 558 /*
551 559 * zpool create [-fn] [-o property=value] ...
552 560 * [-O file-system-property=value] ...
553 561 * [-R root] [-m mountpoint] <pool> <dev> ...
554 562 *
555 563 * -f Force creation, even if devices appear in use
556 564 * -n Do not create the pool, but display the resulting layout if it
557 565 * were to be created.
558 566 * -R Create a pool under an alternate root
559 567 * -m Set default mountpoint for the root dataset. By default it's
560 568 * '/<pool>'
561 569 * -o Set property=value.
562 570 * -O Set fsproperty=value in the pool's root file system
563 571 *
564 572 * Creates the named pool according to the given vdev specification. The
565 573 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
566 574 * we get the nvlist back from get_vdev_spec(), we either print out the contents
567 575 * (if '-n' was specified), or pass it to libzfs to do the creation.
568 576 */
569 577 int
570 578 zpool_do_create(int argc, char **argv)
571 579 {
572 580 boolean_t force = B_FALSE;
573 581 boolean_t dryrun = B_FALSE;
574 582 int c;
575 583 nvlist_t *nvroot = NULL;
576 584 char *poolname;
577 585 int ret = 1;
578 586 char *altroot = NULL;
579 587 char *mountpoint = NULL;
580 588 nvlist_t *fsprops = NULL;
581 589 nvlist_t *props = NULL;
582 590 char *propval;
583 591
584 592 /* check options */
585 593 while ((c = getopt(argc, argv, ":fnR:m:o:O:")) != -1) {
586 594 switch (c) {
587 595 case 'f':
588 596 force = B_TRUE;
589 597 break;
590 598 case 'n':
591 599 dryrun = B_TRUE;
592 600 break;
593 601 case 'R':
594 602 altroot = optarg;
595 603 if (add_prop_list(zpool_prop_to_name(
596 604 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
597 605 goto errout;
598 606 if (nvlist_lookup_string(props,
599 607 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
600 608 &propval) == 0)
601 609 break;
602 610 if (add_prop_list(zpool_prop_to_name(
603 611 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
604 612 goto errout;
605 613 break;
606 614 case 'm':
607 615 mountpoint = optarg;
608 616 break;
609 617 case 'o':
610 618 if ((propval = strchr(optarg, '=')) == NULL) {
611 619 (void) fprintf(stderr, gettext("missing "
612 620 "'=' for -o option\n"));
613 621 goto errout;
614 622 }
615 623 *propval = '\0';
616 624 propval++;
617 625
618 626 if (add_prop_list(optarg, propval, &props, B_TRUE))
619 627 goto errout;
620 628 break;
621 629 case 'O':
622 630 if ((propval = strchr(optarg, '=')) == NULL) {
623 631 (void) fprintf(stderr, gettext("missing "
624 632 "'=' for -O option\n"));
625 633 goto errout;
626 634 }
627 635 *propval = '\0';
628 636 propval++;
629 637
630 638 if (add_prop_list(optarg, propval, &fsprops, B_FALSE))
631 639 goto errout;
632 640 break;
633 641 case ':':
634 642 (void) fprintf(stderr, gettext("missing argument for "
635 643 "'%c' option\n"), optopt);
636 644 goto badusage;
637 645 case '?':
638 646 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
639 647 optopt);
640 648 goto badusage;
641 649 }
642 650 }
643 651
644 652 argc -= optind;
645 653 argv += optind;
646 654
647 655 /* get pool name and check number of arguments */
648 656 if (argc < 1) {
649 657 (void) fprintf(stderr, gettext("missing pool name argument\n"));
650 658 goto badusage;
651 659 }
652 660 if (argc < 2) {
653 661 (void) fprintf(stderr, gettext("missing vdev specification\n"));
654 662 goto badusage;
655 663 }
656 664
657 665 poolname = argv[0];
658 666
659 667 /*
660 668 * As a special case, check for use of '/' in the name, and direct the
661 669 * user to use 'zfs create' instead.
662 670 */
663 671 if (strchr(poolname, '/') != NULL) {
664 672 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
665 673 "character '/' in pool name\n"), poolname);
666 674 (void) fprintf(stderr, gettext("use 'zfs create' to "
667 675 "create a dataset\n"));
668 676 goto errout;
669 677 }
670 678
671 679 /* pass off to get_vdev_spec for bulk processing */
672 680 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
673 681 argc - 1, argv + 1);
674 682 if (nvroot == NULL)
675 683 goto errout;
676 684
677 685 /* make_root_vdev() allows 0 toplevel children if there are spares */
678 686 if (!zfs_allocatable_devs(nvroot)) {
679 687 (void) fprintf(stderr, gettext("invalid vdev "
680 688 "specification: at least one toplevel vdev must be "
681 689 "specified\n"));
682 690 goto errout;
683 691 }
684 692
685 693
686 694 if (altroot != NULL && altroot[0] != '/') {
687 695 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
688 696 "must be an absolute path\n"), altroot);
689 697 goto errout;
690 698 }
691 699
692 700 /*
693 701 * Check the validity of the mountpoint and direct the user to use the
694 702 * '-m' mountpoint option if it looks like its in use.
695 703 */
696 704 if (mountpoint == NULL ||
697 705 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
698 706 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
699 707 char buf[MAXPATHLEN];
700 708 DIR *dirp;
701 709
702 710 if (mountpoint && mountpoint[0] != '/') {
703 711 (void) fprintf(stderr, gettext("invalid mountpoint "
704 712 "'%s': must be an absolute path, 'legacy', or "
705 713 "'none'\n"), mountpoint);
706 714 goto errout;
707 715 }
708 716
709 717 if (mountpoint == NULL) {
710 718 if (altroot != NULL)
711 719 (void) snprintf(buf, sizeof (buf), "%s/%s",
712 720 altroot, poolname);
713 721 else
714 722 (void) snprintf(buf, sizeof (buf), "/%s",
715 723 poolname);
716 724 } else {
717 725 if (altroot != NULL)
718 726 (void) snprintf(buf, sizeof (buf), "%s%s",
719 727 altroot, mountpoint);
720 728 else
721 729 (void) snprintf(buf, sizeof (buf), "%s",
722 730 mountpoint);
723 731 }
724 732
725 733 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
726 734 (void) fprintf(stderr, gettext("mountpoint '%s' : "
727 735 "%s\n"), buf, strerror(errno));
728 736 (void) fprintf(stderr, gettext("use '-m' "
729 737 "option to provide a different default\n"));
730 738 goto errout;
731 739 } else if (dirp) {
732 740 int count = 0;
733 741
734 742 while (count < 3 && readdir(dirp) != NULL)
735 743 count++;
736 744 (void) closedir(dirp);
737 745
738 746 if (count > 2) {
739 747 (void) fprintf(stderr, gettext("mountpoint "
740 748 "'%s' exists and is not empty\n"), buf);
741 749 (void) fprintf(stderr, gettext("use '-m' "
742 750 "option to provide a "
743 751 "different default\n"));
744 752 goto errout;
745 753 }
746 754 }
747 755 }
748 756
749 757 if (dryrun) {
750 758 /*
751 759 * For a dry run invocation, print out a basic message and run
752 760 * through all the vdevs in the list and print out in an
753 761 * appropriate hierarchy.
754 762 */
755 763 (void) printf(gettext("would create '%s' with the "
756 764 "following layout:\n\n"), poolname);
757 765
758 766 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
759 767 if (num_logs(nvroot) > 0)
760 768 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
761 769
762 770 ret = 0;
763 771 } else {
764 772 /*
765 773 * Hand off to libzfs.
766 774 */
767 775 if (zpool_create(g_zfs, poolname,
768 776 nvroot, props, fsprops) == 0) {
769 777 zfs_handle_t *pool = zfs_open(g_zfs, poolname,
770 778 ZFS_TYPE_FILESYSTEM);
771 779 if (pool != NULL) {
772 780 if (mountpoint != NULL)
773 781 verify(zfs_prop_set(pool,
774 782 zfs_prop_to_name(
775 783 ZFS_PROP_MOUNTPOINT),
776 784 mountpoint) == 0);
777 785 if (zfs_mount(pool, NULL, 0) == 0)
778 786 ret = zfs_shareall(pool);
779 787 zfs_close(pool);
780 788 }
781 789 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
782 790 (void) fprintf(stderr, gettext("pool name may have "
783 791 "been omitted\n"));
784 792 }
785 793 }
786 794
787 795 errout:
788 796 nvlist_free(nvroot);
789 797 nvlist_free(fsprops);
790 798 nvlist_free(props);
791 799 return (ret);
792 800 badusage:
793 801 nvlist_free(fsprops);
794 802 nvlist_free(props);
795 803 usage(B_FALSE);
796 804 return (2);
797 805 }
798 806
799 807 /*
|
↓ open down ↓ |
557 lines elided |
↑ open up ↑ |
800 808 * zpool destroy <pool>
801 809 *
802 810 * -f Forcefully unmount any datasets
803 811 *
804 812 * Destroy the given pool. Automatically unmounts any datasets in the pool.
805 813 */
806 814 int
807 815 zpool_do_destroy(int argc, char **argv)
808 816 {
809 817 boolean_t force = B_FALSE;
818 + boolean_t encrypted_only = B_FALSE;
810 819 int c;
811 820 char *pool;
812 821 zpool_handle_t *zhp;
813 822 int ret;
814 823
815 824 /* check options */
816 825 while ((c = getopt(argc, argv, "f")) != -1) {
817 826 switch (c) {
818 827 case 'f':
819 828 force = B_TRUE;
820 829 break;
821 830 case '?':
822 831 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
823 832 optopt);
824 833 usage(B_FALSE);
825 834 }
826 835 }
827 836
828 837 argc -= optind;
829 838 argv += optind;
830 839
831 840 /* check arguments */
832 841 if (argc < 1) {
833 842 (void) fprintf(stderr, gettext("missing pool argument\n"));
834 843 usage(B_FALSE);
835 844 }
836 845 if (argc > 1) {
837 846 (void) fprintf(stderr, gettext("too many arguments\n"));
838 847 usage(B_FALSE);
839 848 }
840 849
841 850 pool = argv[0];
842 851
843 852 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
|
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
844 853 /*
845 854 * As a special case, check for use of '/' in the name, and
846 855 * direct the user to use 'zfs destroy' instead.
847 856 */
848 857 if (strchr(pool, '/') != NULL)
849 858 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
850 859 "destroy a dataset\n"));
851 860 return (1);
852 861 }
853 862
854 - if (zpool_disable_datasets(zhp, force) != 0) {
863 + if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
855 864 (void) fprintf(stderr, gettext("could not destroy '%s': "
856 865 "could not unmount datasets\n"), zpool_get_name(zhp));
857 866 return (1);
858 867 }
859 868
860 869 ret = (zpool_destroy(zhp) != 0);
861 870
862 871 zpool_close(zhp);
863 872
864 873 return (ret);
865 874 }
866 875
867 876 /*
868 877 * zpool export [-f] <pool> ...
869 878 *
870 879 * -f Forcefully unmount datasets
|
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
871 880 *
872 881 * Export the given pools. By default, the command will attempt to cleanly
873 882 * unmount any active datasets within the pool. If the '-f' flag is specified,
874 883 * then the datasets will be forcefully unmounted.
875 884 */
876 885 int
877 886 zpool_do_export(int argc, char **argv)
878 887 {
879 888 boolean_t force = B_FALSE;
880 889 boolean_t hardforce = B_FALSE;
890 + boolean_t encrypted_only = B_FALSE;
881 891 int c;
882 892 zpool_handle_t *zhp;
883 893 int ret;
884 894 int i;
885 895
886 896 /* check options */
887 897 while ((c = getopt(argc, argv, "fF")) != -1) {
888 898 switch (c) {
889 899 case 'f':
890 900 force = B_TRUE;
891 901 break;
892 902 case 'F':
893 903 hardforce = B_TRUE;
894 904 break;
895 905 case '?':
896 906 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
897 907 optopt);
898 908 usage(B_FALSE);
899 909 }
900 910 }
901 911
902 912 argc -= optind;
903 913 argv += optind;
904 914
905 915 /* check arguments */
906 916 if (argc < 1) {
907 917 (void) fprintf(stderr, gettext("missing pool argument\n"));
|
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
908 918 usage(B_FALSE);
909 919 }
910 920
911 921 ret = 0;
912 922 for (i = 0; i < argc; i++) {
913 923 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
914 924 ret = 1;
915 925 continue;
916 926 }
917 927
918 - if (zpool_disable_datasets(zhp, force) != 0) {
928 + if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
919 929 ret = 1;
920 930 zpool_close(zhp);
921 931 continue;
922 932 }
923 933
924 934 if (hardforce) {
925 935 if (zpool_export_force(zhp) != 0)
926 936 ret = 1;
927 937 } else if (zpool_export(zhp, force) != 0) {
928 938 ret = 1;
929 939 }
930 940
931 941 zpool_close(zhp);
932 942 }
933 943
934 944 return (ret);
935 945 }
936 946
937 947 /*
938 948 * Given a vdev configuration, determine the maximum width needed for the device
939 949 * name column.
940 950 */
941 951 static int
942 952 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
943 953 {
944 954 char *name = zpool_vdev_name(g_zfs, zhp, nv);
945 955 nvlist_t **child;
946 956 uint_t c, children;
947 957 int ret;
948 958
949 959 if (strlen(name) + depth > max)
950 960 max = strlen(name) + depth;
951 961
952 962 free(name);
953 963
954 964 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
955 965 &child, &children) == 0) {
956 966 for (c = 0; c < children; c++)
957 967 if ((ret = max_width(zhp, child[c], depth + 2,
958 968 max)) > max)
959 969 max = ret;
960 970 }
961 971
962 972 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
963 973 &child, &children) == 0) {
964 974 for (c = 0; c < children; c++)
965 975 if ((ret = max_width(zhp, child[c], depth + 2,
966 976 max)) > max)
967 977 max = ret;
968 978 }
969 979
970 980 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
971 981 &child, &children) == 0) {
972 982 for (c = 0; c < children; c++)
973 983 if ((ret = max_width(zhp, child[c], depth + 2,
974 984 max)) > max)
975 985 max = ret;
976 986 }
977 987
978 988
979 989 return (max);
980 990 }
981 991
982 992
983 993 /*
984 994 * Print the configuration of an exported pool. Iterate over all vdevs in the
985 995 * pool, printing out the name and status for each one.
986 996 */
987 997 void
988 998 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth,
989 999 boolean_t print_logs)
990 1000 {
991 1001 nvlist_t **child;
992 1002 uint_t c, children;
993 1003 vdev_stat_t *vs;
994 1004 char *type, *vname;
995 1005
996 1006 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
997 1007 if (strcmp(type, VDEV_TYPE_MISSING) == 0)
998 1008 return;
999 1009
1000 1010 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
1001 1011 (uint64_t **)&vs, &c) == 0);
1002 1012
1003 1013 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1004 1014 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1005 1015
1006 1016 if (vs->vs_aux != 0) {
1007 1017 (void) printf(" ");
1008 1018
1009 1019 switch (vs->vs_aux) {
1010 1020 case VDEV_AUX_OPEN_FAILED:
1011 1021 (void) printf(gettext("cannot open"));
1012 1022 break;
1013 1023
1014 1024 case VDEV_AUX_BAD_GUID_SUM:
1015 1025 (void) printf(gettext("missing device"));
1016 1026 break;
1017 1027
1018 1028 case VDEV_AUX_NO_REPLICAS:
1019 1029 (void) printf(gettext("insufficient replicas"));
1020 1030 break;
1021 1031
1022 1032 case VDEV_AUX_VERSION_NEWER:
1023 1033 (void) printf(gettext("newer version"));
1024 1034 break;
1025 1035
1026 1036 case VDEV_AUX_ERR_EXCEEDED:
1027 1037 (void) printf(gettext("too many errors"));
1028 1038 break;
1029 1039
1030 1040 default:
1031 1041 (void) printf(gettext("corrupted data"));
1032 1042 break;
1033 1043 }
1034 1044 }
1035 1045 (void) printf("\n");
1036 1046
1037 1047 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1038 1048 &child, &children) != 0)
1039 1049 return;
1040 1050
1041 1051 for (c = 0; c < children; c++) {
1042 1052 uint64_t is_log = B_FALSE;
1043 1053
1044 1054 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1045 1055 &is_log);
1046 1056 if ((is_log && !print_logs) || (!is_log && print_logs))
1047 1057 continue;
1048 1058
1049 1059 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1050 1060 print_import_config(vname, child[c],
1051 1061 namewidth, depth + 2, B_FALSE);
1052 1062 free(vname);
1053 1063 }
1054 1064
1055 1065 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1056 1066 &child, &children) == 0) {
1057 1067 (void) printf(gettext("\tcache\n"));
1058 1068 for (c = 0; c < children; c++) {
1059 1069 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1060 1070 (void) printf("\t %s\n", vname);
1061 1071 free(vname);
1062 1072 }
1063 1073 }
1064 1074
1065 1075 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1066 1076 &child, &children) == 0) {
1067 1077 (void) printf(gettext("\tspares\n"));
1068 1078 for (c = 0; c < children; c++) {
1069 1079 vname = zpool_vdev_name(g_zfs, NULL, child[c]);
1070 1080 (void) printf("\t %s\n", vname);
1071 1081 free(vname);
1072 1082 }
1073 1083 }
1074 1084 }
1075 1085
1076 1086 /*
1077 1087 * Display the status for the given pool.
1078 1088 */
1079 1089 static void
1080 1090 show_import(nvlist_t *config)
1081 1091 {
1082 1092 uint64_t pool_state;
1083 1093 vdev_stat_t *vs;
1084 1094 char *name;
1085 1095 uint64_t guid;
1086 1096 char *msgid;
1087 1097 nvlist_t *nvroot;
1088 1098 int reason;
1089 1099 const char *health;
1090 1100 uint_t vsc;
1091 1101 int namewidth;
1092 1102
1093 1103 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1094 1104 &name) == 0);
1095 1105 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1096 1106 &guid) == 0);
1097 1107 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1098 1108 &pool_state) == 0);
1099 1109 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1100 1110 &nvroot) == 0);
1101 1111
1102 1112 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
1103 1113 (uint64_t **)&vs, &vsc) == 0);
1104 1114 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1105 1115
1106 1116 reason = zpool_import_status(config, &msgid);
1107 1117
1108 1118 (void) printf(gettext(" pool: %s\n"), name);
1109 1119 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
1110 1120 (void) printf(gettext(" state: %s"), health);
1111 1121 if (pool_state == POOL_STATE_DESTROYED)
1112 1122 (void) printf(gettext(" (DESTROYED)"));
1113 1123 (void) printf("\n");
1114 1124
1115 1125 switch (reason) {
1116 1126 case ZPOOL_STATUS_MISSING_DEV_R:
1117 1127 case ZPOOL_STATUS_MISSING_DEV_NR:
1118 1128 case ZPOOL_STATUS_BAD_GUID_SUM:
1119 1129 (void) printf(gettext("status: One or more devices are missing "
1120 1130 "from the system.\n"));
1121 1131 break;
1122 1132
1123 1133 case ZPOOL_STATUS_CORRUPT_LABEL_R:
1124 1134 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1125 1135 (void) printf(gettext("status: One or more devices contains "
1126 1136 "corrupted data.\n"));
1127 1137 break;
1128 1138
1129 1139 case ZPOOL_STATUS_CORRUPT_DATA:
1130 1140 (void) printf(gettext("status: The pool data is corrupted.\n"));
1131 1141 break;
1132 1142
1133 1143 case ZPOOL_STATUS_OFFLINE_DEV:
1134 1144 (void) printf(gettext("status: One or more devices "
1135 1145 "are offlined.\n"));
1136 1146 break;
1137 1147
1138 1148 case ZPOOL_STATUS_CORRUPT_POOL:
1139 1149 (void) printf(gettext("status: The pool metadata is "
1140 1150 "corrupted.\n"));
1141 1151 break;
1142 1152
1143 1153 case ZPOOL_STATUS_VERSION_OLDER:
1144 1154 (void) printf(gettext("status: The pool is formatted using an "
1145 1155 "older on-disk version.\n"));
1146 1156 break;
1147 1157
1148 1158 case ZPOOL_STATUS_VERSION_NEWER:
1149 1159 (void) printf(gettext("status: The pool is formatted using an "
1150 1160 "incompatible version.\n"));
1151 1161 break;
1152 1162
1153 1163 case ZPOOL_STATUS_HOSTID_MISMATCH:
1154 1164 (void) printf(gettext("status: The pool was last accessed by "
1155 1165 "another system.\n"));
1156 1166 break;
1157 1167
1158 1168 case ZPOOL_STATUS_FAULTED_DEV_R:
1159 1169 case ZPOOL_STATUS_FAULTED_DEV_NR:
1160 1170 (void) printf(gettext("status: One or more devices are "
1161 1171 "faulted.\n"));
1162 1172 break;
1163 1173
1164 1174 case ZPOOL_STATUS_BAD_LOG:
1165 1175 (void) printf(gettext("status: An intent log record cannot be "
1166 1176 "read.\n"));
1167 1177 break;
1168 1178
1169 1179 default:
1170 1180 /*
1171 1181 * No other status can be seen when importing pools.
1172 1182 */
1173 1183 assert(reason == ZPOOL_STATUS_OK);
1174 1184 }
1175 1185
1176 1186 /*
1177 1187 * Print out an action according to the overall state of the pool.
1178 1188 */
1179 1189 if (vs->vs_state == VDEV_STATE_HEALTHY) {
1180 1190 if (reason == ZPOOL_STATUS_VERSION_OLDER)
1181 1191 (void) printf(gettext("action: The pool can be "
1182 1192 "imported using its name or numeric identifier, "
1183 1193 "though\n\tsome features will not be available "
1184 1194 "without an explicit 'zpool upgrade'.\n"));
1185 1195 else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH)
1186 1196 (void) printf(gettext("action: The pool can be "
1187 1197 "imported using its name or numeric "
1188 1198 "identifier and\n\tthe '-f' flag.\n"));
1189 1199 else
1190 1200 (void) printf(gettext("action: The pool can be "
1191 1201 "imported using its name or numeric "
1192 1202 "identifier.\n"));
1193 1203 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1194 1204 (void) printf(gettext("action: The pool can be imported "
1195 1205 "despite missing or damaged devices. The\n\tfault "
1196 1206 "tolerance of the pool may be compromised if imported.\n"));
1197 1207 } else {
1198 1208 switch (reason) {
1199 1209 case ZPOOL_STATUS_VERSION_NEWER:
1200 1210 (void) printf(gettext("action: The pool cannot be "
1201 1211 "imported. Access the pool on a system running "
1202 1212 "newer\n\tsoftware, or recreate the pool from "
1203 1213 "backup.\n"));
1204 1214 break;
1205 1215 case ZPOOL_STATUS_MISSING_DEV_R:
1206 1216 case ZPOOL_STATUS_MISSING_DEV_NR:
1207 1217 case ZPOOL_STATUS_BAD_GUID_SUM:
1208 1218 (void) printf(gettext("action: The pool cannot be "
1209 1219 "imported. Attach the missing\n\tdevices and try "
1210 1220 "again.\n"));
1211 1221 break;
1212 1222 default:
1213 1223 (void) printf(gettext("action: The pool cannot be "
1214 1224 "imported due to damaged devices or data.\n"));
1215 1225 }
1216 1226 }
1217 1227
1218 1228 /*
1219 1229 * If the state is "closed" or "can't open", and the aux state
1220 1230 * is "corrupt data":
1221 1231 */
1222 1232 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1223 1233 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1224 1234 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1225 1235 if (pool_state == POOL_STATE_DESTROYED)
1226 1236 (void) printf(gettext("\tThe pool was destroyed, "
1227 1237 "but can be imported using the '-Df' flags.\n"));
1228 1238 else if (pool_state != POOL_STATE_EXPORTED)
1229 1239 (void) printf(gettext("\tThe pool may be active on "
1230 1240 "another system, but can be imported using\n\t"
1231 1241 "the '-f' flag.\n"));
1232 1242 }
1233 1243
1234 1244 if (msgid != NULL)
1235 1245 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"),
1236 1246 msgid);
1237 1247
1238 1248 (void) printf(gettext("config:\n\n"));
1239 1249
1240 1250 namewidth = max_width(NULL, nvroot, 0, 0);
1241 1251 if (namewidth < 10)
1242 1252 namewidth = 10;
1243 1253
1244 1254 print_import_config(name, nvroot, namewidth, 0, B_FALSE);
1245 1255 if (num_logs(nvroot) > 0) {
1246 1256 (void) printf(gettext("\tlogs\n"));
1247 1257 print_import_config(name, nvroot, namewidth, 0, B_TRUE);
1248 1258 }
1249 1259
1250 1260 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1251 1261 (void) printf(gettext("\n\tAdditional devices are known to "
1252 1262 "be part of this pool, though their\n\texact "
1253 1263 "configuration cannot be determined.\n"));
1254 1264 }
1255 1265 }
|
↓ open down ↓ |
327 lines elided |
↑ open up ↑ |
1256 1266
1257 1267 /*
1258 1268 * Perform the import for the given configuration. This passes the heavy
1259 1269 * lifting off to zpool_import_props(), and then mounts the datasets contained
1260 1270 * within the pool.
1261 1271 */
1262 1272 static int
1263 1273 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1264 1274 int force, nvlist_t *props, boolean_t allowfaulted)
1265 1275 {
1276 + boolean_t encrypted_only = B_FALSE;
1266 1277 zpool_handle_t *zhp;
1267 1278 char *name;
1268 1279 uint64_t state;
1269 1280 uint64_t version;
1270 1281 int error = 0;
1271 1282
1272 1283 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1273 1284 &name) == 0);
1274 1285
1275 1286 verify(nvlist_lookup_uint64(config,
1276 1287 ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1277 1288 verify(nvlist_lookup_uint64(config,
1278 1289 ZPOOL_CONFIG_VERSION, &version) == 0);
1279 1290 if (version > SPA_VERSION) {
1280 1291 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1281 1292 "is formatted using a newer ZFS version\n"), name);
1282 1293 return (1);
1283 1294 } else if (state != POOL_STATE_EXPORTED && !force) {
1284 1295 uint64_t hostid;
1285 1296
1286 1297 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
1287 1298 &hostid) == 0) {
1288 1299 if ((unsigned long)hostid != gethostid()) {
1289 1300 char *hostname;
1290 1301 uint64_t timestamp;
1291 1302 time_t t;
1292 1303
1293 1304 verify(nvlist_lookup_string(config,
1294 1305 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
1295 1306 verify(nvlist_lookup_uint64(config,
1296 1307 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0);
1297 1308 t = timestamp;
1298 1309 (void) fprintf(stderr, gettext("cannot import "
1299 1310 "'%s': pool may be in use from other "
1300 1311 "system, it was last accessed by %s "
1301 1312 "(hostid: 0x%lx) on %s"), name, hostname,
1302 1313 (unsigned long)hostid,
1303 1314 asctime(localtime(&t)));
1304 1315 (void) fprintf(stderr, gettext("use '-f' to "
1305 1316 "import anyway\n"));
1306 1317 return (1);
1307 1318 }
1308 1319 } else {
1309 1320 (void) fprintf(stderr, gettext("cannot import '%s': "
1310 1321 "pool may be in use from other system\n"), name);
1311 1322 (void) fprintf(stderr, gettext("use '-f' to import "
1312 1323 "anyway\n"));
1313 1324 return (1);
1314 1325 }
1315 1326 }
|
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
1316 1327
1317 1328 if (zpool_import_props(g_zfs, config, newname, props,
1318 1329 allowfaulted) != 0)
1319 1330 return (1);
1320 1331
1321 1332 if (newname != NULL)
1322 1333 name = (char *)newname;
1323 1334
1324 1335 verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL);
1325 1336
1337 + /*
1338 + * Attempt to load the crypto keys before mounting up the datasets
1339 + * Note that depending on the value of the keysource property
1340 + * this could cause us to go interactive.
1341 + * We don't mind if this falls though and continue to enable what
1342 + * datasets we can if it does.
1343 + *
1344 + * Use zpool_load_key() and tell it we are doing an import rather than
1345 + * zpool_cmd_key_load().
1346 + *
1347 + * We then attempt enable all datasets not just the encrypted ones.
1348 + */
1349 +
1350 + error = zpool_load_key(zhp, B_TRUE);
1351 + if (error != 0 && error != ENOTSUP) {
1352 + libzfs_handle_t *zpool_hdl = zpool_get_handle(zhp);
1353 + (void) fprintf(stderr, gettext(
1354 + "%s.\nEncrypted datasets with keyscope=pool "
1355 + "will not be mounted.\n"),
1356 + libzfs_error_description(zpool_hdl));
1357 + }
1358 +
1326 1359 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
1327 - zpool_enable_datasets(zhp, mntopts, 0) != 0) {
1360 + zpool_enable_datasets(zhp, mntopts, 0, encrypted_only) != 0) {
1328 1361 zpool_close(zhp);
1329 1362 return (1);
1330 1363 }
1331 1364
1332 1365 zpool_close(zhp);
1333 - return (error);
1366 + return (0);
1334 1367 }
1335 1368
1336 1369 /*
1337 1370 * zpool import [-d dir] [-D]
1338 1371 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1339 1372 * [-d dir | -c cachefile] [-f] -a
1340 1373 * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
1341 1374 * [-d dir | -c cachefile] [-f] <pool | id> [newpool]
1342 1375 *
1343 1376 * -c Read pool information from a cachefile instead of searching
1344 1377 * devices.
1345 1378 *
1346 1379 * -d Scan in a specific directory, other than /dev/dsk. More than
1347 1380 * one directory can be specified using multiple '-d' options.
1348 1381 *
1349 1382 * -D Scan for previously destroyed pools or import all or only
1350 1383 * specified destroyed pools.
1351 1384 *
1352 1385 * -R Temporarily import the pool, with all mountpoints relative to
1353 1386 * the given root. The pool will remain exported when the machine
1354 1387 * is rebooted.
1355 1388 *
1356 1389 * -f Force import, even if it appears that the pool is active.
1357 1390 *
1358 1391 * -F Import even in the presence of faulted vdevs. This is an
1359 1392 * intentionally undocumented option for testing purposes, and
1360 1393 * treats the pool configuration as complete, leaving any bad
1361 1394 * vdevs in the FAULTED state.
1362 1395 *
1363 1396 * -a Import all pools found.
1364 1397 *
1365 1398 * -o Set property=value and/or temporary mount options (without '=').
1366 1399 *
1367 1400 * The import command scans for pools to import, and import pools based on pool
1368 1401 * name and GUID. The pool can also be renamed as part of the import process.
1369 1402 */
1370 1403 int
1371 1404 zpool_do_import(int argc, char **argv)
1372 1405 {
1373 1406 char **searchdirs = NULL;
1374 1407 int nsearch = 0;
1375 1408 int c;
1376 1409 int err;
1377 1410 nvlist_t *pools = NULL;
1378 1411 boolean_t do_all = B_FALSE;
1379 1412 boolean_t do_destroyed = B_FALSE;
1380 1413 char *mntopts = NULL;
1381 1414 boolean_t do_force = B_FALSE;
1382 1415 nvpair_t *elem;
1383 1416 nvlist_t *config;
1384 1417 uint64_t searchguid = 0;
1385 1418 char *searchname = NULL;
1386 1419 char *propval;
1387 1420 nvlist_t *found_config;
1388 1421 nvlist_t *props = NULL;
1389 1422 boolean_t first;
1390 1423 boolean_t allow_faulted = B_FALSE;
1391 1424 uint64_t pool_state;
1392 1425 char *cachefile = NULL;
1393 1426
1394 1427 /* check options */
1395 1428 while ((c = getopt(argc, argv, ":ac:d:DfFo:p:R:")) != -1) {
1396 1429 switch (c) {
1397 1430 case 'a':
1398 1431 do_all = B_TRUE;
1399 1432 break;
1400 1433 case 'c':
1401 1434 cachefile = optarg;
1402 1435 break;
1403 1436 case 'd':
1404 1437 if (searchdirs == NULL) {
1405 1438 searchdirs = safe_malloc(sizeof (char *));
1406 1439 } else {
1407 1440 char **tmp = safe_malloc((nsearch + 1) *
1408 1441 sizeof (char *));
1409 1442 bcopy(searchdirs, tmp, nsearch *
1410 1443 sizeof (char *));
1411 1444 free(searchdirs);
1412 1445 searchdirs = tmp;
1413 1446 }
1414 1447 searchdirs[nsearch++] = optarg;
1415 1448 break;
1416 1449 case 'D':
1417 1450 do_destroyed = B_TRUE;
1418 1451 break;
1419 1452 case 'f':
1420 1453 do_force = B_TRUE;
1421 1454 break;
1422 1455 case 'F':
1423 1456 allow_faulted = B_TRUE;
1424 1457 break;
1425 1458 case 'o':
1426 1459 if ((propval = strchr(optarg, '=')) != NULL) {
1427 1460 *propval = '\0';
1428 1461 propval++;
1429 1462 if (add_prop_list(optarg, propval,
1430 1463 &props, B_TRUE))
1431 1464 goto error;
1432 1465 } else {
1433 1466 mntopts = optarg;
1434 1467 }
1435 1468 break;
1436 1469 case 'R':
1437 1470 if (add_prop_list(zpool_prop_to_name(
1438 1471 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
1439 1472 goto error;
1440 1473 if (nvlist_lookup_string(props,
1441 1474 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
1442 1475 &propval) == 0)
1443 1476 break;
1444 1477 if (add_prop_list(zpool_prop_to_name(
1445 1478 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
1446 1479 goto error;
1447 1480 break;
1448 1481 case ':':
1449 1482 (void) fprintf(stderr, gettext("missing argument for "
1450 1483 "'%c' option\n"), optopt);
1451 1484 usage(B_FALSE);
1452 1485 break;
1453 1486 case '?':
1454 1487 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1455 1488 optopt);
1456 1489 usage(B_FALSE);
1457 1490 }
1458 1491 }
1459 1492
1460 1493 argc -= optind;
1461 1494 argv += optind;
1462 1495
1463 1496 if (cachefile && nsearch != 0) {
1464 1497 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
1465 1498 usage(B_FALSE);
1466 1499 }
1467 1500
1468 1501 if (searchdirs == NULL) {
1469 1502 searchdirs = safe_malloc(sizeof (char *));
1470 1503 searchdirs[0] = "/dev/dsk";
1471 1504 nsearch = 1;
1472 1505 }
1473 1506
1474 1507 /* check argument count */
1475 1508 if (do_all) {
1476 1509 if (argc != 0) {
1477 1510 (void) fprintf(stderr, gettext("too many arguments\n"));
1478 1511 usage(B_FALSE);
1479 1512 }
1480 1513 } else {
1481 1514 if (argc > 2) {
1482 1515 (void) fprintf(stderr, gettext("too many arguments\n"));
1483 1516 usage(B_FALSE);
1484 1517 }
1485 1518
1486 1519 /*
1487 1520 * Check for the SYS_CONFIG privilege. We do this explicitly
1488 1521 * here because otherwise any attempt to discover pools will
1489 1522 * silently fail.
1490 1523 */
1491 1524 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
1492 1525 (void) fprintf(stderr, gettext("cannot "
1493 1526 "discover pools: permission denied\n"));
1494 1527 free(searchdirs);
1495 1528 return (1);
1496 1529 }
1497 1530 }
1498 1531
1499 1532 /*
1500 1533 * Depending on the arguments given, we do one of the following:
1501 1534 *
1502 1535 * <none> Iterate through all pools and display information about
1503 1536 * each one.
1504 1537 *
1505 1538 * -a Iterate through all pools and try to import each one.
1506 1539 *
1507 1540 * <id> Find the pool that corresponds to the given GUID/pool
1508 1541 * name and import that one.
1509 1542 *
1510 1543 * -D Above options applies only to destroyed pools.
1511 1544 */
1512 1545 if (argc != 0) {
1513 1546 char *endptr;
1514 1547
1515 1548 errno = 0;
1516 1549 searchguid = strtoull(argv[0], &endptr, 10);
1517 1550 if (errno != 0 || *endptr != '\0')
1518 1551 searchname = argv[0];
1519 1552 found_config = NULL;
1520 1553 }
1521 1554
1522 1555 if (cachefile) {
1523 1556 pools = zpool_find_import_cached(g_zfs, cachefile, searchname,
1524 1557 searchguid);
1525 1558 } else if (searchname != NULL) {
1526 1559 pools = zpool_find_import_byname(g_zfs, nsearch, searchdirs,
1527 1560 searchname);
1528 1561 } else {
1529 1562 /*
1530 1563 * It's OK to search by guid even if searchguid is 0.
1531 1564 */
1532 1565 pools = zpool_find_import_byguid(g_zfs, nsearch, searchdirs,
1533 1566 searchguid);
1534 1567 }
1535 1568
1536 1569 if (pools == NULL) {
1537 1570 if (argc != 0) {
1538 1571 (void) fprintf(stderr, gettext("cannot import '%s': "
1539 1572 "no such pool available\n"), argv[0]);
1540 1573 }
1541 1574 free(searchdirs);
1542 1575 return (1);
1543 1576 }
1544 1577
1545 1578 /*
1546 1579 * At this point we have a list of import candidate configs. Even if
1547 1580 * we were searching by pool name or guid, we still need to
1548 1581 * post-process the list to deal with pool state and possible
1549 1582 * duplicate names.
1550 1583 */
1551 1584 err = 0;
1552 1585 elem = NULL;
1553 1586 first = B_TRUE;
1554 1587 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
1555 1588
1556 1589 verify(nvpair_value_nvlist(elem, &config) == 0);
1557 1590
1558 1591 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1559 1592 &pool_state) == 0);
1560 1593 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
1561 1594 continue;
1562 1595 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
1563 1596 continue;
1564 1597
1565 1598 if (argc == 0) {
1566 1599 if (first)
1567 1600 first = B_FALSE;
1568 1601 else if (!do_all)
1569 1602 (void) printf("\n");
1570 1603
1571 1604 if (do_all)
1572 1605 err |= do_import(config, NULL, mntopts,
1573 1606 do_force, props, allow_faulted);
1574 1607 else
1575 1608 show_import(config);
1576 1609 } else if (searchname != NULL) {
1577 1610 char *name;
1578 1611
1579 1612 /*
1580 1613 * We are searching for a pool based on name.
1581 1614 */
1582 1615 verify(nvlist_lookup_string(config,
1583 1616 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
1584 1617
1585 1618 if (strcmp(name, searchname) == 0) {
1586 1619 if (found_config != NULL) {
1587 1620 (void) fprintf(stderr, gettext(
1588 1621 "cannot import '%s': more than "
1589 1622 "one matching pool\n"), searchname);
1590 1623 (void) fprintf(stderr, gettext(
1591 1624 "import by numeric ID instead\n"));
1592 1625 err = B_TRUE;
1593 1626 }
1594 1627 found_config = config;
1595 1628 }
1596 1629 } else {
1597 1630 uint64_t guid;
1598 1631
1599 1632 /*
1600 1633 * Search for a pool by guid.
1601 1634 */
1602 1635 verify(nvlist_lookup_uint64(config,
1603 1636 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
1604 1637
1605 1638 if (guid == searchguid)
1606 1639 found_config = config;
1607 1640 }
1608 1641 }
1609 1642
1610 1643 /*
1611 1644 * If we were searching for a specific pool, verify that we found a
1612 1645 * pool, and then do the import.
1613 1646 */
1614 1647 if (argc != 0 && err == 0) {
1615 1648 if (found_config == NULL) {
1616 1649 (void) fprintf(stderr, gettext("cannot import '%s': "
1617 1650 "no such pool available\n"), argv[0]);
1618 1651 err = B_TRUE;
1619 1652 } else {
1620 1653 err |= do_import(found_config, argc == 1 ? NULL :
1621 1654 argv[1], mntopts, do_force, props, allow_faulted);
1622 1655 }
1623 1656 }
1624 1657
1625 1658 /*
1626 1659 * If we were just looking for pools, report an error if none were
1627 1660 * found.
1628 1661 */
1629 1662 if (argc == 0 && first)
1630 1663 (void) fprintf(stderr,
1631 1664 gettext("no pools available to import\n"));
1632 1665
1633 1666 error:
1634 1667 nvlist_free(props);
1635 1668 nvlist_free(pools);
1636 1669 free(searchdirs);
1637 1670
1638 1671 return (err ? 1 : 0);
1639 1672 }
1640 1673
1641 1674 typedef struct iostat_cbdata {
1642 1675 zpool_list_t *cb_list;
1643 1676 int cb_verbose;
1644 1677 int cb_iteration;
1645 1678 int cb_namewidth;
1646 1679 } iostat_cbdata_t;
1647 1680
1648 1681 static void
1649 1682 print_iostat_separator(iostat_cbdata_t *cb)
1650 1683 {
1651 1684 int i = 0;
1652 1685
1653 1686 for (i = 0; i < cb->cb_namewidth; i++)
1654 1687 (void) printf("-");
1655 1688 (void) printf(" ----- ----- ----- ----- ----- -----\n");
1656 1689 }
1657 1690
1658 1691 static void
1659 1692 print_iostat_header(iostat_cbdata_t *cb)
1660 1693 {
1661 1694 (void) printf("%*s capacity operations bandwidth\n",
1662 1695 cb->cb_namewidth, "");
1663 1696 (void) printf("%-*s used avail read write read write\n",
1664 1697 cb->cb_namewidth, "pool");
1665 1698 print_iostat_separator(cb);
1666 1699 }
1667 1700
1668 1701 /*
1669 1702 * Display a single statistic.
1670 1703 */
1671 1704 static void
1672 1705 print_one_stat(uint64_t value)
1673 1706 {
1674 1707 char buf[64];
1675 1708
1676 1709 zfs_nicenum(value, buf, sizeof (buf));
1677 1710 (void) printf(" %5s", buf);
1678 1711 }
1679 1712
1680 1713 /*
1681 1714 * Print out all the statistics for the given vdev. This can either be the
1682 1715 * toplevel configuration, or called recursively. If 'name' is NULL, then this
1683 1716 * is a verbose output, and we don't want to display the toplevel pool stats.
1684 1717 */
1685 1718 void
1686 1719 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
1687 1720 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
1688 1721 {
1689 1722 nvlist_t **oldchild, **newchild;
1690 1723 uint_t c, children;
1691 1724 vdev_stat_t *oldvs, *newvs;
1692 1725 vdev_stat_t zerovs = { 0 };
1693 1726 uint64_t tdelta;
1694 1727 double scale;
1695 1728 char *vname;
1696 1729
1697 1730 if (oldnv != NULL) {
1698 1731 verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS,
1699 1732 (uint64_t **)&oldvs, &c) == 0);
1700 1733 } else {
1701 1734 oldvs = &zerovs;
1702 1735 }
1703 1736
1704 1737 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS,
1705 1738 (uint64_t **)&newvs, &c) == 0);
1706 1739
1707 1740 if (strlen(name) + depth > cb->cb_namewidth)
1708 1741 (void) printf("%*s%s", depth, "", name);
1709 1742 else
1710 1743 (void) printf("%*s%s%*s", depth, "", name,
1711 1744 (int)(cb->cb_namewidth - strlen(name) - depth), "");
1712 1745
1713 1746 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
1714 1747
1715 1748 if (tdelta == 0)
1716 1749 scale = 1.0;
1717 1750 else
1718 1751 scale = (double)NANOSEC / tdelta;
1719 1752
1720 1753 /* only toplevel vdevs have capacity stats */
1721 1754 if (newvs->vs_space == 0) {
1722 1755 (void) printf(" - -");
1723 1756 } else {
1724 1757 print_one_stat(newvs->vs_alloc);
1725 1758 print_one_stat(newvs->vs_space - newvs->vs_alloc);
1726 1759 }
1727 1760
1728 1761 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
1729 1762 oldvs->vs_ops[ZIO_TYPE_READ])));
1730 1763
1731 1764 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
1732 1765 oldvs->vs_ops[ZIO_TYPE_WRITE])));
1733 1766
1734 1767 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
1735 1768 oldvs->vs_bytes[ZIO_TYPE_READ])));
1736 1769
1737 1770 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
1738 1771 oldvs->vs_bytes[ZIO_TYPE_WRITE])));
1739 1772
1740 1773 (void) printf("\n");
1741 1774
1742 1775 if (!cb->cb_verbose)
1743 1776 return;
1744 1777
1745 1778 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
1746 1779 &newchild, &children) != 0)
1747 1780 return;
1748 1781
1749 1782 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
1750 1783 &oldchild, &c) != 0)
1751 1784 return;
1752 1785
1753 1786 for (c = 0; c < children; c++) {
1754 1787 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1755 1788 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1756 1789 newchild[c], cb, depth + 2);
1757 1790 free(vname);
1758 1791 }
1759 1792
1760 1793 /*
1761 1794 * Include level 2 ARC devices in iostat output
1762 1795 */
1763 1796 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
1764 1797 &newchild, &children) != 0)
1765 1798 return;
1766 1799
1767 1800 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
1768 1801 &oldchild, &c) != 0)
1769 1802 return;
1770 1803
1771 1804 if (children > 0) {
1772 1805 (void) printf("%-*s - - - - - "
1773 1806 "-\n", cb->cb_namewidth, "cache");
1774 1807 for (c = 0; c < children; c++) {
1775 1808 vname = zpool_vdev_name(g_zfs, zhp, newchild[c]);
1776 1809 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
1777 1810 newchild[c], cb, depth + 2);
1778 1811 free(vname);
1779 1812 }
1780 1813 }
1781 1814 }
1782 1815
1783 1816 static int
1784 1817 refresh_iostat(zpool_handle_t *zhp, void *data)
1785 1818 {
1786 1819 iostat_cbdata_t *cb = data;
1787 1820 boolean_t missing;
1788 1821
1789 1822 /*
1790 1823 * If the pool has disappeared, remove it from the list and continue.
1791 1824 */
1792 1825 if (zpool_refresh_stats(zhp, &missing) != 0)
1793 1826 return (-1);
1794 1827
1795 1828 if (missing)
1796 1829 pool_list_remove(cb->cb_list, zhp);
1797 1830
1798 1831 return (0);
1799 1832 }
1800 1833
1801 1834 /*
1802 1835 * Callback to print out the iostats for the given pool.
1803 1836 */
1804 1837 int
1805 1838 print_iostat(zpool_handle_t *zhp, void *data)
1806 1839 {
1807 1840 iostat_cbdata_t *cb = data;
1808 1841 nvlist_t *oldconfig, *newconfig;
1809 1842 nvlist_t *oldnvroot, *newnvroot;
1810 1843
1811 1844 newconfig = zpool_get_config(zhp, &oldconfig);
1812 1845
1813 1846 if (cb->cb_iteration == 1)
1814 1847 oldconfig = NULL;
1815 1848
1816 1849 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
1817 1850 &newnvroot) == 0);
1818 1851
1819 1852 if (oldconfig == NULL)
1820 1853 oldnvroot = NULL;
1821 1854 else
1822 1855 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
1823 1856 &oldnvroot) == 0);
1824 1857
1825 1858 /*
1826 1859 * Print out the statistics for the pool.
1827 1860 */
1828 1861 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
1829 1862
1830 1863 if (cb->cb_verbose)
1831 1864 print_iostat_separator(cb);
1832 1865
1833 1866 return (0);
1834 1867 }
1835 1868
1836 1869 int
1837 1870 get_namewidth(zpool_handle_t *zhp, void *data)
1838 1871 {
1839 1872 iostat_cbdata_t *cb = data;
1840 1873 nvlist_t *config, *nvroot;
1841 1874
1842 1875 if ((config = zpool_get_config(zhp, NULL)) != NULL) {
1843 1876 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1844 1877 &nvroot) == 0);
1845 1878 if (!cb->cb_verbose)
1846 1879 cb->cb_namewidth = strlen(zpool_get_name(zhp));
1847 1880 else
1848 1881 cb->cb_namewidth = max_width(zhp, nvroot, 0, 0);
1849 1882 }
1850 1883
1851 1884 /*
1852 1885 * The width must fall into the range [10,38]. The upper limit is the
1853 1886 * maximum we can have and still fit in 80 columns.
1854 1887 */
1855 1888 if (cb->cb_namewidth < 10)
1856 1889 cb->cb_namewidth = 10;
1857 1890 if (cb->cb_namewidth > 38)
1858 1891 cb->cb_namewidth = 38;
1859 1892
1860 1893 return (0);
1861 1894 }
1862 1895
1863 1896 /*
1864 1897 * zpool iostat [-v] [pool] ... [interval [count]]
1865 1898 *
1866 1899 * -v Display statistics for individual vdevs
1867 1900 *
1868 1901 * This command can be tricky because we want to be able to deal with pool
1869 1902 * creation/destruction as well as vdev configuration changes. The bulk of this
1870 1903 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
1871 1904 * on pool_list_update() to detect the addition of new pools. Configuration
1872 1905 * changes are all handled within libzfs.
1873 1906 */
1874 1907 int
1875 1908 zpool_do_iostat(int argc, char **argv)
1876 1909 {
1877 1910 int c;
1878 1911 int ret;
1879 1912 int npools;
1880 1913 unsigned long interval = 0, count = 0;
1881 1914 zpool_list_t *list;
1882 1915 boolean_t verbose = B_FALSE;
1883 1916 iostat_cbdata_t cb;
1884 1917
1885 1918 /* check options */
1886 1919 while ((c = getopt(argc, argv, "v")) != -1) {
1887 1920 switch (c) {
1888 1921 case 'v':
1889 1922 verbose = B_TRUE;
1890 1923 break;
1891 1924 case '?':
1892 1925 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1893 1926 optopt);
1894 1927 usage(B_FALSE);
1895 1928 }
1896 1929 }
1897 1930
1898 1931 argc -= optind;
1899 1932 argv += optind;
1900 1933
1901 1934 /*
1902 1935 * Determine if the last argument is an integer or a pool name
1903 1936 */
1904 1937 if (argc > 0 && isdigit(argv[argc - 1][0])) {
1905 1938 char *end;
1906 1939
1907 1940 errno = 0;
1908 1941 interval = strtoul(argv[argc - 1], &end, 10);
1909 1942
1910 1943 if (*end == '\0' && errno == 0) {
1911 1944 if (interval == 0) {
1912 1945 (void) fprintf(stderr, gettext("interval "
1913 1946 "cannot be zero\n"));
1914 1947 usage(B_FALSE);
1915 1948 }
1916 1949
1917 1950 /*
1918 1951 * Ignore the last parameter
1919 1952 */
1920 1953 argc--;
1921 1954 } else {
1922 1955 /*
1923 1956 * If this is not a valid number, just plow on. The
1924 1957 * user will get a more informative error message later
1925 1958 * on.
1926 1959 */
1927 1960 interval = 0;
1928 1961 }
1929 1962 }
1930 1963
1931 1964 /*
1932 1965 * If the last argument is also an integer, then we have both a count
1933 1966 * and an integer.
1934 1967 */
1935 1968 if (argc > 0 && isdigit(argv[argc - 1][0])) {
1936 1969 char *end;
1937 1970
1938 1971 errno = 0;
1939 1972 count = interval;
1940 1973 interval = strtoul(argv[argc - 1], &end, 10);
1941 1974
1942 1975 if (*end == '\0' && errno == 0) {
1943 1976 if (interval == 0) {
1944 1977 (void) fprintf(stderr, gettext("interval "
1945 1978 "cannot be zero\n"));
1946 1979 usage(B_FALSE);
1947 1980 }
1948 1981
1949 1982 /*
1950 1983 * Ignore the last parameter
1951 1984 */
1952 1985 argc--;
1953 1986 } else {
1954 1987 interval = 0;
1955 1988 }
1956 1989 }
1957 1990
1958 1991 /*
1959 1992 * Construct the list of all interesting pools.
1960 1993 */
1961 1994 ret = 0;
1962 1995 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
1963 1996 return (1);
1964 1997
1965 1998 if (pool_list_count(list) == 0 && argc != 0) {
1966 1999 pool_list_free(list);
1967 2000 return (1);
1968 2001 }
1969 2002
1970 2003 if (pool_list_count(list) == 0 && interval == 0) {
1971 2004 pool_list_free(list);
1972 2005 (void) fprintf(stderr, gettext("no pools available\n"));
1973 2006 return (1);
1974 2007 }
1975 2008
1976 2009 /*
1977 2010 * Enter the main iostat loop.
1978 2011 */
1979 2012 cb.cb_list = list;
1980 2013 cb.cb_verbose = verbose;
1981 2014 cb.cb_iteration = 0;
1982 2015 cb.cb_namewidth = 0;
1983 2016
1984 2017 for (;;) {
1985 2018 pool_list_update(list);
1986 2019
1987 2020 if ((npools = pool_list_count(list)) == 0)
1988 2021 break;
1989 2022
1990 2023 /*
1991 2024 * Refresh all statistics. This is done as an explicit step
1992 2025 * before calculating the maximum name width, so that any
1993 2026 * configuration changes are properly accounted for.
1994 2027 */
1995 2028 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
1996 2029
1997 2030 /*
1998 2031 * Iterate over all pools to determine the maximum width
1999 2032 * for the pool / device name column across all pools.
2000 2033 */
2001 2034 cb.cb_namewidth = 0;
2002 2035 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2003 2036
2004 2037 /*
2005 2038 * If it's the first time, or verbose mode, print the header.
2006 2039 */
2007 2040 if (++cb.cb_iteration == 1 || verbose)
2008 2041 print_iostat_header(&cb);
2009 2042
2010 2043 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
2011 2044
2012 2045 /*
2013 2046 * If there's more than one pool, and we're not in verbose mode
2014 2047 * (which prints a separator for us), then print a separator.
2015 2048 */
2016 2049 if (npools > 1 && !verbose)
2017 2050 print_iostat_separator(&cb);
2018 2051
2019 2052 if (verbose)
2020 2053 (void) printf("\n");
2021 2054
2022 2055 /*
2023 2056 * Flush the output so that redirection to a file isn't buffered
2024 2057 * indefinitely.
2025 2058 */
2026 2059 (void) fflush(stdout);
2027 2060
2028 2061 if (interval == 0)
2029 2062 break;
2030 2063
2031 2064 if (count != 0 && --count == 0)
2032 2065 break;
2033 2066
2034 2067 (void) sleep(interval);
2035 2068 }
2036 2069
2037 2070 pool_list_free(list);
2038 2071
2039 2072 return (ret);
2040 2073 }
2041 2074
2042 2075 typedef struct list_cbdata {
2043 2076 boolean_t cb_scripted;
2044 2077 boolean_t cb_first;
2045 2078 zprop_list_t *cb_proplist;
2046 2079 } list_cbdata_t;
2047 2080
2048 2081 /*
2049 2082 * Given a list of columns to display, output appropriate headers for each one.
2050 2083 */
2051 2084 static void
2052 2085 print_header(zprop_list_t *pl)
2053 2086 {
2054 2087 const char *header;
2055 2088 boolean_t first = B_TRUE;
2056 2089 boolean_t right_justify;
2057 2090
2058 2091 for (; pl != NULL; pl = pl->pl_next) {
2059 2092 if (pl->pl_prop == ZPROP_INVAL)
2060 2093 continue;
2061 2094
2062 2095 if (!first)
2063 2096 (void) printf(" ");
2064 2097 else
2065 2098 first = B_FALSE;
2066 2099
2067 2100 header = zpool_prop_column_name(pl->pl_prop);
2068 2101 right_justify = zpool_prop_align_right(pl->pl_prop);
2069 2102
2070 2103 if (pl->pl_next == NULL && !right_justify)
2071 2104 (void) printf("%s", header);
2072 2105 else if (right_justify)
2073 2106 (void) printf("%*s", pl->pl_width, header);
2074 2107 else
2075 2108 (void) printf("%-*s", pl->pl_width, header);
2076 2109 }
2077 2110
2078 2111 (void) printf("\n");
2079 2112 }
2080 2113
2081 2114 /*
2082 2115 * Given a pool and a list of properties, print out all the properties according
2083 2116 * to the described layout.
2084 2117 */
2085 2118 static void
2086 2119 print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
2087 2120 {
2088 2121 boolean_t first = B_TRUE;
2089 2122 char property[ZPOOL_MAXPROPLEN];
2090 2123 char *propstr;
2091 2124 boolean_t right_justify;
2092 2125 int width;
2093 2126
2094 2127 for (; pl != NULL; pl = pl->pl_next) {
2095 2128 if (!first) {
2096 2129 if (scripted)
2097 2130 (void) printf("\t");
2098 2131 else
2099 2132 (void) printf(" ");
2100 2133 } else {
2101 2134 first = B_FALSE;
2102 2135 }
2103 2136
2104 2137 right_justify = B_FALSE;
2105 2138 if (pl->pl_prop != ZPROP_INVAL) {
2106 2139 if (zpool_get_prop(zhp, pl->pl_prop, property,
2107 2140 sizeof (property), NULL) != 0)
2108 2141 propstr = "-";
2109 2142 else
2110 2143 propstr = property;
2111 2144
2112 2145 right_justify = zpool_prop_align_right(pl->pl_prop);
2113 2146 } else {
2114 2147 propstr = "-";
2115 2148 }
2116 2149
2117 2150 width = pl->pl_width;
2118 2151
2119 2152 /*
2120 2153 * If this is being called in scripted mode, or if this is the
2121 2154 * last column and it is left-justified, don't include a width
2122 2155 * format specifier.
2123 2156 */
2124 2157 if (scripted || (pl->pl_next == NULL && !right_justify))
2125 2158 (void) printf("%s", propstr);
2126 2159 else if (right_justify)
2127 2160 (void) printf("%*s", width, propstr);
2128 2161 else
2129 2162 (void) printf("%-*s", width, propstr);
2130 2163 }
2131 2164
2132 2165 (void) printf("\n");
2133 2166 }
2134 2167
2135 2168 /*
2136 2169 * Generic callback function to list a pool.
2137 2170 */
2138 2171 int
2139 2172 list_callback(zpool_handle_t *zhp, void *data)
2140 2173 {
2141 2174 list_cbdata_t *cbp = data;
2142 2175
2143 2176 if (cbp->cb_first) {
2144 2177 if (!cbp->cb_scripted)
2145 2178 print_header(cbp->cb_proplist);
2146 2179 cbp->cb_first = B_FALSE;
2147 2180 }
2148 2181
2149 2182 print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted);
2150 2183
2151 2184 return (0);
2152 2185 }
2153 2186
2154 2187 /*
2155 2188 * zpool list [-H] [-o prop[,prop]*] [pool] ...
2156 2189 *
2157 2190 * -H Scripted mode. Don't display headers, and separate properties
2158 2191 * by a single tab.
2159 2192 * -o List of properties to display. Defaults to
2160 2193 * "name,size,used,available,capacity,health,altroot"
2161 2194 *
2162 2195 * List all pools in the system, whether or not they're healthy. Output space
2163 2196 * statistics for each one, as well as health status summary.
2164 2197 */
2165 2198 int
2166 2199 zpool_do_list(int argc, char **argv)
2167 2200 {
2168 2201 int c;
2169 2202 int ret;
2170 2203 list_cbdata_t cb = { 0 };
2171 2204 static char default_props[] =
2172 2205 "name,size,used,available,capacity,health,altroot";
2173 2206 char *props = default_props;
2174 2207
2175 2208 /* check options */
2176 2209 while ((c = getopt(argc, argv, ":Ho:")) != -1) {
2177 2210 switch (c) {
2178 2211 case 'H':
2179 2212 cb.cb_scripted = B_TRUE;
2180 2213 break;
2181 2214 case 'o':
2182 2215 props = optarg;
2183 2216 break;
2184 2217 case ':':
2185 2218 (void) fprintf(stderr, gettext("missing argument for "
2186 2219 "'%c' option\n"), optopt);
2187 2220 usage(B_FALSE);
2188 2221 break;
2189 2222 case '?':
2190 2223 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2191 2224 optopt);
2192 2225 usage(B_FALSE);
2193 2226 }
2194 2227 }
2195 2228
2196 2229 argc -= optind;
2197 2230 argv += optind;
2198 2231
2199 2232 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
2200 2233 usage(B_FALSE);
2201 2234
2202 2235 cb.cb_first = B_TRUE;
2203 2236
2204 2237 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
2205 2238 list_callback, &cb);
2206 2239
2207 2240 zprop_free_list(cb.cb_proplist);
2208 2241
2209 2242 if (argc == 0 && cb.cb_first && !cb.cb_scripted) {
2210 2243 (void) printf(gettext("no pools available\n"));
2211 2244 return (0);
2212 2245 }
2213 2246
2214 2247 return (ret);
2215 2248 }
2216 2249
2217 2250 static nvlist_t *
2218 2251 zpool_get_vdev_by_name(nvlist_t *nv, char *name)
2219 2252 {
2220 2253 nvlist_t **child;
2221 2254 uint_t c, children;
2222 2255 nvlist_t *match;
2223 2256 char *path;
2224 2257
2225 2258 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2226 2259 &child, &children) != 0) {
2227 2260 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2228 2261 if (strncmp(name, "/dev/dsk/", 9) == 0)
2229 2262 name += 9;
2230 2263 if (strncmp(path, "/dev/dsk/", 9) == 0)
2231 2264 path += 9;
2232 2265 if (strcmp(name, path) == 0)
2233 2266 return (nv);
2234 2267 return (NULL);
2235 2268 }
2236 2269
2237 2270 for (c = 0; c < children; c++)
2238 2271 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL)
2239 2272 return (match);
2240 2273
2241 2274 return (NULL);
2242 2275 }
2243 2276
2244 2277 static int
2245 2278 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
2246 2279 {
2247 2280 boolean_t force = B_FALSE;
2248 2281 int c;
2249 2282 nvlist_t *nvroot;
2250 2283 char *poolname, *old_disk, *new_disk;
2251 2284 zpool_handle_t *zhp;
2252 2285 int ret;
2253 2286
2254 2287 /* check options */
2255 2288 while ((c = getopt(argc, argv, "f")) != -1) {
2256 2289 switch (c) {
2257 2290 case 'f':
2258 2291 force = B_TRUE;
2259 2292 break;
2260 2293 case '?':
2261 2294 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2262 2295 optopt);
2263 2296 usage(B_FALSE);
2264 2297 }
2265 2298 }
2266 2299
2267 2300 argc -= optind;
2268 2301 argv += optind;
2269 2302
2270 2303 /* get pool name and check number of arguments */
2271 2304 if (argc < 1) {
2272 2305 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2273 2306 usage(B_FALSE);
2274 2307 }
2275 2308
2276 2309 poolname = argv[0];
2277 2310
2278 2311 if (argc < 2) {
2279 2312 (void) fprintf(stderr,
2280 2313 gettext("missing <device> specification\n"));
2281 2314 usage(B_FALSE);
2282 2315 }
2283 2316
2284 2317 old_disk = argv[1];
2285 2318
2286 2319 if (argc < 3) {
2287 2320 if (!replacing) {
2288 2321 (void) fprintf(stderr,
2289 2322 gettext("missing <new_device> specification\n"));
2290 2323 usage(B_FALSE);
2291 2324 }
2292 2325 new_disk = old_disk;
2293 2326 argc -= 1;
2294 2327 argv += 1;
2295 2328 } else {
2296 2329 new_disk = argv[2];
2297 2330 argc -= 2;
2298 2331 argv += 2;
2299 2332 }
2300 2333
2301 2334 if (argc > 1) {
2302 2335 (void) fprintf(stderr, gettext("too many arguments\n"));
2303 2336 usage(B_FALSE);
2304 2337 }
2305 2338
2306 2339 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2307 2340 return (1);
2308 2341
2309 2342 if (zpool_get_config(zhp, NULL) == NULL) {
2310 2343 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
2311 2344 poolname);
2312 2345 zpool_close(zhp);
2313 2346 return (1);
2314 2347 }
2315 2348
2316 2349 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
2317 2350 argc, argv);
2318 2351 if (nvroot == NULL) {
2319 2352 zpool_close(zhp);
2320 2353 return (1);
2321 2354 }
2322 2355
2323 2356 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
2324 2357
2325 2358 nvlist_free(nvroot);
2326 2359 zpool_close(zhp);
2327 2360
2328 2361 return (ret);
2329 2362 }
2330 2363
2331 2364 /*
2332 2365 * zpool replace [-f] <pool> <device> <new_device>
2333 2366 *
2334 2367 * -f Force attach, even if <new_device> appears to be in use.
2335 2368 *
2336 2369 * Replace <device> with <new_device>.
2337 2370 */
2338 2371 /* ARGSUSED */
2339 2372 int
2340 2373 zpool_do_replace(int argc, char **argv)
2341 2374 {
2342 2375 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
2343 2376 }
2344 2377
2345 2378 /*
2346 2379 * zpool attach [-f] <pool> <device> <new_device>
2347 2380 *
2348 2381 * -f Force attach, even if <new_device> appears to be in use.
2349 2382 *
2350 2383 * Attach <new_device> to the mirror containing <device>. If <device> is not
2351 2384 * part of a mirror, then <device> will be transformed into a mirror of
2352 2385 * <device> and <new_device>. In either case, <new_device> will begin life
2353 2386 * with a DTL of [0, now], and will immediately begin to resilver itself.
2354 2387 */
2355 2388 int
2356 2389 zpool_do_attach(int argc, char **argv)
2357 2390 {
2358 2391 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
2359 2392 }
2360 2393
2361 2394 /*
2362 2395 * zpool detach [-f] <pool> <device>
2363 2396 *
2364 2397 * -f Force detach of <device>, even if DTLs argue against it
2365 2398 * (not supported yet)
2366 2399 *
2367 2400 * Detach a device from a mirror. The operation will be refused if <device>
2368 2401 * is the last device in the mirror, or if the DTLs indicate that this device
2369 2402 * has the only valid copy of some data.
2370 2403 */
2371 2404 /* ARGSUSED */
2372 2405 int
2373 2406 zpool_do_detach(int argc, char **argv)
2374 2407 {
2375 2408 int c;
2376 2409 char *poolname, *path;
2377 2410 zpool_handle_t *zhp;
2378 2411 int ret;
2379 2412
2380 2413 /* check options */
2381 2414 while ((c = getopt(argc, argv, "f")) != -1) {
2382 2415 switch (c) {
2383 2416 case 'f':
2384 2417 case '?':
2385 2418 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2386 2419 optopt);
2387 2420 usage(B_FALSE);
2388 2421 }
2389 2422 }
2390 2423
2391 2424 argc -= optind;
2392 2425 argv += optind;
2393 2426
2394 2427 /* get pool name and check number of arguments */
2395 2428 if (argc < 1) {
2396 2429 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2397 2430 usage(B_FALSE);
2398 2431 }
2399 2432
2400 2433 if (argc < 2) {
2401 2434 (void) fprintf(stderr,
2402 2435 gettext("missing <device> specification\n"));
2403 2436 usage(B_FALSE);
2404 2437 }
2405 2438
2406 2439 poolname = argv[0];
2407 2440 path = argv[1];
2408 2441
2409 2442 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2410 2443 return (1);
2411 2444
2412 2445 ret = zpool_vdev_detach(zhp, path);
2413 2446
2414 2447 zpool_close(zhp);
2415 2448
2416 2449 return (ret);
2417 2450 }
2418 2451
2419 2452 /*
2420 2453 * zpool online <pool> <device> ...
2421 2454 */
2422 2455 int
2423 2456 zpool_do_online(int argc, char **argv)
2424 2457 {
2425 2458 int c, i;
2426 2459 char *poolname;
2427 2460 zpool_handle_t *zhp;
2428 2461 int ret = 0;
2429 2462 vdev_state_t newstate;
2430 2463
2431 2464 /* check options */
2432 2465 while ((c = getopt(argc, argv, "t")) != -1) {
2433 2466 switch (c) {
2434 2467 case 't':
2435 2468 case '?':
2436 2469 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2437 2470 optopt);
2438 2471 usage(B_FALSE);
2439 2472 }
2440 2473 }
2441 2474
2442 2475 argc -= optind;
2443 2476 argv += optind;
2444 2477
2445 2478 /* get pool name and check number of arguments */
2446 2479 if (argc < 1) {
2447 2480 (void) fprintf(stderr, gettext("missing pool name\n"));
2448 2481 usage(B_FALSE);
2449 2482 }
2450 2483 if (argc < 2) {
2451 2484 (void) fprintf(stderr, gettext("missing device name\n"));
2452 2485 usage(B_FALSE);
2453 2486 }
2454 2487
2455 2488 poolname = argv[0];
2456 2489
2457 2490 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2458 2491 return (1);
2459 2492
2460 2493 for (i = 1; i < argc; i++) {
2461 2494 if (zpool_vdev_online(zhp, argv[i], 0, &newstate) == 0) {
2462 2495 if (newstate != VDEV_STATE_HEALTHY) {
2463 2496 (void) printf(gettext("warning: device '%s' "
2464 2497 "onlined, but remains in faulted state\n"),
2465 2498 argv[i]);
2466 2499 if (newstate == VDEV_STATE_FAULTED)
2467 2500 (void) printf(gettext("use 'zpool "
2468 2501 "clear' to restore a faulted "
2469 2502 "device\n"));
2470 2503 else
2471 2504 (void) printf(gettext("use 'zpool "
2472 2505 "replace' to replace devices "
2473 2506 "that are no longer present\n"));
2474 2507 }
2475 2508 } else {
2476 2509 ret = 1;
2477 2510 }
2478 2511 }
2479 2512
2480 2513 zpool_close(zhp);
2481 2514
2482 2515 return (ret);
2483 2516 }
2484 2517
2485 2518 /*
2486 2519 * zpool offline [-ft] <pool> <device> ...
2487 2520 *
2488 2521 * -f Force the device into the offline state, even if doing
2489 2522 * so would appear to compromise pool availability.
2490 2523 * (not supported yet)
2491 2524 *
2492 2525 * -t Only take the device off-line temporarily. The offline
2493 2526 * state will not be persistent across reboots.
2494 2527 */
2495 2528 /* ARGSUSED */
2496 2529 int
2497 2530 zpool_do_offline(int argc, char **argv)
2498 2531 {
2499 2532 int c, i;
2500 2533 char *poolname;
2501 2534 zpool_handle_t *zhp;
2502 2535 int ret = 0;
2503 2536 boolean_t istmp = B_FALSE;
2504 2537
2505 2538 /* check options */
2506 2539 while ((c = getopt(argc, argv, "ft")) != -1) {
2507 2540 switch (c) {
2508 2541 case 't':
2509 2542 istmp = B_TRUE;
2510 2543 break;
2511 2544 case 'f':
2512 2545 case '?':
2513 2546 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2514 2547 optopt);
2515 2548 usage(B_FALSE);
2516 2549 }
2517 2550 }
2518 2551
2519 2552 argc -= optind;
2520 2553 argv += optind;
2521 2554
2522 2555 /* get pool name and check number of arguments */
2523 2556 if (argc < 1) {
2524 2557 (void) fprintf(stderr, gettext("missing pool name\n"));
2525 2558 usage(B_FALSE);
2526 2559 }
2527 2560 if (argc < 2) {
2528 2561 (void) fprintf(stderr, gettext("missing device name\n"));
2529 2562 usage(B_FALSE);
2530 2563 }
2531 2564
2532 2565 poolname = argv[0];
2533 2566
2534 2567 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
2535 2568 return (1);
2536 2569
2537 2570 for (i = 1; i < argc; i++) {
2538 2571 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
2539 2572 ret = 1;
2540 2573 }
2541 2574
2542 2575 zpool_close(zhp);
2543 2576
2544 2577 return (ret);
2545 2578 }
2546 2579
2547 2580 /*
2548 2581 * zpool clear <pool> [device]
2549 2582 *
2550 2583 * Clear all errors associated with a pool or a particular device.
2551 2584 */
2552 2585 int
2553 2586 zpool_do_clear(int argc, char **argv)
2554 2587 {
2555 2588 int ret = 0;
2556 2589 zpool_handle_t *zhp;
2557 2590 char *pool, *device;
2558 2591
2559 2592 if (argc < 2) {
2560 2593 (void) fprintf(stderr, gettext("missing pool name\n"));
2561 2594 usage(B_FALSE);
2562 2595 }
2563 2596
2564 2597 if (argc > 3) {
2565 2598 (void) fprintf(stderr, gettext("too many arguments\n"));
2566 2599 usage(B_FALSE);
2567 2600 }
2568 2601
2569 2602 pool = argv[1];
2570 2603 device = argc == 3 ? argv[2] : NULL;
2571 2604
2572 2605 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
2573 2606 return (1);
2574 2607
2575 2608 if (zpool_clear(zhp, device) != 0)
2576 2609 ret = 1;
2577 2610
2578 2611 zpool_close(zhp);
2579 2612
2580 2613 return (ret);
2581 2614 }
2582 2615
2583 2616 typedef struct scrub_cbdata {
2584 2617 int cb_type;
2585 2618 int cb_argc;
2586 2619 char **cb_argv;
2587 2620 } scrub_cbdata_t;
2588 2621
2589 2622 int
2590 2623 scrub_callback(zpool_handle_t *zhp, void *data)
2591 2624 {
2592 2625 scrub_cbdata_t *cb = data;
2593 2626 int err;
2594 2627
2595 2628 /*
2596 2629 * Ignore faulted pools.
2597 2630 */
2598 2631 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
2599 2632 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
2600 2633 "currently unavailable\n"), zpool_get_name(zhp));
2601 2634 return (1);
2602 2635 }
2603 2636
2604 2637 err = zpool_scrub(zhp, cb->cb_type);
2605 2638
2606 2639 return (err != 0);
2607 2640 }
2608 2641
2609 2642 /*
2610 2643 * zpool scrub [-s] <pool> ...
2611 2644 *
2612 2645 * -s Stop. Stops any in-progress scrub.
2613 2646 */
2614 2647 int
2615 2648 zpool_do_scrub(int argc, char **argv)
2616 2649 {
2617 2650 int c;
2618 2651 scrub_cbdata_t cb;
2619 2652
2620 2653 cb.cb_type = POOL_SCRUB_EVERYTHING;
2621 2654
2622 2655 /* check options */
2623 2656 while ((c = getopt(argc, argv, "s")) != -1) {
2624 2657 switch (c) {
2625 2658 case 's':
2626 2659 cb.cb_type = POOL_SCRUB_NONE;
2627 2660 break;
2628 2661 case '?':
2629 2662 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2630 2663 optopt);
2631 2664 usage(B_FALSE);
2632 2665 }
2633 2666 }
2634 2667
2635 2668 cb.cb_argc = argc;
2636 2669 cb.cb_argv = argv;
2637 2670 argc -= optind;
2638 2671 argv += optind;
2639 2672
2640 2673 if (argc < 1) {
2641 2674 (void) fprintf(stderr, gettext("missing pool name argument\n"));
2642 2675 usage(B_FALSE);
2643 2676 }
2644 2677
2645 2678 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
2646 2679 }
2647 2680
2648 2681 typedef struct status_cbdata {
2649 2682 int cb_count;
2650 2683 boolean_t cb_allpools;
2651 2684 boolean_t cb_verbose;
2652 2685 boolean_t cb_explain;
2653 2686 boolean_t cb_first;
2654 2687 } status_cbdata_t;
2655 2688
2656 2689 /*
2657 2690 * Print out detailed scrub status.
2658 2691 */
2659 2692 void
2660 2693 print_scrub_status(nvlist_t *nvroot)
2661 2694 {
2662 2695 vdev_stat_t *vs;
2663 2696 uint_t vsc;
2664 2697 time_t start, end, now;
2665 2698 double fraction_done;
2666 2699 uint64_t examined, total, minutes_left, minutes_taken;
2667 2700 char *scrub_type;
2668 2701
2669 2702 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
2670 2703 (uint64_t **)&vs, &vsc) == 0);
2671 2704
2672 2705 /*
2673 2706 * If there's never been a scrub, there's not much to say.
2674 2707 */
2675 2708 if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) {
2676 2709 (void) printf(gettext("none requested\n"));
2677 2710 return;
2678 2711 }
2679 2712
2680 2713 scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2681 2714 "resilver" : "scrub";
2682 2715
2683 2716 start = vs->vs_scrub_start;
2684 2717 end = vs->vs_scrub_end;
2685 2718 now = time(NULL);
2686 2719 examined = vs->vs_scrub_examined;
2687 2720 total = vs->vs_alloc;
2688 2721
2689 2722 if (end != 0) {
2690 2723 minutes_taken = (uint64_t)((end - start) / 60);
2691 2724
2692 2725 (void) printf(gettext("%s %s after %lluh%um with %llu errors "
2693 2726 "on %s"),
2694 2727 scrub_type, vs->vs_scrub_complete ? "completed" : "stopped",
2695 2728 (u_longlong_t)(minutes_taken / 60),
2696 2729 (uint_t)(minutes_taken % 60),
2697 2730 (u_longlong_t)vs->vs_scrub_errors, ctime(&end));
2698 2731 return;
2699 2732 }
2700 2733
2701 2734 if (examined == 0)
2702 2735 examined = 1;
2703 2736 if (examined > total)
2704 2737 total = examined;
2705 2738
2706 2739 fraction_done = (double)examined / total;
2707 2740 minutes_left = (uint64_t)((now - start) *
2708 2741 (1 - fraction_done) / fraction_done / 60);
2709 2742 minutes_taken = (uint64_t)((now - start) / 60);
2710 2743
2711 2744 (void) printf(gettext("%s in progress for %lluh%um, %.2f%% done, "
2712 2745 "%lluh%um to go\n"),
2713 2746 scrub_type, (u_longlong_t)(minutes_taken / 60),
2714 2747 (uint_t)(minutes_taken % 60), 100 * fraction_done,
2715 2748 (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60));
2716 2749 }
2717 2750
2718 2751 typedef struct spare_cbdata {
2719 2752 uint64_t cb_guid;
2720 2753 zpool_handle_t *cb_zhp;
2721 2754 } spare_cbdata_t;
2722 2755
2723 2756 static boolean_t
2724 2757 find_vdev(nvlist_t *nv, uint64_t search)
2725 2758 {
2726 2759 uint64_t guid;
2727 2760 nvlist_t **child;
2728 2761 uint_t c, children;
2729 2762
2730 2763 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
2731 2764 search == guid)
2732 2765 return (B_TRUE);
2733 2766
2734 2767 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2735 2768 &child, &children) == 0) {
2736 2769 for (c = 0; c < children; c++)
2737 2770 if (find_vdev(child[c], search))
2738 2771 return (B_TRUE);
2739 2772 }
2740 2773
2741 2774 return (B_FALSE);
2742 2775 }
2743 2776
2744 2777 static int
2745 2778 find_spare(zpool_handle_t *zhp, void *data)
2746 2779 {
2747 2780 spare_cbdata_t *cbp = data;
2748 2781 nvlist_t *config, *nvroot;
2749 2782
2750 2783 config = zpool_get_config(zhp, NULL);
2751 2784 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2752 2785 &nvroot) == 0);
2753 2786
2754 2787 if (find_vdev(nvroot, cbp->cb_guid)) {
2755 2788 cbp->cb_zhp = zhp;
2756 2789 return (1);
2757 2790 }
2758 2791
2759 2792 zpool_close(zhp);
2760 2793 return (0);
2761 2794 }
2762 2795
2763 2796 /*
2764 2797 * Print out configuration state as requested by status_callback.
2765 2798 */
2766 2799 void
2767 2800 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
2768 2801 int namewidth, int depth, boolean_t isspare, boolean_t print_logs)
2769 2802 {
2770 2803 nvlist_t **child;
2771 2804 uint_t c, children;
2772 2805 vdev_stat_t *vs;
2773 2806 char rbuf[6], wbuf[6], cbuf[6], repaired[7];
2774 2807 char *vname;
2775 2808 uint64_t notpresent;
2776 2809 spare_cbdata_t cb;
2777 2810 char *state;
2778 2811
2779 2812 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
2780 2813 (uint64_t **)&vs, &c) == 0);
2781 2814
2782 2815 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
2783 2816 &child, &children) != 0)
2784 2817 children = 0;
2785 2818
2786 2819 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
2787 2820 if (isspare) {
2788 2821 /*
2789 2822 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
2790 2823 * online drives.
2791 2824 */
2792 2825 if (vs->vs_aux == VDEV_AUX_SPARED)
2793 2826 state = "INUSE";
2794 2827 else if (vs->vs_state == VDEV_STATE_HEALTHY)
2795 2828 state = "AVAIL";
2796 2829 }
2797 2830
2798 2831 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth,
2799 2832 name, state);
2800 2833
2801 2834 if (!isspare) {
2802 2835 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
2803 2836 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
2804 2837 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
2805 2838 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
2806 2839 }
2807 2840
2808 2841 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
2809 2842 ¬present) == 0) {
2810 2843 char *path;
2811 2844 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
2812 2845 (void) printf(" was %s", path);
2813 2846 } else if (vs->vs_aux != 0) {
2814 2847 (void) printf(" ");
2815 2848
2816 2849 switch (vs->vs_aux) {
2817 2850 case VDEV_AUX_OPEN_FAILED:
2818 2851 (void) printf(gettext("cannot open"));
2819 2852 break;
2820 2853
2821 2854 case VDEV_AUX_BAD_GUID_SUM:
2822 2855 (void) printf(gettext("missing device"));
2823 2856 break;
2824 2857
2825 2858 case VDEV_AUX_NO_REPLICAS:
2826 2859 (void) printf(gettext("insufficient replicas"));
2827 2860 break;
2828 2861
2829 2862 case VDEV_AUX_VERSION_NEWER:
2830 2863 (void) printf(gettext("newer version"));
2831 2864 break;
2832 2865
2833 2866 case VDEV_AUX_SPARED:
2834 2867 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
2835 2868 &cb.cb_guid) == 0);
2836 2869 if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
2837 2870 if (strcmp(zpool_get_name(cb.cb_zhp),
2838 2871 zpool_get_name(zhp)) == 0)
2839 2872 (void) printf(gettext("currently in "
2840 2873 "use"));
2841 2874 else
2842 2875 (void) printf(gettext("in use by "
2843 2876 "pool '%s'"),
2844 2877 zpool_get_name(cb.cb_zhp));
2845 2878 zpool_close(cb.cb_zhp);
2846 2879 } else {
2847 2880 (void) printf(gettext("currently in use"));
2848 2881 }
2849 2882 break;
2850 2883
2851 2884 case VDEV_AUX_ERR_EXCEEDED:
2852 2885 (void) printf(gettext("too many errors"));
2853 2886 break;
2854 2887
2855 2888 case VDEV_AUX_IO_FAILURE:
2856 2889 (void) printf(gettext("experienced I/O failures"));
2857 2890 break;
2858 2891
2859 2892 case VDEV_AUX_BAD_LOG:
2860 2893 (void) printf(gettext("bad intent log"));
2861 2894 break;
2862 2895
2863 2896 default:
2864 2897 (void) printf(gettext("corrupted data"));
2865 2898 break;
2866 2899 }
2867 2900 } else if (vs->vs_scrub_repaired != 0 && children == 0) {
2868 2901 /*
2869 2902 * Report bytes resilvered/repaired on leaf devices.
2870 2903 */
2871 2904 zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired));
2872 2905 (void) printf(gettext(" %s %s"), repaired,
2873 2906 (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ?
2874 2907 "resilvered" : "repaired");
2875 2908 }
2876 2909
2877 2910 (void) printf("\n");
2878 2911
2879 2912 for (c = 0; c < children; c++) {
2880 2913 uint64_t is_log = B_FALSE;
2881 2914
2882 2915 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
2883 2916 &is_log);
2884 2917 if ((is_log && !print_logs) || (!is_log && print_logs))
2885 2918 continue;
2886 2919 vname = zpool_vdev_name(g_zfs, zhp, child[c]);
2887 2920 print_status_config(zhp, vname, child[c],
2888 2921 namewidth, depth + 2, isspare, B_FALSE);
2889 2922 free(vname);
2890 2923 }
2891 2924 }
2892 2925
2893 2926 static void
2894 2927 print_error_log(zpool_handle_t *zhp)
2895 2928 {
2896 2929 nvlist_t *nverrlist = NULL;
2897 2930 nvpair_t *elem;
2898 2931 char *pathname;
2899 2932 size_t len = MAXPATHLEN * 2;
2900 2933
2901 2934 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
2902 2935 (void) printf("errors: List of errors unavailable "
2903 2936 "(insufficient privileges)\n");
2904 2937 return;
2905 2938 }
2906 2939
2907 2940 (void) printf("errors: Permanent errors have been "
2908 2941 "detected in the following files:\n\n");
2909 2942
2910 2943 pathname = safe_malloc(len);
2911 2944 elem = NULL;
2912 2945 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
2913 2946 nvlist_t *nv;
2914 2947 uint64_t dsobj, obj;
2915 2948
2916 2949 verify(nvpair_value_nvlist(elem, &nv) == 0);
2917 2950 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
2918 2951 &dsobj) == 0);
2919 2952 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
2920 2953 &obj) == 0);
2921 2954 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
2922 2955 (void) printf("%7s %s\n", "", pathname);
2923 2956 }
2924 2957 free(pathname);
2925 2958 nvlist_free(nverrlist);
2926 2959 }
2927 2960
2928 2961 static void
2929 2962 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
2930 2963 int namewidth)
2931 2964 {
2932 2965 uint_t i;
2933 2966 char *name;
2934 2967
2935 2968 if (nspares == 0)
2936 2969 return;
2937 2970
2938 2971 (void) printf(gettext("\tspares\n"));
2939 2972
2940 2973 for (i = 0; i < nspares; i++) {
2941 2974 name = zpool_vdev_name(g_zfs, zhp, spares[i]);
2942 2975 print_status_config(zhp, name, spares[i],
2943 2976 namewidth, 2, B_TRUE, B_FALSE);
2944 2977 free(name);
2945 2978 }
2946 2979 }
2947 2980
2948 2981 static void
2949 2982 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
2950 2983 int namewidth)
2951 2984 {
2952 2985 uint_t i;
2953 2986 char *name;
2954 2987
2955 2988 if (nl2cache == 0)
2956 2989 return;
2957 2990
2958 2991 (void) printf(gettext("\tcache\n"));
2959 2992
2960 2993 for (i = 0; i < nl2cache; i++) {
2961 2994 name = zpool_vdev_name(g_zfs, zhp, l2cache[i]);
2962 2995 print_status_config(zhp, name, l2cache[i],
2963 2996 namewidth, 2, B_FALSE, B_FALSE);
2964 2997 free(name);
2965 2998 }
2966 2999 }
2967 3000
2968 3001 /*
2969 3002 * Display a summary of pool status. Displays a summary such as:
2970 3003 *
2971 3004 * pool: tank
2972 3005 * status: DEGRADED
2973 3006 * reason: One or more devices ...
2974 3007 * see: http://www.sun.com/msg/ZFS-xxxx-01
2975 3008 * config:
2976 3009 * mirror DEGRADED
2977 3010 * c1t0d0 OK
2978 3011 * c2t0d0 UNAVAIL
2979 3012 *
2980 3013 * When given the '-v' option, we print out the complete config. If the '-e'
2981 3014 * option is specified, then we print out error rate information as well.
2982 3015 */
|
↓ open down ↓ |
1639 lines elided |
↑ open up ↑ |
2983 3016 int
2984 3017 status_callback(zpool_handle_t *zhp, void *data)
2985 3018 {
2986 3019 status_cbdata_t *cbp = data;
2987 3020 nvlist_t *config, *nvroot;
2988 3021 char *msgid;
2989 3022 int reason;
2990 3023 const char *health;
2991 3024 uint_t c;
2992 3025 vdev_stat_t *vs;
3026 + char keystatus[MAXNAMELEN];
3027 + zprop_source_t srctype;
2993 3028
2994 3029 config = zpool_get_config(zhp, NULL);
2995 3030 reason = zpool_get_status(zhp, &msgid);
2996 3031
2997 3032 cbp->cb_count++;
2998 3033
2999 3034 /*
3000 3035 * If we were given 'zpool status -x', only report those pools with
3001 3036 * problems.
3002 3037 */
3003 3038 if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) {
3004 3039 if (!cbp->cb_allpools) {
3005 3040 (void) printf(gettext("pool '%s' is healthy\n"),
3006 3041 zpool_get_name(zhp));
3007 3042 if (cbp->cb_first)
3008 3043 cbp->cb_first = B_FALSE;
3009 3044 }
3010 3045 return (0);
3011 3046 }
3012 3047
3013 3048 if (cbp->cb_first)
3014 3049 cbp->cb_first = B_FALSE;
3015 3050 else
3016 3051 (void) printf("\n");
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
3017 3052
3018 3053 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3019 3054 &nvroot) == 0);
3020 3055 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
3021 3056 (uint64_t **)&vs, &c) == 0);
3022 3057 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
3023 3058
3024 3059 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
3025 3060 (void) printf(gettext(" state: %s\n"), health);
3026 3061
3062 + (void) zpool_get_prop(zhp, ZPOOL_PROP_KEYSTATUS, keystatus,
3063 + sizeof (keystatus), &srctype);
3064 +
3065 + (void) printf(gettext(" key: %s\n"), keystatus);
3066 +
3027 3067 switch (reason) {
3028 3068 case ZPOOL_STATUS_MISSING_DEV_R:
3029 3069 (void) printf(gettext("status: One or more devices could not "
3030 3070 "be opened. Sufficient replicas exist for\n\tthe pool to "
3031 3071 "continue functioning in a degraded state.\n"));
3032 3072 (void) printf(gettext("action: Attach the missing device and "
3033 3073 "online it using 'zpool online'.\n"));
3034 3074 break;
3035 3075
3036 3076 case ZPOOL_STATUS_MISSING_DEV_NR:
3037 3077 (void) printf(gettext("status: One or more devices could not "
3038 3078 "be opened. There are insufficient\n\treplicas for the "
3039 3079 "pool to continue functioning.\n"));
3040 3080 (void) printf(gettext("action: Attach the missing device and "
3041 3081 "online it using 'zpool online'.\n"));
3042 3082 break;
3043 3083
3044 3084 case ZPOOL_STATUS_CORRUPT_LABEL_R:
3045 3085 (void) printf(gettext("status: One or more devices could not "
3046 3086 "be used because the label is missing or\n\tinvalid. "
3047 3087 "Sufficient replicas exist for the pool to continue\n\t"
3048 3088 "functioning in a degraded state.\n"));
3049 3089 (void) printf(gettext("action: Replace the device using "
3050 3090 "'zpool replace'.\n"));
3051 3091 break;
3052 3092
3053 3093 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
3054 3094 (void) printf(gettext("status: One or more devices could not "
3055 3095 "be used because the label is missing \n\tor invalid. "
3056 3096 "There are insufficient replicas for the pool to "
3057 3097 "continue\n\tfunctioning.\n"));
3058 3098 (void) printf(gettext("action: Destroy and re-create the pool "
3059 3099 "from a backup source.\n"));
3060 3100 break;
3061 3101
3062 3102 case ZPOOL_STATUS_FAILING_DEV:
3063 3103 (void) printf(gettext("status: One or more devices has "
3064 3104 "experienced an unrecoverable error. An\n\tattempt was "
3065 3105 "made to correct the error. Applications are "
3066 3106 "unaffected.\n"));
3067 3107 (void) printf(gettext("action: Determine if the device needs "
3068 3108 "to be replaced, and clear the errors\n\tusing "
3069 3109 "'zpool clear' or replace the device with 'zpool "
3070 3110 "replace'.\n"));
3071 3111 break;
3072 3112
3073 3113 case ZPOOL_STATUS_OFFLINE_DEV:
3074 3114 (void) printf(gettext("status: One or more devices has "
3075 3115 "been taken offline by the administrator.\n\tSufficient "
3076 3116 "replicas exist for the pool to continue functioning in "
3077 3117 "a\n\tdegraded state.\n"));
3078 3118 (void) printf(gettext("action: Online the device using "
3079 3119 "'zpool online' or replace the device with\n\t'zpool "
3080 3120 "replace'.\n"));
3081 3121 break;
3082 3122
3083 3123 case ZPOOL_STATUS_RESILVERING:
3084 3124 (void) printf(gettext("status: One or more devices is "
3085 3125 "currently being resilvered. The pool will\n\tcontinue "
3086 3126 "to function, possibly in a degraded state.\n"));
3087 3127 (void) printf(gettext("action: Wait for the resilver to "
3088 3128 "complete.\n"));
3089 3129 break;
3090 3130
3091 3131 case ZPOOL_STATUS_CORRUPT_DATA:
3092 3132 (void) printf(gettext("status: One or more devices has "
3093 3133 "experienced an error resulting in data\n\tcorruption. "
3094 3134 "Applications may be affected.\n"));
3095 3135 (void) printf(gettext("action: Restore the file in question "
3096 3136 "if possible. Otherwise restore the\n\tentire pool from "
3097 3137 "backup.\n"));
3098 3138 break;
3099 3139
3100 3140 case ZPOOL_STATUS_CORRUPT_POOL:
3101 3141 (void) printf(gettext("status: The pool metadata is corrupted "
3102 3142 "and the pool cannot be opened.\n"));
3103 3143 (void) printf(gettext("action: Destroy and re-create the pool "
3104 3144 "from a backup source.\n"));
3105 3145 break;
3106 3146
3107 3147 case ZPOOL_STATUS_VERSION_OLDER:
3108 3148 (void) printf(gettext("status: The pool is formatted using an "
3109 3149 "older on-disk format. The pool can\n\tstill be used, but "
3110 3150 "some features are unavailable.\n"));
3111 3151 (void) printf(gettext("action: Upgrade the pool using 'zpool "
3112 3152 "upgrade'. Once this is done, the\n\tpool will no longer "
3113 3153 "be accessible on older software versions.\n"));
3114 3154 break;
3115 3155
3116 3156 case ZPOOL_STATUS_VERSION_NEWER:
3117 3157 (void) printf(gettext("status: The pool has been upgraded to a "
3118 3158 "newer, incompatible on-disk version.\n\tThe pool cannot "
3119 3159 "be accessed on this system.\n"));
3120 3160 (void) printf(gettext("action: Access the pool from a system "
3121 3161 "running more recent software, or\n\trestore the pool from "
3122 3162 "backup.\n"));
3123 3163 break;
3124 3164
3125 3165 case ZPOOL_STATUS_FAULTED_DEV_R:
3126 3166 (void) printf(gettext("status: One or more devices are "
3127 3167 "faulted in response to persistent errors.\n\tSufficient "
3128 3168 "replicas exist for the pool to continue functioning "
3129 3169 "in a\n\tdegraded state.\n"));
3130 3170 (void) printf(gettext("action: Replace the faulted device, "
3131 3171 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
3132 3172 break;
3133 3173
3134 3174 case ZPOOL_STATUS_FAULTED_DEV_NR:
3135 3175 (void) printf(gettext("status: One or more devices are "
3136 3176 "faulted in response to persistent errors. There are "
3137 3177 "insufficient replicas for the pool to\n\tcontinue "
3138 3178 "functioning.\n"));
3139 3179 (void) printf(gettext("action: Destroy and re-create the pool "
3140 3180 "from a backup source. Manually marking the device\n"
3141 3181 "\trepaired using 'zpool clear' may allow some data "
3142 3182 "to be recovered.\n"));
3143 3183 break;
3144 3184
3145 3185 case ZPOOL_STATUS_IO_FAILURE_WAIT:
3146 3186 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
3147 3187 (void) printf(gettext("status: One or more devices are "
3148 3188 "faulted in response to IO failures.\n"));
3149 3189 (void) printf(gettext("action: Make sure the affected devices "
3150 3190 "are connected, then run 'zpool clear'.\n"));
3151 3191 break;
3152 3192
3153 3193 case ZPOOL_STATUS_BAD_LOG:
3154 3194 (void) printf(gettext("status: An intent log record "
3155 3195 "could not be read.\n"
3156 3196 "\tWaiting for adminstrator intervention to fix the "
3157 3197 "faulted pool.\n"));
3158 3198 (void) printf(gettext("action: Either restore the affected "
3159 3199 "device(s) and run 'zpool online',\n"
3160 3200 "\tor ignore the intent log records by running "
3161 3201 "'zpool clear'.\n"));
3162 3202 break;
3163 3203
3164 3204 default:
3165 3205 /*
3166 3206 * The remaining errors can't actually be generated, yet.
3167 3207 */
3168 3208 assert(reason == ZPOOL_STATUS_OK);
3169 3209 }
3170 3210
3171 3211 if (msgid != NULL)
3172 3212 (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"),
3173 3213 msgid);
3174 3214
3175 3215 if (config != NULL) {
3176 3216 int namewidth;
3177 3217 uint64_t nerr;
3178 3218 nvlist_t **spares, **l2cache;
3179 3219 uint_t nspares, nl2cache;
3180 3220
3181 3221
3182 3222 (void) printf(gettext(" scrub: "));
3183 3223 print_scrub_status(nvroot);
3184 3224
3185 3225 namewidth = max_width(zhp, nvroot, 0, 0);
3186 3226 if (namewidth < 10)
3187 3227 namewidth = 10;
3188 3228
3189 3229 (void) printf(gettext("config:\n\n"));
3190 3230 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth,
3191 3231 "NAME", "STATE", "READ", "WRITE", "CKSUM");
3192 3232 print_status_config(zhp, zpool_get_name(zhp), nvroot,
3193 3233 namewidth, 0, B_FALSE, B_FALSE);
3194 3234 if (num_logs(nvroot) > 0)
3195 3235 print_status_config(zhp, "logs", nvroot, namewidth, 0,
3196 3236 B_FALSE, B_TRUE);
3197 3237
3198 3238 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
3199 3239 &l2cache, &nl2cache) == 0)
3200 3240 print_l2cache(zhp, l2cache, nl2cache, namewidth);
3201 3241
3202 3242 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
3203 3243 &spares, &nspares) == 0)
3204 3244 print_spares(zhp, spares, nspares, namewidth);
3205 3245
3206 3246 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
3207 3247 &nerr) == 0) {
3208 3248 nvlist_t *nverrlist = NULL;
3209 3249
3210 3250 /*
3211 3251 * If the approximate error count is small, get a
3212 3252 * precise count by fetching the entire log and
3213 3253 * uniquifying the results.
3214 3254 */
3215 3255 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
3216 3256 zpool_get_errlog(zhp, &nverrlist) == 0) {
3217 3257 nvpair_t *elem;
3218 3258
3219 3259 elem = NULL;
3220 3260 nerr = 0;
3221 3261 while ((elem = nvlist_next_nvpair(nverrlist,
3222 3262 elem)) != NULL) {
3223 3263 nerr++;
3224 3264 }
3225 3265 }
3226 3266 nvlist_free(nverrlist);
3227 3267
3228 3268 (void) printf("\n");
3229 3269
3230 3270 if (nerr == 0)
3231 3271 (void) printf(gettext("errors: No known data "
3232 3272 "errors\n"));
3233 3273 else if (!cbp->cb_verbose)
3234 3274 (void) printf(gettext("errors: %llu data "
3235 3275 "errors, use '-v' for a list\n"),
3236 3276 (u_longlong_t)nerr);
3237 3277 else
3238 3278 print_error_log(zhp);
3239 3279 }
3240 3280 } else {
3241 3281 (void) printf(gettext("config: The configuration cannot be "
3242 3282 "determined.\n"));
3243 3283 }
3244 3284
3245 3285 return (0);
3246 3286 }
3247 3287
3248 3288 /*
3249 3289 * zpool status [-vx] [pool] ...
3250 3290 *
3251 3291 * -v Display complete error logs
3252 3292 * -x Display only pools with potential problems
3253 3293 *
3254 3294 * Describes the health status of all pools or some subset.
3255 3295 */
3256 3296 int
3257 3297 zpool_do_status(int argc, char **argv)
3258 3298 {
3259 3299 int c;
3260 3300 int ret;
3261 3301 status_cbdata_t cb = { 0 };
3262 3302
3263 3303 /* check options */
3264 3304 while ((c = getopt(argc, argv, "vx")) != -1) {
3265 3305 switch (c) {
3266 3306 case 'v':
3267 3307 cb.cb_verbose = B_TRUE;
3268 3308 break;
3269 3309 case 'x':
3270 3310 cb.cb_explain = B_TRUE;
3271 3311 break;
3272 3312 case '?':
3273 3313 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3274 3314 optopt);
3275 3315 usage(B_FALSE);
3276 3316 }
3277 3317 }
3278 3318
3279 3319 argc -= optind;
3280 3320 argv += optind;
3281 3321
3282 3322 cb.cb_first = B_TRUE;
3283 3323
3284 3324 if (argc == 0)
3285 3325 cb.cb_allpools = B_TRUE;
3286 3326
3287 3327 ret = for_each_pool(argc, argv, B_TRUE, NULL, status_callback, &cb);
3288 3328
3289 3329 if (argc == 0 && cb.cb_count == 0)
3290 3330 (void) printf(gettext("no pools available\n"));
3291 3331 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
3292 3332 (void) printf(gettext("all pools are healthy\n"));
3293 3333
3294 3334 return (ret);
3295 3335 }
3296 3336
3297 3337 typedef struct upgrade_cbdata {
3298 3338 int cb_all;
3299 3339 int cb_first;
3300 3340 int cb_newer;
3301 3341 int cb_argc;
3302 3342 uint64_t cb_version;
3303 3343 char **cb_argv;
3304 3344 } upgrade_cbdata_t;
3305 3345
3306 3346 static int
3307 3347 upgrade_cb(zpool_handle_t *zhp, void *arg)
3308 3348 {
3309 3349 upgrade_cbdata_t *cbp = arg;
3310 3350 nvlist_t *config;
3311 3351 uint64_t version;
3312 3352 int ret = 0;
3313 3353
3314 3354 config = zpool_get_config(zhp, NULL);
3315 3355 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
3316 3356 &version) == 0);
3317 3357
3318 3358 if (!cbp->cb_newer && version < SPA_VERSION) {
3319 3359 if (!cbp->cb_all) {
3320 3360 if (cbp->cb_first) {
3321 3361 (void) printf(gettext("The following pools are "
3322 3362 "out of date, and can be upgraded. After "
3323 3363 "being\nupgraded, these pools will no "
3324 3364 "longer be accessible by older software "
3325 3365 "versions.\n\n"));
3326 3366 (void) printf(gettext("VER POOL\n"));
3327 3367 (void) printf(gettext("--- ------------\n"));
3328 3368 cbp->cb_first = B_FALSE;
3329 3369 }
3330 3370
3331 3371 (void) printf("%2llu %s\n", (u_longlong_t)version,
3332 3372 zpool_get_name(zhp));
3333 3373 } else {
3334 3374 cbp->cb_first = B_FALSE;
3335 3375 ret = zpool_upgrade(zhp, cbp->cb_version);
3336 3376 if (!ret) {
3337 3377 (void) printf(gettext("Successfully upgraded "
3338 3378 "'%s'\n\n"), zpool_get_name(zhp));
3339 3379 }
3340 3380 }
3341 3381 } else if (cbp->cb_newer && version > SPA_VERSION) {
3342 3382 assert(!cbp->cb_all);
3343 3383
3344 3384 if (cbp->cb_first) {
3345 3385 (void) printf(gettext("The following pools are "
3346 3386 "formatted using a newer software version and\n"
3347 3387 "cannot be accessed on the current system.\n\n"));
3348 3388 (void) printf(gettext("VER POOL\n"));
3349 3389 (void) printf(gettext("--- ------------\n"));
3350 3390 cbp->cb_first = B_FALSE;
3351 3391 }
3352 3392
3353 3393 (void) printf("%2llu %s\n", (u_longlong_t)version,
3354 3394 zpool_get_name(zhp));
3355 3395 }
3356 3396
3357 3397 zpool_close(zhp);
3358 3398 return (ret);
3359 3399 }
3360 3400
3361 3401 /* ARGSUSED */
3362 3402 static int
3363 3403 upgrade_one(zpool_handle_t *zhp, void *data)
3364 3404 {
3365 3405 upgrade_cbdata_t *cbp = data;
3366 3406 uint64_t cur_version;
3367 3407 int ret;
3368 3408
3369 3409 if (strcmp("log", zpool_get_name(zhp)) == 0) {
3370 3410 (void) printf(gettext("'log' is now a reserved word\n"
3371 3411 "Pool 'log' must be renamed using export and import"
3372 3412 " to upgrade.\n"));
3373 3413 return (1);
3374 3414 }
3375 3415
3376 3416 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
3377 3417 if (cur_version > cbp->cb_version) {
3378 3418 (void) printf(gettext("Pool '%s' is already formatted "
3379 3419 "using more current version '%llu'.\n"),
3380 3420 zpool_get_name(zhp), cur_version);
3381 3421 return (0);
3382 3422 }
3383 3423 if (cur_version == cbp->cb_version) {
3384 3424 (void) printf(gettext("Pool '%s' is already formatted "
3385 3425 "using the current version.\n"), zpool_get_name(zhp));
3386 3426 return (0);
3387 3427 }
3388 3428
3389 3429 ret = zpool_upgrade(zhp, cbp->cb_version);
3390 3430
3391 3431 if (!ret) {
3392 3432 (void) printf(gettext("Successfully upgraded '%s' "
3393 3433 "from version %llu to version %llu\n\n"),
3394 3434 zpool_get_name(zhp), (u_longlong_t)cur_version,
3395 3435 (u_longlong_t)cbp->cb_version);
3396 3436 }
3397 3437
3398 3438 return (ret != 0);
3399 3439 }
3400 3440
3401 3441 /*
3402 3442 * zpool upgrade
3403 3443 * zpool upgrade -v
3404 3444 * zpool upgrade [-V version] <-a | pool ...>
3405 3445 *
3406 3446 * With no arguments, display downrev'd ZFS pool available for upgrade.
3407 3447 * Individual pools can be upgraded by specifying the pool, and '-a' will
3408 3448 * upgrade all pools.
3409 3449 */
3410 3450 int
3411 3451 zpool_do_upgrade(int argc, char **argv)
3412 3452 {
3413 3453 int c;
3414 3454 upgrade_cbdata_t cb = { 0 };
3415 3455 int ret = 0;
3416 3456 boolean_t showversions = B_FALSE;
3417 3457 char *end;
3418 3458
3419 3459
3420 3460 /* check options */
3421 3461 while ((c = getopt(argc, argv, "avV:")) != -1) {
3422 3462 switch (c) {
3423 3463 case 'a':
3424 3464 cb.cb_all = B_TRUE;
3425 3465 break;
3426 3466 case 'v':
3427 3467 showversions = B_TRUE;
3428 3468 break;
3429 3469 case 'V':
3430 3470 cb.cb_version = strtoll(optarg, &end, 10);
3431 3471 if (*end != '\0' || cb.cb_version > SPA_VERSION ||
3432 3472 cb.cb_version < SPA_VERSION_1) {
3433 3473 (void) fprintf(stderr,
3434 3474 gettext("invalid version '%s'\n"), optarg);
3435 3475 usage(B_FALSE);
3436 3476 }
3437 3477 break;
3438 3478 case '?':
3439 3479 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3440 3480 optopt);
3441 3481 usage(B_FALSE);
3442 3482 }
3443 3483 }
3444 3484
3445 3485 cb.cb_argc = argc;
3446 3486 cb.cb_argv = argv;
3447 3487 argc -= optind;
3448 3488 argv += optind;
3449 3489
3450 3490 if (cb.cb_version == 0) {
3451 3491 cb.cb_version = SPA_VERSION;
3452 3492 } else if (!cb.cb_all && argc == 0) {
3453 3493 (void) fprintf(stderr, gettext("-V option is "
3454 3494 "incompatible with other arguments\n"));
3455 3495 usage(B_FALSE);
3456 3496 }
3457 3497
3458 3498 if (showversions) {
3459 3499 if (cb.cb_all || argc != 0) {
3460 3500 (void) fprintf(stderr, gettext("-v option is "
3461 3501 "incompatible with other arguments\n"));
3462 3502 usage(B_FALSE);
3463 3503 }
3464 3504 } else if (cb.cb_all) {
3465 3505 if (argc != 0) {
3466 3506 (void) fprintf(stderr, gettext("-a option should not "
3467 3507 "be used along with a pool name\n"));
3468 3508 usage(B_FALSE);
3469 3509 }
3470 3510 }
3471 3511
3472 3512 (void) printf(gettext("This system is currently running "
3473 3513 "ZFS pool version %llu.\n\n"), SPA_VERSION);
3474 3514 cb.cb_first = B_TRUE;
3475 3515 if (showversions) {
3476 3516 (void) printf(gettext("The following versions are "
3477 3517 "supported:\n\n"));
3478 3518 (void) printf(gettext("VER DESCRIPTION\n"));
3479 3519 (void) printf("--- -----------------------------------------"
3480 3520 "---------------\n");
3481 3521 (void) printf(gettext(" 1 Initial ZFS version\n"));
3482 3522 (void) printf(gettext(" 2 Ditto blocks "
3483 3523 "(replicated metadata)\n"));
3484 3524 (void) printf(gettext(" 3 Hot spares and double parity "
3485 3525 "RAID-Z\n"));
3486 3526 (void) printf(gettext(" 4 zpool history\n"));
3487 3527 (void) printf(gettext(" 5 Compression using the gzip "
3488 3528 "algorithm\n"));
3489 3529 (void) printf(gettext(" 6 bootfs pool property\n"));
|
↓ open down ↓ |
453 lines elided |
↑ open up ↑ |
3490 3530 (void) printf(gettext(" 7 Separate intent log devices\n"));
3491 3531 (void) printf(gettext(" 8 Delegated administration\n"));
3492 3532 (void) printf(gettext(" 9 refquota and refreservation "
3493 3533 "properties\n"));
3494 3534 (void) printf(gettext(" 10 Cache devices\n"));
3495 3535 (void) printf(gettext(" 11 Improved scrub performance\n"));
3496 3536 (void) printf(gettext(" 12 Snapshot properties\n"));
3497 3537 (void) printf(gettext(" 13 snapused property\n"));
3498 3538 (void) printf(gettext(" 14 passthrough-x aclinherit "
3499 3539 "support\n"));
3540 + (void) printf(gettext(" 15 Cryptographic support.\n"));
3500 3541 (void) printf(gettext("For more information on a particular "
3501 3542 "version, including supported releases, see:\n\n"));
3502 3543 (void) printf("http://www.opensolaris.org/os/community/zfs/"
3503 3544 "version/N\n\n");
3504 3545 (void) printf(gettext("Where 'N' is the version number.\n"));
3505 3546 } else if (argc == 0) {
3506 3547 int notfound;
3507 3548
3508 3549 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3509 3550 notfound = cb.cb_first;
3510 3551
3511 3552 if (!cb.cb_all && ret == 0) {
3512 3553 if (!cb.cb_first)
3513 3554 (void) printf("\n");
3514 3555 cb.cb_first = B_TRUE;
3515 3556 cb.cb_newer = B_TRUE;
3516 3557 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
3517 3558 if (!cb.cb_first) {
3518 3559 notfound = B_FALSE;
3519 3560 (void) printf("\n");
3520 3561 }
3521 3562 }
3522 3563
3523 3564 if (ret == 0) {
3524 3565 if (notfound)
3525 3566 (void) printf(gettext("All pools are formatted "
3526 3567 "using this version.\n"));
3527 3568 else if (!cb.cb_all)
3528 3569 (void) printf(gettext("Use 'zpool upgrade -v' "
3529 3570 "for a list of available versions and "
3530 3571 "their associated\nfeatures.\n"));
3531 3572 }
3532 3573 } else {
3533 3574 ret = for_each_pool(argc, argv, B_FALSE, NULL,
3534 3575 upgrade_one, &cb);
3535 3576 }
3536 3577
3537 3578 return (ret);
3538 3579 }
3539 3580
3540 3581 typedef struct hist_cbdata {
3541 3582 boolean_t first;
3542 3583 int longfmt;
3543 3584 int internal;
3544 3585 } hist_cbdata_t;
3545 3586
3546 3587 char *hist_event_table[LOG_END] = {
3547 3588 "invalid event",
3548 3589 "pool create",
3549 3590 "vdev add",
3550 3591 "pool remove",
3551 3592 "pool destroy",
3552 3593 "pool export",
3553 3594 "pool import",
3554 3595 "vdev attach",
3555 3596 "vdev replace",
3556 3597 "vdev detach",
3557 3598 "vdev online",
3558 3599 "vdev offline",
3559 3600 "vdev upgrade",
3560 3601 "pool clear",
3561 3602 "pool scrub",
3562 3603 "pool property set",
3563 3604 "create",
3564 3605 "clone",
3565 3606 "destroy",
3566 3607 "destroy_begin_sync",
3567 3608 "inherit",
3568 3609 "property set",
3569 3610 "quota set",
3570 3611 "permission update",
3571 3612 "permission remove",
3572 3613 "permission who remove",
3573 3614 "promote",
3574 3615 "receive",
|
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
3575 3616 "rename",
3576 3617 "reservation set",
3577 3618 "replay_inc_sync",
3578 3619 "replay_full_sync",
3579 3620 "rollback",
3580 3621 "snapshot",
3581 3622 "filesystem version upgrade",
3582 3623 "refquota set",
3583 3624 "refreservation set",
3584 3625 "pool scrub done",
3626 + "crypto key create",
3585 3627 };
3586 3628
3587 3629 /*
3588 3630 * Print out the command history for a specific pool.
3589 3631 */
3590 3632 static int
3591 3633 get_history_one(zpool_handle_t *zhp, void *data)
3592 3634 {
3593 3635 nvlist_t *nvhis;
3594 3636 nvlist_t **records;
3595 3637 uint_t numrecords;
3596 3638 char *cmdstr;
3597 3639 char *pathstr;
3598 3640 uint64_t dst_time;
3599 3641 time_t tsec;
3600 3642 struct tm t;
3601 3643 char tbuf[30];
3602 3644 int ret, i;
3603 3645 uint64_t who;
3604 3646 struct passwd *pwd;
3605 3647 char *hostname;
3606 3648 char *zonename;
3607 3649 char internalstr[MAXPATHLEN];
3608 3650 hist_cbdata_t *cb = (hist_cbdata_t *)data;
3609 3651 uint64_t txg;
3610 3652 uint64_t ievent;
3611 3653
3612 3654 cb->first = B_FALSE;
3613 3655
3614 3656 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
3615 3657
3616 3658 if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
3617 3659 return (ret);
3618 3660
3619 3661 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
3620 3662 &records, &numrecords) == 0);
3621 3663 for (i = 0; i < numrecords; i++) {
3622 3664 if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME,
3623 3665 &dst_time) != 0)
3624 3666 continue;
3625 3667
3626 3668 /* is it an internal event or a standard event? */
3627 3669 if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD,
3628 3670 &cmdstr) != 0) {
3629 3671 if (cb->internal == 0)
3630 3672 continue;
3631 3673
3632 3674 if (nvlist_lookup_uint64(records[i],
3633 3675 ZPOOL_HIST_INT_EVENT, &ievent) != 0)
3634 3676 continue;
3635 3677 verify(nvlist_lookup_uint64(records[i],
3636 3678 ZPOOL_HIST_TXG, &txg) == 0);
3637 3679 verify(nvlist_lookup_string(records[i],
3638 3680 ZPOOL_HIST_INT_STR, &pathstr) == 0);
3639 3681 if (ievent >= LOG_END)
3640 3682 continue;
3641 3683 (void) snprintf(internalstr,
3642 3684 sizeof (internalstr),
3643 3685 "[internal %s txg:%lld] %s",
3644 3686 hist_event_table[ievent], txg,
3645 3687 pathstr);
3646 3688 cmdstr = internalstr;
3647 3689 }
3648 3690 tsec = dst_time;
3649 3691 (void) localtime_r(&tsec, &t);
3650 3692 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
3651 3693 (void) printf("%s %s", tbuf, cmdstr);
3652 3694
3653 3695 if (!cb->longfmt) {
3654 3696 (void) printf("\n");
3655 3697 continue;
3656 3698 }
3657 3699 (void) printf(" [");
3658 3700 if (nvlist_lookup_uint64(records[i],
3659 3701 ZPOOL_HIST_WHO, &who) == 0) {
3660 3702 pwd = getpwuid((uid_t)who);
3661 3703 if (pwd)
3662 3704 (void) printf("user %s on",
3663 3705 pwd->pw_name);
3664 3706 else
3665 3707 (void) printf("user %d on",
3666 3708 (int)who);
3667 3709 } else {
3668 3710 (void) printf(gettext("no info]\n"));
3669 3711 continue;
3670 3712 }
3671 3713 if (nvlist_lookup_string(records[i],
3672 3714 ZPOOL_HIST_HOST, &hostname) == 0) {
3673 3715 (void) printf(" %s", hostname);
3674 3716 }
3675 3717 if (nvlist_lookup_string(records[i],
3676 3718 ZPOOL_HIST_ZONE, &zonename) == 0) {
3677 3719 (void) printf(":%s", zonename);
3678 3720 }
3679 3721
3680 3722 (void) printf("]");
3681 3723 (void) printf("\n");
3682 3724 }
3683 3725 (void) printf("\n");
3684 3726 nvlist_free(nvhis);
3685 3727
3686 3728 return (ret);
3687 3729 }
3688 3730
3689 3731 /*
3690 3732 * zpool history <pool>
3691 3733 *
3692 3734 * Displays the history of commands that modified pools.
3693 3735 */
3694 3736
3695 3737
3696 3738 int
3697 3739 zpool_do_history(int argc, char **argv)
3698 3740 {
3699 3741 hist_cbdata_t cbdata = { 0 };
3700 3742 int ret;
3701 3743 int c;
3702 3744
3703 3745 cbdata.first = B_TRUE;
3704 3746 /* check options */
3705 3747 while ((c = getopt(argc, argv, "li")) != -1) {
3706 3748 switch (c) {
3707 3749 case 'l':
3708 3750 cbdata.longfmt = 1;
3709 3751 break;
3710 3752 case 'i':
3711 3753 cbdata.internal = 1;
3712 3754 break;
3713 3755 case '?':
3714 3756 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3715 3757 optopt);
3716 3758 usage(B_FALSE);
3717 3759 }
3718 3760 }
3719 3761 argc -= optind;
3720 3762 argv += optind;
3721 3763
3722 3764 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
3723 3765 &cbdata);
3724 3766
3725 3767 if (argc == 0 && cbdata.first == B_TRUE) {
3726 3768 (void) printf(gettext("no pools available\n"));
3727 3769 return (0);
3728 3770 }
3729 3771
3730 3772 return (ret);
3731 3773 }
3732 3774
3733 3775 static int
3734 3776 get_callback(zpool_handle_t *zhp, void *data)
3735 3777 {
3736 3778 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
3737 3779 char value[MAXNAMELEN];
3738 3780 zprop_source_t srctype;
3739 3781 zprop_list_t *pl;
3740 3782
3741 3783 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
3742 3784
3743 3785 /*
3744 3786 * Skip the special fake placeholder. This will also skip
3745 3787 * over the name property when 'all' is specified.
3746 3788 */
3747 3789 if (pl->pl_prop == ZPOOL_PROP_NAME &&
3748 3790 pl == cbp->cb_proplist)
3749 3791 continue;
3750 3792
3751 3793 if (zpool_get_prop(zhp, pl->pl_prop,
3752 3794 value, sizeof (value), &srctype) != 0)
3753 3795 continue;
3754 3796
3755 3797 zprop_print_one_property(zpool_get_name(zhp), cbp,
3756 3798 zpool_prop_to_name(pl->pl_prop), value, srctype, NULL);
3757 3799 }
3758 3800 return (0);
3759 3801 }
3760 3802
3761 3803 int
3762 3804 zpool_do_get(int argc, char **argv)
3763 3805 {
3764 3806 zprop_get_cbdata_t cb = { 0 };
3765 3807 zprop_list_t fake_name = { 0 };
3766 3808 int ret;
3767 3809
3768 3810 if (argc < 3)
3769 3811 usage(B_FALSE);
3770 3812
3771 3813 cb.cb_first = B_TRUE;
3772 3814 cb.cb_sources = ZPROP_SRC_ALL;
3773 3815 cb.cb_columns[0] = GET_COL_NAME;
3774 3816 cb.cb_columns[1] = GET_COL_PROPERTY;
3775 3817 cb.cb_columns[2] = GET_COL_VALUE;
3776 3818 cb.cb_columns[3] = GET_COL_SOURCE;
3777 3819 cb.cb_type = ZFS_TYPE_POOL;
3778 3820
3779 3821 if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist,
3780 3822 ZFS_TYPE_POOL) != 0)
3781 3823 usage(B_FALSE);
3782 3824
3783 3825 if (cb.cb_proplist != NULL) {
3784 3826 fake_name.pl_prop = ZPOOL_PROP_NAME;
3785 3827 fake_name.pl_width = strlen(gettext("NAME"));
3786 3828 fake_name.pl_next = cb.cb_proplist;
3787 3829 cb.cb_proplist = &fake_name;
3788 3830 }
3789 3831
3790 3832 ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist,
3791 3833 get_callback, &cb);
3792 3834
3793 3835 if (cb.cb_proplist == &fake_name)
3794 3836 zprop_free_list(fake_name.pl_next);
3795 3837 else
3796 3838 zprop_free_list(cb.cb_proplist);
3797 3839
3798 3840 return (ret);
3799 3841 }
3800 3842
3801 3843 typedef struct set_cbdata {
3802 3844 char *cb_propname;
3803 3845 char *cb_value;
|
↓ open down ↓ |
209 lines elided |
↑ open up ↑ |
3804 3846 boolean_t cb_any_successful;
3805 3847 } set_cbdata_t;
3806 3848
3807 3849 int
3808 3850 set_callback(zpool_handle_t *zhp, void *data)
3809 3851 {
3810 3852 int error;
3811 3853 set_cbdata_t *cb = (set_cbdata_t *)data;
3812 3854
3813 3855 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
3814 -
3815 3856 if (!error)
3816 3857 cb->cb_any_successful = B_TRUE;
3817 3858
3818 3859 return (error);
3819 3860 }
3820 3861
3821 3862 int
3822 3863 zpool_do_set(int argc, char **argv)
3823 3864 {
3824 3865 set_cbdata_t cb = { 0 };
3825 3866 int error;
3826 3867
3827 3868 if (argc > 1 && argv[1][0] == '-') {
3828 3869 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3829 3870 argv[1][1]);
3830 3871 usage(B_FALSE);
3831 3872 }
3832 3873
3833 3874 if (argc < 2) {
3834 3875 (void) fprintf(stderr, gettext("missing property=value "
3835 3876 "argument\n"));
3836 3877 usage(B_FALSE);
3837 3878 }
3838 3879
3839 3880 if (argc < 3) {
3840 3881 (void) fprintf(stderr, gettext("missing pool name\n"));
3841 3882 usage(B_FALSE);
3842 3883 }
3843 3884
3844 3885 if (argc > 3) {
3845 3886 (void) fprintf(stderr, gettext("too many pool names\n"));
3846 3887 usage(B_FALSE);
3847 3888 }
3848 3889
3849 3890 cb.cb_propname = argv[1];
3850 3891 cb.cb_value = strchr(cb.cb_propname, '=');
3851 3892 if (cb.cb_value == NULL) {
3852 3893 (void) fprintf(stderr, gettext("missing value in "
3853 3894 "property=value argument\n"));
3854 3895 usage(B_FALSE);
3855 3896 }
|
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
3856 3897
3857 3898 *(cb.cb_value) = '\0';
3858 3899 cb.cb_value++;
3859 3900
3860 3901 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
3861 3902 set_callback, &cb);
3862 3903
3863 3904 return (error);
3864 3905 }
3865 3906
3907 +
3908 +static int
3909 +/* LINTED E_FUNC_ARG_UNUSED */
3910 +key_callback_load(zpool_handle_t *zhp, void *data)
3911 +{
3912 + int ret;
3913 + if (zpool_keysource_prompt(zhp)) {
3914 + char *smf_fmri = getenv("SMF_FMRI");
3915 +
3916 + if (smf_fmri != NULL &&
3917 + strcmp(smf_fmri, "svc:/system/device/local") == 0) {
3918 + return (0);
3919 + }
3920 + }
3921 + ret = zpool_cmd_key_load(zhp);
3922 + if (ret != 0 && !(ret == EEXIST || ret == ENOTSUP)) {
3923 + return (1);
3924 + }
3925 +
3926 + return (0);
3927 +}
3928 +
3929 +static int
3930 +/* LINTED E_FUNC_ARG_UNUSED */
3931 +key_callback_unload(zpool_handle_t *zhp, void *data)
3932 +{
3933 + int ret;
3934 +
3935 + ret = zpool_cmd_key_unload(zhp);
3936 + if (ret != 0 && !(ret == ENOENT || ret == ENOTSUP)) {
3937 + return (1);
3938 + }
3939 +
3940 + return (0);
3941 +}
3942 +
3943 +
3944 +static int
3945 +zpool_do_key(int argc, char **argv)
3946 +{
3947 + int error = 1, options = 0;
3948 + nvlist_t *props = NULL;
3949 + char c, *propval = NULL;
3950 + boolean_t load = B_FALSE, unload = B_FALSE, change = B_FALSE;
3951 + boolean_t do_all = B_FALSE;
3952 + zpool_handle_t *zhp = NULL;
3953 +
3954 + while ((c = getopt(argc, argv, "aluco:")) != -1) {
3955 + switch (c) {
3956 + case 'a':
3957 + do_all = B_TRUE;
3958 + break;
3959 +
3960 + case 'l':
3961 + load = B_TRUE;
3962 + break;
3963 +
3964 + case 'u':
3965 + unload = B_TRUE;
3966 + break;
3967 +
3968 + case 'c':
3969 + change = B_TRUE;
3970 + break;
3971 +
3972 + case 'o':
3973 + if ((propval = strchr(optarg, '=')) == NULL) {
3974 + (void) fprintf(stderr, gettext("missing "
3975 + "'=' for -o option\n"));
3976 + return (error);
3977 + }
3978 +
3979 + *propval = '\0';
3980 + propval++;
3981 + if (strcmp(optarg, "keysource") != 0) {
3982 + (void) fprintf(stderr, gettext(
3983 + "Invalid property for key change: "
3984 + "\"%s\"\n"),
3985 + optarg);
3986 + return (error);
3987 + }
3988 + if (add_prop_list(optarg, propval, &props, B_TRUE))
3989 + return (error);
3990 +
3991 + options += 2;
3992 + break;
3993 +
3994 + }
3995 + }
3996 +
3997 + if (!change && props != NULL) {
3998 + (void) fprintf(stderr, gettext("Properties are not allowed to "
3999 + "be used in this command.\n"));
4000 + goto error;
4001 + }
4002 +
4003 + if (((load || unload) && (argc > 3)) ||
4004 + (change && ((argc - options) > 3))) {
4005 + (void) fprintf(stderr,
4006 + gettext("too many arguments\n"));
4007 + usage(B_FALSE);
4008 + goto error;
4009 + } else if ((load || unload) && (argc < 3)) {
4010 + (void) fprintf(stderr, gettext("missing dataset "
4011 + "argument (specify -a for all)\n"));
4012 + usage(B_FALSE);
4013 + goto error;
4014 + } else if (change && ((argc - options) < 3)) {
4015 + (void) fprintf(stderr, gettext("missing dataset "
4016 + "argument\n"));
4017 + usage(B_FALSE);
4018 + goto error;
4019 + }
4020 +
4021 + if (do_all == B_FALSE) {
4022 + zhp = zpool_open(g_zfs, argv[argc - 1]);
4023 + if (zhp == NULL)
4024 + goto error;
4025 + }
4026 +
4027 + if (load) {
4028 + if (do_all)
4029 + error = for_each_pool(0, NULL, B_TRUE, NULL,
4030 + key_callback_load, NULL);
4031 + else
4032 + error = zpool_cmd_key_load(zhp);
4033 +
4034 + } else if (unload) {
4035 + if (do_all)
4036 + error = for_each_pool(0, NULL, B_TRUE, NULL,
4037 + key_callback_unload, NULL);
4038 + else
4039 + error = zpool_cmd_key_unload(zhp);
4040 +
4041 + } else if (change) {
4042 + if (do_all) {
4043 + (void) fprintf(stderr, gettext("cannot use '-a' with "
4044 + "change operation.\n"));
4045 + usage(B_FALSE);
4046 + goto error;
4047 + }
4048 +
4049 + error = zpool_cmd_key_change(zhp, props);
4050 +
4051 + } else
4052 + usage(B_FALSE);
4053 +
4054 + if (zhp != NULL && !do_all)
4055 + zpool_close(zhp);
4056 +
4057 +error:
4058 + nvlist_free(props);
4059 + if (error != 0)
4060 + return (1);
4061 + return (0);
4062 +}
4063 +
3866 4064 static int
3867 4065 find_command_idx(char *command, int *idx)
3868 4066 {
3869 4067 int i;
3870 4068
3871 4069 for (i = 0; i < NCOMMAND; i++) {
3872 4070 if (command_table[i].name == NULL)
3873 4071 continue;
3874 4072
3875 4073 if (strcmp(command, command_table[i].name) == 0) {
3876 4074 *idx = i;
3877 4075 return (0);
3878 4076 }
3879 4077 }
3880 4078 return (1);
3881 4079 }
3882 4080
3883 4081 int
3884 4082 main(int argc, char **argv)
3885 4083 {
3886 4084 int ret;
3887 4085 int i;
3888 4086 char *cmdname;
3889 4087
3890 4088 (void) setlocale(LC_ALL, "");
3891 4089 (void) textdomain(TEXT_DOMAIN);
3892 4090
3893 4091 if ((g_zfs = libzfs_init()) == NULL) {
3894 4092 (void) fprintf(stderr, gettext("internal error: failed to "
3895 4093 "initialize ZFS library\n"));
3896 4094 return (1);
3897 4095 }
3898 4096
3899 4097 libzfs_print_on_error(g_zfs, B_TRUE);
3900 4098
3901 4099 opterr = 0;
3902 4100
3903 4101 /*
3904 4102 * Make sure the user has specified some command.
3905 4103 */
3906 4104 if (argc < 2) {
3907 4105 (void) fprintf(stderr, gettext("missing command\n"));
3908 4106 usage(B_FALSE);
3909 4107 }
3910 4108
3911 4109 cmdname = argv[1];
3912 4110
3913 4111 /*
3914 4112 * Special case '-?'
3915 4113 */
3916 4114 if (strcmp(cmdname, "-?") == 0)
3917 4115 usage(B_TRUE);
3918 4116
3919 4117 zpool_set_history_str("zpool", argc, argv, history_str);
3920 4118 verify(zpool_stage_history(g_zfs, history_str) == 0);
3921 4119
3922 4120 /*
3923 4121 * Run the appropriate command.
3924 4122 */
3925 4123 if (find_command_idx(cmdname, &i) == 0) {
3926 4124 current_command = &command_table[i];
3927 4125 ret = command_table[i].func(argc - 1, argv + 1);
3928 4126 } else if (strchr(cmdname, '=')) {
3929 4127 verify(find_command_idx("set", &i) == 0);
3930 4128 current_command = &command_table[i];
3931 4129 ret = command_table[i].func(argc, argv);
3932 4130 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
3933 4131 /*
3934 4132 * 'freeze' is a vile debugging abomination, so we treat
3935 4133 * it as such.
3936 4134 */
3937 4135 char buf[16384];
3938 4136 int fd = open(ZFS_DEV, O_RDWR);
3939 4137 (void) strcpy((void *)buf, argv[2]);
3940 4138 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
3941 4139 } else {
3942 4140 (void) fprintf(stderr, gettext("unrecognized "
3943 4141 "command '%s'\n"), cmdname);
3944 4142 usage(B_FALSE);
3945 4143 }
3946 4144
3947 4145 libzfs_fini(g_zfs);
3948 4146
3949 4147 /*
3950 4148 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
3951 4149 * for the purposes of running ::findleaks.
3952 4150 */
3953 4151 if (getenv("ZFS_ABORT") != NULL) {
3954 4152 (void) printf("dumping core by request\n");
3955 4153 abort();
3956 4154 }
3957 4155
3958 4156 return (ret);
3959 4157 }
|
↓ open down ↓ |
84 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX