1 789 ahrens /* 2 789 ahrens * CDDL HEADER START 3 789 ahrens * 4 789 ahrens * The contents of this file are subject to the terms of the 5 1485 lling * Common Development and Distribution License (the "License"). 6 1485 lling * You may not use this file except in compliance with the License. 7 789 ahrens * 8 789 ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 789 ahrens * or http://www.opensolaris.org/os/licensing. 10 789 ahrens * See the License for the specific language governing permissions 11 789 ahrens * and limitations under the License. 12 789 ahrens * 13 789 ahrens * When distributing Covered Code, include this CDDL HEADER in each 14 789 ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 789 ahrens * If applicable, add the following below this CDDL HEADER, with the 16 789 ahrens * fields enclosed by brackets "[]" replaced with your own identifying 17 789 ahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18 789 ahrens * 19 789 ahrens * CDDL HEADER END 20 789 ahrens */ 21 2082 eschrock 22 789 ahrens /* 23 8525 Eric * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 789 ahrens * Use is subject to license terms. 25 789 ahrens */ 26 789 ahrens 27 789 ahrens #include <assert.h> 28 789 ahrens #include <ctype.h> 29 789 ahrens #include <dirent.h> 30 789 ahrens #include <errno.h> 31 789 ahrens #include <fcntl.h> 32 789 ahrens #include <libgen.h> 33 789 ahrens #include <libintl.h> 34 789 ahrens #include <libuutil.h> 35 789 ahrens #include <locale.h> 36 789 ahrens #include <stdio.h> 37 789 ahrens #include <stdlib.h> 38 789 ahrens #include <string.h> 39 789 ahrens #include <strings.h> 40 789 ahrens #include <unistd.h> 41 789 ahrens #include <priv.h> 42 4543 marks #include <pwd.h> 43 4543 marks #include <zone.h> 44 3912 lling #include <sys/fs/zfs.h> 45 789 ahrens 46 789 ahrens #include <sys/stat.h> 47 789 ahrens 48 789 ahrens #include <libzfs.h> 49 789 ahrens 50 789 ahrens #include "zpool_util.h" 51 5913 perrin #include "zfs_comutil.h" 52 10265 Krishnendu 53 10265 Krishnendu #include "statcommon.h" 54 789 ahrens 55 789 ahrens static int zpool_do_create(int, char **); 56 789 ahrens static int zpool_do_destroy(int, char **); 57 789 ahrens 58 789 ahrens static int zpool_do_add(int, char **); 59 2082 eschrock static int zpool_do_remove(int, char **); 60 789 ahrens 61 789 ahrens static int zpool_do_list(int, char **); 62 789 ahrens static int zpool_do_iostat(int, char **); 63 789 ahrens static int zpool_do_status(int, char **); 64 789 ahrens 65 789 ahrens static int zpool_do_online(int, char **); 66 789 ahrens static int zpool_do_offline(int, char **); 67 1544 eschrock static int zpool_do_clear(int, char **); 68 789 ahrens 69 789 ahrens static int zpool_do_attach(int, char **); 70 789 ahrens static int zpool_do_detach(int, char **); 71 789 ahrens static int zpool_do_replace(int, char **); 72 789 ahrens 73 789 ahrens static int zpool_do_scrub(int, char **); 74 789 ahrens 75 789 ahrens static int zpool_do_import(int, char **); 76 789 ahrens static int zpool_do_export(int, char **); 77 789 ahrens 78 1760 eschrock static int zpool_do_upgrade(int, char **); 79 1760 eschrock 80 2926 ek110237 static int zpool_do_history(int, char **); 81 3912 lling 82 3912 lling static int zpool_do_get(int, char **); 83 3912 lling static int zpool_do_set(int, char **); 84 2926 ek110237 85 789 ahrens /* 86 789 ahrens * These libumem hooks provide a reasonable set of defaults for the allocator's 87 789 ahrens * debugging facilities. 88 789 ahrens */ 89 6865 rm160521 90 6865 rm160521 #ifdef DEBUG 91 789 ahrens const char * 92 2082 eschrock _umem_debug_init(void) 93 789 ahrens { 94 789 ahrens return ("default,verbose"); /* $UMEM_DEBUG setting */ 95 789 ahrens } 96 789 ahrens 97 789 ahrens const char * 98 789 ahrens _umem_logging_init(void) 99 789 ahrens { 100 789 ahrens return ("fail,contents"); /* $UMEM_LOGGING setting */ 101 789 ahrens } 102 6865 rm160521 #endif 103 789 ahrens 104 1387 eschrock typedef enum { 105 1387 eschrock HELP_ADD, 106 1387 eschrock HELP_ATTACH, 107 1544 eschrock HELP_CLEAR, 108 1387 eschrock HELP_CREATE, 109 1387 eschrock HELP_DESTROY, 110 1387 eschrock HELP_DETACH, 111 1387 eschrock HELP_EXPORT, 112 2926 ek110237 HELP_HISTORY, 113 1387 eschrock HELP_IMPORT, 114 1387 eschrock HELP_IOSTAT, 115 1387 eschrock HELP_LIST, 116 1387 eschrock HELP_OFFLINE, 117 1387 eschrock HELP_ONLINE, 118 1387 eschrock HELP_REPLACE, 119 2082 eschrock HELP_REMOVE, 120 1387 eschrock HELP_SCRUB, 121 1760 eschrock HELP_STATUS, 122 3912 lling HELP_UPGRADE, 123 3912 lling HELP_GET, 124 3912 lling HELP_SET 125 1387 eschrock } zpool_help_t; 126 1387 eschrock 127 1387 eschrock 128 789 ahrens typedef struct zpool_command { 129 789 ahrens const char *name; 130 789 ahrens int (*func)(int, char **); 131 1387 eschrock zpool_help_t usage; 132 789 ahrens } zpool_command_t; 133 789 ahrens 134 789 ahrens /* 135 789 ahrens * Master command table. Each ZFS command has a name, associated function, and 136 1544 eschrock * usage message. The usage messages need to be internationalized, so we have 137 1544 eschrock * to have a function to return the usage message based on a command index. 138 1387 eschrock * 139 1387 eschrock * These commands are organized according to how they are displayed in the usage 140 1387 eschrock * message. An empty command (one with a NULL name) indicates an empty line in 141 1387 eschrock * the generic usage message. 142 789 ahrens */ 143 789 ahrens static zpool_command_t command_table[] = { 144 1387 eschrock { "create", zpool_do_create, HELP_CREATE }, 145 1387 eschrock { "destroy", zpool_do_destroy, HELP_DESTROY }, 146 789 ahrens { NULL }, 147 1387 eschrock { "add", zpool_do_add, HELP_ADD }, 148 2082 eschrock { "remove", zpool_do_remove, HELP_REMOVE }, 149 789 ahrens { NULL }, 150 1387 eschrock { "list", zpool_do_list, HELP_LIST }, 151 1387 eschrock { "iostat", zpool_do_iostat, HELP_IOSTAT }, 152 1387 eschrock { "status", zpool_do_status, HELP_STATUS }, 153 789 ahrens { NULL }, 154 1387 eschrock { "online", zpool_do_online, HELP_ONLINE }, 155 1387 eschrock { "offline", zpool_do_offline, HELP_OFFLINE }, 156 1544 eschrock { "clear", zpool_do_clear, HELP_CLEAR }, 157 789 ahrens { NULL }, 158 1387 eschrock { "attach", zpool_do_attach, HELP_ATTACH }, 159 1387 eschrock { "detach", zpool_do_detach, HELP_DETACH }, 160 1387 eschrock { "replace", zpool_do_replace, HELP_REPLACE }, 161 789 ahrens { NULL }, 162 1387 eschrock { "scrub", zpool_do_scrub, HELP_SCRUB }, 163 789 ahrens { NULL }, 164 1387 eschrock { "import", zpool_do_import, HELP_IMPORT }, 165 1387 eschrock { "export", zpool_do_export, HELP_EXPORT }, 166 2926 ek110237 { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, 167 2926 ek110237 { NULL }, 168 3912 lling { "history", zpool_do_history, HELP_HISTORY }, 169 3912 lling { "get", zpool_do_get, HELP_GET }, 170 3912 lling { "set", zpool_do_set, HELP_SET }, 171 789 ahrens }; 172 789 ahrens 173 789 ahrens #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 174 789 ahrens 175 789 ahrens zpool_command_t *current_command; 176 4988 ek110237 static char history_str[HIS_MAX_RECORD_LEN]; 177 10265 Krishnendu 178 10265 Krishnendu static uint_t timestamp_fmt = NODATE; 179 1387 eschrock 180 1387 eschrock static const char * 181 1387 eschrock get_usage(zpool_help_t idx) { 182 1387 eschrock switch (idx) { 183 1387 eschrock case HELP_ADD: 184 1387 eschrock return (gettext("\tadd [-fn] <pool> <vdev> ...\n")); 185 1387 eschrock case HELP_ATTACH: 186 1387 eschrock return (gettext("\tattach [-f] <pool> <device> " 187 4849 ahrens "<new-device>\n")); 188 1544 eschrock case HELP_CLEAR: 189 10921 Tim return (gettext("\tclear [-nF] <pool> [device]\n")); 190 1387 eschrock case HELP_CREATE: 191 5094 lling return (gettext("\tcreate [-fn] [-o property=value] ... \n" 192 7184 timh "\t [-O file-system-property=value] ... \n" 193 5094 lling "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n")); 194 1387 eschrock case HELP_DESTROY: 195 1387 eschrock return (gettext("\tdestroy [-f] <pool>\n")); 196 1387 eschrock case HELP_DETACH: 197 1387 eschrock return (gettext("\tdetach <pool> <device>\n")); 198 1387 eschrock case HELP_EXPORT: 199 1387 eschrock return (gettext("\texport [-f] <pool> ...\n")); 200 2926 ek110237 case HELP_HISTORY: 201 4543 marks return (gettext("\thistory [-il] [<pool>] ...\n")); 202 1387 eschrock case HELP_IMPORT: 203 1631 darrenm return (gettext("\timport [-d dir] [-D]\n" 204 10921 Tim "\timport [-d dir | -c cachefile] [-n] -F <pool | id>\n" 205 5363 eschrock "\timport [-o mntopts] [-o property=value] ... \n" 206 5363 eschrock "\t [-d dir | -c cachefile] [-D] [-f] [-R root] -a\n" 207 5363 eschrock "\timport [-o mntopts] [-o property=value] ... \n" 208 5363 eschrock "\t [-d dir | -c cachefile] [-D] [-f] [-R root] " 209 5363 eschrock "<pool | id> [newpool]\n")); 210 1387 eschrock case HELP_IOSTAT: 211 10265 Krishnendu return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval " 212 1387 eschrock "[count]]\n")); 213 1387 eschrock case HELP_LIST: 214 5094 lling return (gettext("\tlist [-H] [-o property[,...]] " 215 5094 lling "[pool] ...\n")); 216 1387 eschrock case HELP_OFFLINE: 217 1485 lling return (gettext("\toffline [-t] <pool> <device> ...\n")); 218 1387 eschrock case HELP_ONLINE: 219 1485 lling return (gettext("\tonline <pool> <device> ...\n")); 220 1387 eschrock case HELP_REPLACE: 221 1387 eschrock return (gettext("\treplace [-f] <pool> <device> " 222 4849 ahrens "[new-device]\n")); 223 2082 eschrock case HELP_REMOVE: 224 5450 brendan return (gettext("\tremove <pool> <device> ...\n")); 225 1387 eschrock case HELP_SCRUB: 226 1387 eschrock return (gettext("\tscrub [-s] <pool> ...\n")); 227 1387 eschrock case HELP_STATUS: 228 1387 eschrock return (gettext("\tstatus [-vx] [pool] ...\n")); 229 1760 eschrock case HELP_UPGRADE: 230 1760 eschrock return (gettext("\tupgrade\n" 231 1760 eschrock "\tupgrade -v\n" 232 5094 lling "\tupgrade [-V version] <-a | pool ...>\n")); 233 3912 lling case HELP_GET: 234 4849 ahrens return (gettext("\tget <\"all\" | property[,...]> " 235 3912 lling "<pool> ...\n")); 236 3912 lling case HELP_SET: 237 3912 lling return (gettext("\tset <property=value> <pool> \n")); 238 1387 eschrock } 239 1387 eschrock 240 1387 eschrock abort(); 241 1387 eschrock /* NOTREACHED */ 242 1387 eschrock } 243 789 ahrens 244 789 ahrens 245 789 ahrens /* 246 3912 lling * Callback routine that will print out a pool property value. 247 3912 lling */ 248 5094 lling static int 249 5094 lling print_prop_cb(int prop, void *cb) 250 3912 lling { 251 3912 lling FILE *fp = cb; 252 3912 lling 253 10922 Jeff (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop)); 254 5094 lling 255 5094 lling if (zpool_prop_readonly(prop)) 256 5094 lling (void) fprintf(fp, " NO "); 257 5094 lling else 258 10922 Jeff (void) fprintf(fp, " YES "); 259 3912 lling 260 3912 lling if (zpool_prop_values(prop) == NULL) 261 3912 lling (void) fprintf(fp, "-\n"); 262 3912 lling else 263 3912 lling (void) fprintf(fp, "%s\n", zpool_prop_values(prop)); 264 3912 lling 265 5094 lling return (ZPROP_CONT); 266 3912 lling } 267 3912 lling 268 3912 lling /* 269 789 ahrens * Display usage message. If we're inside a command, display only the usage for 270 789 ahrens * that command. Otherwise, iterate over the entire command table and display 271 789 ahrens * a complete usage message. 272 789 ahrens */ 273 789 ahrens void 274 2082 eschrock usage(boolean_t requested) 275 789 ahrens { 276 789 ahrens FILE *fp = requested ? stdout : stderr; 277 789 ahrens 278 789 ahrens if (current_command == NULL) { 279 789 ahrens int i; 280 789 ahrens 281 789 ahrens (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 282 789 ahrens (void) fprintf(fp, 283 789 ahrens gettext("where 'command' is one of the following:\n\n")); 284 789 ahrens 285 789 ahrens for (i = 0; i < NCOMMAND; i++) { 286 789 ahrens if (command_table[i].name == NULL) 287 789 ahrens (void) fprintf(fp, "\n"); 288 789 ahrens else 289 789 ahrens (void) fprintf(fp, "%s", 290 1387 eschrock get_usage(command_table[i].usage)); 291 789 ahrens } 292 789 ahrens } else { 293 789 ahrens (void) fprintf(fp, gettext("usage:\n")); 294 1387 eschrock (void) fprintf(fp, "%s", get_usage(current_command->usage)); 295 3912 lling } 296 3912 lling 297 3912 lling if (current_command != NULL && 298 3912 lling ((strcmp(current_command->name, "set") == 0) || 299 5094 lling (strcmp(current_command->name, "get") == 0) || 300 5094 lling (strcmp(current_command->name, "list") == 0))) { 301 3912 lling 302 3912 lling (void) fprintf(fp, 303 3912 lling gettext("\nthe following properties are supported:\n")); 304 3912 lling 305 10922 Jeff (void) fprintf(fp, "\n\t%-15s %s %s\n\n", 306 5094 lling "PROPERTY", "EDIT", "VALUES"); 307 3912 lling 308 3912 lling /* Iterate over all properties */ 309 5094 lling (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, 310 5094 lling ZFS_TYPE_POOL); 311 2676 eschrock } 312 2676 eschrock 313 2676 eschrock /* 314 2676 eschrock * See comments at end of main(). 315 2676 eschrock */ 316 2676 eschrock if (getenv("ZFS_ABORT") != NULL) { 317 2676 eschrock (void) printf("dumping core by request\n"); 318 2676 eschrock abort(); 319 789 ahrens } 320 789 ahrens 321 789 ahrens exit(requested ? 0 : 2); 322 789 ahrens } 323 789 ahrens 324 789 ahrens void 325 4527 perrin print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, 326 4527 perrin boolean_t print_logs) 327 789 ahrens { 328 789 ahrens nvlist_t **child; 329 789 ahrens uint_t c, children; 330 1171 eschrock char *vname; 331 789 ahrens 332 789 ahrens if (name != NULL) 333 789 ahrens (void) printf("\t%*s%s\n", indent, "", name); 334 789 ahrens 335 789 ahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 336 789 ahrens &child, &children) != 0) 337 789 ahrens return; 338 789 ahrens 339 1171 eschrock for (c = 0; c < children; c++) { 340 4527 perrin uint64_t is_log = B_FALSE; 341 4527 perrin 342 4527 perrin (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 343 4527 perrin &is_log); 344 4527 perrin if ((is_log && !print_logs) || (!is_log && print_logs)) 345 4527 perrin continue; 346 4527 perrin 347 10594 George vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 348 4527 perrin print_vdev_tree(zhp, vname, child[c], indent + 2, 349 4527 perrin B_FALSE); 350 1171 eschrock free(vname); 351 1171 eschrock } 352 5094 lling } 353 5094 lling 354 5094 lling /* 355 5094 lling * Add a property pair (name, string-value) into a property nvlist. 356 5094 lling */ 357 5094 lling static int 358 7184 timh add_prop_list(const char *propname, char *propval, nvlist_t **props, 359 7184 timh boolean_t poolprop) 360 5094 lling { 361 7184 timh zpool_prop_t prop = ZPROP_INVAL; 362 7184 timh zfs_prop_t fprop; 363 7184 timh nvlist_t *proplist; 364 7184 timh const char *normnm; 365 5094 lling char *strval; 366 5094 lling 367 5094 lling if (*props == NULL && 368 5094 lling nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) { 369 5094 lling (void) fprintf(stderr, 370 5094 lling gettext("internal error: out of memory\n")); 371 5094 lling return (1); 372 5094 lling } 373 5094 lling 374 5094 lling proplist = *props; 375 5094 lling 376 7184 timh if (poolprop) { 377 7184 timh if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) { 378 7184 timh (void) fprintf(stderr, gettext("property '%s' is " 379 7184 timh "not a valid pool property\n"), propname); 380 7184 timh return (2); 381 7184 timh } 382 7184 timh normnm = zpool_prop_to_name(prop); 383 7184 timh } else { 384 9396 Matthew if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) { 385 9396 Matthew normnm = zfs_prop_to_name(fprop); 386 9396 Matthew } else { 387 9396 Matthew normnm = propname; 388 7184 timh } 389 5094 lling } 390 5094 lling 391 7184 timh if (nvlist_lookup_string(proplist, normnm, &strval) == 0 && 392 7184 timh prop != ZPOOL_PROP_CACHEFILE) { 393 5094 lling (void) fprintf(stderr, gettext("property '%s' " 394 5094 lling "specified multiple times\n"), propname); 395 5094 lling return (2); 396 5094 lling } 397 5094 lling 398 7184 timh if (nvlist_add_string(proplist, normnm, propval) != 0) { 399 5094 lling (void) fprintf(stderr, gettext("internal " 400 5094 lling "error: out of memory\n")); 401 5094 lling return (1); 402 5094 lling } 403 5094 lling 404 5094 lling return (0); 405 789 ahrens } 406 789 ahrens 407 789 ahrens /* 408 789 ahrens * zpool add [-fn] <pool> <vdev> ... 409 789 ahrens * 410 789 ahrens * -f Force addition of devices, even if they appear in use 411 789 ahrens * -n Do not add the devices, but display the resulting layout if 412 789 ahrens * they were to be added. 413 789 ahrens * 414 789 ahrens * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 415 789 ahrens * handled by get_vdev_spec(), which constructs the nvlist needed to pass to 416 789 ahrens * libzfs. 417 789 ahrens */ 418 789 ahrens int 419 789 ahrens zpool_do_add(int argc, char **argv) 420 789 ahrens { 421 2082 eschrock boolean_t force = B_FALSE; 422 2082 eschrock boolean_t dryrun = B_FALSE; 423 789 ahrens int c; 424 789 ahrens nvlist_t *nvroot; 425 789 ahrens char *poolname; 426 789 ahrens int ret; 427 789 ahrens zpool_handle_t *zhp; 428 789 ahrens nvlist_t *config; 429 789 ahrens 430 789 ahrens /* check options */ 431 789 ahrens while ((c = getopt(argc, argv, "fn")) != -1) { 432 789 ahrens switch (c) { 433 789 ahrens case 'f': 434 2082 eschrock force = B_TRUE; 435 789 ahrens break; 436 789 ahrens case 'n': 437 2082 eschrock dryrun = B_TRUE; 438 789 ahrens break; 439 789 ahrens case '?': 440 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 441 789 ahrens optopt); 442 2082 eschrock usage(B_FALSE); 443 789 ahrens } 444 789 ahrens } 445 789 ahrens 446 789 ahrens argc -= optind; 447 789 ahrens argv += optind; 448 789 ahrens 449 789 ahrens /* get pool name and check number of arguments */ 450 789 ahrens if (argc < 1) { 451 789 ahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 452 2082 eschrock usage(B_FALSE); 453 789 ahrens } 454 789 ahrens if (argc < 2) { 455 789 ahrens (void) fprintf(stderr, gettext("missing vdev specification\n")); 456 2082 eschrock usage(B_FALSE); 457 789 ahrens } 458 789 ahrens 459 789 ahrens poolname = argv[0]; 460 789 ahrens 461 789 ahrens argc--; 462 789 ahrens argv++; 463 789 ahrens 464 2082 eschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 465 789 ahrens return (1); 466 789 ahrens 467 952 eschrock if ((config = zpool_get_config(zhp, NULL)) == NULL) { 468 789 ahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 469 789 ahrens poolname); 470 789 ahrens zpool_close(zhp); 471 789 ahrens return (1); 472 789 ahrens } 473 789 ahrens 474 789 ahrens /* pass off to get_vdev_spec for processing */ 475 7343 Eric nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun, 476 7343 Eric argc, argv); 477 789 ahrens if (nvroot == NULL) { 478 789 ahrens zpool_close(zhp); 479 789 ahrens return (1); 480 789 ahrens } 481 789 ahrens 482 789 ahrens if (dryrun) { 483 789 ahrens nvlist_t *poolnvroot; 484 789 ahrens 485 789 ahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 486 789 ahrens &poolnvroot) == 0); 487 789 ahrens 488 789 ahrens (void) printf(gettext("would update '%s' to the following " 489 789 ahrens "configuration:\n"), zpool_get_name(zhp)); 490 789 ahrens 491 4527 perrin /* print original main pool and new tree */ 492 4527 perrin print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE); 493 4527 perrin print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE); 494 4527 perrin 495 4527 perrin /* Do the same for the logs */ 496 4527 perrin if (num_logs(poolnvroot) > 0) { 497 4527 perrin print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE); 498 4527 perrin print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE); 499 4527 perrin } else if (num_logs(nvroot) > 0) { 500 4527 perrin print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE); 501 4527 perrin } 502 789 ahrens 503 789 ahrens ret = 0; 504 789 ahrens } else { 505 789 ahrens ret = (zpool_add(zhp, nvroot) != 0); 506 789 ahrens } 507 789 ahrens 508 2082 eschrock nvlist_free(nvroot); 509 2082 eschrock zpool_close(zhp); 510 2082 eschrock 511 2082 eschrock return (ret); 512 2082 eschrock } 513 2082 eschrock 514 2082 eschrock /* 515 5450 brendan * zpool remove <pool> <vdev> ... 516 2082 eschrock * 517 2082 eschrock * Removes the given vdev from the pool. Currently, this only supports removing 518 5450 brendan * spares and cache devices from the pool. Eventually, we'll want to support 519 5450 brendan * removing leaf vdevs (as an alias for 'detach') as well as toplevel vdevs. 520 2082 eschrock */ 521 2082 eschrock int 522 2082 eschrock zpool_do_remove(int argc, char **argv) 523 2082 eschrock { 524 2082 eschrock char *poolname; 525 5450 brendan int i, ret = 0; 526 2082 eschrock zpool_handle_t *zhp; 527 2082 eschrock 528 2082 eschrock argc--; 529 2082 eschrock argv++; 530 2082 eschrock 531 2082 eschrock /* get pool name and check number of arguments */ 532 2082 eschrock if (argc < 1) { 533 2082 eschrock (void) fprintf(stderr, gettext("missing pool name argument\n")); 534 2082 eschrock usage(B_FALSE); 535 2082 eschrock } 536 2082 eschrock if (argc < 2) { 537 2082 eschrock (void) fprintf(stderr, gettext("missing device\n")); 538 2082 eschrock usage(B_FALSE); 539 2082 eschrock } 540 2082 eschrock 541 2082 eschrock poolname = argv[0]; 542 2082 eschrock 543 2082 eschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 544 2082 eschrock return (1); 545 2082 eschrock 546 5450 brendan for (i = 1; i < argc; i++) { 547 5450 brendan if (zpool_vdev_remove(zhp, argv[i]) != 0) 548 5450 brendan ret = 1; 549 5450 brendan } 550 2082 eschrock 551 789 ahrens return (ret); 552 789 ahrens } 553 789 ahrens 554 789 ahrens /* 555 7184 timh * zpool create [-fn] [-o property=value] ... 556 7184 timh * [-O file-system-property=value] ... 557 7184 timh * [-R root] [-m mountpoint] <pool> <dev> ... 558 789 ahrens * 559 789 ahrens * -f Force creation, even if devices appear in use 560 789 ahrens * -n Do not create the pool, but display the resulting layout if it 561 789 ahrens * were to be created. 562 789 ahrens * -R Create a pool under an alternate root 563 789 ahrens * -m Set default mountpoint for the root dataset. By default it's 564 789 ahrens * '/<pool>' 565 5094 lling * -o Set property=value. 566 7184 timh * -O Set fsproperty=value in the pool's root file system 567 789 ahrens * 568 3912 lling * Creates the named pool according to the given vdev specification. The 569 789 ahrens * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once 570 789 ahrens * we get the nvlist back from get_vdev_spec(), we either print out the contents 571 789 ahrens * (if '-n' was specified), or pass it to libzfs to do the creation. 572 789 ahrens */ 573 789 ahrens int 574 789 ahrens zpool_do_create(int argc, char **argv) 575 789 ahrens { 576 2082 eschrock boolean_t force = B_FALSE; 577 2082 eschrock boolean_t dryrun = B_FALSE; 578 789 ahrens int c; 579 5094 lling nvlist_t *nvroot = NULL; 580 789 ahrens char *poolname; 581 5094 lling int ret = 1; 582 789 ahrens char *altroot = NULL; 583 789 ahrens char *mountpoint = NULL; 584 7184 timh nvlist_t *fsprops = NULL; 585 5094 lling nvlist_t *props = NULL; 586 5363 eschrock char *propval; 587 789 ahrens 588 789 ahrens /* check options */ 589 7184 timh while ((c = getopt(argc, argv, ":fnR:m:o:O:")) != -1) { 590 789 ahrens switch (c) { 591 789 ahrens case 'f': 592 2082 eschrock force = B_TRUE; 593 789 ahrens break; 594 789 ahrens case 'n': 595 2082 eschrock dryrun = B_TRUE; 596 789 ahrens break; 597 789 ahrens case 'R': 598 789 ahrens altroot = optarg; 599 5094 lling if (add_prop_list(zpool_prop_to_name( 600 7184 timh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 601 5094 lling goto errout; 602 5363 eschrock if (nvlist_lookup_string(props, 603 5363 eschrock zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 604 5363 eschrock &propval) == 0) 605 5363 eschrock break; 606 5094 lling if (add_prop_list(zpool_prop_to_name( 607 7184 timh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 608 5094 lling goto errout; 609 789 ahrens break; 610 789 ahrens case 'm': 611 789 ahrens mountpoint = optarg; 612 789 ahrens break; 613 5094 lling case 'o': 614 5094 lling if ((propval = strchr(optarg, '=')) == NULL) { 615 5094 lling (void) fprintf(stderr, gettext("missing " 616 5094 lling "'=' for -o option\n")); 617 5094 lling goto errout; 618 5094 lling } 619 5094 lling *propval = '\0'; 620 5094 lling propval++; 621 5094 lling 622 7184 timh if (add_prop_list(optarg, propval, &props, B_TRUE)) 623 7184 timh goto errout; 624 7184 timh break; 625 7184 timh case 'O': 626 7184 timh if ((propval = strchr(optarg, '=')) == NULL) { 627 7184 timh (void) fprintf(stderr, gettext("missing " 628 7184 timh "'=' for -O option\n")); 629 7184 timh goto errout; 630 7184 timh } 631 7184 timh *propval = '\0'; 632 7184 timh propval++; 633 7184 timh 634 7184 timh if (add_prop_list(optarg, propval, &fsprops, B_FALSE)) 635 5094 lling goto errout; 636 5094 lling break; 637 789 ahrens case ':': 638 789 ahrens (void) fprintf(stderr, gettext("missing argument for " 639 789 ahrens "'%c' option\n"), optopt); 640 5094 lling goto badusage; 641 789 ahrens case '?': 642 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 643 789 ahrens optopt); 644 5094 lling goto badusage; 645 789 ahrens } 646 789 ahrens } 647 789 ahrens 648 789 ahrens argc -= optind; 649 789 ahrens argv += optind; 650 789 ahrens 651 789 ahrens /* get pool name and check number of arguments */ 652 789 ahrens if (argc < 1) { 653 789 ahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 654 5094 lling goto badusage; 655 789 ahrens } 656 789 ahrens if (argc < 2) { 657 789 ahrens (void) fprintf(stderr, gettext("missing vdev specification\n")); 658 5094 lling goto badusage; 659 789 ahrens } 660 789 ahrens 661 789 ahrens poolname = argv[0]; 662 789 ahrens 663 789 ahrens /* 664 789 ahrens * As a special case, check for use of '/' in the name, and direct the 665 789 ahrens * user to use 'zfs create' instead. 666 789 ahrens */ 667 789 ahrens if (strchr(poolname, '/') != NULL) { 668 789 ahrens (void) fprintf(stderr, gettext("cannot create '%s': invalid " 669 789 ahrens "character '/' in pool name\n"), poolname); 670 789 ahrens (void) fprintf(stderr, gettext("use 'zfs create' to " 671 789 ahrens "create a dataset\n")); 672 5094 lling goto errout; 673 789 ahrens } 674 789 ahrens 675 789 ahrens /* pass off to get_vdev_spec for bulk processing */ 676 7343 Eric nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun, 677 7343 Eric argc - 1, argv + 1); 678 789 ahrens if (nvroot == NULL) 679 7184 timh goto errout; 680 2082 eschrock 681 2082 eschrock /* make_root_vdev() allows 0 toplevel children if there are spares */ 682 5913 perrin if (!zfs_allocatable_devs(nvroot)) { 683 2082 eschrock (void) fprintf(stderr, gettext("invalid vdev " 684 2082 eschrock "specification: at least one toplevel vdev must be " 685 2082 eschrock "specified\n")); 686 5094 lling goto errout; 687 2082 eschrock } 688 2082 eschrock 689 789 ahrens 690 789 ahrens if (altroot != NULL && altroot[0] != '/') { 691 789 ahrens (void) fprintf(stderr, gettext("invalid alternate root '%s': " 692 2676 eschrock "must be an absolute path\n"), altroot); 693 5094 lling goto errout; 694 789 ahrens } 695 789 ahrens 696 789 ahrens /* 697 789 ahrens * Check the validity of the mountpoint and direct the user to use the 698 789 ahrens * '-m' mountpoint option if it looks like its in use. 699 789 ahrens */ 700 789 ahrens if (mountpoint == NULL || 701 789 ahrens (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 702 789 ahrens strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) { 703 789 ahrens char buf[MAXPATHLEN]; 704 5904 timh DIR *dirp; 705 789 ahrens 706 789 ahrens if (mountpoint && mountpoint[0] != '/') { 707 789 ahrens (void) fprintf(stderr, gettext("invalid mountpoint " 708 789 ahrens "'%s': must be an absolute path, 'legacy', or " 709 789 ahrens "'none'\n"), mountpoint); 710 5094 lling goto errout; 711 789 ahrens } 712 789 ahrens 713 789 ahrens if (mountpoint == NULL) { 714 789 ahrens if (altroot != NULL) 715 789 ahrens (void) snprintf(buf, sizeof (buf), "%s/%s", 716 789 ahrens altroot, poolname); 717 789 ahrens else 718 789 ahrens (void) snprintf(buf, sizeof (buf), "/%s", 719 789 ahrens poolname); 720 789 ahrens } else { 721 789 ahrens if (altroot != NULL) 722 789 ahrens (void) snprintf(buf, sizeof (buf), "%s%s", 723 789 ahrens altroot, mountpoint); 724 789 ahrens else 725 789 ahrens (void) snprintf(buf, sizeof (buf), "%s", 726 789 ahrens mountpoint); 727 789 ahrens } 728 789 ahrens 729 5904 timh if ((dirp = opendir(buf)) == NULL && errno != ENOENT) { 730 5904 timh (void) fprintf(stderr, gettext("mountpoint '%s' : " 731 5904 timh "%s\n"), buf, strerror(errno)); 732 789 ahrens (void) fprintf(stderr, gettext("use '-m' " 733 789 ahrens "option to provide a different default\n")); 734 5094 lling goto errout; 735 5904 timh } else if (dirp) { 736 5904 timh int count = 0; 737 5904 timh 738 5904 timh while (count < 3 && readdir(dirp) != NULL) 739 5904 timh count++; 740 5904 timh (void) closedir(dirp); 741 5904 timh 742 5904 timh if (count > 2) { 743 5904 timh (void) fprintf(stderr, gettext("mountpoint " 744 5904 timh "'%s' exists and is not empty\n"), buf); 745 5904 timh (void) fprintf(stderr, gettext("use '-m' " 746 5904 timh "option to provide a " 747 5904 timh "different default\n")); 748 5904 timh goto errout; 749 5904 timh } 750 789 ahrens } 751 789 ahrens } 752 789 ahrens 753 789 ahrens if (dryrun) { 754 789 ahrens /* 755 789 ahrens * For a dry run invocation, print out a basic message and run 756 789 ahrens * through all the vdevs in the list and print out in an 757 789 ahrens * appropriate hierarchy. 758 789 ahrens */ 759 789 ahrens (void) printf(gettext("would create '%s' with the " 760 789 ahrens "following layout:\n\n"), poolname); 761 789 ahrens 762 4527 perrin print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE); 763 4527 perrin if (num_logs(nvroot) > 0) 764 4527 perrin print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE); 765 789 ahrens 766 789 ahrens ret = 0; 767 789 ahrens } else { 768 789 ahrens /* 769 789 ahrens * Hand off to libzfs. 770 789 ahrens */ 771 7184 timh if (zpool_create(g_zfs, poolname, 772 7184 timh nvroot, props, fsprops) == 0) { 773 2082 eschrock zfs_handle_t *pool = zfs_open(g_zfs, poolname, 774 789 ahrens ZFS_TYPE_FILESYSTEM); 775 789 ahrens if (pool != NULL) { 776 789 ahrens if (mountpoint != NULL) 777 789 ahrens verify(zfs_prop_set(pool, 778 2676 eschrock zfs_prop_to_name( 779 2676 eschrock ZFS_PROP_MOUNTPOINT), 780 789 ahrens mountpoint) == 0); 781 789 ahrens if (zfs_mount(pool, NULL, 0) == 0) 782 5331 amw ret = zfs_shareall(pool); 783 789 ahrens zfs_close(pool); 784 789 ahrens } 785 2082 eschrock } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { 786 2082 eschrock (void) fprintf(stderr, gettext("pool name may have " 787 2082 eschrock "been omitted\n")); 788 789 ahrens } 789 789 ahrens } 790 789 ahrens 791 5094 lling errout: 792 5363 eschrock nvlist_free(nvroot); 793 7184 timh nvlist_free(fsprops); 794 5363 eschrock nvlist_free(props); 795 789 ahrens return (ret); 796 5094 lling badusage: 797 7184 timh nvlist_free(fsprops); 798 5094 lling nvlist_free(props); 799 5094 lling usage(B_FALSE); 800 5094 lling return (2); 801 789 ahrens } 802 789 ahrens 803 789 ahrens /* 804 789 ahrens * zpool destroy <pool> 805 789 ahrens * 806 789 ahrens * -f Forcefully unmount any datasets 807 789 ahrens * 808 789 ahrens * Destroy the given pool. Automatically unmounts any datasets in the pool. 809 789 ahrens */ 810 789 ahrens int 811 789 ahrens zpool_do_destroy(int argc, char **argv) 812 789 ahrens { 813 2082 eschrock boolean_t force = B_FALSE; 814 789 ahrens int c; 815 789 ahrens char *pool; 816 789 ahrens zpool_handle_t *zhp; 817 789 ahrens int ret; 818 789 ahrens 819 789 ahrens /* check options */ 820 789 ahrens while ((c = getopt(argc, argv, "f")) != -1) { 821 789 ahrens switch (c) { 822 789 ahrens case 'f': 823 2082 eschrock force = B_TRUE; 824 789 ahrens break; 825 789 ahrens case '?': 826 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 827 789 ahrens optopt); 828 2082 eschrock usage(B_FALSE); 829 789 ahrens } 830 789 ahrens } 831 789 ahrens 832 789 ahrens argc -= optind; 833 789 ahrens argv += optind; 834 789 ahrens 835 789 ahrens /* check arguments */ 836 789 ahrens if (argc < 1) { 837 789 ahrens (void) fprintf(stderr, gettext("missing pool argument\n")); 838 2082 eschrock usage(B_FALSE); 839 789 ahrens } 840 789 ahrens if (argc > 1) { 841 789 ahrens (void) fprintf(stderr, gettext("too many arguments\n")); 842 2082 eschrock usage(B_FALSE); 843 789 ahrens } 844 789 ahrens 845 789 ahrens pool = argv[0]; 846 789 ahrens 847 2082 eschrock if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 848 789 ahrens /* 849 789 ahrens * As a special case, check for use of '/' in the name, and 850 789 ahrens * direct the user to use 'zfs destroy' instead. 851 789 ahrens */ 852 789 ahrens if (strchr(pool, '/') != NULL) 853 789 ahrens (void) fprintf(stderr, gettext("use 'zfs destroy' to " 854 789 ahrens "destroy a dataset\n")); 855 789 ahrens return (1); 856 789 ahrens } 857 789 ahrens 858 3126 ahl if (zpool_disable_datasets(zhp, force) != 0) { 859 789 ahrens (void) fprintf(stderr, gettext("could not destroy '%s': " 860 789 ahrens "could not unmount datasets\n"), zpool_get_name(zhp)); 861 789 ahrens return (1); 862 789 ahrens } 863 789 ahrens 864 789 ahrens ret = (zpool_destroy(zhp) != 0); 865 789 ahrens 866 789 ahrens zpool_close(zhp); 867 789 ahrens 868 789 ahrens return (ret); 869 789 ahrens } 870 789 ahrens 871 789 ahrens /* 872 789 ahrens * zpool export [-f] <pool> ... 873 789 ahrens * 874 789 ahrens * -f Forcefully unmount datasets 875 789 ahrens * 876 3912 lling * Export the given pools. By default, the command will attempt to cleanly 877 789 ahrens * unmount any active datasets within the pool. If the '-f' flag is specified, 878 789 ahrens * then the datasets will be forcefully unmounted. 879 789 ahrens */ 880 789 ahrens int 881 789 ahrens zpool_do_export(int argc, char **argv) 882 789 ahrens { 883 2082 eschrock boolean_t force = B_FALSE; 884 8211 George boolean_t hardforce = B_FALSE; 885 789 ahrens int c; 886 789 ahrens zpool_handle_t *zhp; 887 789 ahrens int ret; 888 789 ahrens int i; 889 789 ahrens 890 789 ahrens /* check options */ 891 8211 George while ((c = getopt(argc, argv, "fF")) != -1) { 892 789 ahrens switch (c) { 893 789 ahrens case 'f': 894 2082 eschrock force = B_TRUE; 895 8211 George break; 896 8211 George case 'F': 897 8211 George hardforce = B_TRUE; 898 789 ahrens break; 899 789 ahrens case '?': 900 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 901 789 ahrens optopt); 902 2082 eschrock usage(B_FALSE); 903 789 ahrens } 904 789 ahrens } 905 789 ahrens 906 789 ahrens argc -= optind; 907 789 ahrens argv += optind; 908 789 ahrens 909 789 ahrens /* check arguments */ 910 789 ahrens if (argc < 1) { 911 789 ahrens (void) fprintf(stderr, gettext("missing pool argument\n")); 912 2082 eschrock usage(B_FALSE); 913 789 ahrens } 914 789 ahrens 915 789 ahrens ret = 0; 916 789 ahrens for (i = 0; i < argc; i++) { 917 2082 eschrock if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) { 918 789 ahrens ret = 1; 919 789 ahrens continue; 920 789 ahrens } 921 789 ahrens 922 3126 ahl if (zpool_disable_datasets(zhp, force) != 0) { 923 789 ahrens ret = 1; 924 789 ahrens zpool_close(zhp); 925 789 ahrens continue; 926 789 ahrens } 927 789 ahrens 928 8211 George if (hardforce) { 929 8211 George if (zpool_export_force(zhp) != 0) 930 8211 George ret = 1; 931 8211 George } else if (zpool_export(zhp, force) != 0) { 932 789 ahrens ret = 1; 933 8211 George } 934 789 ahrens 935 789 ahrens zpool_close(zhp); 936 789 ahrens } 937 789 ahrens 938 789 ahrens return (ret); 939 789 ahrens } 940 789 ahrens 941 789 ahrens /* 942 789 ahrens * Given a vdev configuration, determine the maximum width needed for the device 943 789 ahrens * name column. 944 789 ahrens */ 945 789 ahrens static int 946 1354 eschrock max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max) 947 789 ahrens { 948 10594 George char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE); 949 789 ahrens nvlist_t **child; 950 789 ahrens uint_t c, children; 951 789 ahrens int ret; 952 789 ahrens 953 789 ahrens if (strlen(name) + depth > max) 954 789 ahrens max = strlen(name) + depth; 955 1171 eschrock 956 1171 eschrock free(name); 957 789 ahrens 958 2082 eschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 959 2082 eschrock &child, &children) == 0) { 960 2082 eschrock for (c = 0; c < children; c++) 961 2082 eschrock if ((ret = max_width(zhp, child[c], depth + 2, 962 2082 eschrock max)) > max) 963 2082 eschrock max = ret; 964 2082 eschrock } 965 2082 eschrock 966 5450 brendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 967 5450 brendan &child, &children) == 0) { 968 5450 brendan for (c = 0; c < children; c++) 969 5450 brendan if ((ret = max_width(zhp, child[c], depth + 2, 970 5450 brendan max)) > max) 971 5450 brendan max = ret; 972 5450 brendan } 973 5450 brendan 974 789 ahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 975 2082 eschrock &child, &children) == 0) { 976 2082 eschrock for (c = 0; c < children; c++) 977 2082 eschrock if ((ret = max_width(zhp, child[c], depth + 2, 978 2082 eschrock max)) > max) 979 2082 eschrock max = ret; 980 2082 eschrock } 981 789 ahrens 982 789 ahrens 983 789 ahrens return (max); 984 789 ahrens } 985 789 ahrens 986 9701 George typedef struct spare_cbdata { 987 9701 George uint64_t cb_guid; 988 9701 George zpool_handle_t *cb_zhp; 989 9701 George } spare_cbdata_t; 990 9701 George 991 9701 George static boolean_t 992 9701 George find_vdev(nvlist_t *nv, uint64_t search) 993 9701 George { 994 9701 George uint64_t guid; 995 9701 George nvlist_t **child; 996 9701 George uint_t c, children; 997 9701 George 998 9701 George if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 999 9701 George search == guid) 1000 9701 George return (B_TRUE); 1001 9701 George 1002 9701 George if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1003 9701 George &child, &children) == 0) { 1004 9701 George for (c = 0; c < children; c++) 1005 9701 George if (find_vdev(child[c], search)) 1006 9701 George return (B_TRUE); 1007 9701 George } 1008 9701 George 1009 9701 George return (B_FALSE); 1010 9701 George } 1011 9701 George 1012 9701 George static int 1013 9701 George find_spare(zpool_handle_t *zhp, void *data) 1014 9701 George { 1015 9701 George spare_cbdata_t *cbp = data; 1016 9701 George nvlist_t *config, *nvroot; 1017 9701 George 1018 9701 George config = zpool_get_config(zhp, NULL); 1019 9701 George verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1020 9701 George &nvroot) == 0); 1021 9701 George 1022 9701 George if (find_vdev(nvroot, cbp->cb_guid)) { 1023 9701 George cbp->cb_zhp = zhp; 1024 9701 George return (1); 1025 9701 George } 1026 9701 George 1027 9701 George zpool_close(zhp); 1028 9701 George return (0); 1029 9701 George } 1030 9701 George 1031 9701 George /* 1032 9701 George * Print out configuration state as requested by status_callback. 1033 9701 George */ 1034 9701 George void 1035 9701 George print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 1036 9701 George int namewidth, int depth, boolean_t isspare) 1037 9701 George { 1038 9701 George nvlist_t **child; 1039 9701 George uint_t c, children; 1040 9701 George vdev_stat_t *vs; 1041 9701 George char rbuf[6], wbuf[6], cbuf[6], repaired[7]; 1042 9701 George char *vname; 1043 9701 George uint64_t notpresent; 1044 9701 George spare_cbdata_t cb; 1045 9701 George char *state; 1046 9701 George 1047 9701 George verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 1048 9701 George (uint64_t **)&vs, &c) == 0); 1049 9701 George 1050 9701 George if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1051 9701 George &child, &children) != 0) 1052 9701 George children = 0; 1053 9701 George 1054 9701 George state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1055 9701 George if (isspare) { 1056 9701 George /* 1057 9701 George * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 1058 9701 George * online drives. 1059 9701 George */ 1060 9701 George if (vs->vs_aux == VDEV_AUX_SPARED) 1061 9701 George state = "INUSE"; 1062 9701 George else if (vs->vs_state == VDEV_STATE_HEALTHY) 1063 9701 George state = "AVAIL"; 1064 9701 George } 1065 9701 George 1066 9701 George (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, 1067 9701 George name, state); 1068 9701 George 1069 9701 George if (!isspare) { 1070 9701 George zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 1071 9701 George zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 1072 9701 George zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 1073 9701 George (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 1074 9701 George } 1075 9701 George 1076 9701 George if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1077 9701 George ¬present) == 0) { 1078 9701 George char *path; 1079 9701 George verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 1080 9701 George (void) printf(" was %s", path); 1081 9701 George } else if (vs->vs_aux != 0) { 1082 9701 George (void) printf(" "); 1083 9701 George 1084 9701 George switch (vs->vs_aux) { 1085 9701 George case VDEV_AUX_OPEN_FAILED: 1086 9701 George (void) printf(gettext("cannot open")); 1087 9701 George break; 1088 9701 George 1089 9701 George case VDEV_AUX_BAD_GUID_SUM: 1090 9701 George (void) printf(gettext("missing device")); 1091 9701 George break; 1092 9701 George 1093 9701 George case VDEV_AUX_NO_REPLICAS: 1094 9701 George (void) printf(gettext("insufficient replicas")); 1095 9701 George break; 1096 9701 George 1097 9701 George case VDEV_AUX_VERSION_NEWER: 1098 9701 George (void) printf(gettext("newer version")); 1099 9701 George break; 1100 9701 George 1101 9701 George case VDEV_AUX_SPARED: 1102 9701 George verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 1103 9701 George &cb.cb_guid) == 0); 1104 9701 George if (zpool_iter(g_zfs, find_spare, &cb) == 1) { 1105 9701 George if (strcmp(zpool_get_name(cb.cb_zhp), 1106 9701 George zpool_get_name(zhp)) == 0) 1107 9701 George (void) printf(gettext("currently in " 1108 9701 George "use")); 1109 9701 George else 1110 9701 George (void) printf(gettext("in use by " 1111 9701 George "pool '%s'"), 1112 9701 George zpool_get_name(cb.cb_zhp)); 1113 9701 George zpool_close(cb.cb_zhp); 1114 9701 George } else { 1115 9701 George (void) printf(gettext("currently in use")); 1116 9701 George } 1117 9701 George break; 1118 9701 George 1119 9701 George case VDEV_AUX_ERR_EXCEEDED: 1120 9701 George (void) printf(gettext("too many errors")); 1121 9701 George break; 1122 9701 George 1123 9701 George case VDEV_AUX_IO_FAILURE: 1124 9701 George (void) printf(gettext("experienced I/O failures")); 1125 9701 George break; 1126 9701 George 1127 9701 George case VDEV_AUX_BAD_LOG: 1128 9701 George (void) printf(gettext("bad intent log")); 1129 9701 George break; 1130 9701 George 1131 10817 Eric case VDEV_AUX_EXTERNAL: 1132 10817 Eric (void) printf(gettext("external device fault")); 1133 10817 Eric break; 1134 10817 Eric 1135 9701 George default: 1136 9701 George (void) printf(gettext("corrupted data")); 1137 9701 George break; 1138 9701 George } 1139 9701 George } else if (vs->vs_scrub_repaired != 0 && children == 0) { 1140 9701 George /* 1141 9701 George * Report bytes resilvered/repaired on leaf devices. 1142 9701 George */ 1143 9701 George zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired)); 1144 9701 George (void) printf(gettext(" %s %s"), repaired, 1145 9701 George (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 1146 9701 George "resilvered" : "repaired"); 1147 9701 George } 1148 9701 George 1149 9701 George (void) printf("\n"); 1150 9701 George 1151 9701 George for (c = 0; c < children; c++) { 1152 10594 George uint64_t islog = B_FALSE, ishole = B_FALSE; 1153 10594 George 1154 10594 George /* Don't print logs or holes here */ 1155 10594 George (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1156 10594 George &islog); 1157 10594 George (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, 1158 10594 George &ishole); 1159 10594 George if (islog || ishole) 1160 10594 George continue; 1161 10594 George vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE); 1162 10594 George print_status_config(zhp, vname, child[c], 1163 10594 George namewidth, depth + 2, isspare); 1164 10594 George free(vname); 1165 10594 George } 1166 10594 George } 1167 10594 George 1168 10594 George 1169 10594 George /* 1170 10594 George * Print the configuration of an exported pool. Iterate over all vdevs in the 1171 10594 George * pool, printing out the name and status for each one. 1172 10594 George */ 1173 10594 George void 1174 10594 George print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) 1175 10594 George { 1176 10594 George nvlist_t **child; 1177 10594 George uint_t c, children; 1178 10594 George vdev_stat_t *vs; 1179 10594 George char *type, *vname; 1180 10594 George 1181 10594 George verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 1182 10594 George if (strcmp(type, VDEV_TYPE_MISSING) == 0 || 1183 10594 George strcmp(type, VDEV_TYPE_HOLE) == 0) 1184 10594 George return; 1185 10594 George 1186 10594 George verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 1187 10594 George (uint64_t **)&vs, &c) == 0); 1188 10594 George 1189 10594 George (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name); 1190 10594 George (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); 1191 10594 George 1192 10594 George if (vs->vs_aux != 0) { 1193 10594 George (void) printf(" "); 1194 10594 George 1195 10594 George switch (vs->vs_aux) { 1196 10594 George case VDEV_AUX_OPEN_FAILED: 1197 10594 George (void) printf(gettext("cannot open")); 1198 10594 George break; 1199 10594 George 1200 10594 George case VDEV_AUX_BAD_GUID_SUM: 1201 10594 George (void) printf(gettext("missing device")); 1202 10594 George break; 1203 10594 George 1204 10594 George case VDEV_AUX_NO_REPLICAS: 1205 10594 George (void) printf(gettext("insufficient replicas")); 1206 10594 George break; 1207 10594 George 1208 10594 George case VDEV_AUX_VERSION_NEWER: 1209 10594 George (void) printf(gettext("newer version")); 1210 10594 George break; 1211 10594 George 1212 10594 George case VDEV_AUX_ERR_EXCEEDED: 1213 10594 George (void) printf(gettext("too many errors")); 1214 10594 George break; 1215 10594 George 1216 10594 George default: 1217 10594 George (void) printf(gettext("corrupted data")); 1218 10594 George break; 1219 10594 George } 1220 10594 George } 1221 10594 George (void) printf("\n"); 1222 10594 George 1223 10594 George if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1224 10594 George &child, &children) != 0) 1225 10594 George return; 1226 10594 George 1227 10594 George for (c = 0; c < children; c++) { 1228 9701 George uint64_t is_log = B_FALSE; 1229 9701 George 1230 9701 George (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1231 9701 George &is_log); 1232 9701 George if (is_log) 1233 9701 George continue; 1234 10594 George 1235 10594 George vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE); 1236 9701 George print_import_config(vname, child[c], namewidth, depth + 2); 1237 2082 eschrock free(vname); 1238 2082 eschrock } 1239 2082 eschrock 1240 5450 brendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1241 5450 brendan &child, &children) == 0) { 1242 5450 brendan (void) printf(gettext("\tcache\n")); 1243 5450 brendan for (c = 0; c < children; c++) { 1244 10594 George vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE); 1245 5450 brendan (void) printf("\t %s\n", vname); 1246 5450 brendan free(vname); 1247 5450 brendan } 1248 5450 brendan } 1249 5450 brendan 1250 2082 eschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1251 5450 brendan &child, &children) == 0) { 1252 5450 brendan (void) printf(gettext("\tspares\n")); 1253 5450 brendan for (c = 0; c < children; c++) { 1254 10594 George vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE); 1255 5450 brendan (void) printf("\t %s\n", vname); 1256 5450 brendan free(vname); 1257 5450 brendan } 1258 1171 eschrock } 1259 789 ahrens } 1260 789 ahrens 1261 9701 George /* 1262 9701 George * Print log vdevs. 1263 9701 George * Logs are recorded as top level vdevs in the main pool child array 1264 9701 George * but with "is_log" set to 1. We use either print_status_config() or 1265 9701 George * print_import_config() to print the top level logs then any log 1266 9701 George * children (eg mirrored slogs) are printed recursively - which 1267 9701 George * works because only the top level vdev is marked "is_log" 1268 9701 George */ 1269 9701 George static void 1270 9701 George print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose) 1271 9701 George { 1272 9701 George uint_t c, children; 1273 9701 George nvlist_t **child; 1274 9701 George 1275 9701 George if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, 1276 9701 George &children) != 0) 1277 9701 George return; 1278 9701 George 1279 9701 George (void) printf(gettext("\tlogs\n")); 1280 9701 George 1281 9701 George for (c = 0; c < children; c++) { 1282 9701 George uint64_t is_log = B_FALSE; 1283 9701 George char *name; 1284 9701 George 1285 9701 George (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1286 9701 George &is_log); 1287 9701 George if (!is_log) 1288 9701 George continue; 1289 10594 George name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE); 1290 9701 George if (verbose) 1291 9701 George print_status_config(zhp, name, child[c], namewidth, 1292 9701 George 2, B_FALSE); 1293 9701 George else 1294 9701 George print_import_config(name, child[c], namewidth, 2); 1295 9701 George free(name); 1296 9701 George } 1297 9701 George } 1298 10921 Tim 1299 789 ahrens /* 1300 789 ahrens * Display the status for the given pool. 1301 789 ahrens */ 1302 789 ahrens static void 1303 789 ahrens show_import(nvlist_t *config) 1304 789 ahrens { 1305 789 ahrens uint64_t pool_state; 1306 789 ahrens vdev_stat_t *vs; 1307 789 ahrens char *name; 1308 789 ahrens uint64_t guid; 1309 789 ahrens char *msgid; 1310 789 ahrens nvlist_t *nvroot; 1311 789 ahrens int reason; 1312 3741 mmusante const char *health; 1313 789 ahrens uint_t vsc; 1314 789 ahrens int namewidth; 1315 789 ahrens 1316 789 ahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1317 789 ahrens &name) == 0); 1318 789 ahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 1319 789 ahrens &guid) == 0); 1320 789 ahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 1321 789 ahrens &pool_state) == 0); 1322 789 ahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1323 789 ahrens &nvroot) == 0); 1324 789 ahrens 1325 789 ahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 1326 789 ahrens (uint64_t **)&vs, &vsc) == 0); 1327 5094 lling health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1328 789 ahrens 1329 789 ahrens reason = zpool_import_status(config, &msgid); 1330 789 ahrens 1331 3741 mmusante (void) printf(gettext(" pool: %s\n"), name); 1332 3741 mmusante (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); 1333 3741 mmusante (void) printf(gettext(" state: %s"), health); 1334 1631 darrenm if (pool_state == POOL_STATE_DESTROYED) 1335 3912 lling (void) printf(gettext(" (DESTROYED)")); 1336 1631 darrenm (void) printf("\n"); 1337 789 ahrens 1338 789 ahrens switch (reason) { 1339 789 ahrens case ZPOOL_STATUS_MISSING_DEV_R: 1340 789 ahrens case ZPOOL_STATUS_MISSING_DEV_NR: 1341 789 ahrens case ZPOOL_STATUS_BAD_GUID_SUM: 1342 789 ahrens (void) printf(gettext("status: One or more devices are missing " 1343 789 ahrens "from the system.\n")); 1344 789 ahrens break; 1345 789 ahrens 1346 789 ahrens case ZPOOL_STATUS_CORRUPT_LABEL_R: 1347 789 ahrens case ZPOOL_STATUS_CORRUPT_LABEL_NR: 1348 789 ahrens (void) printf(gettext("status: One or more devices contains " 1349 789 ahrens "corrupted data.\n")); 1350 789 ahrens break; 1351 789 ahrens 1352 789 ahrens case ZPOOL_STATUS_CORRUPT_DATA: 1353 789 ahrens (void) printf(gettext("status: The pool data is corrupted.\n")); 1354 1485 lling break; 1355 1485 lling 1356 1485 lling case ZPOOL_STATUS_OFFLINE_DEV: 1357 1485 lling (void) printf(gettext("status: One or more devices " 1358 1485 lling "are offlined.\n")); 1359 1544 eschrock break; 1360 1544 eschrock 1361 1544 eschrock case ZPOOL_STATUS_CORRUPT_POOL: 1362 1544 eschrock (void) printf(gettext("status: The pool metadata is " 1363 1544 eschrock "corrupted.\n")); 1364 789 ahrens break; 1365 789 ahrens 1366 1760 eschrock case ZPOOL_STATUS_VERSION_OLDER: 1367 1760 eschrock (void) printf(gettext("status: The pool is formatted using an " 1368 1760 eschrock "older on-disk version.\n")); 1369 1760 eschrock break; 1370 1760 eschrock 1371 1760 eschrock case ZPOOL_STATUS_VERSION_NEWER: 1372 1760 eschrock (void) printf(gettext("status: The pool is formatted using an " 1373 1760 eschrock "incompatible version.\n")); 1374 1760 eschrock break; 1375 7294 perrin 1376 3975 ek110237 case ZPOOL_STATUS_HOSTID_MISMATCH: 1377 3975 ek110237 (void) printf(gettext("status: The pool was last accessed by " 1378 3975 ek110237 "another system.\n")); 1379 3975 ek110237 break; 1380 7294 perrin 1381 4451 eschrock case ZPOOL_STATUS_FAULTED_DEV_R: 1382 4451 eschrock case ZPOOL_STATUS_FAULTED_DEV_NR: 1383 4451 eschrock (void) printf(gettext("status: One or more devices are " 1384 4451 eschrock "faulted.\n")); 1385 7294 perrin break; 1386 7294 perrin 1387 7294 perrin case ZPOOL_STATUS_BAD_LOG: 1388 7294 perrin (void) printf(gettext("status: An intent log record cannot be " 1389 7294 perrin "read.\n")); 1390 4451 eschrock break; 1391 4451 eschrock 1392 789 ahrens default: 1393 789 ahrens /* 1394 789 ahrens * No other status can be seen when importing pools. 1395 789 ahrens */ 1396 789 ahrens assert(reason == ZPOOL_STATUS_OK); 1397 789 ahrens } 1398 789 ahrens 1399 789 ahrens /* 1400 789 ahrens * Print out an action according to the overall state of the pool. 1401 789 ahrens */ 1402 3741 mmusante if (vs->vs_state == VDEV_STATE_HEALTHY) { 1403 1760 eschrock if (reason == ZPOOL_STATUS_VERSION_OLDER) 1404 1760 eschrock (void) printf(gettext("action: The pool can be " 1405 1760 eschrock "imported using its name or numeric identifier, " 1406 1760 eschrock "though\n\tsome features will not be available " 1407 1760 eschrock "without an explicit 'zpool upgrade'.\n")); 1408 3975 ek110237 else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) 1409 3975 ek110237 (void) printf(gettext("action: The pool can be " 1410 3975 ek110237 "imported using its name or numeric " 1411 3975 ek110237 "identifier and\n\tthe '-f' flag.\n")); 1412 789 ahrens else 1413 1760 eschrock (void) printf(gettext("action: The pool can be " 1414 1760 eschrock "imported using its name or numeric " 1415 1760 eschrock "identifier.\n")); 1416 3741 mmusante } else if (vs->vs_state == VDEV_STATE_DEGRADED) { 1417 789 ahrens (void) printf(gettext("action: The pool can be imported " 1418 789 ahrens "despite missing or damaged devices. The\n\tfault " 1419 1760 eschrock "tolerance of the pool may be compromised if imported.\n")); 1420 789 ahrens } else { 1421 1760 eschrock switch (reason) { 1422 1760 eschrock case ZPOOL_STATUS_VERSION_NEWER: 1423 1760 eschrock (void) printf(gettext("action: The pool cannot be " 1424 1760 eschrock "imported. Access the pool on a system running " 1425 1760 eschrock "newer\n\tsoftware, or recreate the pool from " 1426 1760 eschrock "backup.\n")); 1427 1760 eschrock break; 1428 1760 eschrock case ZPOOL_STATUS_MISSING_DEV_R: 1429 1760 eschrock case ZPOOL_STATUS_MISSING_DEV_NR: 1430 1760 eschrock case ZPOOL_STATUS_BAD_GUID_SUM: 1431 789 ahrens (void) printf(gettext("action: The pool cannot be " 1432 789 ahrens "imported. Attach the missing\n\tdevices and try " 1433 789 ahrens "again.\n")); 1434 1760 eschrock break; 1435 1760 eschrock default: 1436 789 ahrens (void) printf(gettext("action: The pool cannot be " 1437 789 ahrens "imported due to damaged devices or data.\n")); 1438 1760 eschrock } 1439 1760 eschrock } 1440 1760 eschrock 1441 3741 mmusante /* 1442 3741 mmusante * If the state is "closed" or "can't open", and the aux state 1443 3741 mmusante * is "corrupt data": 1444 3741 mmusante */ 1445 3741 mmusante if (((vs->vs_state == VDEV_STATE_CLOSED) || 1446 3741 mmusante (vs->vs_state == VDEV_STATE_CANT_OPEN)) && 1447 3741 mmusante (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) { 1448 1760 eschrock if (pool_state == POOL_STATE_DESTROYED) 1449 1760 eschrock (void) printf(gettext("\tThe pool was destroyed, " 1450 1760 eschrock "but can be imported using the '-Df' flags.\n")); 1451 1760 eschrock else if (pool_state != POOL_STATE_EXPORTED) 1452 1760 eschrock (void) printf(gettext("\tThe pool may be active on " 1453 5853 ek110237 "another system, but can be imported using\n\t" 1454 1760 eschrock "the '-f' flag.\n")); 1455 789 ahrens } 1456 789 ahrens 1457 789 ahrens if (msgid != NULL) 1458 789 ahrens (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), 1459 789 ahrens msgid); 1460 789 ahrens 1461 789 ahrens (void) printf(gettext("config:\n\n")); 1462 789 ahrens 1463 1354 eschrock namewidth = max_width(NULL, nvroot, 0, 0); 1464 789 ahrens if (namewidth < 10) 1465 789 ahrens namewidth = 10; 1466 4527 perrin 1467 9701 George print_import_config(name, nvroot, namewidth, 0); 1468 9701 George if (num_logs(nvroot) > 0) 1469 9701 George print_logs(NULL, nvroot, namewidth, B_FALSE); 1470 789 ahrens 1471 789 ahrens if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 1472 3741 mmusante (void) printf(gettext("\n\tAdditional devices are known to " 1473 789 ahrens "be part of this pool, though their\n\texact " 1474 3741 mmusante "configuration cannot be determined.\n")); 1475 789 ahrens } 1476 789 ahrens } 1477 789 ahrens 1478 789 ahrens /* 1479 789 ahrens * Perform the import for the given configuration. This passes the heavy 1480 5094 lling * lifting off to zpool_import_props(), and then mounts the datasets contained 1481 5094 lling * within the pool. 1482 789 ahrens */ 1483 789 ahrens static int 1484 789 ahrens do_import(nvlist_t *config, const char *newname, const char *mntopts, 1485 10000 Victor int force, nvlist_t *props, boolean_t do_verbatim) 1486 789 ahrens { 1487 789 ahrens zpool_handle_t *zhp; 1488 789 ahrens char *name; 1489 789 ahrens uint64_t state; 1490 1760 eschrock uint64_t version; 1491 789 ahrens 1492 789 ahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1493 789 ahrens &name) == 0); 1494 789 ahrens 1495 789 ahrens verify(nvlist_lookup_uint64(config, 1496 789 ahrens ZPOOL_CONFIG_POOL_STATE, &state) == 0); 1497 1760 eschrock verify(nvlist_lookup_uint64(config, 1498 1760 eschrock ZPOOL_CONFIG_VERSION, &version) == 0); 1499 4577 ahrens if (version > SPA_VERSION) { 1500 1760 eschrock (void) fprintf(stderr, gettext("cannot import '%s': pool " 1501 1760 eschrock "is formatted using a newer ZFS version\n"), name); 1502 1760 eschrock return (1); 1503 1760 eschrock } else if (state != POOL_STATE_EXPORTED && !force) { 1504 3975 ek110237 uint64_t hostid; 1505 3975 ek110237 1506 3975 ek110237 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, 1507 3975 ek110237 &hostid) == 0) { 1508 3975 ek110237 if ((unsigned long)hostid != gethostid()) { 1509 3975 ek110237 char *hostname; 1510 3975 ek110237 uint64_t timestamp; 1511 3975 ek110237 time_t t; 1512 3975 ek110237 1513 3975 ek110237 verify(nvlist_lookup_string(config, 1514 3975 ek110237 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0); 1515 3975 ek110237 verify(nvlist_lookup_uint64(config, 1516 3975 ek110237 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0); 1517 3975 ek110237 t = timestamp; 1518 3975 ek110237 (void) fprintf(stderr, gettext("cannot import " 1519 3975 ek110237 "'%s': pool may be in use from other " 1520 3975 ek110237 "system, it was last accessed by %s " 1521 3975 ek110237 "(hostid: 0x%lx) on %s"), name, hostname, 1522 3975 ek110237 (unsigned long)hostid, 1523 3975 ek110237 asctime(localtime(&t))); 1524 3975 ek110237 (void) fprintf(stderr, gettext("use '-f' to " 1525 3975 ek110237 "import anyway\n")); 1526 3975 ek110237 return (1); 1527 3975 ek110237 } 1528 3975 ek110237 } else { 1529 3975 ek110237 (void) fprintf(stderr, gettext("cannot import '%s': " 1530 3975 ek110237 "pool may be in use from other system\n"), name); 1531 3975 ek110237 (void) fprintf(stderr, gettext("use '-f' to import " 1532 3975 ek110237 "anyway\n")); 1533 3975 ek110237 return (1); 1534 3975 ek110237 } 1535 789 ahrens } 1536 789 ahrens 1537 10000 Victor if (zpool_import_props(g_zfs, config, newname, props, do_verbatim) != 0) 1538 789 ahrens return (1); 1539 789 ahrens 1540 789 ahrens if (newname != NULL) 1541 789 ahrens name = (char *)newname; 1542 2926 ek110237 1543 10000 Victor if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL) 1544 10000 Victor return (1); 1545 789 ahrens 1546 8525 Eric if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 1547 8525 Eric zpool_enable_datasets(zhp, mntopts, 0) != 0) { 1548 789 ahrens zpool_close(zhp); 1549 789 ahrens return (1); 1550 789 ahrens } 1551 789 ahrens 1552 789 ahrens zpool_close(zhp); 1553 10921 Tim return (0); 1554 789 ahrens } 1555 789 ahrens 1556 789 ahrens /* 1557 1631 darrenm * zpool import [-d dir] [-D] 1558 5363 eschrock * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 1559 5363 eschrock * [-d dir | -c cachefile] [-f] -a 1560 5363 eschrock * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 1561 10921 Tim * [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool] 1562 5363 eschrock * 1563 5363 eschrock * -c Read pool information from a cachefile instead of searching 1564 5363 eschrock * devices. 1565 789 ahrens * 1566 789 ahrens * -d Scan in a specific directory, other than /dev/dsk. More than 1567 789 ahrens * one directory can be specified using multiple '-d' options. 1568 1631 darrenm * 1569 1631 darrenm * -D Scan for previously destroyed pools or import all or only 1570 1631 darrenm * specified destroyed pools. 1571 789 ahrens * 1572 789 ahrens * -R Temporarily import the pool, with all mountpoints relative to 1573 789 ahrens * the given root. The pool will remain exported when the machine 1574 789 ahrens * is rebooted. 1575 789 ahrens * 1576 10921 Tim * -V Import even in the presence of faulted vdevs. This is an 1577 6643 eschrock * intentionally undocumented option for testing purposes, and 1578 6643 eschrock * treats the pool configuration as complete, leaving any bad 1579 10000 Victor * vdevs in the FAULTED state. In other words, it does verbatim 1580 10000 Victor * import. 1581 10921 Tim * 1582 10921 Tim * -f Force import, even if it appears that the pool is active. 1583 10921 Tim * 1584 10921 Tim * -F Attempt rewind if necessary. 1585 10921 Tim * 1586 10921 Tim * -n See if rewind would work, but don't actually rewind. 1587 6643 eschrock * 1588 789 ahrens * -a Import all pools found. 1589 789 ahrens * 1590 5094 lling * -o Set property=value and/or temporary mount options (without '='). 1591 4543 marks * 1592 789 ahrens * The import command scans for pools to import, and import pools based on pool 1593 789 ahrens * name and GUID. The pool can also be renamed as part of the import process. 1594 789 ahrens */ 1595 789 ahrens int 1596 789 ahrens zpool_do_import(int argc, char **argv) 1597 789 ahrens { 1598 789 ahrens char **searchdirs = NULL; 1599 789 ahrens int nsearch = 0; 1600 789 ahrens int c; 1601 789 ahrens int err; 1602 5363 eschrock nvlist_t *pools = NULL; 1603 2082 eschrock boolean_t do_all = B_FALSE; 1604 2082 eschrock boolean_t do_destroyed = B_FALSE; 1605 789 ahrens char *mntopts = NULL; 1606 2082 eschrock boolean_t do_force = B_FALSE; 1607 789 ahrens nvpair_t *elem; 1608 789 ahrens nvlist_t *config; 1609 6807 ck153898 uint64_t searchguid = 0; 1610 6807 ck153898 char *searchname = NULL; 1611 5094 lling char *propval; 1612 789 ahrens nvlist_t *found_config; 1613 10921 Tim nvlist_t *policy = NULL; 1614 4543 marks nvlist_t *props = NULL; 1615 2082 eschrock boolean_t first; 1616 10000 Victor boolean_t do_verbatim = B_FALSE; 1617 10921 Tim uint32_t rewind_policy = ZPOOL_NO_REWIND; 1618 10921 Tim boolean_t dryrun = B_FALSE; 1619 10921 Tim boolean_t do_rewind = B_FALSE; 1620 10921 Tim boolean_t xtreme_rewind = B_FALSE; 1621 1631 darrenm uint64_t pool_state; 1622 5363 eschrock char *cachefile = NULL; 1623 789 ahrens 1624 789 ahrens /* check options */ 1625 10921 Tim while ((c = getopt(argc, argv, ":aCc:d:DEfFno:p:rR:VX")) != -1) { 1626 789 ahrens switch (c) { 1627 789 ahrens case 'a': 1628 2082 eschrock do_all = B_TRUE; 1629 5363 eschrock break; 1630 5363 eschrock case 'c': 1631 5363 eschrock cachefile = optarg; 1632 789 ahrens break; 1633 789 ahrens case 'd': 1634 789 ahrens if (searchdirs == NULL) { 1635 789 ahrens searchdirs = safe_malloc(sizeof (char *)); 1636 789 ahrens } else { 1637 789 ahrens char **tmp = safe_malloc((nsearch + 1) * 1638 789 ahrens sizeof (char *)); 1639 789 ahrens bcopy(searchdirs, tmp, nsearch * 1640 789 ahrens sizeof (char *)); 1641 789 ahrens free(searchdirs); 1642 789 ahrens searchdirs = tmp; 1643 789 ahrens } 1644 789 ahrens searchdirs[nsearch++] = optarg; 1645 1631 darrenm break; 1646 1631 darrenm case 'D': 1647 2082 eschrock do_destroyed = B_TRUE; 1648 789 ahrens break; 1649 789 ahrens case 'f': 1650 2082 eschrock do_force = B_TRUE; 1651 6643 eschrock break; 1652 6643 eschrock case 'F': 1653 10921 Tim do_rewind = B_TRUE; 1654 10921 Tim break; 1655 10921 Tim case 'n': 1656 10921 Tim dryrun = B_TRUE; 1657 789 ahrens break; 1658 789 ahrens case 'o': 1659 5094 lling if ((propval = strchr(optarg, '=')) != NULL) { 1660 5094 lling *propval = '\0'; 1661 5094 lling propval++; 1662 7184 timh if (add_prop_list(optarg, propval, 1663 7184 timh &props, B_TRUE)) 1664 5094 lling goto error; 1665 5094 lling } else { 1666 5094 lling mntopts = optarg; 1667 5094 lling } 1668 789 ahrens break; 1669 789 ahrens case 'R': 1670 5094 lling if (add_prop_list(zpool_prop_to_name( 1671 7184 timh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 1672 5094 lling goto error; 1673 5363 eschrock if (nvlist_lookup_string(props, 1674 5363 eschrock zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 1675 5363 eschrock &propval) == 0) 1676 5363 eschrock break; 1677 5094 lling if (add_prop_list(zpool_prop_to_name( 1678 7184 timh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 1679 5094 lling goto error; 1680 789 ahrens break; 1681 10921 Tim case 'V': 1682 10921 Tim do_verbatim = B_TRUE; 1683 10921 Tim break; 1684 10921 Tim case 'X': 1685 10921 Tim xtreme_rewind = B_TRUE; 1686 10921 Tim break; 1687 789 ahrens case ':': 1688 789 ahrens (void) fprintf(stderr, gettext("missing argument for " 1689 789 ahrens "'%c' option\n"), optopt); 1690 2082 eschrock usage(B_FALSE); 1691 789 ahrens break; 1692 789 ahrens case '?': 1693 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1694 789 ahrens optopt); 1695 2082 eschrock usage(B_FALSE); 1696 789 ahrens } 1697 789 ahrens } 1698 789 ahrens 1699 789 ahrens argc -= optind; 1700 789 ahrens argv += optind; 1701 5363 eschrock 1702 5363 eschrock if (cachefile && nsearch != 0) { 1703 5363 eschrock (void) fprintf(stderr, gettext("-c is incompatible with -d\n")); 1704 5363 eschrock usage(B_FALSE); 1705 5363 eschrock } 1706 10921 Tim 1707 10921 Tim if ((dryrun || xtreme_rewind) && !do_rewind) { 1708 10921 Tim (void) fprintf(stderr, 1709 10921 Tim gettext("-n or -X only meaningful with -F\n")); 1710 10921 Tim usage(B_FALSE); 1711 10921 Tim } 1712 10921 Tim if (dryrun) 1713 10921 Tim rewind_policy = ZPOOL_TRY_REWIND; 1714 10921 Tim else if (do_rewind) 1715 10921 Tim rewind_policy = ZPOOL_DO_REWIND; 1716 10921 Tim if (xtreme_rewind) 1717 10921 Tim rewind_policy |= ZPOOL_EXTREME_REWIND; 1718 10921 Tim 1719 10921 Tim /* In the future, we can capture further policy and include it here */ 1720 10921 Tim if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 1721 10921 Tim nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0) 1722 10921 Tim goto error; 1723 789 ahrens 1724 789 ahrens if (searchdirs == NULL) { 1725 789 ahrens searchdirs = safe_malloc(sizeof (char *)); 1726 789 ahrens searchdirs[0] = "/dev/dsk"; 1727 789 ahrens nsearch = 1; 1728 789 ahrens } 1729 789 ahrens 1730 789 ahrens /* check argument count */ 1731 789 ahrens if (do_all) { 1732 789 ahrens if (argc != 0) { 1733 789 ahrens (void) fprintf(stderr, gettext("too many arguments\n")); 1734 2082 eschrock usage(B_FALSE); 1735 789 ahrens } 1736 789 ahrens } else { 1737 789 ahrens if (argc > 2) { 1738 789 ahrens (void) fprintf(stderr, gettext("too many arguments\n")); 1739 2082 eschrock usage(B_FALSE); 1740 789 ahrens } 1741 789 ahrens 1742 789 ahrens /* 1743 789 ahrens * Check for the SYS_CONFIG privilege. We do this explicitly 1744 789 ahrens * here because otherwise any attempt to discover pools will 1745 789 ahrens * silently fail. 1746 789 ahrens */ 1747 789 ahrens if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 1748 789 ahrens (void) fprintf(stderr, gettext("cannot " 1749 789 ahrens "discover pools: permission denied\n")); 1750 2082 eschrock free(searchdirs); 1751 10921 Tim nvlist_free(policy); 1752 789 ahrens return (1); 1753 789 ahrens } 1754 789 ahrens } 1755 789 ahrens 1756 789 ahrens /* 1757 789 ahrens * Depending on the arguments given, we do one of the following: 1758 789 ahrens * 1759 789 ahrens * <none> Iterate through all pools and display information about 1760 789 ahrens * each one. 1761 789 ahrens * 1762 789 ahrens * -a Iterate through all pools and try to import each one. 1763 789 ahrens * 1764 789 ahrens * <id> Find the pool that corresponds to the given GUID/pool 1765 789 ahrens * name and import that one. 1766 1631 darrenm * 1767 1631 darrenm * -D Above options applies only to destroyed pools. 1768 789 ahrens */ 1769 789 ahrens if (argc != 0) { 1770 789 ahrens char *endptr; 1771 789 ahrens 1772 789 ahrens errno = 0; 1773 789 ahrens searchguid = strtoull(argv[0], &endptr, 10); 1774 789 ahrens if (errno != 0 || *endptr != '\0') 1775 789 ahrens searchname = argv[0]; 1776 789 ahrens found_config = NULL; 1777 789 ahrens } 1778 789 ahrens 1779 6807 ck153898 if (cachefile) { 1780 6957 ck153898 pools = zpool_find_import_cached(g_zfs, cachefile, searchname, 1781 6957 ck153898 searchguid); 1782 6807 ck153898 } else if (searchname != NULL) { 1783 6807 ck153898 pools = zpool_find_import_byname(g_zfs, nsearch, searchdirs, 1784 6807 ck153898 searchname); 1785 6807 ck153898 } else { 1786 6807 ck153898 /* 1787 6807 ck153898 * It's OK to search by guid even if searchguid is 0. 1788 6807 ck153898 */ 1789 6807 ck153898 pools = zpool_find_import_byguid(g_zfs, nsearch, searchdirs, 1790 6807 ck153898 searchguid); 1791 6807 ck153898 } 1792 6807 ck153898 1793 6807 ck153898 if (pools == NULL) { 1794 6807 ck153898 if (argc != 0) { 1795 6807 ck153898 (void) fprintf(stderr, gettext("cannot import '%s': " 1796 6807 ck153898 "no such pool available\n"), argv[0]); 1797 6807 ck153898 } 1798 6807 ck153898 free(searchdirs); 1799 10921 Tim nvlist_free(policy); 1800 6807 ck153898 return (1); 1801 6807 ck153898 } 1802 6807 ck153898 1803 6807 ck153898 /* 1804 6807 ck153898 * At this point we have a list of import candidate configs. Even if 1805 6807 ck153898 * we were searching by pool name or guid, we still need to 1806 6807 ck153898 * post-process the list to deal with pool state and possible 1807 6807 ck153898 * duplicate names. 1808 6807 ck153898 */ 1809 789 ahrens err = 0; 1810 789 ahrens elem = NULL; 1811 2082 eschrock first = B_TRUE; 1812 789 ahrens while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 1813 789 ahrens 1814 789 ahrens verify(nvpair_value_nvlist(elem, &config) == 0); 1815 1631 darrenm 1816 1631 darrenm verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 1817 1631 darrenm &pool_state) == 0); 1818 1631 darrenm if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) 1819 1631 darrenm continue; 1820 1631 darrenm if (do_destroyed && pool_state != POOL_STATE_DESTROYED) 1821 1631 darrenm continue; 1822 10921 Tim 1823 10921 Tim verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY, 1824 10921 Tim policy) == 0); 1825 789 ahrens 1826 789 ahrens if (argc == 0) { 1827 789 ahrens if (first) 1828 2082 eschrock first = B_FALSE; 1829 2474 eschrock else if (!do_all) 1830 789 ahrens (void) printf("\n"); 1831 789 ahrens 1832 10921 Tim if (do_all) { 1833 789 ahrens err |= do_import(config, NULL, mntopts, 1834 10000 Victor do_force, props, do_verbatim); 1835 10921 Tim } else { 1836 789 ahrens show_import(config); 1837 10921 Tim } 1838 789 ahrens } else if (searchname != NULL) { 1839 789 ahrens char *name; 1840 789 ahrens 1841 789 ahrens /* 1842 789 ahrens * We are searching for a pool based on name. 1843 789 ahrens */ 1844 789 ahrens verify(nvlist_lookup_string(config, 1845 789 ahrens ZPOOL_CONFIG_POOL_NAME, &name) == 0); 1846 789 ahrens 1847 789 ahrens if (strcmp(name, searchname) == 0) { 1848 789 ahrens if (found_config != NULL) { 1849 789 ahrens (void) fprintf(stderr, gettext( 1850 789 ahrens "cannot import '%s': more than " 1851 789 ahrens "one matching pool\n"), searchname); 1852 789 ahrens (void) fprintf(stderr, gettext( 1853 789 ahrens "import by numeric ID instead\n")); 1854 2082 eschrock err = B_TRUE; 1855 789 ahrens } 1856 789 ahrens found_config = config; 1857 789 ahrens } 1858 789 ahrens } else { 1859 789 ahrens uint64_t guid; 1860 789 ahrens 1861 789 ahrens /* 1862 789 ahrens * Search for a pool by guid. 1863 789 ahrens */ 1864 789 ahrens verify(nvlist_lookup_uint64(config, 1865 789 ahrens ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 1866 789 ahrens 1867 789 ahrens if (guid == searchguid) 1868 789 ahrens found_config = config; 1869 789 ahrens } 1870 789 ahrens } 1871 789 ahrens 1872 789 ahrens /* 1873 789 ahrens * If we were searching for a specific pool, verify that we found a 1874 789 ahrens * pool, and then do the import. 1875 789 ahrens */ 1876 789 ahrens if (argc != 0 && err == 0) { 1877 789 ahrens if (found_config == NULL) { 1878 789 ahrens (void) fprintf(stderr, gettext("cannot import '%s': " 1879 789 ahrens "no such pool available\n"), argv[0]); 1880 2082 eschrock err = B_TRUE; 1881 789 ahrens } else { 1882 789 ahrens err |= do_import(found_config, argc == 1 ? NULL : 1883 10000 Victor argv[1], mntopts, do_force, props, do_verbatim); 1884 789 ahrens } 1885 789 ahrens } 1886 789 ahrens 1887 789 ahrens /* 1888 789 ahrens * If we were just looking for pools, report an error if none were 1889 789 ahrens * found. 1890 789 ahrens */ 1891 789 ahrens if (argc == 0 && first) 1892 789 ahrens (void) fprintf(stderr, 1893 789 ahrens gettext("no pools available to import\n")); 1894 789 ahrens 1895 4543 marks error: 1896 5363 eschrock nvlist_free(props); 1897 789 ahrens nvlist_free(pools); 1898 10921 Tim nvlist_free(policy); 1899 2082 eschrock free(searchdirs); 1900 789 ahrens 1901 789 ahrens return (err ? 1 : 0); 1902 789 ahrens } 1903 789 ahrens 1904 789 ahrens typedef struct iostat_cbdata { 1905 789 ahrens zpool_list_t *cb_list; 1906 789 ahrens int cb_verbose; 1907 789 ahrens int cb_iteration; 1908 789 ahrens int cb_namewidth; 1909 789 ahrens } iostat_cbdata_t; 1910 789 ahrens 1911 789 ahrens static void 1912 789 ahrens print_iostat_separator(iostat_cbdata_t *cb) 1913 789 ahrens { 1914 789 ahrens int i = 0; 1915 789 ahrens 1916 789 ahrens for (i = 0; i < cb->cb_namewidth; i++) 1917 789 ahrens (void) printf("-"); 1918 789 ahrens (void) printf(" ----- ----- ----- ----- ----- -----\n"); 1919 789 ahrens } 1920 789 ahrens 1921 789 ahrens static void 1922 789 ahrens print_iostat_header(iostat_cbdata_t *cb) 1923 789 ahrens { 1924 789 ahrens (void) printf("%*s capacity operations bandwidth\n", 1925 789 ahrens cb->cb_namewidth, ""); 1926 10956 George (void) printf("%-*s alloc free read write read write\n", 1927 789 ahrens cb->cb_namewidth, "pool"); 1928 789 ahrens print_iostat_separator(cb); 1929 789 ahrens } 1930 789 ahrens 1931 789 ahrens /* 1932 789 ahrens * Display a single statistic. 1933 789 ahrens */ 1934 5094 lling static void 1935 789 ahrens print_one_stat(uint64_t value) 1936 789 ahrens { 1937 789 ahrens char buf[64]; 1938 789 ahrens 1939 789 ahrens zfs_nicenum(value, buf, sizeof (buf)); 1940 789 ahrens (void) printf(" %5s", buf); 1941 789 ahrens } 1942 789 ahrens 1943 789 ahrens /* 1944 789 ahrens * Print out all the statistics for the given vdev. This can either be the 1945 789 ahrens * toplevel configuration, or called recursively. If 'name' is NULL, then this 1946 789 ahrens * is a verbose output, and we don't want to display the toplevel pool stats. 1947 789 ahrens */ 1948 789 ahrens void 1949 1354 eschrock print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 1950 1354 eschrock nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 1951 789 ahrens { 1952 789 ahrens nvlist_t **oldchild, **newchild; 1953 789 ahrens uint_t c, children; 1954 789 ahrens vdev_stat_t *oldvs, *newvs; 1955 789 ahrens vdev_stat_t zerovs = { 0 }; 1956 789 ahrens uint64_t tdelta; 1957 789 ahrens double scale; 1958 1171 eschrock char *vname; 1959 789 ahrens 1960 789 ahrens if (oldnv != NULL) { 1961 789 ahrens verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS, 1962 789 ahrens (uint64_t **)&oldvs, &c) == 0); 1963 789 ahrens } else { 1964 789 ahrens oldvs = &zerovs; 1965 789 ahrens } 1966 789 ahrens 1967 789 ahrens verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS, 1968 789 ahrens (uint64_t **)&newvs, &c) == 0); 1969 789 ahrens 1970 789 ahrens if (strlen(name) + depth > cb->cb_namewidth) 1971 789 ahrens (void) printf("%*s%s", depth, "", name); 1972 789 ahrens else 1973 789 ahrens (void) printf("%*s%s%*s", depth, "", name, 1974 789 ahrens (int)(cb->cb_namewidth - strlen(name) - depth), ""); 1975 789 ahrens 1976 789 ahrens tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 1977 789 ahrens 1978 789 ahrens if (tdelta == 0) 1979 789 ahrens scale = 1.0; 1980 789 ahrens else 1981 789 ahrens scale = (double)NANOSEC / tdelta; 1982 789 ahrens 1983 789 ahrens /* only toplevel vdevs have capacity stats */ 1984 789 ahrens if (newvs->vs_space == 0) { 1985 789 ahrens (void) printf(" - -"); 1986 789 ahrens } else { 1987 789 ahrens print_one_stat(newvs->vs_alloc); 1988 789 ahrens print_one_stat(newvs->vs_space - newvs->vs_alloc); 1989 789 ahrens } 1990 789 ahrens 1991 789 ahrens print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] - 1992 789 ahrens oldvs->vs_ops[ZIO_TYPE_READ]))); 1993 789 ahrens 1994 789 ahrens print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] - 1995 789 ahrens oldvs->vs_ops[ZIO_TYPE_WRITE]))); 1996 789 ahrens 1997 789 ahrens print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] - 1998 789 ahrens oldvs->vs_bytes[ZIO_TYPE_READ]))); 1999 789 ahrens 2000 789 ahrens print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] - 2001 789 ahrens oldvs->vs_bytes[ZIO_TYPE_WRITE]))); 2002 789 ahrens 2003 789 ahrens (void) printf("\n"); 2004 789 ahrens 2005 789 ahrens if (!cb->cb_verbose) 2006 789 ahrens return; 2007 789 ahrens 2008 789 ahrens if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 2009 789 ahrens &newchild, &children) != 0) 2010 789 ahrens return; 2011 789 ahrens 2012 789 ahrens if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 2013 789 ahrens &oldchild, &c) != 0) 2014 789 ahrens return; 2015 789 ahrens 2016 1171 eschrock for (c = 0; c < children; c++) { 2017 10594 George vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE); 2018 1354 eschrock print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 2019 1171 eschrock newchild[c], cb, depth + 2); 2020 1171 eschrock free(vname); 2021 5450 brendan } 2022 5450 brendan 2023 5450 brendan /* 2024 5450 brendan * Include level 2 ARC devices in iostat output 2025 5450 brendan */ 2026 5450 brendan if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, 2027 5450 brendan &newchild, &children) != 0) 2028 5450 brendan return; 2029 5450 brendan 2030 5450 brendan if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, 2031 5450 brendan &oldchild, &c) != 0) 2032 5450 brendan return; 2033 5450 brendan 2034 5450 brendan if (children > 0) { 2035 5450 brendan (void) printf("%-*s - - - - - " 2036 5450 brendan "-\n", cb->cb_namewidth, "cache"); 2037 5450 brendan for (c = 0; c < children; c++) { 2038 10594 George vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 2039 10594 George B_FALSE); 2040 5450 brendan print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 2041 5450 brendan newchild[c], cb, depth + 2); 2042 5450 brendan free(vname); 2043 5450 brendan } 2044 1171 eschrock } 2045 789 ahrens } 2046 789 ahrens 2047 952 eschrock static int 2048 952 eschrock refresh_iostat(zpool_handle_t *zhp, void *data) 2049 952 eschrock { 2050 952 eschrock iostat_cbdata_t *cb = data; 2051 2142 eschrock boolean_t missing; 2052 952 eschrock 2053 952 eschrock /* 2054 952 eschrock * If the pool has disappeared, remove it from the list and continue. 2055 952 eschrock */ 2056 2142 eschrock if (zpool_refresh_stats(zhp, &missing) != 0) 2057 2142 eschrock return (-1); 2058 2142 eschrock 2059 2142 eschrock if (missing) 2060 952 eschrock pool_list_remove(cb->cb_list, zhp); 2061 952 eschrock 2062 952 eschrock return (0); 2063 952 eschrock } 2064 952 eschrock 2065 789 ahrens /* 2066 789 ahrens * Callback to print out the iostats for the given pool. 2067 789 ahrens */ 2068 789 ahrens int 2069 789 ahrens print_iostat(zpool_handle_t *zhp, void *data) 2070 789 ahrens { 2071 789 ahrens iostat_cbdata_t *cb = data; 2072 789 ahrens nvlist_t *oldconfig, *newconfig; 2073 789 ahrens nvlist_t *oldnvroot, *newnvroot; 2074 789 ahrens 2075 952 eschrock newconfig = zpool_get_config(zhp, &oldconfig); 2076 789 ahrens 2077 952 eschrock if (cb->cb_iteration == 1) 2078 789 ahrens oldconfig = NULL; 2079 789 ahrens 2080 789 ahrens verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 2081 789 ahrens &newnvroot) == 0); 2082 789 ahrens 2083 952 eschrock if (oldconfig == NULL) 2084 789 ahrens oldnvroot = NULL; 2085 952 eschrock else 2086 952 eschrock verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 2087 952 eschrock &oldnvroot) == 0); 2088 789 ahrens 2089 789 ahrens /* 2090 789 ahrens * Print out the statistics for the pool. 2091 789 ahrens */ 2092 1354 eschrock print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 2093 789 ahrens 2094 789 ahrens if (cb->cb_verbose) 2095 789 ahrens print_iostat_separator(cb); 2096 789 ahrens 2097 789 ahrens return (0); 2098 789 ahrens } 2099 789 ahrens 2100 789 ahrens int 2101 789 ahrens get_namewidth(zpool_handle_t *zhp, void *data) 2102 789 ahrens { 2103 789 ahrens iostat_cbdata_t *cb = data; 2104 789 ahrens nvlist_t *config, *nvroot; 2105 789 ahrens 2106 952 eschrock if ((config = zpool_get_config(zhp, NULL)) != NULL) { 2107 789 ahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2108 789 ahrens &nvroot) == 0); 2109 789 ahrens if (!cb->cb_verbose) 2110 789 ahrens cb->cb_namewidth = strlen(zpool_get_name(zhp)); 2111 789 ahrens else 2112 1354 eschrock cb->cb_namewidth = max_width(zhp, nvroot, 0, 0); 2113 789 ahrens } 2114 789 ahrens 2115 789 ahrens /* 2116 789 ahrens * The width must fall into the range [10,38]. The upper limit is the 2117 789 ahrens * maximum we can have and still fit in 80 columns. 2118 789 ahrens */ 2119 789 ahrens if (cb->cb_namewidth < 10) 2120 789 ahrens cb->cb_namewidth = 10; 2121 789 ahrens if (cb->cb_namewidth > 38) 2122 789 ahrens cb->cb_namewidth = 38; 2123 789 ahrens 2124 789 ahrens return (0); 2125 789 ahrens } 2126 789 ahrens 2127 789 ahrens /* 2128 10265 Krishnendu * zpool iostat [-T d|u] [-v] [pool] ... [interval [count]] 2129 10265 Krishnendu * 2130 10265 Krishnendu * -T Display a timestamp in date(1) or Unix format 2131 789 ahrens * -v Display statistics for individual vdevs 2132 789 ahrens * 2133 789 ahrens * This command can be tricky because we want to be able to deal with pool 2134 789 ahrens * creation/destruction as well as vdev configuration changes. The bulk of this 2135 789 ahrens * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 2136 789 ahrens * on pool_list_update() to detect the addition of new pools. Configuration 2137 789 ahrens * changes are all handled within libzfs. 2138 789 ahrens */ 2139 789 ahrens int 2140 789 ahrens zpool_do_iostat(int argc, char **argv) 2141 789 ahrens { 2142 789 ahrens int c; 2143 789 ahrens int ret; 2144 789 ahrens int npools; 2145 789 ahrens unsigned long interval = 0, count = 0; 2146 789 ahrens zpool_list_t *list; 2147 2082 eschrock boolean_t verbose = B_FALSE; 2148 789 ahrens iostat_cbdata_t cb; 2149 789 ahrens 2150 789 ahrens /* check options */ 2151 10265 Krishnendu while ((c = getopt(argc, argv, "T:v")) != -1) { 2152 10265 Krishnendu switch (c) { 2153 10265 Krishnendu case 'T': 2154 10265 Krishnendu if (optarg) { 2155 10265 Krishnendu if (*optarg == 'u') 2156 10265 Krishnendu timestamp_fmt = UDATE; 2157 10265 Krishnendu else if (*optarg == 'd') 2158 10265 Krishnendu timestamp_fmt = DDATE; 2159 10265 Krishnendu else 2160 10265 Krishnendu usage(B_FALSE); 2161 10265 Krishnendu } else { 2162 10265 Krishnendu usage(B_FALSE); 2163 10265 Krishnendu } 2164 10265 Krishnendu break; 2165 789 ahrens case 'v': 2166 2082 eschrock verbose = B_TRUE; 2167 789 ahrens break; 2168 789 ahrens case '?': 2169 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2170 789 ahrens optopt); 2171 2082 eschrock usage(B_FALSE); 2172 789 ahrens } 2173 789 ahrens } 2174 789 ahrens 2175 789 ahrens argc -= optind; 2176 789 ahrens argv += optind; 2177 789 ahrens 2178 789 ahrens /* 2179 789 ahrens * Determine if the last argument is an integer or a pool name 2180 789 ahrens */ 2181 789 ahrens if (argc > 0 && isdigit(argv[argc - 1][0])) { 2182 789 ahrens char *end; 2183 789 ahrens 2184 789 ahrens errno = 0; 2185 789 ahrens interval = strtoul(argv[argc - 1], &end, 10); 2186 789 ahrens 2187 789 ahrens if (*end == '\0' && errno == 0) { 2188 789 ahrens if (interval == 0) { 2189 789 ahrens (void) fprintf(stderr, gettext("interval " 2190 789 ahrens "cannot be zero\n")); 2191 2082 eschrock usage(B_FALSE); 2192 789 ahrens } 2193 789 ahrens 2194 789 ahrens /* 2195 789 ahrens * Ignore the last parameter 2196 789 ahrens */ 2197 789 ahrens argc--; 2198 789 ahrens } else { 2199 789 ahrens /* 2200 789 ahrens * If this is not a valid number, just plow on. The 2201 789 ahrens * user will get a more informative error message later 2202 789 ahrens * on. 2203 789 ahrens */ 2204 789 ahrens interval = 0; 2205 789 ahrens } 2206 789 ahrens } 2207 789 ahrens 2208 789 ahrens /* 2209 789 ahrens * If the last argument is also an integer, then we have both a count 2210 789 ahrens * and an integer. 2211 789 ahrens */ 2212 789 ahrens if (argc > 0 && isdigit(argv[argc - 1][0])) { 2213 789 ahrens char *end; 2214 789 ahrens 2215 789 ahrens errno = 0; 2216 789 ahrens count = interval; 2217 789 ahrens interval = strtoul(argv[argc - 1], &end, 10); 2218 789 ahrens 2219 789 ahrens if (*end == '\0' && errno == 0) { 2220 789 ahrens if (interval == 0) { 2221 789 ahrens (void) fprintf(stderr, gettext("interval " 2222 789 ahrens "cannot be zero\n")); 2223 2082 eschrock usage(B_FALSE); 2224 789 ahrens } 2225 789 ahrens 2226 789 ahrens /* 2227 789 ahrens * Ignore the last parameter 2228 789 ahrens */ 2229 789 ahrens argc--; 2230 789 ahrens } else { 2231 789 ahrens interval = 0; 2232 789 ahrens } 2233 789 ahrens } 2234 789 ahrens 2235 789 ahrens /* 2236 789 ahrens * Construct the list of all interesting pools. 2237 789 ahrens */ 2238 789 ahrens ret = 0; 2239 3912 lling if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL) 2240 789 ahrens return (1); 2241 789 ahrens 2242 2082 eschrock if (pool_list_count(list) == 0 && argc != 0) { 2243 2082 eschrock pool_list_free(list); 2244 789 ahrens return (1); 2245 2082 eschrock } 2246 789 ahrens 2247 789 ahrens if (pool_list_count(list) == 0 && interval == 0) { 2248 2082 eschrock pool_list_free(list); 2249 789 ahrens (void) fprintf(stderr, gettext("no pools available\n")); 2250 789 ahrens return (1); 2251 789 ahrens } 2252 789 ahrens 2253 789 ahrens /* 2254 789 ahrens * Enter the main iostat loop. 2255 789 ahrens */ 2256 789 ahrens cb.cb_list = list; 2257 789 ahrens cb.cb_verbose = verbose; 2258 789 ahrens cb.cb_iteration = 0; 2259 789 ahrens cb.cb_namewidth = 0; 2260 789 ahrens 2261 789 ahrens for (;;) { 2262 789 ahrens pool_list_update(list); 2263 789 ahrens 2264 789 ahrens if ((npools = pool_list_count(list)) == 0) 2265 789 ahrens break; 2266 789 ahrens 2267 789 ahrens /* 2268 952 eschrock * Refresh all statistics. This is done as an explicit step 2269 952 eschrock * before calculating the maximum name width, so that any 2270 952 eschrock * configuration changes are properly accounted for. 2271 952 eschrock */ 2272 2082 eschrock (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb); 2273 952 eschrock 2274 952 eschrock /* 2275 789 ahrens * Iterate over all pools to determine the maximum width 2276 789 ahrens * for the pool / device name column across all pools. 2277 789 ahrens */ 2278 789 ahrens cb.cb_namewidth = 0; 2279 2082 eschrock (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 2280 10265 Krishnendu 2281 10265 Krishnendu if (timestamp_fmt != NODATE) 2282 10265 Krishnendu print_timestamp(timestamp_fmt); 2283 789 ahrens 2284 789 ahrens /* 2285 789 ahrens * If it's the first time, or verbose mode, print the header. 2286 789 ahrens */ 2287 789 ahrens if (++cb.cb_iteration == 1 || verbose) 2288 789 ahrens print_iostat_header(&cb); 2289 789 ahrens 2290 2082 eschrock (void) pool_list_iter(list, B_FALSE, print_iostat, &cb); 2291 789 ahrens 2292 789 ahrens /* 2293 789 ahrens * If there's more than one pool, and we're not in verbose mode 2294 789 ahrens * (which prints a separator for us), then print a separator. 2295 789 ahrens */ 2296 789 ahrens if (npools > 1 && !verbose) 2297 789 ahrens print_iostat_separator(&cb); 2298 789 ahrens 2299 789 ahrens if (verbose) 2300 789 ahrens (void) printf("\n"); 2301 3377 eschrock 2302 3377 eschrock /* 2303 3377 eschrock * Flush the output so that redirection to a file isn't buffered 2304 3377 eschrock * indefinitely. 2305 3377 eschrock */ 2306 3377 eschrock (void) fflush(stdout); 2307 789 ahrens 2308 789 ahrens if (interval == 0) 2309 789 ahrens break; 2310 789 ahrens 2311 789 ahrens if (count != 0 && --count == 0) 2312 789 ahrens break; 2313 789 ahrens 2314 789 ahrens (void) sleep(interval); 2315 789 ahrens } 2316 789 ahrens 2317 789 ahrens pool_list_free(list); 2318 789 ahrens 2319 789 ahrens return (ret); 2320 789 ahrens } 2321 789 ahrens 2322 789 ahrens typedef struct list_cbdata { 2323 2082 eschrock boolean_t cb_scripted; 2324 2082 eschrock boolean_t cb_first; 2325 5094 lling zprop_list_t *cb_proplist; 2326 789 ahrens } list_cbdata_t; 2327 789 ahrens 2328 789 ahrens /* 2329 789 ahrens * Given a list of columns to display, output appropriate headers for each one. 2330 789 ahrens */ 2331 5094 lling static void 2332 5094 lling print_header(zprop_list_t *pl) 2333 789 ahrens { 2334 5094 lling const char *header; 2335 5094 lling boolean_t first = B_TRUE; 2336 5094 lling boolean_t right_justify; 2337 789 ahrens 2338 5094 lling for (; pl != NULL; pl = pl->pl_next) { 2339 5094 lling if (pl->pl_prop == ZPROP_INVAL) 2340 5094 lling continue; 2341 5094 lling 2342 5094 lling if (!first) 2343 789 ahrens (void) printf(" "); 2344 789 ahrens else 2345 5094 lling first = B_FALSE; 2346 789 ahrens 2347 5094 lling header = zpool_prop_column_name(pl->pl_prop); 2348 5094 lling right_justify = zpool_prop_align_right(pl->pl_prop); 2349 5094 lling 2350 5094 lling if (pl->pl_next == NULL && !right_justify) 2351 5094 lling (void) printf("%s", header); 2352 5094 lling else if (right_justify) 2353 5094 lling (void) printf("%*s", pl->pl_width, header); 2354 5094 lling else 2355 5094 lling (void) printf("%-*s", pl->pl_width, header); 2356 789 ahrens } 2357 789 ahrens 2358 789 ahrens (void) printf("\n"); 2359 789 ahrens } 2360 789 ahrens 2361 5094 lling /* 2362 5094 lling * Given a pool and a list of properties, print out all the properties according 2363 5094 lling * to the described layout. 2364 5094 lling */ 2365 5094 lling static void 2366 5094 lling print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted) 2367 5094 lling { 2368 5094 lling boolean_t first = B_TRUE; 2369 5094 lling char property[ZPOOL_MAXPROPLEN]; 2370 5094 lling char *propstr; 2371 5094 lling boolean_t right_justify; 2372 5094 lling int width; 2373 5094 lling 2374 5094 lling for (; pl != NULL; pl = pl->pl_next) { 2375 5094 lling if (!first) { 2376 5094 lling if (scripted) 2377 5094 lling (void) printf("\t"); 2378 5094 lling else 2379 5094 lling (void) printf(" "); 2380 5094 lling } else { 2381 5094 lling first = B_FALSE; 2382 5094 lling } 2383 5094 lling 2384 5094 lling right_justify = B_FALSE; 2385 5094 lling if (pl->pl_prop != ZPROP_INVAL) { 2386 5094 lling if (zpool_get_prop(zhp, pl->pl_prop, property, 2387 5094 lling sizeof (property), NULL) != 0) 2388 5094 lling propstr = "-"; 2389 5094 lling else 2390 5094 lling propstr = property; 2391 5094 lling 2392 5094 lling right_justify = zpool_prop_align_right(pl->pl_prop); 2393 5094 lling } else { 2394 5094 lling propstr = "-"; 2395 5094 lling } 2396 5094 lling 2397 5094 lling width = pl->pl_width; 2398 5094 lling 2399 5094 lling /* 2400 5094 lling * If this is being called in scripted mode, or if this is the 2401 5094 lling * last column and it is left-justified, don't include a width 2402 5094 lling * format specifier. 2403 5094 lling */ 2404 5094 lling if (scripted || (pl->pl_next == NULL && !right_justify)) 2405 5094 lling (void) printf("%s", propstr); 2406 5094 lling else if (right_justify) 2407 5094 lling (void) printf("%*s", width, propstr); 2408 5094 lling else 2409 5094 lling (void) printf("%-*s", width, propstr); 2410 5094 lling } 2411 5094 lling 2412 5094 lling (void) printf("\n"); 2413 5094 lling } 2414 5094 lling 2415 5094 lling /* 2416 5094 lling * Generic callback function to list a pool. 2417 5094 lling */ 2418 789 ahrens int 2419 789 ahrens list_callback(zpool_handle_t *zhp, void *data) 2420 789 ahrens { 2421 789 ahrens list_cbdata_t *cbp = data; 2422 789 ahrens 2423 789 ahrens if (cbp->cb_first) { 2424 789 ahrens if (!cbp->cb_scripted) 2425 5094 lling print_header(cbp->cb_proplist); 2426 2082 eschrock cbp->cb_first = B_FALSE; 2427 789 ahrens } 2428 789 ahrens 2429 5094 lling print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted); 2430 789 ahrens 2431 789 ahrens return (0); 2432 789 ahrens } 2433 789 ahrens 2434 789 ahrens /* 2435 5094 lling * zpool list [-H] [-o prop[,prop]*] [pool] ... 2436 789 ahrens * 2437 5094 lling * -H Scripted mode. Don't display headers, and separate properties 2438 5094 lling * by a single tab. 2439 5094 lling * -o List of properties to display. Defaults to 2440 10956 George * "name,size,allocated,free,capacity,health,altroot" 2441 789 ahrens * 2442 789 ahrens * List all pools in the system, whether or not they're healthy. Output space 2443 789 ahrens * statistics for each one, as well as health status summary. 2444 789 ahrens */ 2445 789 ahrens int 2446 789 ahrens zpool_do_list(int argc, char **argv) 2447 789 ahrens { 2448 789 ahrens int c; 2449 789 ahrens int ret; 2450 789 ahrens list_cbdata_t cb = { 0 }; 2451 5094 lling static char default_props[] = 2452 10956 George "name,size,allocated,free,capacity,dedupratio,health,altroot"; 2453 5094 lling char *props = default_props; 2454 789 ahrens 2455 789 ahrens /* check options */ 2456 789 ahrens while ((c = getopt(argc, argv, ":Ho:")) != -1) { 2457 789 ahrens switch (c) { 2458 789 ahrens case 'H': 2459 2082 eschrock cb.cb_scripted = B_TRUE; 2460 789 ahrens break; 2461 789 ahrens case 'o': 2462 5094 lling props = optarg; 2463 789 ahrens break; 2464 789 ahrens case ':': 2465 789 ahrens (void) fprintf(stderr, gettext("missing argument for " 2466 789 ahrens "'%c' option\n"), optopt); 2467 2082 eschrock usage(B_FALSE); 2468 789 ahrens break; 2469 789 ahrens case '?': 2470 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2471 789 ahrens optopt); 2472 2082 eschrock usage(B_FALSE); 2473 789 ahrens } 2474 789 ahrens } 2475 789 ahrens 2476 789 ahrens argc -= optind; 2477 789 ahrens argv += optind; 2478 789 ahrens 2479 5094 lling if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) 2480 5094 lling usage(B_FALSE); 2481 789 ahrens 2482 2082 eschrock cb.cb_first = B_TRUE; 2483 789 ahrens 2484 5094 lling ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, 2485 5094 lling list_callback, &cb); 2486 5094 lling 2487 5094 lling zprop_free_list(cb.cb_proplist); 2488 789 ahrens 2489 4221 mmusante if (argc == 0 && cb.cb_first && !cb.cb_scripted) { 2490 789 ahrens (void) printf(gettext("no pools available\n")); 2491 789 ahrens return (0); 2492 789 ahrens } 2493 789 ahrens 2494 789 ahrens return (ret); 2495 789 ahrens } 2496 789 ahrens 2497 789 ahrens static nvlist_t * 2498 789 ahrens zpool_get_vdev_by_name(nvlist_t *nv, char *name) 2499 789 ahrens { 2500 789 ahrens nvlist_t **child; 2501 789 ahrens uint_t c, children; 2502 789 ahrens nvlist_t *match; 2503 789 ahrens char *path; 2504 789 ahrens 2505 789 ahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2506 789 ahrens &child, &children) != 0) { 2507 789 ahrens verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 2508 789 ahrens if (strncmp(name, "/dev/dsk/", 9) == 0) 2509 789 ahrens name += 9; 2510 789 ahrens if (strncmp(path, "/dev/dsk/", 9) == 0) 2511 789 ahrens path += 9; 2512 789 ahrens if (strcmp(name, path) == 0) 2513 789 ahrens return (nv); 2514 789 ahrens return (NULL); 2515 789 ahrens } 2516 789 ahrens 2517 789 ahrens for (c = 0; c < children; c++) 2518 789 ahrens if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL) 2519 789 ahrens return (match); 2520 789 ahrens 2521 789 ahrens return (NULL); 2522 789 ahrens } 2523 789 ahrens 2524 789 ahrens static int 2525 789 ahrens zpool_do_attach_or_replace(int argc, char **argv, int replacing) 2526 789 ahrens { 2527 2082 eschrock boolean_t force = B_FALSE; 2528 789 ahrens int c; 2529 789 ahrens nvlist_t *nvroot; 2530 789 ahrens char *poolname, *old_disk, *new_disk; 2531 789 ahrens zpool_handle_t *zhp; 2532 2082 eschrock int ret; 2533 789 ahrens 2534 789 ahrens /* check options */ 2535 789 ahrens while ((c = getopt(argc, argv, "f")) != -1) { 2536 789 ahrens switch (c) { 2537 789 ahrens case 'f': 2538 2082 eschrock force = B_TRUE; 2539 789 ahrens break; 2540 789 ahrens case '?': 2541 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2542 789 ahrens optopt); 2543 2082 eschrock usage(B_FALSE); 2544 789 ahrens } 2545 789 ahrens } 2546 789 ahrens 2547 789 ahrens argc -= optind; 2548 789 ahrens argv += optind; 2549 789 ahrens 2550 789 ahrens /* get pool name and check number of arguments */ 2551 789 ahrens if (argc < 1) { 2552 789 ahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 2553 2082 eschrock usage(B_FALSE); 2554 789 ahrens } 2555 789 ahrens 2556 789 ahrens poolname = argv[0]; 2557 789 ahrens 2558 789 ahrens if (argc < 2) { 2559 789 ahrens (void) fprintf(stderr, 2560 789 ahrens gettext("missing <device> specification\n")); 2561 2082 eschrock usage(B_FALSE); 2562 789 ahrens } 2563 789 ahrens 2564 789 ahrens old_disk = argv[1]; 2565 789 ahrens 2566 789 ahrens if (argc < 3) { 2567 789 ahrens if (!replacing) { 2568 789 ahrens (void) fprintf(stderr, 2569 789 ahrens gettext("missing <new_device> specification\n")); 2570 2082 eschrock usage(B_FALSE); 2571 789 ahrens } 2572 789 ahrens new_disk = old_disk; 2573 789 ahrens argc -= 1; 2574 789 ahrens argv += 1; 2575 789 ahrens } else { 2576 789 ahrens new_disk = argv[2]; 2577 789 ahrens argc -= 2; 2578 789 ahrens argv += 2; 2579 789 ahrens } 2580 789 ahrens 2581 789 ahrens if (argc > 1) { 2582 789 ahrens (void) fprintf(stderr, gettext("too many arguments\n")); 2583 2082 eschrock usage(B_FALSE); 2584 789 ahrens } 2585 789 ahrens 2586 2082 eschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2587 789 ahrens return (1); 2588 789 ahrens 2589 4276 taylor if (zpool_get_config(zhp, NULL) == NULL) { 2590 789 ahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 2591 789 ahrens poolname); 2592 789 ahrens zpool_close(zhp); 2593 789 ahrens return (1); 2594 789 ahrens } 2595 789 ahrens 2596 7343 Eric nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE, 2597 7343 Eric argc, argv); 2598 789 ahrens if (nvroot == NULL) { 2599 789 ahrens zpool_close(zhp); 2600 789 ahrens return (1); 2601 789 ahrens } 2602 789 ahrens 2603 2082 eschrock ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); 2604 2082 eschrock 2605 2082 eschrock nvlist_free(nvroot); 2606 2082 eschrock zpool_close(zhp); 2607 2082 eschrock 2608 2082 eschrock return (ret); 2609 789 ahrens } 2610 789 ahrens 2611 789 ahrens /* 2612 789 ahrens * zpool replace [-f] <pool> <device> <new_device> 2613 789 ahrens * 2614 789 ahrens * -f Force attach, even if <new_device> appears to be in use. 2615 789 ahrens * 2616 789 ahrens * Replace <device> with <new_device>. 2617 789 ahrens */ 2618 789 ahrens /* ARGSUSED */ 2619 789 ahrens int 2620 789 ahrens zpool_do_replace(int argc, char **argv) 2621 789 ahrens { 2622 789 ahrens return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 2623 789 ahrens } 2624 789 ahrens 2625 789 ahrens /* 2626 789 ahrens * zpool attach [-f] <pool> <device> <new_device> 2627 789 ahrens * 2628 789 ahrens * -f Force attach, even if <new_device> appears to be in use. 2629 789 ahrens * 2630 789 ahrens * Attach <new_device> to the mirror containing <device>. If <device> is not 2631 789 ahrens * part of a mirror, then <device> will be transformed into a mirror of 2632 789 ahrens * <device> and <new_device>. In either case, <new_device> will begin life 2633 789 ahrens * with a DTL of [0, now], and will immediately begin to resilver itself. 2634 789 ahrens */ 2635 789 ahrens int 2636 789 ahrens zpool_do_attach(int argc, char **argv) 2637 789 ahrens { 2638 789 ahrens return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 2639 789 ahrens } 2640 789 ahrens 2641 789 ahrens /* 2642 789 ahrens * zpool detach [-f] <pool> <device> 2643 789 ahrens * 2644 789 ahrens * -f Force detach of <device>, even if DTLs argue against it 2645 789 ahrens * (not supported yet) 2646 789 ahrens * 2647 789 ahrens * Detach a device from a mirror. The operation will be refused if <device> 2648 789 ahrens * is the last device in the mirror, or if the DTLs indicate that this device 2649 789 ahrens * has the only valid copy of some data. 2650 789 ahrens */ 2651 789 ahrens /* ARGSUSED */ 2652 789 ahrens int 2653 789 ahrens zpool_do_detach(int argc, char **argv) 2654 789 ahrens { 2655 789 ahrens int c; 2656 789 ahrens char *poolname, *path; 2657 789 ahrens zpool_handle_t *zhp; 2658 2082 eschrock int ret; 2659 789 ahrens 2660 789 ahrens /* check options */ 2661 789 ahrens while ((c = getopt(argc, argv, "f")) != -1) { 2662 789 ahrens switch (c) { 2663 789 ahrens case 'f': 2664 789 ahrens case '?': 2665 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2666 789 ahrens optopt); 2667 2082 eschrock usage(B_FALSE); 2668 789 ahrens } 2669 789 ahrens } 2670 789 ahrens 2671 789 ahrens argc -= optind; 2672 789 ahrens argv += optind; 2673 789 ahrens 2674 789 ahrens /* get pool name and check number of arguments */ 2675 789 ahrens if (argc < 1) { 2676 789 ahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 2677 2082 eschrock usage(B_FALSE); 2678 789 ahrens } 2679 789 ahrens 2680 789 ahrens if (argc < 2) { 2681 789 ahrens (void) fprintf(stderr, 2682 789 ahrens gettext("missing <device> specification\n")); 2683 2082 eschrock usage(B_FALSE); 2684 789 ahrens } 2685 789 ahrens 2686 789 ahrens poolname = argv[0]; 2687 789 ahrens path = argv[1]; 2688 789 ahrens 2689 2082 eschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2690 789 ahrens return (1); 2691 789 ahrens 2692 2082 eschrock ret = zpool_vdev_detach(zhp, path); 2693 2082 eschrock 2694 2082 eschrock zpool_close(zhp); 2695 2082 eschrock 2696 2082 eschrock return (ret); 2697 789 ahrens } 2698 789 ahrens 2699 789 ahrens /* 2700 1485 lling * zpool online <pool> <device> ... 2701 789 ahrens */ 2702 789 ahrens int 2703 789 ahrens zpool_do_online(int argc, char **argv) 2704 789 ahrens { 2705 789 ahrens int c, i; 2706 789 ahrens char *poolname; 2707 789 ahrens zpool_handle_t *zhp; 2708 789 ahrens int ret = 0; 2709 4451 eschrock vdev_state_t newstate; 2710 9816 George int flags = 0; 2711 9816 George 2712 9816 George /* check options */ 2713 9816 George while ((c = getopt(argc, argv, "et")) != -1) { 2714 9816 George switch (c) { 2715 9816 George case 'e': 2716 9816 George flags |= ZFS_ONLINE_EXPAND; 2717 9816 George break; 2718 789 ahrens case 't': 2719 789 ahrens case '?': 2720 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2721 789 ahrens optopt); 2722 2082 eschrock usage(B_FALSE); 2723 789 ahrens } 2724 789 ahrens } 2725 789 ahrens 2726 789 ahrens argc -= optind; 2727 789 ahrens argv += optind; 2728 789 ahrens 2729 789 ahrens /* get pool name and check number of arguments */ 2730 789 ahrens if (argc < 1) { 2731 789 ahrens (void) fprintf(stderr, gettext("missing pool name\n")); 2732 2082 eschrock usage(B_FALSE); 2733 789 ahrens } 2734 789 ahrens if (argc < 2) { 2735 789 ahrens (void) fprintf(stderr, gettext("missing device name\n")); 2736 2082 eschrock usage(B_FALSE); 2737 789 ahrens } 2738 789 ahrens 2739 789 ahrens poolname = argv[0]; 2740 789 ahrens 2741 2082 eschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2742 789 ahrens return (1); 2743 789 ahrens 2744 4451 eschrock for (i = 1; i < argc; i++) { 2745 9816 George if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) { 2746 4451 eschrock if (newstate != VDEV_STATE_HEALTHY) { 2747 4451 eschrock (void) printf(gettext("warning: device '%s' " 2748 4451 eschrock "onlined, but remains in faulted state\n"), 2749 4451 eschrock argv[i]); 2750 4451 eschrock if (newstate == VDEV_STATE_FAULTED) 2751 4451 eschrock (void) printf(gettext("use 'zpool " 2752 4451 eschrock "clear' to restore a faulted " 2753 4451 eschrock "device\n")); 2754 4451 eschrock else 2755 4451 eschrock (void) printf(gettext("use 'zpool " 2756 4451 eschrock "replace' to replace devices " 2757 4451 eschrock "that are no longer present\n")); 2758 4451 eschrock } 2759 4451 eschrock } else { 2760 789 ahrens ret = 1; 2761 4451 eschrock } 2762 4451 eschrock } 2763 2082 eschrock 2764 2082 eschrock zpool_close(zhp); 2765 789 ahrens 2766 789 ahrens return (ret); 2767 789 ahrens } 2768 789 ahrens 2769 789 ahrens /* 2770 1485 lling * zpool offline [-ft] <pool> <device> ... 2771 789 ahrens * 2772 789 ahrens * -f Force the device into the offline state, even if doing 2773 789 ahrens * so would appear to compromise pool availability. 2774 789 ahrens * (not supported yet) 2775 789 ahrens * 2776 789 ahrens * -t Only take the device off-line temporarily. The offline 2777 789 ahrens * state will not be persistent across reboots. 2778 789 ahrens */ 2779 789 ahrens /* ARGSUSED */ 2780 789 ahrens int 2781 789 ahrens zpool_do_offline(int argc, char **argv) 2782 789 ahrens { 2783 789 ahrens int c, i; 2784 789 ahrens char *poolname; 2785 789 ahrens zpool_handle_t *zhp; 2786 2082 eschrock int ret = 0; 2787 2082 eschrock boolean_t istmp = B_FALSE; 2788 789 ahrens 2789 789 ahrens /* check options */ 2790 789 ahrens while ((c = getopt(argc, argv, "ft")) != -1) { 2791 789 ahrens switch (c) { 2792 1485 lling case 't': 2793 2082 eschrock istmp = B_TRUE; 2794 1485 lling break; 2795 789 ahrens case 'f': 2796 789 ahrens case '?': 2797 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2798 789 ahrens optopt); 2799 2082 eschrock usage(B_FALSE); 2800 789 ahrens } 2801 789 ahrens } 2802 789 ahrens 2803 789 ahrens argc -= optind; 2804 789 ahrens argv += optind; 2805 789 ahrens 2806 789 ahrens /* get pool name and check number of arguments */ 2807 789 ahrens if (argc < 1) { 2808 789 ahrens (void) fprintf(stderr, gettext("missing pool name\n")); 2809 2082 eschrock usage(B_FALSE); 2810 789 ahrens } 2811 789 ahrens if (argc < 2) { 2812 789 ahrens (void) fprintf(stderr, gettext("missing device name\n")); 2813 2082 eschrock usage(B_FALSE); 2814 789 ahrens } 2815 789 ahrens 2816 789 ahrens poolname = argv[0]; 2817 789 ahrens 2818 2082 eschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2819 789 ahrens return (1); 2820 789 ahrens 2821 4451 eschrock for (i = 1; i < argc; i++) { 2822 4451 eschrock if (zpool_vdev_offline(zhp, argv[i], istmp) != 0) 2823 789 ahrens ret = 1; 2824 4451 eschrock } 2825 2082 eschrock 2826 2082 eschrock zpool_close(zhp); 2827 789 ahrens 2828 789 ahrens return (ret); 2829 789 ahrens } 2830 789 ahrens 2831 1544 eschrock /* 2832 1544 eschrock * zpool clear <pool> [device] 2833 1544 eschrock * 2834 1544 eschrock * Clear all errors associated with a pool or a particular device. 2835 1544 eschrock */ 2836 1544 eschrock int 2837 1544 eschrock zpool_do_clear(int argc, char **argv) 2838 1544 eschrock { 2839 10921 Tim int c; 2840 10921 Tim int ret = 0; 2841 10921 Tim boolean_t dryrun = B_FALSE; 2842 10921 Tim boolean_t do_rewind = B_FALSE; 2843 10921 Tim boolean_t xtreme_rewind = B_FALSE; 2844 10921 Tim uint32_t rewind_policy = ZPOOL_NO_REWIND; 2845 10921 Tim nvlist_t *policy = NULL; 2846 1544 eschrock zpool_handle_t *zhp; 2847 1544 eschrock char *pool, *device; 2848 1544 eschrock 2849 10921 Tim /* check options */ 2850 10921 Tim while ((c = getopt(argc, argv, "FnX")) != -1) { 2851 10921 Tim switch (c) { 2852 10921 Tim case 'F': 2853 10921 Tim do_rewind = B_TRUE; 2854 10921 Tim break; 2855 10921 Tim case 'n': 2856 10921 Tim dryrun = B_TRUE; 2857 10921 Tim break; 2858 10921 Tim case 'X': 2859 10921 Tim xtreme_rewind = B_TRUE; 2860 10921 Tim break; 2861 10921 Tim case '?': 2862 10921 Tim (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2863 10921 Tim optopt); 2864 10921 Tim usage(B_FALSE); 2865 10921 Tim } 2866 10921 Tim } 2867 10921 Tim 2868 10921 Tim argc -= optind; 2869 10921 Tim argv += optind; 2870 10921 Tim 2871 10921 Tim if (argc < 1) { 2872 1544 eschrock (void) fprintf(stderr, gettext("missing pool name\n")); 2873 2082 eschrock usage(B_FALSE); 2874 1544 eschrock } 2875 1544 eschrock 2876 10921 Tim if (argc > 2) { 2877 1544 eschrock (void) fprintf(stderr, gettext("too many arguments\n")); 2878 2082 eschrock usage(B_FALSE); 2879 1544 eschrock } 2880 1544 eschrock 2881 10921 Tim if ((dryrun || xtreme_rewind) && !do_rewind) { 2882 10921 Tim (void) fprintf(stderr, 2883 10921 Tim gettext("-n or -X only meaningful with -F\n")); 2884 10921 Tim usage(B_FALSE); 2885 10921 Tim } 2886 10921 Tim if (dryrun) 2887 10921 Tim rewind_policy = ZPOOL_TRY_REWIND; 2888 10921 Tim else if (do_rewind) 2889 10921 Tim rewind_policy = ZPOOL_DO_REWIND; 2890 10921 Tim if (xtreme_rewind) 2891 10921 Tim rewind_policy |= ZPOOL_EXTREME_REWIND; 2892 10921 Tim 2893 10921 Tim /* In future, further rewind policy choices can be passed along here */ 2894 10921 Tim if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 2895 10921 Tim nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0) 2896 10921 Tim return (1); 2897 10921 Tim 2898 10921 Tim pool = argv[0]; 2899 10921 Tim device = argc == 2 ? argv[1] : NULL; 2900 10921 Tim 2901 10921 Tim if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 2902 10921 Tim nvlist_free(policy); 2903 10921 Tim return (1); 2904 10921 Tim } 2905 10921 Tim 2906 10921 Tim if (zpool_clear(zhp, device, policy) != 0) 2907 1544 eschrock ret = 1; 2908 1544 eschrock 2909 1544 eschrock zpool_close(zhp); 2910 10921 Tim 2911 10921 Tim nvlist_free(policy); 2912 1544 eschrock 2913 1544 eschrock return (ret); 2914 1544 eschrock } 2915 1544 eschrock 2916 789 ahrens typedef struct scrub_cbdata { 2917 789 ahrens int cb_type; 2918 2926 ek110237 int cb_argc; 2919 2926 ek110237 char **cb_argv; 2920 789 ahrens } scrub_cbdata_t; 2921 789 ahrens 2922 789 ahrens int 2923 789 ahrens scrub_callback(zpool_handle_t *zhp, void *data) 2924 789 ahrens { 2925 789 ahrens scrub_cbdata_t *cb = data; 2926 2926 ek110237 int err; 2927 1544 eschrock 2928 1544 eschrock /* 2929 1544 eschrock * Ignore faulted pools. 2930 1544 eschrock */ 2931 1544 eschrock if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 2932 1544 eschrock (void) fprintf(stderr, gettext("cannot scrub '%s': pool is " 2933 1544 eschrock "currently unavailable\n"), zpool_get_name(zhp)); 2934 1544 eschrock return (1); 2935 1544 eschrock } 2936 789 ahrens 2937 2926 ek110237 err = zpool_scrub(zhp, cb->cb_type); 2938 2926 ek110237 2939 2926 ek110237 return (err != 0); 2940 789 ahrens } 2941 789 ahrens 2942 789 ahrens /* 2943 789 ahrens * zpool scrub [-s] <pool> ... 2944 789 ahrens * 2945 789 ahrens * -s Stop. Stops any in-progress scrub. 2946 789 ahrens */ 2947 789 ahrens int 2948 789 ahrens zpool_do_scrub(int argc, char **argv) 2949 789 ahrens { 2950 789 ahrens int c; 2951 789 ahrens scrub_cbdata_t cb; 2952 789 ahrens 2953 789 ahrens cb.cb_type = POOL_SCRUB_EVERYTHING; 2954 789 ahrens 2955 789 ahrens /* check options */ 2956 789 ahrens while ((c = getopt(argc, argv, "s")) != -1) { 2957 789 ahrens switch (c) { 2958 789 ahrens case 's': 2959 789 ahrens cb.cb_type = POOL_SCRUB_NONE; 2960 789 ahrens break; 2961 789 ahrens case '?': 2962 789 ahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2963 789 ahrens optopt); 2964 2082 eschrock usage(B_FALSE); 2965 789 ahrens } 2966 789 ahrens } 2967 789 ahrens 2968 2926 ek110237 cb.cb_argc = argc; 2969 2926 ek110237 cb.cb_argv = argv; 2970 789 ahrens argc -= optind; 2971 789 ahrens argv += optind; 2972 789 ahrens 2973 789 ahrens if (argc < 1) { 2974 789 ahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 2975 2082 eschrock usage(B_FALSE); 2976 789 ahrens } 2977 789 ahrens 2978 3912 lling return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 2979 789 ahrens } 2980 789 ahrens 2981 789 ahrens typedef struct status_cbdata { 2982 2082 eschrock int cb_count; 2983 2676 eschrock boolean_t cb_allpools; 2984 2082 eschrock boolean_t cb_verbose; 2985 2082 eschrock boolean_t cb_explain; 2986 2082 eschrock boolean_t cb_first; 2987 11149 George boolean_t cb_dedup_stats; 2988 789 ahrens } status_cbdata_t; 2989 789 ahrens 2990 789 ahrens /* 2991 789 ahrens * Print out detailed scrub status. 2992 789 ahrens */ 2993 789 ahrens void 2994 789 ahrens print_scrub_status(nvlist_t *nvroot) 2995 789 ahrens { 2996 789 ahrens vdev_stat_t *vs; 2997 789 ahrens uint_t vsc; 2998 789 ahrens time_t start, end, now; 2999 789 ahrens double fraction_done; 3000 5853 ek110237 uint64_t examined, total, minutes_left, minutes_taken; 3001 789 ahrens char *scrub_type; 3002 789 ahrens 3003 789 ahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 3004 789 ahrens (uint64_t **)&vs, &vsc) == 0); 3005 789 ahrens 3006 789 ahrens /* 3007 789 ahrens * If there's never been a scrub, there's not much to say. 3008 789 ahrens */ 3009 789 ahrens if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) { 3010 789 ahrens (void) printf(gettext("none requested\n")); 3011 789 ahrens return; 3012 789 ahrens } 3013 789 ahrens 3014 789 ahrens scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 3015 789 ahrens "resilver" : "scrub"; 3016 789 ahrens 3017 789 ahrens start = vs->vs_scrub_start; 3018 789 ahrens end = vs->vs_scrub_end; 3019 789 ahrens now = time(NULL); 3020 789 ahrens examined = vs->vs_scrub_examined; 3021 789 ahrens total = vs->vs_alloc; 3022 789 ahrens 3023 789 ahrens if (end != 0) { 3024 5853 ek110237 minutes_taken = (uint64_t)((end - start) / 60); 3025 5853 ek110237 3026 5853 ek110237 (void) printf(gettext("%s %s after %lluh%um with %llu errors " 3027 5853 ek110237 "on %s"), 3028 789 ahrens scrub_type, vs->vs_scrub_complete ? "completed" : "stopped", 3029 5853 ek110237 (u_longlong_t)(minutes_taken / 60), 3030 5853 ek110237 (uint_t)(minutes_taken % 60), 3031 789 ahrens (u_longlong_t)vs->vs_scrub_errors, ctime(&end)); 3032 789 ahrens return; 3033 789 ahrens } 3034 789 ahrens 3035 789 ahrens if (examined == 0) 3036 789 ahrens examined = 1; 3037 789 ahrens if (examined > total) 3038 789 ahrens total = examined; 3039 789 ahrens 3040 789 ahrens fraction_done = (double)examined / total; 3041 789 ahrens minutes_left = (uint64_t)((now - start) * 3042 789 ahrens (1 - fraction_done) / fraction_done / 60); 3043 5853 ek110237 minutes_taken = (uint64_t)((now - start) / 60); 3044 789 ahrens 3045 5853 ek110237 (void) printf(gettext("%s in progress for %lluh%um, %.2f%% done, " 3046 5853 ek110237 "%lluh%um to go\n"), 3047 5853 ek110237 scrub_type, (u_longlong_t)(minutes_taken / 60), 3048 5853 ek110237 (uint_t)(minutes_taken % 60), 100 * fraction_done, 3049 789 ahrens (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60)); 3050 789 ahrens } 3051 789 ahrens 3052 1544 eschrock static void 3053 1544 eschrock print_error_log(zpool_handle_t *zhp) 3054 1544 eschrock { 3055 4820 ek110237 nvlist_t *nverrlist = NULL; 3056 3444 ek110237 nvpair_t *elem; 3057 3444 ek110237 char *pathname; 3058 3444 ek110237 size_t len = MAXPATHLEN * 2; 3059 1544 eschrock 3060 3444 ek110237 if (zpool_get_errlog(zhp, &nverrlist) != 0) { 3061 1544 eschrock (void) printf("errors: List of errors unavailable " 3062 1544 eschrock "(insufficient privileges)\n"); 3063 1544 eschrock return; 3064 1544 eschrock } 3065 1544 eschrock 3066 3444 ek110237 (void) printf("errors: Permanent errors have been " 3067 3444 ek110237 "detected in the following files:\n\n"); 3068 1544 eschrock 3069 3444 ek110237 pathname = safe_malloc(len); 3070 3444 ek110237 elem = NULL; 3071 3444 ek110237 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 3072 3444 ek110237 nvlist_t *nv; 3073 3444 ek110237 uint64_t dsobj, obj; 3074 1544 eschrock 3075 3444 ek110237 verify(nvpair_value_nvlist(elem, &nv) == 0); 3076 3444 ek110237 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 3077 3444 ek110237 &dsobj) == 0); 3078 3444 ek110237 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 3079 3444 ek110237 &obj) == 0); 3080 3444 ek110237 zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 3081 3444 ek110237 (void) printf("%7s %s\n", "", pathname); 3082 1544 eschrock } 3083 3444 ek110237 free(pathname); 3084 3444 ek110237 nvlist_free(nverrlist); 3085 1544 eschrock } 3086 1544 eschrock 3087 2082 eschrock static void 3088 2082 eschrock print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares, 3089 2082 eschrock int namewidth) 3090 2082 eschrock { 3091 2082 eschrock uint_t i; 3092 2082 eschrock char *name; 3093 2082 eschrock 3094 2082 eschrock if (nspares == 0) 3095 2082 eschrock return; 3096 2082 eschrock 3097 2082 eschrock (void) printf(gettext("\tspares\n")); 3098 2082 eschrock 3099 2082 eschrock for (i = 0; i < nspares; i++) { 3100 10594 George name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE); 3101 2082 eschrock print_status_config(zhp, name, spares[i], 3102 9391