1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5441d80aaSlling * Common Development and Distribution License (the "License"). 6441d80aaSlling * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 2199653d4eSeschrock 22fa9e4066Sahrens /* 23379c004dSEric Schrock * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24fa9e4066Sahrens * Use is subject to license terms. 25fa9e4066Sahrens */ 26fa9e4066Sahrens 27fa9e4066Sahrens #include <assert.h> 28fa9e4066Sahrens #include <ctype.h> 29fa9e4066Sahrens #include <dirent.h> 30fa9e4066Sahrens #include <errno.h> 31fa9e4066Sahrens #include <fcntl.h> 32fa9e4066Sahrens #include <libgen.h> 33fa9e4066Sahrens #include <libintl.h> 34fa9e4066Sahrens #include <libuutil.h> 35fa9e4066Sahrens #include <locale.h> 36fa9e4066Sahrens #include <stdio.h> 37fa9e4066Sahrens #include <stdlib.h> 38fa9e4066Sahrens #include <string.h> 39fa9e4066Sahrens #include <strings.h> 40fa9e4066Sahrens #include <unistd.h> 41fa9e4066Sahrens #include <priv.h> 42ecd6cf80Smarks #include <pwd.h> 43ecd6cf80Smarks #include <zone.h> 44b1b8ab34Slling #include <sys/fs/zfs.h> 45fa9e4066Sahrens 46fa9e4066Sahrens #include <sys/stat.h> 47fa9e4066Sahrens 48fa9e4066Sahrens #include <libzfs.h> 49fa9e4066Sahrens 50fa9e4066Sahrens #include "zpool_util.h" 51b7b97454Sperrin #include "zfs_comutil.h" 52fa9e4066Sahrens 53fa9e4066Sahrens static int zpool_do_create(int, char **); 54fa9e4066Sahrens static int zpool_do_destroy(int, char **); 55fa9e4066Sahrens 56fa9e4066Sahrens static int zpool_do_add(int, char **); 5799653d4eSeschrock static int zpool_do_remove(int, char **); 58fa9e4066Sahrens 59fa9e4066Sahrens static int zpool_do_list(int, char **); 60fa9e4066Sahrens static int zpool_do_iostat(int, char **); 61fa9e4066Sahrens static int zpool_do_status(int, char **); 62fa9e4066Sahrens 63fa9e4066Sahrens static int zpool_do_online(int, char **); 64fa9e4066Sahrens static int zpool_do_offline(int, char **); 65ea8dc4b6Seschrock static int zpool_do_clear(int, char **); 66fa9e4066Sahrens 67fa9e4066Sahrens static int zpool_do_attach(int, char **); 68fa9e4066Sahrens static int zpool_do_detach(int, char **); 69fa9e4066Sahrens static int zpool_do_replace(int, char **); 70fa9e4066Sahrens 71fa9e4066Sahrens static int zpool_do_scrub(int, char **); 72fa9e4066Sahrens 73fa9e4066Sahrens static int zpool_do_import(int, char **); 74fa9e4066Sahrens static int zpool_do_export(int, char **); 75fa9e4066Sahrens 76eaca9bbdSeschrock static int zpool_do_upgrade(int, char **); 77eaca9bbdSeschrock 7806eeb2adSek110237 static int zpool_do_history(int, char **); 7906eeb2adSek110237 80b1b8ab34Slling static int zpool_do_get(int, char **); 81b1b8ab34Slling static int zpool_do_set(int, char **); 82b1b8ab34Slling 83fa9e4066Sahrens /* 84fa9e4066Sahrens * These libumem hooks provide a reasonable set of defaults for the allocator's 85fa9e4066Sahrens * debugging facilities. 86fa9e4066Sahrens */ 8729ab75c9Srm160521 8829ab75c9Srm160521 #ifdef DEBUG 89fa9e4066Sahrens const char * 9099653d4eSeschrock _umem_debug_init(void) 91fa9e4066Sahrens { 92fa9e4066Sahrens return ("default,verbose"); /* $UMEM_DEBUG setting */ 93fa9e4066Sahrens } 94fa9e4066Sahrens 95fa9e4066Sahrens const char * 96fa9e4066Sahrens _umem_logging_init(void) 97fa9e4066Sahrens { 98fa9e4066Sahrens return ("fail,contents"); /* $UMEM_LOGGING setting */ 99fa9e4066Sahrens } 10029ab75c9Srm160521 #endif 101fa9e4066Sahrens 10265cd9f28Seschrock typedef enum { 10365cd9f28Seschrock HELP_ADD, 10465cd9f28Seschrock HELP_ATTACH, 105ea8dc4b6Seschrock HELP_CLEAR, 10665cd9f28Seschrock HELP_CREATE, 10765cd9f28Seschrock HELP_DESTROY, 10865cd9f28Seschrock HELP_DETACH, 10965cd9f28Seschrock HELP_EXPORT, 11006eeb2adSek110237 HELP_HISTORY, 11165cd9f28Seschrock HELP_IMPORT, 11265cd9f28Seschrock HELP_IOSTAT, 11365cd9f28Seschrock HELP_LIST, 11465cd9f28Seschrock HELP_OFFLINE, 11565cd9f28Seschrock HELP_ONLINE, 11665cd9f28Seschrock HELP_REPLACE, 11799653d4eSeschrock HELP_REMOVE, 11865cd9f28Seschrock HELP_SCRUB, 119eaca9bbdSeschrock HELP_STATUS, 120b1b8ab34Slling HELP_UPGRADE, 121b1b8ab34Slling HELP_GET, 122b1b8ab34Slling HELP_SET 12365cd9f28Seschrock } zpool_help_t; 12465cd9f28Seschrock 12565cd9f28Seschrock 126fa9e4066Sahrens typedef struct zpool_command { 127fa9e4066Sahrens const char *name; 128fa9e4066Sahrens int (*func)(int, char **); 12965cd9f28Seschrock zpool_help_t usage; 130fa9e4066Sahrens } zpool_command_t; 131fa9e4066Sahrens 132fa9e4066Sahrens /* 133fa9e4066Sahrens * Master command table. Each ZFS command has a name, associated function, and 134ea8dc4b6Seschrock * usage message. The usage messages need to be internationalized, so we have 135ea8dc4b6Seschrock * to have a function to return the usage message based on a command index. 13665cd9f28Seschrock * 13765cd9f28Seschrock * These commands are organized according to how they are displayed in the usage 13865cd9f28Seschrock * message. An empty command (one with a NULL name) indicates an empty line in 13965cd9f28Seschrock * the generic usage message. 140fa9e4066Sahrens */ 141fa9e4066Sahrens static zpool_command_t command_table[] = { 14265cd9f28Seschrock { "create", zpool_do_create, HELP_CREATE }, 14365cd9f28Seschrock { "destroy", zpool_do_destroy, HELP_DESTROY }, 144fa9e4066Sahrens { NULL }, 14565cd9f28Seschrock { "add", zpool_do_add, HELP_ADD }, 14699653d4eSeschrock { "remove", zpool_do_remove, HELP_REMOVE }, 147fa9e4066Sahrens { NULL }, 14865cd9f28Seschrock { "list", zpool_do_list, HELP_LIST }, 14965cd9f28Seschrock { "iostat", zpool_do_iostat, HELP_IOSTAT }, 15065cd9f28Seschrock { "status", zpool_do_status, HELP_STATUS }, 151fa9e4066Sahrens { NULL }, 15265cd9f28Seschrock { "online", zpool_do_online, HELP_ONLINE }, 15365cd9f28Seschrock { "offline", zpool_do_offline, HELP_OFFLINE }, 154ea8dc4b6Seschrock { "clear", zpool_do_clear, HELP_CLEAR }, 155fa9e4066Sahrens { NULL }, 15665cd9f28Seschrock { "attach", zpool_do_attach, HELP_ATTACH }, 15765cd9f28Seschrock { "detach", zpool_do_detach, HELP_DETACH }, 15865cd9f28Seschrock { "replace", zpool_do_replace, HELP_REPLACE }, 159fa9e4066Sahrens { NULL }, 16065cd9f28Seschrock { "scrub", zpool_do_scrub, HELP_SCRUB }, 161fa9e4066Sahrens { NULL }, 16265cd9f28Seschrock { "import", zpool_do_import, HELP_IMPORT }, 16365cd9f28Seschrock { "export", zpool_do_export, HELP_EXPORT }, 16406eeb2adSek110237 { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, 16506eeb2adSek110237 { NULL }, 166b1b8ab34Slling { "history", zpool_do_history, HELP_HISTORY }, 167b1b8ab34Slling { "get", zpool_do_get, HELP_GET }, 168b1b8ab34Slling { "set", zpool_do_set, HELP_SET }, 169fa9e4066Sahrens }; 170fa9e4066Sahrens 171fa9e4066Sahrens #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 172fa9e4066Sahrens 173fa9e4066Sahrens zpool_command_t *current_command; 1742a6b87f0Sek110237 static char history_str[HIS_MAX_RECORD_LEN]; 175fa9e4066Sahrens 17665cd9f28Seschrock static const char * 17765cd9f28Seschrock get_usage(zpool_help_t idx) { 17865cd9f28Seschrock switch (idx) { 17965cd9f28Seschrock case HELP_ADD: 18065cd9f28Seschrock return (gettext("\tadd [-fn] <pool> <vdev> ...\n")); 18165cd9f28Seschrock case HELP_ATTACH: 18265cd9f28Seschrock return (gettext("\tattach [-f] <pool> <device> " 183e45ce728Sahrens "<new-device>\n")); 184ea8dc4b6Seschrock case HELP_CLEAR: 185ea8dc4b6Seschrock return (gettext("\tclear <pool> [device]\n")); 18665cd9f28Seschrock case HELP_CREATE: 187990b4856Slling return (gettext("\tcreate [-fn] [-o property=value] ... \n" 1880a48a24eStimh "\t [-O file-system-property=value] ... \n" 189990b4856Slling "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n")); 19065cd9f28Seschrock case HELP_DESTROY: 19165cd9f28Seschrock return (gettext("\tdestroy [-f] <pool>\n")); 19265cd9f28Seschrock case HELP_DETACH: 19365cd9f28Seschrock return (gettext("\tdetach <pool> <device>\n")); 19465cd9f28Seschrock case HELP_EXPORT: 19565cd9f28Seschrock return (gettext("\texport [-f] <pool> ...\n")); 19606eeb2adSek110237 case HELP_HISTORY: 197ecd6cf80Smarks return (gettext("\thistory [-il] [<pool>] ...\n")); 19865cd9f28Seschrock case HELP_IMPORT: 1994c58d714Sdarrenm return (gettext("\timport [-d dir] [-D]\n" 2002f8aaab3Seschrock "\timport [-o mntopts] [-o property=value] ... \n" 2012f8aaab3Seschrock "\t [-d dir | -c cachefile] [-D] [-f] [-R root] -a\n" 2022f8aaab3Seschrock "\timport [-o mntopts] [-o property=value] ... \n" 2032f8aaab3Seschrock "\t [-d dir | -c cachefile] [-D] [-f] [-R root] " 2042f8aaab3Seschrock "<pool | id> [newpool]\n")); 20565cd9f28Seschrock case HELP_IOSTAT: 20665cd9f28Seschrock return (gettext("\tiostat [-v] [pool] ... [interval " 20765cd9f28Seschrock "[count]]\n")); 20865cd9f28Seschrock case HELP_LIST: 209990b4856Slling return (gettext("\tlist [-H] [-o property[,...]] " 210990b4856Slling "[pool] ...\n")); 21165cd9f28Seschrock case HELP_OFFLINE: 212441d80aaSlling return (gettext("\toffline [-t] <pool> <device> ...\n")); 21365cd9f28Seschrock case HELP_ONLINE: 214441d80aaSlling return (gettext("\tonline <pool> <device> ...\n")); 21565cd9f28Seschrock case HELP_REPLACE: 21665cd9f28Seschrock return (gettext("\treplace [-f] <pool> <device> " 217e45ce728Sahrens "[new-device]\n")); 21899653d4eSeschrock case HELP_REMOVE: 219fa94a07fSbrendan return (gettext("\tremove <pool> <device> ...\n")); 22065cd9f28Seschrock case HELP_SCRUB: 22165cd9f28Seschrock return (gettext("\tscrub [-s] <pool> ...\n")); 22265cd9f28Seschrock case HELP_STATUS: 22365cd9f28Seschrock return (gettext("\tstatus [-vx] [pool] ...\n")); 224eaca9bbdSeschrock case HELP_UPGRADE: 225eaca9bbdSeschrock return (gettext("\tupgrade\n" 226eaca9bbdSeschrock "\tupgrade -v\n" 227990b4856Slling "\tupgrade [-V version] <-a | pool ...>\n")); 228b1b8ab34Slling case HELP_GET: 229e45ce728Sahrens return (gettext("\tget <\"all\" | property[,...]> " 230b1b8ab34Slling "<pool> ...\n")); 231b1b8ab34Slling case HELP_SET: 232b1b8ab34Slling return (gettext("\tset <property=value> <pool> \n")); 23365cd9f28Seschrock } 23465cd9f28Seschrock 23565cd9f28Seschrock abort(); 23665cd9f28Seschrock /* NOTREACHED */ 23765cd9f28Seschrock } 23865cd9f28Seschrock 239fa9e4066Sahrens 240fa9e4066Sahrens /* 241b1b8ab34Slling * Callback routine that will print out a pool property value. 242b1b8ab34Slling */ 243990b4856Slling static int 244990b4856Slling print_prop_cb(int prop, void *cb) 245b1b8ab34Slling { 246b1b8ab34Slling FILE *fp = cb; 247b1b8ab34Slling 248b1b8ab34Slling (void) fprintf(fp, "\t%-13s ", zpool_prop_to_name(prop)); 249b1b8ab34Slling 250990b4856Slling if (zpool_prop_readonly(prop)) 251990b4856Slling (void) fprintf(fp, " NO "); 252990b4856Slling else 253990b4856Slling (void) fprintf(fp, " YES "); 254990b4856Slling 255b1b8ab34Slling if (zpool_prop_values(prop) == NULL) 256b1b8ab34Slling (void) fprintf(fp, "-\n"); 257b1b8ab34Slling else 258b1b8ab34Slling (void) fprintf(fp, "%s\n", zpool_prop_values(prop)); 259b1b8ab34Slling 260990b4856Slling return (ZPROP_CONT); 261b1b8ab34Slling } 262b1b8ab34Slling 263b1b8ab34Slling /* 264fa9e4066Sahrens * Display usage message. If we're inside a command, display only the usage for 265fa9e4066Sahrens * that command. Otherwise, iterate over the entire command table and display 266fa9e4066Sahrens * a complete usage message. 267fa9e4066Sahrens */ 268fa9e4066Sahrens void 26999653d4eSeschrock usage(boolean_t requested) 270fa9e4066Sahrens { 271fa9e4066Sahrens FILE *fp = requested ? stdout : stderr; 272fa9e4066Sahrens 273fa9e4066Sahrens if (current_command == NULL) { 274fa9e4066Sahrens int i; 275fa9e4066Sahrens 276fa9e4066Sahrens (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 277fa9e4066Sahrens (void) fprintf(fp, 278fa9e4066Sahrens gettext("where 'command' is one of the following:\n\n")); 279fa9e4066Sahrens 280fa9e4066Sahrens for (i = 0; i < NCOMMAND; i++) { 281fa9e4066Sahrens if (command_table[i].name == NULL) 282fa9e4066Sahrens (void) fprintf(fp, "\n"); 283fa9e4066Sahrens else 284fa9e4066Sahrens (void) fprintf(fp, "%s", 28565cd9f28Seschrock get_usage(command_table[i].usage)); 286fa9e4066Sahrens } 287fa9e4066Sahrens } else { 288fa9e4066Sahrens (void) fprintf(fp, gettext("usage:\n")); 28965cd9f28Seschrock (void) fprintf(fp, "%s", get_usage(current_command->usage)); 290fa9e4066Sahrens } 291fa9e4066Sahrens 292b1b8ab34Slling if (current_command != NULL && 293b1b8ab34Slling ((strcmp(current_command->name, "set") == 0) || 294990b4856Slling (strcmp(current_command->name, "get") == 0) || 295990b4856Slling (strcmp(current_command->name, "list") == 0))) { 296b1b8ab34Slling 297b1b8ab34Slling (void) fprintf(fp, 298b1b8ab34Slling gettext("\nthe following properties are supported:\n")); 299b1b8ab34Slling 300990b4856Slling (void) fprintf(fp, "\n\t%-13s %s %s\n\n", 301990b4856Slling "PROPERTY", "EDIT", "VALUES"); 302b1b8ab34Slling 303b1b8ab34Slling /* Iterate over all properties */ 304990b4856Slling (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, 305990b4856Slling ZFS_TYPE_POOL); 306b1b8ab34Slling } 307b1b8ab34Slling 308e9dbad6fSeschrock /* 309e9dbad6fSeschrock * See comments at end of main(). 310e9dbad6fSeschrock */ 311e9dbad6fSeschrock if (getenv("ZFS_ABORT") != NULL) { 312e9dbad6fSeschrock (void) printf("dumping core by request\n"); 313e9dbad6fSeschrock abort(); 314e9dbad6fSeschrock } 315e9dbad6fSeschrock 316fa9e4066Sahrens exit(requested ? 0 : 2); 317fa9e4066Sahrens } 318fa9e4066Sahrens 319fa9e4066Sahrens void 3208654d025Sperrin print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, 3218654d025Sperrin boolean_t print_logs) 322fa9e4066Sahrens { 323fa9e4066Sahrens nvlist_t **child; 324fa9e4066Sahrens uint_t c, children; 325afefbcddSeschrock char *vname; 326fa9e4066Sahrens 327fa9e4066Sahrens if (name != NULL) 328fa9e4066Sahrens (void) printf("\t%*s%s\n", indent, "", name); 329fa9e4066Sahrens 330fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 331fa9e4066Sahrens &child, &children) != 0) 332fa9e4066Sahrens return; 333fa9e4066Sahrens 334afefbcddSeschrock for (c = 0; c < children; c++) { 3358654d025Sperrin uint64_t is_log = B_FALSE; 3368654d025Sperrin 3378654d025Sperrin (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 3388654d025Sperrin &is_log); 3398654d025Sperrin if ((is_log && !print_logs) || (!is_log && print_logs)) 3408654d025Sperrin continue; 3418654d025Sperrin 34299653d4eSeschrock vname = zpool_vdev_name(g_zfs, zhp, child[c]); 3438654d025Sperrin print_vdev_tree(zhp, vname, child[c], indent + 2, 3448654d025Sperrin B_FALSE); 345afefbcddSeschrock free(vname); 346afefbcddSeschrock } 347fa9e4066Sahrens } 348fa9e4066Sahrens 349fa9e4066Sahrens /* 350990b4856Slling * Add a property pair (name, string-value) into a property nvlist. 351990b4856Slling */ 352990b4856Slling static int 3530a48a24eStimh add_prop_list(const char *propname, char *propval, nvlist_t **props, 3540a48a24eStimh boolean_t poolprop) 355990b4856Slling { 3560a48a24eStimh zpool_prop_t prop = ZPROP_INVAL; 3570a48a24eStimh zfs_prop_t fprop; 358990b4856Slling nvlist_t *proplist; 3590a48a24eStimh const char *normnm; 3600a48a24eStimh char *strval; 361990b4856Slling 362990b4856Slling if (*props == NULL && 363990b4856Slling nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) { 364990b4856Slling (void) fprintf(stderr, 365990b4856Slling gettext("internal error: out of memory\n")); 366990b4856Slling return (1); 367990b4856Slling } 368990b4856Slling 369990b4856Slling proplist = *props; 370990b4856Slling 3710a48a24eStimh if (poolprop) { 372990b4856Slling if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) { 373990b4856Slling (void) fprintf(stderr, gettext("property '%s' is " 374990b4856Slling "not a valid pool property\n"), propname); 375990b4856Slling return (2); 376990b4856Slling } 3770a48a24eStimh normnm = zpool_prop_to_name(prop); 3780a48a24eStimh } else { 37914843421SMatthew Ahrens if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) { 3800a48a24eStimh normnm = zfs_prop_to_name(fprop); 38114843421SMatthew Ahrens } else { 38214843421SMatthew Ahrens normnm = propname; 38314843421SMatthew Ahrens } 3840a48a24eStimh } 385990b4856Slling 3860a48a24eStimh if (nvlist_lookup_string(proplist, normnm, &strval) == 0 && 3870a48a24eStimh prop != ZPOOL_PROP_CACHEFILE) { 388990b4856Slling (void) fprintf(stderr, gettext("property '%s' " 389990b4856Slling "specified multiple times\n"), propname); 390990b4856Slling return (2); 391990b4856Slling } 392990b4856Slling 3930a48a24eStimh if (nvlist_add_string(proplist, normnm, propval) != 0) { 394990b4856Slling (void) fprintf(stderr, gettext("internal " 395990b4856Slling "error: out of memory\n")); 396990b4856Slling return (1); 397990b4856Slling } 398990b4856Slling 399990b4856Slling return (0); 400990b4856Slling } 401990b4856Slling 402990b4856Slling /* 403fa9e4066Sahrens * zpool add [-fn] <pool> <vdev> ... 404fa9e4066Sahrens * 405fa9e4066Sahrens * -f Force addition of devices, even if they appear in use 406fa9e4066Sahrens * -n Do not add the devices, but display the resulting layout if 407fa9e4066Sahrens * they were to be added. 408fa9e4066Sahrens * 409fa9e4066Sahrens * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 410fa9e4066Sahrens * handled by get_vdev_spec(), which constructs the nvlist needed to pass to 411fa9e4066Sahrens * libzfs. 412fa9e4066Sahrens */ 413fa9e4066Sahrens int 414fa9e4066Sahrens zpool_do_add(int argc, char **argv) 415fa9e4066Sahrens { 41699653d4eSeschrock boolean_t force = B_FALSE; 41799653d4eSeschrock boolean_t dryrun = B_FALSE; 418fa9e4066Sahrens int c; 419fa9e4066Sahrens nvlist_t *nvroot; 420fa9e4066Sahrens char *poolname; 421fa9e4066Sahrens int ret; 422fa9e4066Sahrens zpool_handle_t *zhp; 423fa9e4066Sahrens nvlist_t *config; 424fa9e4066Sahrens 425fa9e4066Sahrens /* check options */ 426fa9e4066Sahrens while ((c = getopt(argc, argv, "fn")) != -1) { 427fa9e4066Sahrens switch (c) { 428fa9e4066Sahrens case 'f': 42999653d4eSeschrock force = B_TRUE; 430fa9e4066Sahrens break; 431fa9e4066Sahrens case 'n': 43299653d4eSeschrock dryrun = B_TRUE; 433fa9e4066Sahrens break; 434fa9e4066Sahrens case '?': 435fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 436fa9e4066Sahrens optopt); 43799653d4eSeschrock usage(B_FALSE); 438fa9e4066Sahrens } 439fa9e4066Sahrens } 440fa9e4066Sahrens 441fa9e4066Sahrens argc -= optind; 442fa9e4066Sahrens argv += optind; 443fa9e4066Sahrens 444fa9e4066Sahrens /* get pool name and check number of arguments */ 445fa9e4066Sahrens if (argc < 1) { 446fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 44799653d4eSeschrock usage(B_FALSE); 448fa9e4066Sahrens } 449fa9e4066Sahrens if (argc < 2) { 450fa9e4066Sahrens (void) fprintf(stderr, gettext("missing vdev specification\n")); 45199653d4eSeschrock usage(B_FALSE); 452fa9e4066Sahrens } 453fa9e4066Sahrens 454fa9e4066Sahrens poolname = argv[0]; 455fa9e4066Sahrens 456fa9e4066Sahrens argc--; 457fa9e4066Sahrens argv++; 458fa9e4066Sahrens 45999653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 460fa9e4066Sahrens return (1); 461fa9e4066Sahrens 462088e9d47Seschrock if ((config = zpool_get_config(zhp, NULL)) == NULL) { 463fa9e4066Sahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 464fa9e4066Sahrens poolname); 465fa9e4066Sahrens zpool_close(zhp); 466fa9e4066Sahrens return (1); 467fa9e4066Sahrens } 468fa9e4066Sahrens 469fa9e4066Sahrens /* pass off to get_vdev_spec for processing */ 470705040edSEric Taylor nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun, 471705040edSEric Taylor argc, argv); 472fa9e4066Sahrens if (nvroot == NULL) { 473fa9e4066Sahrens zpool_close(zhp); 474fa9e4066Sahrens return (1); 475fa9e4066Sahrens } 476fa9e4066Sahrens 477fa9e4066Sahrens if (dryrun) { 478fa9e4066Sahrens nvlist_t *poolnvroot; 479fa9e4066Sahrens 480fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 481fa9e4066Sahrens &poolnvroot) == 0); 482fa9e4066Sahrens 483fa9e4066Sahrens (void) printf(gettext("would update '%s' to the following " 484fa9e4066Sahrens "configuration:\n"), zpool_get_name(zhp)); 485fa9e4066Sahrens 4868654d025Sperrin /* print original main pool and new tree */ 4878654d025Sperrin print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE); 4888654d025Sperrin print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE); 4898654d025Sperrin 4908654d025Sperrin /* Do the same for the logs */ 4918654d025Sperrin if (num_logs(poolnvroot) > 0) { 4928654d025Sperrin print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE); 4938654d025Sperrin print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE); 4948654d025Sperrin } else if (num_logs(nvroot) > 0) { 4958654d025Sperrin print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE); 4968654d025Sperrin } 497fa9e4066Sahrens 498fa9e4066Sahrens ret = 0; 499fa9e4066Sahrens } else { 500fa9e4066Sahrens ret = (zpool_add(zhp, nvroot) != 0); 501fa9e4066Sahrens } 502fa9e4066Sahrens 50399653d4eSeschrock nvlist_free(nvroot); 50499653d4eSeschrock zpool_close(zhp); 50599653d4eSeschrock 50699653d4eSeschrock return (ret); 50799653d4eSeschrock } 50899653d4eSeschrock 50999653d4eSeschrock /* 510fa94a07fSbrendan * zpool remove <pool> <vdev> ... 51199653d4eSeschrock * 51299653d4eSeschrock * Removes the given vdev from the pool. Currently, this only supports removing 513fa94a07fSbrendan * spares and cache devices from the pool. Eventually, we'll want to support 514fa94a07fSbrendan * removing leaf vdevs (as an alias for 'detach') as well as toplevel vdevs. 51599653d4eSeschrock */ 51699653d4eSeschrock int 51799653d4eSeschrock zpool_do_remove(int argc, char **argv) 51899653d4eSeschrock { 51999653d4eSeschrock char *poolname; 520fa94a07fSbrendan int i, ret = 0; 52199653d4eSeschrock zpool_handle_t *zhp; 52299653d4eSeschrock 52399653d4eSeschrock argc--; 52499653d4eSeschrock argv++; 52599653d4eSeschrock 52699653d4eSeschrock /* get pool name and check number of arguments */ 52799653d4eSeschrock if (argc < 1) { 52899653d4eSeschrock (void) fprintf(stderr, gettext("missing pool name argument\n")); 52999653d4eSeschrock usage(B_FALSE); 53099653d4eSeschrock } 53199653d4eSeschrock if (argc < 2) { 53299653d4eSeschrock (void) fprintf(stderr, gettext("missing device\n")); 53399653d4eSeschrock usage(B_FALSE); 53499653d4eSeschrock } 53599653d4eSeschrock 53699653d4eSeschrock poolname = argv[0]; 53799653d4eSeschrock 53899653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 53999653d4eSeschrock return (1); 54099653d4eSeschrock 541fa94a07fSbrendan for (i = 1; i < argc; i++) { 542fa94a07fSbrendan if (zpool_vdev_remove(zhp, argv[i]) != 0) 543fa94a07fSbrendan ret = 1; 544fa94a07fSbrendan } 54599653d4eSeschrock 546fa9e4066Sahrens return (ret); 547fa9e4066Sahrens } 548fa9e4066Sahrens 549fa9e4066Sahrens /* 5500a48a24eStimh * zpool create [-fn] [-o property=value] ... 5510a48a24eStimh * [-O file-system-property=value] ... 5520a48a24eStimh * [-R root] [-m mountpoint] <pool> <dev> ... 553fa9e4066Sahrens * 554fa9e4066Sahrens * -f Force creation, even if devices appear in use 555fa9e4066Sahrens * -n Do not create the pool, but display the resulting layout if it 556fa9e4066Sahrens * were to be created. 557fa9e4066Sahrens * -R Create a pool under an alternate root 558fa9e4066Sahrens * -m Set default mountpoint for the root dataset. By default it's 559fa9e4066Sahrens * '/<pool>' 560990b4856Slling * -o Set property=value. 5610a48a24eStimh * -O Set fsproperty=value in the pool's root file system 562fa9e4066Sahrens * 563b1b8ab34Slling * Creates the named pool according to the given vdev specification. The 564fa9e4066Sahrens * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once 565fa9e4066Sahrens * we get the nvlist back from get_vdev_spec(), we either print out the contents 566fa9e4066Sahrens * (if '-n' was specified), or pass it to libzfs to do the creation. 567fa9e4066Sahrens */ 568fa9e4066Sahrens int 569fa9e4066Sahrens zpool_do_create(int argc, char **argv) 570fa9e4066Sahrens { 57199653d4eSeschrock boolean_t force = B_FALSE; 57299653d4eSeschrock boolean_t dryrun = B_FALSE; 573fa9e4066Sahrens int c; 574990b4856Slling nvlist_t *nvroot = NULL; 575fa9e4066Sahrens char *poolname; 576990b4856Slling int ret = 1; 577fa9e4066Sahrens char *altroot = NULL; 578fa9e4066Sahrens char *mountpoint = NULL; 5790a48a24eStimh nvlist_t *fsprops = NULL; 580990b4856Slling nvlist_t *props = NULL; 5812f8aaab3Seschrock char *propval; 582fa9e4066Sahrens 583fa9e4066Sahrens /* check options */ 5840a48a24eStimh while ((c = getopt(argc, argv, ":fnR:m:o:O:")) != -1) { 585fa9e4066Sahrens switch (c) { 586fa9e4066Sahrens case 'f': 58799653d4eSeschrock force = B_TRUE; 588fa9e4066Sahrens break; 589fa9e4066Sahrens case 'n': 59099653d4eSeschrock dryrun = B_TRUE; 591fa9e4066Sahrens break; 592fa9e4066Sahrens case 'R': 593fa9e4066Sahrens altroot = optarg; 594990b4856Slling if (add_prop_list(zpool_prop_to_name( 5950a48a24eStimh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 596990b4856Slling goto errout; 5972f8aaab3Seschrock if (nvlist_lookup_string(props, 5982f8aaab3Seschrock zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 5992f8aaab3Seschrock &propval) == 0) 6002f8aaab3Seschrock break; 601990b4856Slling if (add_prop_list(zpool_prop_to_name( 6020a48a24eStimh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 603990b4856Slling goto errout; 604fa9e4066Sahrens break; 605fa9e4066Sahrens case 'm': 606fa9e4066Sahrens mountpoint = optarg; 607fa9e4066Sahrens break; 608990b4856Slling case 'o': 609990b4856Slling if ((propval = strchr(optarg, '=')) == NULL) { 610990b4856Slling (void) fprintf(stderr, gettext("missing " 611990b4856Slling "'=' for -o option\n")); 612990b4856Slling goto errout; 613990b4856Slling } 614990b4856Slling *propval = '\0'; 615990b4856Slling propval++; 616990b4856Slling 6170a48a24eStimh if (add_prop_list(optarg, propval, &props, B_TRUE)) 6180a48a24eStimh goto errout; 6190a48a24eStimh break; 6200a48a24eStimh case 'O': 6210a48a24eStimh if ((propval = strchr(optarg, '=')) == NULL) { 6220a48a24eStimh (void) fprintf(stderr, gettext("missing " 6230a48a24eStimh "'=' for -O option\n")); 6240a48a24eStimh goto errout; 6250a48a24eStimh } 6260a48a24eStimh *propval = '\0'; 6270a48a24eStimh propval++; 6280a48a24eStimh 6290a48a24eStimh if (add_prop_list(optarg, propval, &fsprops, B_FALSE)) 630990b4856Slling goto errout; 631990b4856Slling break; 632fa9e4066Sahrens case ':': 633fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 634fa9e4066Sahrens "'%c' option\n"), optopt); 635990b4856Slling goto badusage; 636fa9e4066Sahrens case '?': 637fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 638fa9e4066Sahrens optopt); 639990b4856Slling goto badusage; 640fa9e4066Sahrens } 641fa9e4066Sahrens } 642fa9e4066Sahrens 643fa9e4066Sahrens argc -= optind; 644fa9e4066Sahrens argv += optind; 645fa9e4066Sahrens 646fa9e4066Sahrens /* get pool name and check number of arguments */ 647fa9e4066Sahrens if (argc < 1) { 648fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 649990b4856Slling goto badusage; 650fa9e4066Sahrens } 651fa9e4066Sahrens if (argc < 2) { 652fa9e4066Sahrens (void) fprintf(stderr, gettext("missing vdev specification\n")); 653990b4856Slling goto badusage; 654fa9e4066Sahrens } 655fa9e4066Sahrens 656fa9e4066Sahrens poolname = argv[0]; 657fa9e4066Sahrens 658fa9e4066Sahrens /* 659fa9e4066Sahrens * As a special case, check for use of '/' in the name, and direct the 660fa9e4066Sahrens * user to use 'zfs create' instead. 661fa9e4066Sahrens */ 662fa9e4066Sahrens if (strchr(poolname, '/') != NULL) { 663fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot create '%s': invalid " 664fa9e4066Sahrens "character '/' in pool name\n"), poolname); 665fa9e4066Sahrens (void) fprintf(stderr, gettext("use 'zfs create' to " 666fa9e4066Sahrens "create a dataset\n")); 667990b4856Slling goto errout; 668fa9e4066Sahrens } 669fa9e4066Sahrens 670fa9e4066Sahrens /* pass off to get_vdev_spec for bulk processing */ 671705040edSEric Taylor nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun, 672705040edSEric Taylor argc - 1, argv + 1); 673fa9e4066Sahrens if (nvroot == NULL) 6740a48a24eStimh goto errout; 675fa9e4066Sahrens 67699653d4eSeschrock /* make_root_vdev() allows 0 toplevel children if there are spares */ 677b7b97454Sperrin if (!zfs_allocatable_devs(nvroot)) { 67899653d4eSeschrock (void) fprintf(stderr, gettext("invalid vdev " 67999653d4eSeschrock "specification: at least one toplevel vdev must be " 68099653d4eSeschrock "specified\n")); 681990b4856Slling goto errout; 68299653d4eSeschrock } 68399653d4eSeschrock 68499653d4eSeschrock 685fa9e4066Sahrens if (altroot != NULL && altroot[0] != '/') { 686fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid alternate root '%s': " 687e9dbad6fSeschrock "must be an absolute path\n"), altroot); 688990b4856Slling goto errout; 689fa9e4066Sahrens } 690fa9e4066Sahrens 691fa9e4066Sahrens /* 692fa9e4066Sahrens * Check the validity of the mountpoint and direct the user to use the 693fa9e4066Sahrens * '-m' mountpoint option if it looks like its in use. 694fa9e4066Sahrens */ 695fa9e4066Sahrens if (mountpoint == NULL || 696fa9e4066Sahrens (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 697fa9e4066Sahrens strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) { 698fa9e4066Sahrens char buf[MAXPATHLEN]; 69911022c7cStimh DIR *dirp; 700fa9e4066Sahrens 701fa9e4066Sahrens if (mountpoint && mountpoint[0] != '/') { 702fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid mountpoint " 703fa9e4066Sahrens "'%s': must be an absolute path, 'legacy', or " 704fa9e4066Sahrens "'none'\n"), mountpoint); 705990b4856Slling goto errout; 706fa9e4066Sahrens } 707fa9e4066Sahrens 708fa9e4066Sahrens if (mountpoint == NULL) { 709fa9e4066Sahrens if (altroot != NULL) 710fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s/%s", 711fa9e4066Sahrens altroot, poolname); 712fa9e4066Sahrens else 713fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "/%s", 714fa9e4066Sahrens poolname); 715fa9e4066Sahrens } else { 716fa9e4066Sahrens if (altroot != NULL) 717fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s%s", 718fa9e4066Sahrens altroot, mountpoint); 719fa9e4066Sahrens else 720fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s", 721fa9e4066Sahrens mountpoint); 722fa9e4066Sahrens } 723fa9e4066Sahrens 72411022c7cStimh if ((dirp = opendir(buf)) == NULL && errno != ENOENT) { 72511022c7cStimh (void) fprintf(stderr, gettext("mountpoint '%s' : " 72611022c7cStimh "%s\n"), buf, strerror(errno)); 727fa9e4066Sahrens (void) fprintf(stderr, gettext("use '-m' " 728fa9e4066Sahrens "option to provide a different default\n")); 729990b4856Slling goto errout; 73011022c7cStimh } else if (dirp) { 73111022c7cStimh int count = 0; 73211022c7cStimh 73311022c7cStimh while (count < 3 && readdir(dirp) != NULL) 73411022c7cStimh count++; 73511022c7cStimh (void) closedir(dirp); 73611022c7cStimh 73711022c7cStimh if (count > 2) { 73811022c7cStimh (void) fprintf(stderr, gettext("mountpoint " 73911022c7cStimh "'%s' exists and is not empty\n"), buf); 74011022c7cStimh (void) fprintf(stderr, gettext("use '-m' " 74111022c7cStimh "option to provide a " 74211022c7cStimh "different default\n")); 74311022c7cStimh goto errout; 74411022c7cStimh } 745fa9e4066Sahrens } 746fa9e4066Sahrens } 747fa9e4066Sahrens 748fa9e4066Sahrens if (dryrun) { 749fa9e4066Sahrens /* 750fa9e4066Sahrens * For a dry run invocation, print out a basic message and run 751fa9e4066Sahrens * through all the vdevs in the list and print out in an 752fa9e4066Sahrens * appropriate hierarchy. 753fa9e4066Sahrens */ 754fa9e4066Sahrens (void) printf(gettext("would create '%s' with the " 755fa9e4066Sahrens "following layout:\n\n"), poolname); 756fa9e4066Sahrens 7578654d025Sperrin print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE); 7588654d025Sperrin if (num_logs(nvroot) > 0) 7598654d025Sperrin print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE); 760fa9e4066Sahrens 761fa9e4066Sahrens ret = 0; 762fa9e4066Sahrens } else { 763fa9e4066Sahrens /* 764fa9e4066Sahrens * Hand off to libzfs. 765fa9e4066Sahrens */ 7660a48a24eStimh if (zpool_create(g_zfs, poolname, 7670a48a24eStimh nvroot, props, fsprops) == 0) { 76899653d4eSeschrock zfs_handle_t *pool = zfs_open(g_zfs, poolname, 769fa9e4066Sahrens ZFS_TYPE_FILESYSTEM); 770fa9e4066Sahrens if (pool != NULL) { 771fa9e4066Sahrens if (mountpoint != NULL) 772fa9e4066Sahrens verify(zfs_prop_set(pool, 773e9dbad6fSeschrock zfs_prop_to_name( 774e9dbad6fSeschrock ZFS_PROP_MOUNTPOINT), 775fa9e4066Sahrens mountpoint) == 0); 776fa9e4066Sahrens if (zfs_mount(pool, NULL, 0) == 0) 777da6c28aaSamw ret = zfs_shareall(pool); 778fa9e4066Sahrens zfs_close(pool); 779fa9e4066Sahrens } 78099653d4eSeschrock } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { 78199653d4eSeschrock (void) fprintf(stderr, gettext("pool name may have " 78299653d4eSeschrock "been omitted\n")); 783fa9e4066Sahrens } 784fa9e4066Sahrens } 785fa9e4066Sahrens 786990b4856Slling errout: 787fa9e4066Sahrens nvlist_free(nvroot); 7880a48a24eStimh nvlist_free(fsprops); 789990b4856Slling nvlist_free(props); 790fa9e4066Sahrens return (ret); 791990b4856Slling badusage: 7920a48a24eStimh nvlist_free(fsprops); 793990b4856Slling nvlist_free(props); 794990b4856Slling usage(B_FALSE); 795990b4856Slling return (2); 796fa9e4066Sahrens } 797fa9e4066Sahrens 798fa9e4066Sahrens /* 799fa9e4066Sahrens * zpool destroy <pool> 800fa9e4066Sahrens * 801fa9e4066Sahrens * -f Forcefully unmount any datasets 802fa9e4066Sahrens * 803fa9e4066Sahrens * Destroy the given pool. Automatically unmounts any datasets in the pool. 804fa9e4066Sahrens */ 805fa9e4066Sahrens int 806fa9e4066Sahrens zpool_do_destroy(int argc, char **argv) 807fa9e4066Sahrens { 80899653d4eSeschrock boolean_t force = B_FALSE; 809fa9e4066Sahrens int c; 810fa9e4066Sahrens char *pool; 811fa9e4066Sahrens zpool_handle_t *zhp; 812fa9e4066Sahrens int ret; 813fa9e4066Sahrens 814fa9e4066Sahrens /* check options */ 815fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) { 816fa9e4066Sahrens switch (c) { 817fa9e4066Sahrens case 'f': 81899653d4eSeschrock force = B_TRUE; 819fa9e4066Sahrens break; 820fa9e4066Sahrens case '?': 821fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 822fa9e4066Sahrens optopt); 82399653d4eSeschrock usage(B_FALSE); 824fa9e4066Sahrens } 825fa9e4066Sahrens } 826fa9e4066Sahrens 827fa9e4066Sahrens argc -= optind; 828fa9e4066Sahrens argv += optind; 829fa9e4066Sahrens 830fa9e4066Sahrens /* check arguments */ 831fa9e4066Sahrens if (argc < 1) { 832fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool argument\n")); 83399653d4eSeschrock usage(B_FALSE); 834fa9e4066Sahrens } 835fa9e4066Sahrens if (argc > 1) { 836fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 83799653d4eSeschrock usage(B_FALSE); 838fa9e4066Sahrens } 839fa9e4066Sahrens 840fa9e4066Sahrens pool = argv[0]; 841fa9e4066Sahrens 84299653d4eSeschrock if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 843fa9e4066Sahrens /* 844fa9e4066Sahrens * As a special case, check for use of '/' in the name, and 845fa9e4066Sahrens * direct the user to use 'zfs destroy' instead. 846fa9e4066Sahrens */ 847fa9e4066Sahrens if (strchr(pool, '/') != NULL) 848fa9e4066Sahrens (void) fprintf(stderr, gettext("use 'zfs destroy' to " 849fa9e4066Sahrens "destroy a dataset\n")); 850fa9e4066Sahrens return (1); 851fa9e4066Sahrens } 852fa9e4066Sahrens 853f3861e1aSahl if (zpool_disable_datasets(zhp, force) != 0) { 854fa9e4066Sahrens (void) fprintf(stderr, gettext("could not destroy '%s': " 855fa9e4066Sahrens "could not unmount datasets\n"), zpool_get_name(zhp)); 856fa9e4066Sahrens return (1); 857fa9e4066Sahrens } 858fa9e4066Sahrens 859fa9e4066Sahrens ret = (zpool_destroy(zhp) != 0); 860fa9e4066Sahrens 861fa9e4066Sahrens zpool_close(zhp); 862fa9e4066Sahrens 863fa9e4066Sahrens return (ret); 864fa9e4066Sahrens } 865fa9e4066Sahrens 866fa9e4066Sahrens /* 867fa9e4066Sahrens * zpool export [-f] <pool> ... 868fa9e4066Sahrens * 869fa9e4066Sahrens * -f Forcefully unmount datasets 870fa9e4066Sahrens * 871b1b8ab34Slling * Export the given pools. By default, the command will attempt to cleanly 872fa9e4066Sahrens * unmount any active datasets within the pool. If the '-f' flag is specified, 873fa9e4066Sahrens * then the datasets will be forcefully unmounted. 874fa9e4066Sahrens */ 875fa9e4066Sahrens int 876fa9e4066Sahrens zpool_do_export(int argc, char **argv) 877fa9e4066Sahrens { 87899653d4eSeschrock boolean_t force = B_FALSE; 879394ab0cbSGeorge Wilson boolean_t hardforce = B_FALSE; 880fa9e4066Sahrens int c; 881fa9e4066Sahrens zpool_handle_t *zhp; 882fa9e4066Sahrens int ret; 883fa9e4066Sahrens int i; 884fa9e4066Sahrens 885fa9e4066Sahrens /* check options */ 886394ab0cbSGeorge Wilson while ((c = getopt(argc, argv, "fF")) != -1) { 887fa9e4066Sahrens switch (c) { 888fa9e4066Sahrens case 'f': 88999653d4eSeschrock force = B_TRUE; 890fa9e4066Sahrens break; 891394ab0cbSGeorge Wilson case 'F': 892394ab0cbSGeorge Wilson hardforce = B_TRUE; 893394ab0cbSGeorge Wilson break; 894fa9e4066Sahrens case '?': 895fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 896fa9e4066Sahrens optopt); 89799653d4eSeschrock usage(B_FALSE); 898fa9e4066Sahrens } 899fa9e4066Sahrens } 900fa9e4066Sahrens 901fa9e4066Sahrens argc -= optind; 902fa9e4066Sahrens argv += optind; 903fa9e4066Sahrens 904fa9e4066Sahrens /* check arguments */ 905fa9e4066Sahrens if (argc < 1) { 906fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool argument\n")); 90799653d4eSeschrock usage(B_FALSE); 908fa9e4066Sahrens } 909fa9e4066Sahrens 910fa9e4066Sahrens ret = 0; 911fa9e4066Sahrens for (i = 0; i < argc; i++) { 91299653d4eSeschrock if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) { 913fa9e4066Sahrens ret = 1; 914fa9e4066Sahrens continue; 915fa9e4066Sahrens } 916fa9e4066Sahrens 917f3861e1aSahl if (zpool_disable_datasets(zhp, force) != 0) { 918fa9e4066Sahrens ret = 1; 919fa9e4066Sahrens zpool_close(zhp); 920fa9e4066Sahrens continue; 921fa9e4066Sahrens } 922fa9e4066Sahrens 923394ab0cbSGeorge Wilson if (hardforce) { 924394ab0cbSGeorge Wilson if (zpool_export_force(zhp) != 0) 925fa9e4066Sahrens ret = 1; 926394ab0cbSGeorge Wilson } else if (zpool_export(zhp, force) != 0) { 927394ab0cbSGeorge Wilson ret = 1; 928394ab0cbSGeorge Wilson } 929fa9e4066Sahrens 930fa9e4066Sahrens zpool_close(zhp); 931fa9e4066Sahrens } 932fa9e4066Sahrens 933fa9e4066Sahrens return (ret); 934fa9e4066Sahrens } 935fa9e4066Sahrens 936fa9e4066Sahrens /* 937fa9e4066Sahrens * Given a vdev configuration, determine the maximum width needed for the device 938fa9e4066Sahrens * name column. 939fa9e4066Sahrens */ 940fa9e4066Sahrens static int 941c67d9675Seschrock max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max) 942fa9e4066Sahrens { 94399653d4eSeschrock char *name = zpool_vdev_name(g_zfs, zhp, nv); 944fa9e4066Sahrens nvlist_t **child; 945fa9e4066Sahrens uint_t c, children; 946fa9e4066Sahrens int ret; 947fa9e4066Sahrens 948fa9e4066Sahrens if (strlen(name) + depth > max) 949fa9e4066Sahrens max = strlen(name) + depth; 950fa9e4066Sahrens 951afefbcddSeschrock free(name); 952afefbcddSeschrock 95399653d4eSeschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 95499653d4eSeschrock &child, &children) == 0) { 955fa9e4066Sahrens for (c = 0; c < children; c++) 95699653d4eSeschrock if ((ret = max_width(zhp, child[c], depth + 2, 95799653d4eSeschrock max)) > max) 958fa9e4066Sahrens max = ret; 95999653d4eSeschrock } 96099653d4eSeschrock 961fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 962fa94a07fSbrendan &child, &children) == 0) { 963fa94a07fSbrendan for (c = 0; c < children; c++) 964fa94a07fSbrendan if ((ret = max_width(zhp, child[c], depth + 2, 965fa94a07fSbrendan max)) > max) 966fa94a07fSbrendan max = ret; 967fa94a07fSbrendan } 968fa94a07fSbrendan 96999653d4eSeschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 97099653d4eSeschrock &child, &children) == 0) { 97199653d4eSeschrock for (c = 0; c < children; c++) 97299653d4eSeschrock if ((ret = max_width(zhp, child[c], depth + 2, 97399653d4eSeschrock max)) > max) 97499653d4eSeschrock max = ret; 97599653d4eSeschrock } 97699653d4eSeschrock 977fa9e4066Sahrens 978fa9e4066Sahrens return (max); 979fa9e4066Sahrens } 980fa9e4066Sahrens 981e6ca193dSGeorge Wilson typedef struct spare_cbdata { 982e6ca193dSGeorge Wilson uint64_t cb_guid; 983e6ca193dSGeorge Wilson zpool_handle_t *cb_zhp; 984e6ca193dSGeorge Wilson } spare_cbdata_t; 985e6ca193dSGeorge Wilson 986e6ca193dSGeorge Wilson static boolean_t 987e6ca193dSGeorge Wilson find_vdev(nvlist_t *nv, uint64_t search) 988e6ca193dSGeorge Wilson { 989e6ca193dSGeorge Wilson uint64_t guid; 990e6ca193dSGeorge Wilson nvlist_t **child; 991e6ca193dSGeorge Wilson uint_t c, children; 992e6ca193dSGeorge Wilson 993e6ca193dSGeorge Wilson if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 994e6ca193dSGeorge Wilson search == guid) 995e6ca193dSGeorge Wilson return (B_TRUE); 996e6ca193dSGeorge Wilson 997e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 998e6ca193dSGeorge Wilson &child, &children) == 0) { 999e6ca193dSGeorge Wilson for (c = 0; c < children; c++) 1000e6ca193dSGeorge Wilson if (find_vdev(child[c], search)) 1001e6ca193dSGeorge Wilson return (B_TRUE); 1002e6ca193dSGeorge Wilson } 1003e6ca193dSGeorge Wilson 1004e6ca193dSGeorge Wilson return (B_FALSE); 1005e6ca193dSGeorge Wilson } 1006e6ca193dSGeorge Wilson 1007e6ca193dSGeorge Wilson static int 1008e6ca193dSGeorge Wilson find_spare(zpool_handle_t *zhp, void *data) 1009e6ca193dSGeorge Wilson { 1010e6ca193dSGeorge Wilson spare_cbdata_t *cbp = data; 1011e6ca193dSGeorge Wilson nvlist_t *config, *nvroot; 1012e6ca193dSGeorge Wilson 1013e6ca193dSGeorge Wilson config = zpool_get_config(zhp, NULL); 1014e6ca193dSGeorge Wilson verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1015e6ca193dSGeorge Wilson &nvroot) == 0); 1016e6ca193dSGeorge Wilson 1017e6ca193dSGeorge Wilson if (find_vdev(nvroot, cbp->cb_guid)) { 1018e6ca193dSGeorge Wilson cbp->cb_zhp = zhp; 1019e6ca193dSGeorge Wilson return (1); 1020e6ca193dSGeorge Wilson } 1021e6ca193dSGeorge Wilson 1022e6ca193dSGeorge Wilson zpool_close(zhp); 1023e6ca193dSGeorge Wilson return (0); 1024e6ca193dSGeorge Wilson } 1025e6ca193dSGeorge Wilson 1026e6ca193dSGeorge Wilson /* 1027e6ca193dSGeorge Wilson * Print out configuration state as requested by status_callback. 1028e6ca193dSGeorge Wilson */ 1029e6ca193dSGeorge Wilson void 1030e6ca193dSGeorge Wilson print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 1031e6ca193dSGeorge Wilson int namewidth, int depth, boolean_t isspare) 1032e6ca193dSGeorge Wilson { 1033e6ca193dSGeorge Wilson nvlist_t **child; 1034e6ca193dSGeorge Wilson uint_t c, children; 1035e6ca193dSGeorge Wilson vdev_stat_t *vs; 1036e6ca193dSGeorge Wilson char rbuf[6], wbuf[6], cbuf[6], repaired[7]; 1037e6ca193dSGeorge Wilson char *vname; 1038e6ca193dSGeorge Wilson uint64_t notpresent; 1039e6ca193dSGeorge Wilson spare_cbdata_t cb; 1040e6ca193dSGeorge Wilson char *state; 1041e6ca193dSGeorge Wilson 1042e6ca193dSGeorge Wilson verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 1043e6ca193dSGeorge Wilson (uint64_t **)&vs, &c) == 0); 1044e6ca193dSGeorge Wilson 1045e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1046e6ca193dSGeorge Wilson &child, &children) != 0) 1047e6ca193dSGeorge Wilson children = 0; 1048e6ca193dSGeorge Wilson 1049e6ca193dSGeorge Wilson state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1050e6ca193dSGeorge Wilson if (isspare) { 1051e6ca193dSGeorge Wilson /* 1052e6ca193dSGeorge Wilson * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 1053e6ca193dSGeorge Wilson * online drives. 1054e6ca193dSGeorge Wilson */ 1055e6ca193dSGeorge Wilson if (vs->vs_aux == VDEV_AUX_SPARED) 1056e6ca193dSGeorge Wilson state = "INUSE"; 1057e6ca193dSGeorge Wilson else if (vs->vs_state == VDEV_STATE_HEALTHY) 1058e6ca193dSGeorge Wilson state = "AVAIL"; 1059e6ca193dSGeorge Wilson } 1060e6ca193dSGeorge Wilson 1061e6ca193dSGeorge Wilson (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, 1062e6ca193dSGeorge Wilson name, state); 1063e6ca193dSGeorge Wilson 1064e6ca193dSGeorge Wilson if (!isspare) { 1065e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 1066e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 1067e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 1068e6ca193dSGeorge Wilson (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 1069e6ca193dSGeorge Wilson } 1070e6ca193dSGeorge Wilson 1071e6ca193dSGeorge Wilson if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1072e6ca193dSGeorge Wilson ¬present) == 0) { 1073e6ca193dSGeorge Wilson char *path; 1074e6ca193dSGeorge Wilson verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 1075e6ca193dSGeorge Wilson (void) printf(" was %s", path); 1076e6ca193dSGeorge Wilson } else if (vs->vs_aux != 0) { 1077e6ca193dSGeorge Wilson (void) printf(" "); 1078e6ca193dSGeorge Wilson 1079e6ca193dSGeorge Wilson switch (vs->vs_aux) { 1080e6ca193dSGeorge Wilson case VDEV_AUX_OPEN_FAILED: 1081e6ca193dSGeorge Wilson (void) printf(gettext("cannot open")); 1082e6ca193dSGeorge Wilson break; 1083e6ca193dSGeorge Wilson 1084e6ca193dSGeorge Wilson case VDEV_AUX_BAD_GUID_SUM: 1085e6ca193dSGeorge Wilson (void) printf(gettext("missing device")); 1086e6ca193dSGeorge Wilson break; 1087e6ca193dSGeorge Wilson 1088e6ca193dSGeorge Wilson case VDEV_AUX_NO_REPLICAS: 1089e6ca193dSGeorge Wilson (void) printf(gettext("insufficient replicas")); 1090e6ca193dSGeorge Wilson break; 1091e6ca193dSGeorge Wilson 1092e6ca193dSGeorge Wilson case VDEV_AUX_VERSION_NEWER: 1093e6ca193dSGeorge Wilson (void) printf(gettext("newer version")); 1094e6ca193dSGeorge Wilson break; 1095e6ca193dSGeorge Wilson 1096e6ca193dSGeorge Wilson case VDEV_AUX_SPARED: 1097e6ca193dSGeorge Wilson verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 1098e6ca193dSGeorge Wilson &cb.cb_guid) == 0); 1099e6ca193dSGeorge Wilson if (zpool_iter(g_zfs, find_spare, &cb) == 1) { 1100e6ca193dSGeorge Wilson if (strcmp(zpool_get_name(cb.cb_zhp), 1101e6ca193dSGeorge Wilson zpool_get_name(zhp)) == 0) 1102e6ca193dSGeorge Wilson (void) printf(gettext("currently in " 1103e6ca193dSGeorge Wilson "use")); 1104e6ca193dSGeorge Wilson else 1105e6ca193dSGeorge Wilson (void) printf(gettext("in use by " 1106e6ca193dSGeorge Wilson "pool '%s'"), 1107e6ca193dSGeorge Wilson zpool_get_name(cb.cb_zhp)); 1108e6ca193dSGeorge Wilson zpool_close(cb.cb_zhp); 1109e6ca193dSGeorge Wilson } else { 1110e6ca193dSGeorge Wilson (void) printf(gettext("currently in use")); 1111e6ca193dSGeorge Wilson } 1112e6ca193dSGeorge Wilson break; 1113e6ca193dSGeorge Wilson 1114e6ca193dSGeorge Wilson case VDEV_AUX_ERR_EXCEEDED: 1115e6ca193dSGeorge Wilson (void) printf(gettext("too many errors")); 1116e6ca193dSGeorge Wilson break; 1117e6ca193dSGeorge Wilson 1118e6ca193dSGeorge Wilson case VDEV_AUX_IO_FAILURE: 1119e6ca193dSGeorge Wilson (void) printf(gettext("experienced I/O failures")); 1120e6ca193dSGeorge Wilson break; 1121e6ca193dSGeorge Wilson 1122e6ca193dSGeorge Wilson case VDEV_AUX_BAD_LOG: 1123e6ca193dSGeorge Wilson (void) printf(gettext("bad intent log")); 1124e6ca193dSGeorge Wilson break; 1125e6ca193dSGeorge Wilson 1126e6ca193dSGeorge Wilson default: 1127e6ca193dSGeorge Wilson (void) printf(gettext("corrupted data")); 1128e6ca193dSGeorge Wilson break; 1129e6ca193dSGeorge Wilson } 1130e6ca193dSGeorge Wilson } else if (vs->vs_scrub_repaired != 0 && children == 0) { 1131e6ca193dSGeorge Wilson /* 1132e6ca193dSGeorge Wilson * Report bytes resilvered/repaired on leaf devices. 1133e6ca193dSGeorge Wilson */ 1134e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_scrub_repaired, repaired, sizeof (repaired)); 1135e6ca193dSGeorge Wilson (void) printf(gettext(" %s %s"), repaired, 1136e6ca193dSGeorge Wilson (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 1137e6ca193dSGeorge Wilson "resilvered" : "repaired"); 1138e6ca193dSGeorge Wilson } 1139e6ca193dSGeorge Wilson 1140e6ca193dSGeorge Wilson (void) printf("\n"); 1141e6ca193dSGeorge Wilson 1142e6ca193dSGeorge Wilson for (c = 0; c < children; c++) { 1143e6ca193dSGeorge Wilson uint64_t is_log = B_FALSE; 1144e6ca193dSGeorge Wilson 1145e6ca193dSGeorge Wilson /* Don't print logs here */ 1146e6ca193dSGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1147e6ca193dSGeorge Wilson &is_log); 1148e6ca193dSGeorge Wilson if (is_log) 1149e6ca193dSGeorge Wilson continue; 1150e6ca193dSGeorge Wilson vname = zpool_vdev_name(g_zfs, zhp, child[c]); 1151e6ca193dSGeorge Wilson print_status_config(zhp, vname, child[c], 1152e6ca193dSGeorge Wilson namewidth, depth + 2, isspare); 1153e6ca193dSGeorge Wilson free(vname); 1154e6ca193dSGeorge Wilson } 1155e6ca193dSGeorge Wilson } 1156e6ca193dSGeorge Wilson 1157fa9e4066Sahrens 1158fa9e4066Sahrens /* 1159fa9e4066Sahrens * Print the configuration of an exported pool. Iterate over all vdevs in the 1160fa9e4066Sahrens * pool, printing out the name and status for each one. 1161fa9e4066Sahrens */ 1162fa9e4066Sahrens void 1163e6ca193dSGeorge Wilson print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) 1164fa9e4066Sahrens { 1165fa9e4066Sahrens nvlist_t **child; 1166fa9e4066Sahrens uint_t c, children; 1167fa9e4066Sahrens vdev_stat_t *vs; 1168afefbcddSeschrock char *type, *vname; 1169fa9e4066Sahrens 1170fa9e4066Sahrens verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 1171fa9e4066Sahrens if (strcmp(type, VDEV_TYPE_MISSING) == 0) 1172fa9e4066Sahrens return; 1173fa9e4066Sahrens 1174fa9e4066Sahrens verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, 1175fa9e4066Sahrens (uint64_t **)&vs, &c) == 0); 1176fa9e4066Sahrens 1177fa9e4066Sahrens (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name); 1178990b4856Slling (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); 1179fa9e4066Sahrens 1180fa9e4066Sahrens if (vs->vs_aux != 0) { 11813d7072f8Seschrock (void) printf(" "); 1182fa9e4066Sahrens 1183fa9e4066Sahrens switch (vs->vs_aux) { 1184fa9e4066Sahrens case VDEV_AUX_OPEN_FAILED: 1185fa9e4066Sahrens (void) printf(gettext("cannot open")); 1186fa9e4066Sahrens break; 1187fa9e4066Sahrens 1188fa9e4066Sahrens case VDEV_AUX_BAD_GUID_SUM: 1189fa9e4066Sahrens (void) printf(gettext("missing device")); 1190fa9e4066Sahrens break; 1191fa9e4066Sahrens 1192fa9e4066Sahrens case VDEV_AUX_NO_REPLICAS: 1193fa9e4066Sahrens (void) printf(gettext("insufficient replicas")); 1194fa9e4066Sahrens break; 1195fa9e4066Sahrens 1196eaca9bbdSeschrock case VDEV_AUX_VERSION_NEWER: 1197eaca9bbdSeschrock (void) printf(gettext("newer version")); 1198eaca9bbdSeschrock break; 1199eaca9bbdSeschrock 12003d7072f8Seschrock case VDEV_AUX_ERR_EXCEEDED: 12013d7072f8Seschrock (void) printf(gettext("too many errors")); 12023d7072f8Seschrock break; 12033d7072f8Seschrock 1204fa9e4066Sahrens default: 1205fa9e4066Sahrens (void) printf(gettext("corrupted data")); 1206fa9e4066Sahrens break; 1207fa9e4066Sahrens } 1208fa9e4066Sahrens } 1209fa9e4066Sahrens (void) printf("\n"); 1210fa9e4066Sahrens 1211fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1212fa9e4066Sahrens &child, &children) != 0) 1213fa9e4066Sahrens return; 1214fa9e4066Sahrens 1215afefbcddSeschrock for (c = 0; c < children; c++) { 12168654d025Sperrin uint64_t is_log = B_FALSE; 12178654d025Sperrin 12188654d025Sperrin (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 12198654d025Sperrin &is_log); 1220e6ca193dSGeorge Wilson if (is_log) 12218654d025Sperrin continue; 12228654d025Sperrin 122399653d4eSeschrock vname = zpool_vdev_name(g_zfs, NULL, child[c]); 1224e6ca193dSGeorge Wilson print_import_config(vname, child[c], namewidth, depth + 2); 1225afefbcddSeschrock free(vname); 1226afefbcddSeschrock } 122799653d4eSeschrock 1228fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1229fa94a07fSbrendan &child, &children) == 0) { 1230fa94a07fSbrendan (void) printf(gettext("\tcache\n")); 1231fa94a07fSbrendan for (c = 0; c < children; c++) { 1232fa94a07fSbrendan vname = zpool_vdev_name(g_zfs, NULL, child[c]); 1233fa94a07fSbrendan (void) printf("\t %s\n", vname); 1234fa94a07fSbrendan free(vname); 1235fa94a07fSbrendan } 1236fa94a07fSbrendan } 123799653d4eSeschrock 1238fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1239fa94a07fSbrendan &child, &children) == 0) { 124099653d4eSeschrock (void) printf(gettext("\tspares\n")); 124199653d4eSeschrock for (c = 0; c < children; c++) { 124299653d4eSeschrock vname = zpool_vdev_name(g_zfs, NULL, child[c]); 124399653d4eSeschrock (void) printf("\t %s\n", vname); 124499653d4eSeschrock free(vname); 124599653d4eSeschrock } 1246fa9e4066Sahrens } 1247fa94a07fSbrendan } 1248fa9e4066Sahrens 1249fa9e4066Sahrens /* 1250e6ca193dSGeorge Wilson * Print log vdevs. 1251e6ca193dSGeorge Wilson * Logs are recorded as top level vdevs in the main pool child array 1252e6ca193dSGeorge Wilson * but with "is_log" set to 1. We use either print_status_config() or 1253e6ca193dSGeorge Wilson * print_import_config() to print the top level logs then any log 1254e6ca193dSGeorge Wilson * children (eg mirrored slogs) are printed recursively - which 1255e6ca193dSGeorge Wilson * works because only the top level vdev is marked "is_log" 1256e6ca193dSGeorge Wilson */ 1257e6ca193dSGeorge Wilson static void 1258e6ca193dSGeorge Wilson print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose) 1259e6ca193dSGeorge Wilson { 1260e6ca193dSGeorge Wilson uint_t c, children; 1261e6ca193dSGeorge Wilson nvlist_t **child; 1262e6ca193dSGeorge Wilson 1263e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, 1264e6ca193dSGeorge Wilson &children) != 0) 1265e6ca193dSGeorge Wilson return; 1266e6ca193dSGeorge Wilson 1267e6ca193dSGeorge Wilson (void) printf(gettext("\tlogs\n")); 1268e6ca193dSGeorge Wilson 1269e6ca193dSGeorge Wilson for (c = 0; c < children; c++) { 1270e6ca193dSGeorge Wilson uint64_t is_log = B_FALSE; 1271e6ca193dSGeorge Wilson char *name; 1272e6ca193dSGeorge Wilson 1273e6ca193dSGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1274e6ca193dSGeorge Wilson &is_log); 1275e6ca193dSGeorge Wilson if (!is_log) 1276e6ca193dSGeorge Wilson continue; 1277e6ca193dSGeorge Wilson name = zpool_vdev_name(g_zfs, zhp, child[c]); 1278e6ca193dSGeorge Wilson if (verbose) 1279e6ca193dSGeorge Wilson print_status_config(zhp, name, child[c], namewidth, 1280e6ca193dSGeorge Wilson 2, B_FALSE); 1281e6ca193dSGeorge Wilson else 1282e6ca193dSGeorge Wilson print_import_config(name, child[c], namewidth, 2); 1283e6ca193dSGeorge Wilson free(name); 1284e6ca193dSGeorge Wilson } 1285e6ca193dSGeorge Wilson } 1286e6ca193dSGeorge Wilson /* 1287fa9e4066Sahrens * Display the status for the given pool. 1288fa9e4066Sahrens */ 1289fa9e4066Sahrens static void 1290fa9e4066Sahrens show_import(nvlist_t *config) 1291fa9e4066Sahrens { 1292fa9e4066Sahrens uint64_t pool_state; 1293fa9e4066Sahrens vdev_stat_t *vs; 1294fa9e4066Sahrens char *name; 1295fa9e4066Sahrens uint64_t guid; 1296fa9e4066Sahrens char *msgid; 1297fa9e4066Sahrens nvlist_t *nvroot; 1298fa9e4066Sahrens int reason; 129946657f8dSmmusante const char *health; 1300fa9e4066Sahrens uint_t vsc; 1301fa9e4066Sahrens int namewidth; 1302fa9e4066Sahrens 1303fa9e4066Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1304fa9e4066Sahrens &name) == 0); 1305fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 1306fa9e4066Sahrens &guid) == 0); 1307fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 1308fa9e4066Sahrens &pool_state) == 0); 1309fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1310fa9e4066Sahrens &nvroot) == 0); 1311fa9e4066Sahrens 1312fa9e4066Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 1313fa9e4066Sahrens (uint64_t **)&vs, &vsc) == 0); 1314990b4856Slling health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1315fa9e4066Sahrens 1316fa9e4066Sahrens reason = zpool_import_status(config, &msgid); 1317fa9e4066Sahrens 131846657f8dSmmusante (void) printf(gettext(" pool: %s\n"), name); 131946657f8dSmmusante (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); 132046657f8dSmmusante (void) printf(gettext(" state: %s"), health); 13214c58d714Sdarrenm if (pool_state == POOL_STATE_DESTROYED) 132246657f8dSmmusante (void) printf(gettext(" (DESTROYED)")); 13234c58d714Sdarrenm (void) printf("\n"); 1324fa9e4066Sahrens 1325fa9e4066Sahrens switch (reason) { 1326fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_R: 1327fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_NR: 1328fa9e4066Sahrens case ZPOOL_STATUS_BAD_GUID_SUM: 1329fa9e4066Sahrens (void) printf(gettext("status: One or more devices are missing " 1330fa9e4066Sahrens "from the system.\n")); 1331fa9e4066Sahrens break; 1332fa9e4066Sahrens 1333fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_R: 1334fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_NR: 1335fa9e4066Sahrens (void) printf(gettext("status: One or more devices contains " 1336fa9e4066Sahrens "corrupted data.\n")); 1337fa9e4066Sahrens break; 1338fa9e4066Sahrens 1339fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_DATA: 1340fa9e4066Sahrens (void) printf(gettext("status: The pool data is corrupted.\n")); 1341fa9e4066Sahrens break; 1342fa9e4066Sahrens 1343441d80aaSlling case ZPOOL_STATUS_OFFLINE_DEV: 1344441d80aaSlling (void) printf(gettext("status: One or more devices " 1345441d80aaSlling "are offlined.\n")); 1346441d80aaSlling break; 1347441d80aaSlling 1348ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_POOL: 1349ea8dc4b6Seschrock (void) printf(gettext("status: The pool metadata is " 1350ea8dc4b6Seschrock "corrupted.\n")); 1351ea8dc4b6Seschrock break; 1352ea8dc4b6Seschrock 1353eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_OLDER: 1354eaca9bbdSeschrock (void) printf(gettext("status: The pool is formatted using an " 1355eaca9bbdSeschrock "older on-disk version.\n")); 1356eaca9bbdSeschrock break; 1357eaca9bbdSeschrock 1358eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 1359eaca9bbdSeschrock (void) printf(gettext("status: The pool is formatted using an " 1360eaca9bbdSeschrock "incompatible version.\n")); 1361eaca9bbdSeschrock break; 1362b87f3af3Sperrin 136395173954Sek110237 case ZPOOL_STATUS_HOSTID_MISMATCH: 136495173954Sek110237 (void) printf(gettext("status: The pool was last accessed by " 136595173954Sek110237 "another system.\n")); 136695173954Sek110237 break; 1367b87f3af3Sperrin 13683d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_R: 13693d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_NR: 13703d7072f8Seschrock (void) printf(gettext("status: One or more devices are " 13713d7072f8Seschrock "faulted.\n")); 13723d7072f8Seschrock break; 13733d7072f8Seschrock 1374b87f3af3Sperrin case ZPOOL_STATUS_BAD_LOG: 1375b87f3af3Sperrin (void) printf(gettext("status: An intent log record cannot be " 1376b87f3af3Sperrin "read.\n")); 1377b87f3af3Sperrin break; 1378b87f3af3Sperrin 1379fa9e4066Sahrens default: 1380fa9e4066Sahrens /* 1381fa9e4066Sahrens * No other status can be seen when importing pools. 1382fa9e4066Sahrens */ 1383fa9e4066Sahrens assert(reason == ZPOOL_STATUS_OK); 1384fa9e4066Sahrens } 1385fa9e4066Sahrens 1386fa9e4066Sahrens /* 1387fa9e4066Sahrens * Print out an action according to the overall state of the pool. 1388fa9e4066Sahrens */ 138946657f8dSmmusante if (vs->vs_state == VDEV_STATE_HEALTHY) { 1390eaca9bbdSeschrock if (reason == ZPOOL_STATUS_VERSION_OLDER) 1391eaca9bbdSeschrock (void) printf(gettext("action: The pool can be " 1392eaca9bbdSeschrock "imported using its name or numeric identifier, " 1393eaca9bbdSeschrock "though\n\tsome features will not be available " 1394eaca9bbdSeschrock "without an explicit 'zpool upgrade'.\n")); 139595173954Sek110237 else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) 139695173954Sek110237 (void) printf(gettext("action: The pool can be " 139795173954Sek110237 "imported using its name or numeric " 139895173954Sek110237 "identifier and\n\tthe '-f' flag.\n")); 1399fa9e4066Sahrens else 1400eaca9bbdSeschrock (void) printf(gettext("action: The pool can be " 1401eaca9bbdSeschrock "imported using its name or numeric " 1402eaca9bbdSeschrock "identifier.\n")); 140346657f8dSmmusante } else if (vs->vs_state == VDEV_STATE_DEGRADED) { 1404fa9e4066Sahrens (void) printf(gettext("action: The pool can be imported " 1405fa9e4066Sahrens "despite missing or damaged devices. The\n\tfault " 1406eaca9bbdSeschrock "tolerance of the pool may be compromised if imported.\n")); 1407fa9e4066Sahrens } else { 1408eaca9bbdSeschrock switch (reason) { 1409eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 1410eaca9bbdSeschrock (void) printf(gettext("action: The pool cannot be " 1411eaca9bbdSeschrock "imported. Access the pool on a system running " 1412eaca9bbdSeschrock "newer\n\tsoftware, or recreate the pool from " 1413eaca9bbdSeschrock "backup.\n")); 1414eaca9bbdSeschrock break; 1415eaca9bbdSeschrock case ZPOOL_STATUS_MISSING_DEV_R: 1416eaca9bbdSeschrock case ZPOOL_STATUS_MISSING_DEV_NR: 1417eaca9bbdSeschrock case ZPOOL_STATUS_BAD_GUID_SUM: 1418fa9e4066Sahrens (void) printf(gettext("action: The pool cannot be " 1419fa9e4066Sahrens "imported. Attach the missing\n\tdevices and try " 1420fa9e4066Sahrens "again.\n")); 1421eaca9bbdSeschrock break; 1422eaca9bbdSeschrock default: 1423fa9e4066Sahrens (void) printf(gettext("action: The pool cannot be " 1424fa9e4066Sahrens "imported due to damaged devices or data.\n")); 1425fa9e4066Sahrens } 1426eaca9bbdSeschrock } 1427eaca9bbdSeschrock 142846657f8dSmmusante /* 142946657f8dSmmusante * If the state is "closed" or "can't open", and the aux state 143046657f8dSmmusante * is "corrupt data": 143146657f8dSmmusante */ 143246657f8dSmmusante if (((vs->vs_state == VDEV_STATE_CLOSED) || 143346657f8dSmmusante (vs->vs_state == VDEV_STATE_CANT_OPEN)) && 143446657f8dSmmusante (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) { 1435eaca9bbdSeschrock if (pool_state == POOL_STATE_DESTROYED) 1436eaca9bbdSeschrock (void) printf(gettext("\tThe pool was destroyed, " 1437eaca9bbdSeschrock "but can be imported using the '-Df' flags.\n")); 1438eaca9bbdSeschrock else if (pool_state != POOL_STATE_EXPORTED) 1439eaca9bbdSeschrock (void) printf(gettext("\tThe pool may be active on " 144018ce54dfSek110237 "another system, but can be imported using\n\t" 1441eaca9bbdSeschrock "the '-f' flag.\n")); 1442eaca9bbdSeschrock } 1443fa9e4066Sahrens 1444fa9e4066Sahrens if (msgid != NULL) 1445fa9e4066Sahrens (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), 1446fa9e4066Sahrens msgid); 1447fa9e4066Sahrens 1448fa9e4066Sahrens (void) printf(gettext("config:\n\n")); 1449fa9e4066Sahrens 1450c67d9675Seschrock namewidth = max_width(NULL, nvroot, 0, 0); 1451fa9e4066Sahrens if (namewidth < 10) 1452fa9e4066Sahrens namewidth = 10; 14538654d025Sperrin 1454e6ca193dSGeorge Wilson print_import_config(name, nvroot, namewidth, 0); 1455e6ca193dSGeorge Wilson if (num_logs(nvroot) > 0) 1456e6ca193dSGeorge Wilson print_logs(NULL, nvroot, namewidth, B_FALSE); 1457fa9e4066Sahrens 1458fa9e4066Sahrens if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 145946657f8dSmmusante (void) printf(gettext("\n\tAdditional devices are known to " 1460fa9e4066Sahrens "be part of this pool, though their\n\texact " 146146657f8dSmmusante "configuration cannot be determined.\n")); 1462fa9e4066Sahrens } 1463fa9e4066Sahrens } 1464fa9e4066Sahrens 1465fa9e4066Sahrens /* 1466fa9e4066Sahrens * Perform the import for the given configuration. This passes the heavy 1467990b4856Slling * lifting off to zpool_import_props(), and then mounts the datasets contained 1468990b4856Slling * within the pool. 1469fa9e4066Sahrens */ 1470fa9e4066Sahrens static int 1471fa9e4066Sahrens do_import(nvlist_t *config, const char *newname, const char *mntopts, 1472*4f0f5e5bSVictor Latushkin int force, nvlist_t *props, boolean_t do_verbatim) 1473fa9e4066Sahrens { 1474fa9e4066Sahrens zpool_handle_t *zhp; 1475fa9e4066Sahrens char *name; 1476fa9e4066Sahrens uint64_t state; 1477eaca9bbdSeschrock uint64_t version; 1478ecd6cf80Smarks int error = 0; 1479fa9e4066Sahrens 1480fa9e4066Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1481fa9e4066Sahrens &name) == 0); 1482fa9e4066Sahrens 1483fa9e4066Sahrens verify(nvlist_lookup_uint64(config, 1484fa9e4066Sahrens ZPOOL_CONFIG_POOL_STATE, &state) == 0); 1485eaca9bbdSeschrock verify(nvlist_lookup_uint64(config, 1486eaca9bbdSeschrock ZPOOL_CONFIG_VERSION, &version) == 0); 1487e7437265Sahrens if (version > SPA_VERSION) { 1488eaca9bbdSeschrock (void) fprintf(stderr, gettext("cannot import '%s': pool " 1489eaca9bbdSeschrock "is formatted using a newer ZFS version\n"), name); 1490eaca9bbdSeschrock return (1); 1491eaca9bbdSeschrock } else if (state != POOL_STATE_EXPORTED && !force) { 149295173954Sek110237 uint64_t hostid; 149395173954Sek110237 149495173954Sek110237 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, 149595173954Sek110237 &hostid) == 0) { 149695173954Sek110237 if ((unsigned long)hostid != gethostid()) { 149795173954Sek110237 char *hostname; 149895173954Sek110237 uint64_t timestamp; 149995173954Sek110237 time_t t; 150095173954Sek110237 150195173954Sek110237 verify(nvlist_lookup_string(config, 150295173954Sek110237 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0); 150395173954Sek110237 verify(nvlist_lookup_uint64(config, 150495173954Sek110237 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0); 150595173954Sek110237 t = timestamp; 150695173954Sek110237 (void) fprintf(stderr, gettext("cannot import " 150795173954Sek110237 "'%s': pool may be in use from other " 150895173954Sek110237 "system, it was last accessed by %s " 150995173954Sek110237 "(hostid: 0x%lx) on %s"), name, hostname, 151095173954Sek110237 (unsigned long)hostid, 151195173954Sek110237 asctime(localtime(&t))); 151295173954Sek110237 (void) fprintf(stderr, gettext("use '-f' to " 151395173954Sek110237 "import anyway\n")); 1514fa9e4066Sahrens return (1); 1515fa9e4066Sahrens } 151695173954Sek110237 } else { 151795173954Sek110237 (void) fprintf(stderr, gettext("cannot import '%s': " 151895173954Sek110237 "pool may be in use from other system\n"), name); 151995173954Sek110237 (void) fprintf(stderr, gettext("use '-f' to import " 152095173954Sek110237 "anyway\n")); 152195173954Sek110237 return (1); 152295173954Sek110237 } 152395173954Sek110237 } 1524fa9e4066Sahrens 1525*4f0f5e5bSVictor Latushkin if (zpool_import_props(g_zfs, config, newname, props, do_verbatim) != 0) 1526fa9e4066Sahrens return (1); 1527fa9e4066Sahrens 1528fa9e4066Sahrens if (newname != NULL) 1529fa9e4066Sahrens name = (char *)newname; 1530fa9e4066Sahrens 1531*4f0f5e5bSVictor Latushkin if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL) 1532*4f0f5e5bSVictor Latushkin return (1); 1533fa9e4066Sahrens 1534379c004dSEric Schrock if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 1535379c004dSEric Schrock zpool_enable_datasets(zhp, mntopts, 0) != 0) { 1536fa9e4066Sahrens zpool_close(zhp); 1537fa9e4066Sahrens return (1); 1538fa9e4066Sahrens } 1539fa9e4066Sahrens 1540fa9e4066Sahrens zpool_close(zhp); 1541ecd6cf80Smarks return (error); 1542fa9e4066Sahrens } 1543fa9e4066Sahrens 1544fa9e4066Sahrens /* 15454c58d714Sdarrenm * zpool import [-d dir] [-D] 15462f8aaab3Seschrock * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 15472f8aaab3Seschrock * [-d dir | -c cachefile] [-f] -a 15482f8aaab3Seschrock * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 15492f8aaab3Seschrock * [-d dir | -c cachefile] [-f] <pool | id> [newpool] 15502f8aaab3Seschrock * 15512f8aaab3Seschrock * -c Read pool information from a cachefile instead of searching 15522f8aaab3Seschrock * devices. 1553fa9e4066Sahrens * 1554fa9e4066Sahrens * -d Scan in a specific directory, other than /dev/dsk. More than 1555fa9e4066Sahrens * one directory can be specified using multiple '-d' options. 1556fa9e4066Sahrens * 15574c58d714Sdarrenm * -D Scan for previously destroyed pools or import all or only 15584c58d714Sdarrenm * specified destroyed pools. 15594c58d714Sdarrenm * 1560fa9e4066Sahrens * -R Temporarily import the pool, with all mountpoints relative to 1561fa9e4066Sahrens * the given root. The pool will remain exported when the machine 1562fa9e4066Sahrens * is rebooted. 1563fa9e4066Sahrens * 1564fa9e4066Sahrens * -f Force import, even if it appears that the pool is active. 1565fa9e4066Sahrens * 1566c5904d13Seschrock * -F Import even in the presence of faulted vdevs. This is an 1567c5904d13Seschrock * intentionally undocumented option for testing purposes, and 1568c5904d13Seschrock * treats the pool configuration as complete, leaving any bad 1569*4f0f5e5bSVictor Latushkin * vdevs in the FAULTED state. In other words, it does verbatim 1570*4f0f5e5bSVictor Latushkin * import. 1571c5904d13Seschrock * 1572fa9e4066Sahrens * -a Import all pools found. 1573fa9e4066Sahrens * 1574990b4856Slling * -o Set property=value and/or temporary mount options (without '='). 1575ecd6cf80Smarks * 1576fa9e4066Sahrens * The import command scans for pools to import, and import pools based on pool 1577fa9e4066Sahrens * name and GUID. The pool can also be renamed as part of the import process. 1578fa9e4066Sahrens */ 1579fa9e4066Sahrens int 1580fa9e4066Sahrens zpool_do_import(int argc, char **argv) 1581fa9e4066Sahrens { 1582fa9e4066Sahrens char **searchdirs = NULL; 1583fa9e4066Sahrens int nsearch = 0; 1584fa9e4066Sahrens int c; 1585fa9e4066Sahrens int err; 15862f8aaab3Seschrock nvlist_t *pools = NULL; 158799653d4eSeschrock boolean_t do_all = B_FALSE; 158899653d4eSeschrock boolean_t do_destroyed = B_FALSE; 1589fa9e4066Sahrens char *mntopts = NULL; 159099653d4eSeschrock boolean_t do_force = B_FALSE; 1591fa9e4066Sahrens nvpair_t *elem; 1592fa9e4066Sahrens nvlist_t *config; 159324e697d4Sck153898 uint64_t searchguid = 0; 159424e697d4Sck153898 char *searchname = NULL; 1595990b4856Slling char *propval; 1596fa9e4066Sahrens nvlist_t *found_config; 1597ecd6cf80Smarks nvlist_t *props = NULL; 159899653d4eSeschrock boolean_t first; 1599*4f0f5e5bSVictor Latushkin boolean_t do_verbatim = B_FALSE; 16004c58d714Sdarrenm uint64_t pool_state; 16012f8aaab3Seschrock char *cachefile = NULL; 1602fa9e4066Sahrens 1603fa9e4066Sahrens /* check options */ 1604c5904d13Seschrock while ((c = getopt(argc, argv, ":ac:d:DfFo:p:R:")) != -1) { 1605fa9e4066Sahrens switch (c) { 1606fa9e4066Sahrens case 'a': 160799653d4eSeschrock do_all = B_TRUE; 1608fa9e4066Sahrens break; 16092f8aaab3Seschrock case 'c': 16102f8aaab3Seschrock cachefile = optarg; 16112f8aaab3Seschrock break; 1612fa9e4066Sahrens case 'd': 1613fa9e4066Sahrens if (searchdirs == NULL) { 1614fa9e4066Sahrens searchdirs = safe_malloc(sizeof (char *)); 1615fa9e4066Sahrens } else { 1616fa9e4066Sahrens char **tmp = safe_malloc((nsearch + 1) * 1617fa9e4066Sahrens sizeof (char *)); 1618fa9e4066Sahrens bcopy(searchdirs, tmp, nsearch * 1619fa9e4066Sahrens sizeof (char *)); 1620fa9e4066Sahrens free(searchdirs); 1621fa9e4066Sahrens searchdirs = tmp; 1622fa9e4066Sahrens } 1623fa9e4066Sahrens searchdirs[nsearch++] = optarg; 1624fa9e4066Sahrens break; 16254c58d714Sdarrenm case 'D': 162699653d4eSeschrock do_destroyed = B_TRUE; 16274c58d714Sdarrenm break; 1628fa9e4066Sahrens case 'f': 162999653d4eSeschrock do_force = B_TRUE; 1630fa9e4066Sahrens break; 1631c5904d13Seschrock case 'F': 1632*4f0f5e5bSVictor Latushkin do_verbatim = B_TRUE; 1633c5904d13Seschrock break; 1634fa9e4066Sahrens case 'o': 1635990b4856Slling if ((propval = strchr(optarg, '=')) != NULL) { 1636990b4856Slling *propval = '\0'; 1637990b4856Slling propval++; 16380a48a24eStimh if (add_prop_list(optarg, propval, 16390a48a24eStimh &props, B_TRUE)) 1640990b4856Slling goto error; 1641990b4856Slling } else { 1642fa9e4066Sahrens mntopts = optarg; 1643990b4856Slling } 1644fa9e4066Sahrens break; 1645fa9e4066Sahrens case 'R': 1646990b4856Slling if (add_prop_list(zpool_prop_to_name( 16470a48a24eStimh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 1648990b4856Slling goto error; 16492f8aaab3Seschrock if (nvlist_lookup_string(props, 16502f8aaab3Seschrock zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 16512f8aaab3Seschrock &propval) == 0) 16522f8aaab3Seschrock break; 1653990b4856Slling if (add_prop_list(zpool_prop_to_name( 16540a48a24eStimh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 1655990b4856Slling goto error; 1656fa9e4066Sahrens break; 1657fa9e4066Sahrens case ':': 1658fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 1659fa9e4066Sahrens "'%c' option\n"), optopt); 166099653d4eSeschrock usage(B_FALSE); 1661fa9e4066Sahrens break; 1662fa9e4066Sahrens case '?': 1663fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1664fa9e4066Sahrens optopt); 166599653d4eSeschrock usage(B_FALSE); 1666fa9e4066Sahrens } 1667fa9e4066Sahrens } 1668fa9e4066Sahrens 1669fa9e4066Sahrens argc -= optind; 1670fa9e4066Sahrens argv += optind; 1671fa9e4066Sahrens 16722f8aaab3Seschrock if (cachefile && nsearch != 0) { 16732f8aaab3Seschrock (void) fprintf(stderr, gettext("-c is incompatible with -d\n")); 16742f8aaab3Seschrock usage(B_FALSE); 16752f8aaab3Seschrock } 16762f8aaab3Seschrock 1677fa9e4066Sahrens if (searchdirs == NULL) { 1678fa9e4066Sahrens searchdirs = safe_malloc(sizeof (char *)); 1679fa9e4066Sahrens searchdirs[0] = "/dev/dsk"; 1680fa9e4066Sahrens nsearch = 1; 1681fa9e4066Sahrens } 1682fa9e4066Sahrens 1683fa9e4066Sahrens /* check argument count */ 1684fa9e4066Sahrens if (do_all) { 1685fa9e4066Sahrens if (argc != 0) { 1686fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 168799653d4eSeschrock usage(B_FALSE); 1688fa9e4066Sahrens } 1689fa9e4066Sahrens } else { 1690fa9e4066Sahrens if (argc > 2) { 1691fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 169299653d4eSeschrock usage(B_FALSE); 1693fa9e4066Sahrens } 1694fa9e4066Sahrens 1695fa9e4066Sahrens /* 1696fa9e4066Sahrens * Check for the SYS_CONFIG privilege. We do this explicitly 1697fa9e4066Sahrens * here because otherwise any attempt to discover pools will 1698fa9e4066Sahrens * silently fail. 1699fa9e4066Sahrens */ 1700fa9e4066Sahrens if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 1701fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot " 1702fa9e4066Sahrens "discover pools: permission denied\n")); 170399653d4eSeschrock free(searchdirs); 1704fa9e4066Sahrens return (1); 1705fa9e4066Sahrens } 1706fa9e4066Sahrens } 1707fa9e4066Sahrens 1708fa9e4066Sahrens /* 1709fa9e4066Sahrens * Depending on the arguments given, we do one of the following: 1710fa9e4066Sahrens * 1711fa9e4066Sahrens * <none> Iterate through all pools and display information about 1712fa9e4066Sahrens * each one. 1713fa9e4066Sahrens * 1714fa9e4066Sahrens * -a Iterate through all pools and try to import each one. 1715fa9e4066Sahrens * 1716fa9e4066Sahrens * <id> Find the pool that corresponds to the given GUID/pool 1717fa9e4066Sahrens * name and import that one. 17184c58d714Sdarrenm * 17194c58d714Sdarrenm * -D Above options applies only to destroyed pools. 1720fa9e4066Sahrens */ 1721fa9e4066Sahrens if (argc != 0) { 1722fa9e4066Sahrens char *endptr; 1723fa9e4066Sahrens 1724fa9e4066Sahrens errno = 0; 1725fa9e4066Sahrens searchguid = strtoull(argv[0], &endptr, 10); 1726fa9e4066Sahrens if (errno != 0 || *endptr != '\0') 1727fa9e4066Sahrens searchname = argv[0]; 1728fa9e4066Sahrens found_config = NULL; 1729fa9e4066Sahrens } 1730fa9e4066Sahrens 173124e697d4Sck153898 if (cachefile) { 1732e829d913Sck153898 pools = zpool_find_import_cached(g_zfs, cachefile, searchname, 1733e829d913Sck153898 searchguid); 173424e697d4Sck153898 } else if (searchname != NULL) { 173524e697d4Sck153898 pools = zpool_find_import_byname(g_zfs, nsearch, searchdirs, 173624e697d4Sck153898 searchname); 173724e697d4Sck153898 } else { 173824e697d4Sck153898 /* 173924e697d4Sck153898 * It's OK to search by guid even if searchguid is 0. 174024e697d4Sck153898 */ 174124e697d4Sck153898 pools = zpool_find_import_byguid(g_zfs, nsearch, searchdirs, 174224e697d4Sck153898 searchguid); 174324e697d4Sck153898 } 174424e697d4Sck153898 174524e697d4Sck153898 if (pools == NULL) { 174624e697d4Sck153898 if (argc != 0) { 174724e697d4Sck153898 (void) fprintf(stderr, gettext("cannot import '%s': " 174824e697d4Sck153898 "no such pool available\n"), argv[0]); 174924e697d4Sck153898 } 175024e697d4Sck153898 free(searchdirs); 175124e697d4Sck153898 return (1); 175224e697d4Sck153898 } 175324e697d4Sck153898 175424e697d4Sck153898 /* 175524e697d4Sck153898 * At this point we have a list of import candidate configs. Even if 175624e697d4Sck153898 * we were searching by pool name or guid, we still need to 175724e697d4Sck153898 * post-process the list to deal with pool state and possible 175824e697d4Sck153898 * duplicate names. 175924e697d4Sck153898 */ 1760fa9e4066Sahrens err = 0; 1761fa9e4066Sahrens elem = NULL; 176299653d4eSeschrock first = B_TRUE; 1763fa9e4066Sahrens while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 1764fa9e4066Sahrens 1765fa9e4066Sahrens verify(nvpair_value_nvlist(elem, &config) == 0); 1766fa9e4066Sahrens 17674c58d714Sdarrenm verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 17684c58d714Sdarrenm &pool_state) == 0); 17694c58d714Sdarrenm if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) 17704c58d714Sdarrenm continue; 17714c58d714Sdarrenm if (do_destroyed && pool_state != POOL_STATE_DESTROYED) 17724c58d714Sdarrenm continue; 17734c58d714Sdarrenm 1774fa9e4066Sahrens if (argc == 0) { 1775fa9e4066Sahrens if (first) 177699653d4eSeschrock first = B_FALSE; 17773bb79becSeschrock else if (!do_all) 1778fa9e4066Sahrens (void) printf("\n"); 1779fa9e4066Sahrens 1780fa9e4066Sahrens if (do_all) 1781fa9e4066Sahrens err |= do_import(config, NULL, mntopts, 1782*4f0f5e5bSVictor Latushkin do_force, props, do_verbatim); 1783fa9e4066Sahrens else 1784fa9e4066Sahrens show_import(config); 1785fa9e4066Sahrens } else if (searchname != NULL) { 1786fa9e4066Sahrens char *name; 1787fa9e4066Sahrens 1788fa9e4066Sahrens /* 1789fa9e4066Sahrens * We are searching for a pool based on name. 1790fa9e4066Sahrens */ 1791fa9e4066Sahrens verify(nvlist_lookup_string(config, 1792fa9e4066Sahrens ZPOOL_CONFIG_POOL_NAME, &name) == 0); 1793fa9e4066Sahrens 1794fa9e4066Sahrens if (strcmp(name, searchname) == 0) { 1795fa9e4066Sahrens if (found_config != NULL) { 1796fa9e4066Sahrens (void) fprintf(stderr, gettext( 1797fa9e4066Sahrens "cannot import '%s': more than " 1798fa9e4066Sahrens "one matching pool\n"), searchname); 1799fa9e4066Sahrens (void) fprintf(stderr, gettext( 1800fa9e4066Sahrens "import by numeric ID instead\n")); 180199653d4eSeschrock err = B_TRUE; 1802fa9e4066Sahrens } 1803fa9e4066Sahrens found_config = config; 1804fa9e4066Sahrens } 1805fa9e4066Sahrens } else { 1806fa9e4066Sahrens uint64_t guid; 1807fa9e4066Sahrens 1808fa9e4066Sahrens /* 1809fa9e4066Sahrens * Search for a pool by guid. 1810fa9e4066Sahrens */ 1811fa9e4066Sahrens verify(nvlist_lookup_uint64(config, 1812fa9e4066Sahrens ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 1813fa9e4066Sahrens 1814fa9e4066Sahrens if (guid == searchguid) 1815fa9e4066Sahrens found_config = config; 1816fa9e4066Sahrens } 1817fa9e4066Sahrens } 1818fa9e4066Sahrens 1819fa9e4066Sahrens /* 1820fa9e4066Sahrens * If we were searching for a specific pool, verify that we found a 1821fa9e4066Sahrens * pool, and then do the import. 1822fa9e4066Sahrens */ 1823fa9e4066Sahrens if (argc != 0 && err == 0) { 1824fa9e4066Sahrens if (found_config == NULL) { 1825fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot import '%s': " 1826fa9e4066Sahrens "no such pool available\n"), argv[0]); 182799653d4eSeschrock err = B_TRUE; 1828fa9e4066Sahrens } else { 1829fa9e4066Sahrens err |= do_import(found_config, argc == 1 ? NULL : 1830*4f0f5e5bSVictor Latushkin argv[1], mntopts, do_force, props, do_verbatim); 1831fa9e4066Sahrens } 1832fa9e4066Sahrens } 1833fa9e4066Sahrens 1834fa9e4066Sahrens /* 1835fa9e4066Sahrens * If we were just looking for pools, report an error if none were 1836fa9e4066Sahrens * found. 1837fa9e4066Sahrens */ 1838fa9e4066Sahrens if (argc == 0 && first) 1839fa9e4066Sahrens (void) fprintf(stderr, 1840fa9e4066Sahrens gettext("no pools available to import\n")); 1841fa9e4066Sahrens 1842ecd6cf80Smarks error: 1843ecd6cf80Smarks nvlist_free(props); 1844fa9e4066Sahrens nvlist_free(pools); 184599653d4eSeschrock free(searchdirs); 1846fa9e4066Sahrens 1847fa9e4066Sahrens return (err ? 1 : 0); 1848fa9e4066Sahrens } 1849fa9e4066Sahrens 1850fa9e4066Sahrens typedef struct iostat_cbdata { 1851fa9e4066Sahrens zpool_list_t *cb_list; 1852fa9e4066Sahrens int cb_verbose; 1853fa9e4066Sahrens int cb_iteration; 1854fa9e4066Sahrens int cb_namewidth; 1855fa9e4066Sahrens } iostat_cbdata_t; 1856fa9e4066Sahrens 1857fa9e4066Sahrens static void 1858fa9e4066Sahrens print_iostat_separator(iostat_cbdata_t *cb) 1859fa9e4066Sahrens { 1860fa9e4066Sahrens int i = 0; 1861fa9e4066Sahrens 1862fa9e4066Sahrens for (i = 0; i < cb->cb_namewidth; i++) 1863fa9e4066Sahrens (void) printf("-"); 1864fa9e4066Sahrens (void) printf(" ----- ----- ----- ----- ----- -----\n"); 1865fa9e4066Sahrens } 1866fa9e4066Sahrens 1867fa9e4066Sahrens static void 1868fa9e4066Sahrens print_iostat_header(iostat_cbdata_t *cb) 1869fa9e4066Sahrens { 1870fa9e4066Sahrens (void) printf("%*s capacity operations bandwidth\n", 1871fa9e4066Sahrens cb->cb_namewidth, ""); 1872fa9e4066Sahrens (void) printf("%-*s used avail read write read write\n", 1873fa9e4066Sahrens cb->cb_namewidth, "pool"); 1874fa9e4066Sahrens print_iostat_separator(cb); 1875fa9e4066Sahrens } 1876fa9e4066Sahrens 1877fa9e4066Sahrens /* 1878fa9e4066Sahrens * Display a single statistic. 1879fa9e4066Sahrens */ 1880990b4856Slling static void 1881fa9e4066Sahrens print_one_stat(uint64_t value) 1882fa9e4066Sahrens { 1883fa9e4066Sahrens char buf[64]; 1884fa9e4066Sahrens 1885fa9e4066Sahrens zfs_nicenum(value, buf, sizeof (buf)); 1886fa9e4066Sahrens (void) printf(" %5s", buf); 1887fa9e4066Sahrens } 1888fa9e4066Sahrens 1889fa9e4066Sahrens /* 1890fa9e4066Sahrens * Print out all the statistics for the given vdev. This can either be the 1891fa9e4066Sahrens * toplevel configuration, or called recursively. If 'name' is NULL, then this 1892fa9e4066Sahrens * is a verbose output, and we don't want to display the toplevel pool stats. 1893fa9e4066Sahrens */ 1894fa9e4066Sahrens void 1895c67d9675Seschrock print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 1896c67d9675Seschrock nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 1897fa9e4066Sahrens { 1898fa9e4066Sahrens nvlist_t **oldchild, **newchild; 1899fa9e4066Sahrens uint_t c, children; 1900fa9e4066Sahrens vdev_stat_t *oldvs, *newvs; 1901fa9e4066Sahrens vdev_stat_t zerovs = { 0 }; 1902fa9e4066Sahrens uint64_t tdelta; 1903fa9e4066Sahrens double scale; 1904afefbcddSeschrock char *vname; 1905fa9e4066Sahrens 1906fa9e4066Sahrens if (oldnv != NULL) { 1907fa9e4066Sahrens verify(nvlist_lookup_uint64_array(oldnv, ZPOOL_CONFIG_STATS, 1908fa9e4066Sahrens (uint64_t **)&oldvs, &c) == 0); 1909fa9e4066Sahrens } else { 1910fa9e4066Sahrens oldvs = &zerovs; 1911fa9e4066Sahrens } 1912fa9e4066Sahrens 1913fa9e4066Sahrens verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_STATS, 1914fa9e4066Sahrens (uint64_t **)&newvs, &c) == 0); 1915fa9e4066Sahrens 1916fa9e4066Sahrens if (strlen(name) + depth > cb->cb_namewidth) 1917fa9e4066Sahrens (void) printf("%*s%s", depth, "", name); 1918fa9e4066Sahrens else 1919fa9e4066Sahrens (void) printf("%*s%s%*s", depth, "", name, 1920fa9e4066Sahrens (int)(cb->cb_namewidth - strlen(name) - depth), ""); 1921fa9e4066Sahrens 1922fa9e4066Sahrens tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 1923fa9e4066Sahrens 1924fa9e4066Sahrens if (tdelta == 0) 1925fa9e4066Sahrens scale = 1.0; 1926fa9e4066Sahrens else 1927fa9e4066Sahrens scale = (double)NANOSEC / tdelta; 1928fa9e4066Sahrens 1929fa9e4066Sahrens /* only toplevel vdevs have capacity stats */ 1930fa9e4066Sahrens if (newvs->vs_space == 0) { 1931fa9e4066Sahrens (void) printf(" - -"); 1932fa9e4066Sahrens } else { 1933fa9e4066Sahrens print_one_stat(newvs->vs_alloc); 1934fa9e4066Sahrens print_one_stat(newvs->vs_space - newvs->vs_alloc); 1935fa9e4066Sahrens } 1936fa9e4066Sahrens 1937fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] - 1938fa9e4066Sahrens oldvs->vs_ops[ZIO_TYPE_READ]))); 1939fa9e4066Sahrens 1940fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] - 1941fa9e4066Sahrens oldvs->vs_ops[ZIO_TYPE_WRITE]))); 1942fa9e4066Sahrens 1943fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] - 1944fa9e4066Sahrens oldvs->vs_bytes[ZIO_TYPE_READ]))); 1945fa9e4066Sahrens 1946fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] - 1947fa9e4066Sahrens oldvs->vs_bytes[ZIO_TYPE_WRITE]))); 1948fa9e4066Sahrens 1949fa9e4066Sahrens (void) printf("\n"); 1950fa9e4066Sahrens 1951fa9e4066Sahrens if (!cb->cb_verbose) 1952fa9e4066Sahrens return; 1953fa9e4066Sahrens 1954fa9e4066Sahrens if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 1955fa9e4066Sahrens &newchild, &children) != 0) 1956fa9e4066Sahrens return; 1957fa9e4066Sahrens 1958fa9e4066Sahrens if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 1959fa9e4066Sahrens &oldchild, &c) != 0) 1960fa9e4066Sahrens return; 1961fa9e4066Sahrens 1962afefbcddSeschrock for (c = 0; c < children; c++) { 196399653d4eSeschrock vname = zpool_vdev_name(g_zfs, zhp, newchild[c]); 1964c67d9675Seschrock print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 1965afefbcddSeschrock newchild[c], cb, depth + 2); 1966afefbcddSeschrock free(vname); 1967afefbcddSeschrock } 1968fa94a07fSbrendan 1969fa94a07fSbrendan /* 1970fa94a07fSbrendan * Include level 2 ARC devices in iostat output 1971fa94a07fSbrendan */ 1972fa94a07fSbrendan if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, 1973fa94a07fSbrendan &newchild, &children) != 0) 1974fa94a07fSbrendan return; 1975fa94a07fSbrendan 1976fa94a07fSbrendan if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, 1977fa94a07fSbrendan &oldchild, &c) != 0) 1978fa94a07fSbrendan return; 1979fa94a07fSbrendan 1980fa94a07fSbrendan if (children > 0) { 1981fa94a07fSbrendan (void) printf("%-*s - - - - - " 1982fa94a07fSbrendan "-\n", cb->cb_namewidth, "cache"); 1983fa94a07fSbrendan for (c = 0; c < children; c++) { 1984fa94a07fSbrendan vname = zpool_vdev_name(g_zfs, zhp, newchild[c]); 1985fa94a07fSbrendan print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 1986fa94a07fSbrendan newchild[c], cb, depth + 2); 1987fa94a07fSbrendan free(vname); 1988fa94a07fSbrendan } 1989fa94a07fSbrendan } 1990fa9e4066Sahrens } 1991fa9e4066Sahrens 1992088e9d47Seschrock static int 1993088e9d47Seschrock refresh_iostat(zpool_handle_t *zhp, void *data) 1994088e9d47Seschrock { 1995088e9d47Seschrock iostat_cbdata_t *cb = data; 199694de1d4cSeschrock boolean_t missing; 1997088e9d47Seschrock 1998088e9d47Seschrock /* 1999088e9d47Seschrock * If the pool has disappeared, remove it from the list and continue. 2000088e9d47Seschrock */ 200194de1d4cSeschrock if (zpool_refresh_stats(zhp, &missing) != 0) 200294de1d4cSeschrock return (-1); 200394de1d4cSeschrock 200494de1d4cSeschrock if (missing) 2005088e9d47Seschrock pool_list_remove(cb->cb_list, zhp); 2006088e9d47Seschrock 2007088e9d47Seschrock return (0); 2008088e9d47Seschrock } 2009088e9d47Seschrock 2010fa9e4066Sahrens /* 2011fa9e4066Sahrens * Callback to print out the iostats for the given pool. 2012fa9e4066Sahrens */ 2013fa9e4066Sahrens int 2014fa9e4066Sahrens print_iostat(zpool_handle_t *zhp, void *data) 2015fa9e4066Sahrens { 2016fa9e4066Sahrens iostat_cbdata_t *cb = data; 2017fa9e4066Sahrens nvlist_t *oldconfig, *newconfig; 2018fa9e4066Sahrens nvlist_t *oldnvroot, *newnvroot; 2019fa9e4066Sahrens 2020088e9d47Seschrock newconfig = zpool_get_config(zhp, &oldconfig); 2021fa9e4066Sahrens 2022088e9d47Seschrock if (cb->cb_iteration == 1) 2023fa9e4066Sahrens oldconfig = NULL; 2024fa9e4066Sahrens 2025fa9e4066Sahrens verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 2026fa9e4066Sahrens &newnvroot) == 0); 2027fa9e4066Sahrens 2028088e9d47Seschrock if (oldconfig == NULL) 2029fa9e4066Sahrens oldnvroot = NULL; 2030088e9d47Seschrock else 2031088e9d47Seschrock verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 2032088e9d47Seschrock &oldnvroot) == 0); 2033fa9e4066Sahrens 2034fa9e4066Sahrens /* 2035fa9e4066Sahrens * Print out the statistics for the pool. 2036fa9e4066Sahrens */ 2037c67d9675Seschrock print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 2038fa9e4066Sahrens 2039fa9e4066Sahrens if (cb->cb_verbose) 2040fa9e4066Sahrens print_iostat_separator(cb); 2041fa9e4066Sahrens 2042fa9e4066Sahrens return (0); 2043fa9e4066Sahrens } 2044fa9e4066Sahrens 2045fa9e4066Sahrens int 2046fa9e4066Sahrens get_namewidth(zpool_handle_t *zhp, void *data) 2047fa9e4066Sahrens { 2048fa9e4066Sahrens iostat_cbdata_t *cb = data; 2049fa9e4066Sahrens nvlist_t *config, *nvroot; 2050fa9e4066Sahrens 2051088e9d47Seschrock if ((config = zpool_get_config(zhp, NULL)) != NULL) { 2052fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2053fa9e4066Sahrens &nvroot) == 0); 2054fa9e4066Sahrens if (!cb->cb_verbose) 2055fa9e4066Sahrens cb->cb_namewidth = strlen(zpool_get_name(zhp)); 2056fa9e4066Sahrens else 2057c67d9675Seschrock cb->cb_namewidth = max_width(zhp, nvroot, 0, 0); 2058fa9e4066Sahrens } 2059fa9e4066Sahrens 2060fa9e4066Sahrens /* 2061fa9e4066Sahrens * The width must fall into the range [10,38]. The upper limit is the 2062fa9e4066Sahrens * maximum we can have and still fit in 80 columns. 2063fa9e4066Sahrens */ 2064fa9e4066Sahrens if (cb->cb_namewidth < 10) 2065fa9e4066Sahrens cb->cb_namewidth = 10; 2066fa9e4066Sahrens if (cb->cb_namewidth > 38) 2067fa9e4066Sahrens cb->cb_namewidth = 38; 2068fa9e4066Sahrens 2069fa9e4066Sahrens return (0); 2070fa9e4066Sahrens } 2071fa9e4066Sahrens 2072fa9e4066Sahrens /* 2073fa9e4066Sahrens * zpool iostat [-v] [pool] ... [interval [count]] 2074fa9e4066Sahrens * 2075fa9e4066Sahrens * -v Display statistics for individual vdevs 2076fa9e4066Sahrens * 2077fa9e4066Sahrens * This command can be tricky because we want to be able to deal with pool 2078fa9e4066Sahrens * creation/destruction as well as vdev configuration changes. The bulk of this 2079fa9e4066Sahrens * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 2080fa9e4066Sahrens * on pool_list_update() to detect the addition of new pools. Configuration 2081fa9e4066Sahrens * changes are all handled within libzfs. 2082fa9e4066Sahrens */ 2083fa9e4066Sahrens int 2084fa9e4066Sahrens zpool_do_iostat(int argc, char **argv) 2085fa9e4066Sahrens { 2086fa9e4066Sahrens int c; 2087fa9e4066Sahrens int ret; 2088fa9e4066Sahrens int npools; 2089fa9e4066Sahrens unsigned long interval = 0, count = 0; 2090fa9e4066Sahrens zpool_list_t *list; 209199653d4eSeschrock boolean_t verbose = B_FALSE; 2092fa9e4066Sahrens iostat_cbdata_t cb; 2093fa9e4066Sahrens 2094fa9e4066Sahrens /* check options */ 2095fa9e4066Sahrens while ((c = getopt(argc, argv, "v")) != -1) { 2096fa9e4066Sahrens switch (c) { 2097fa9e4066Sahrens case 'v': 209899653d4eSeschrock verbose = B_TRUE; 2099fa9e4066Sahrens break; 2100fa9e4066Sahrens case '?': 2101fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2102fa9e4066Sahrens optopt); 210399653d4eSeschrock usage(B_FALSE); 2104fa9e4066Sahrens } 2105fa9e4066Sahrens } 2106fa9e4066Sahrens 2107fa9e4066Sahrens argc -= optind; 2108fa9e4066Sahrens argv += optind; 2109fa9e4066Sahrens 2110fa9e4066Sahrens /* 2111fa9e4066Sahrens * Determine if the last argument is an integer or a pool name 2112fa9e4066Sahrens */ 2113fa9e4066Sahrens if (argc > 0 && isdigit(argv[argc - 1][0])) { 2114fa9e4066Sahrens char *end; 2115fa9e4066Sahrens 2116fa9e4066Sahrens errno = 0; 2117fa9e4066Sahrens interval = strtoul(argv[argc - 1], &end, 10); 2118fa9e4066Sahrens 2119fa9e4066Sahrens if (*end == '\0' && errno == 0) { 2120fa9e4066Sahrens if (interval == 0) { 2121fa9e4066Sahrens (void) fprintf(stderr, gettext("interval " 2122fa9e4066Sahrens "cannot be zero\n")); 212399653d4eSeschrock usage(B_FALSE); 2124fa9e4066Sahrens } 2125fa9e4066Sahrens 2126fa9e4066Sahrens /* 2127fa9e4066Sahrens * Ignore the last parameter 2128fa9e4066Sahrens */ 2129fa9e4066Sahrens argc--; 2130fa9e4066Sahrens } else { 2131fa9e4066Sahrens /* 2132fa9e4066Sahrens * If this is not a valid number, just plow on. The 2133fa9e4066Sahrens * user will get a more informative error message later 2134fa9e4066Sahrens * on. 2135fa9e4066Sahrens */ 2136fa9e4066Sahrens interval = 0; 2137fa9e4066Sahrens } 2138fa9e4066Sahrens } 2139fa9e4066Sahrens 2140fa9e4066Sahrens /* 2141fa9e4066Sahrens * If the last argument is also an integer, then we have both a count 2142fa9e4066Sahrens * and an integer. 2143fa9e4066Sahrens */ 2144fa9e4066Sahrens if (argc > 0 && isdigit(argv[argc - 1][0])) { 2145fa9e4066Sahrens char *end; 2146fa9e4066Sahrens 2147fa9e4066Sahrens errno = 0; 2148fa9e4066Sahrens count = interval; 2149fa9e4066Sahrens interval = strtoul(argv[argc - 1], &end, 10); 2150fa9e4066Sahrens 2151fa9e4066Sahrens if (*end == '\0' && errno == 0) { 2152fa9e4066Sahrens if (interval == 0) { 2153fa9e4066Sahrens (void) fprintf(stderr, gettext("interval " 2154fa9e4066Sahrens "cannot be zero\n")); 215599653d4eSeschrock usage(B_FALSE); 2156fa9e4066Sahrens } 2157fa9e4066Sahrens 2158fa9e4066Sahrens /* 2159fa9e4066Sahrens * Ignore the last parameter 2160fa9e4066Sahrens */ 2161fa9e4066Sahrens argc--; 2162fa9e4066Sahrens } else { 2163fa9e4066Sahrens interval = 0; 2164fa9e4066Sahrens } 2165fa9e4066Sahrens } 2166fa9e4066Sahrens 2167fa9e4066Sahrens /* 2168fa9e4066Sahrens * Construct the list of all interesting pools. 2169fa9e4066Sahrens */ 2170fa9e4066Sahrens ret = 0; 2171b1b8ab34Slling if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL) 2172fa9e4066Sahrens return (1); 2173fa9e4066Sahrens 217499653d4eSeschrock if (pool_list_count(list) == 0 && argc != 0) { 217599653d4eSeschrock pool_list_free(list); 2176fa9e4066Sahrens return (1); 217799653d4eSeschrock } 2178fa9e4066Sahrens 2179fa9e4066Sahrens if (pool_list_count(list) == 0 && interval == 0) { 218099653d4eSeschrock pool_list_free(list); 2181fa9e4066Sahrens (void) fprintf(stderr, gettext("no pools available\n")); 2182fa9e4066Sahrens return (1); 2183fa9e4066Sahrens } 2184fa9e4066Sahrens 2185fa9e4066Sahrens /* 2186fa9e4066Sahrens * Enter the main iostat loop. 2187fa9e4066Sahrens */ 2188fa9e4066Sahrens cb.cb_list = list; 2189fa9e4066Sahrens cb.cb_verbose = verbose; 2190fa9e4066Sahrens cb.cb_iteration = 0; 2191fa9e4066Sahrens cb.cb_namewidth = 0; 2192fa9e4066Sahrens 2193fa9e4066Sahrens for (;;) { 2194fa9e4066Sahrens pool_list_update(list); 2195fa9e4066Sahrens 2196fa9e4066Sahrens if ((npools = pool_list_count(list)) == 0) 2197fa9e4066Sahrens break; 2198fa9e4066Sahrens 2199fa9e4066Sahrens /* 2200088e9d47Seschrock * Refresh all statistics. This is done as an explicit step 2201088e9d47Seschrock * before calculating the maximum name width, so that any 2202088e9d47Seschrock * configuration changes are properly accounted for. 2203088e9d47Seschrock */ 220499653d4eSeschrock (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb); 2205088e9d47Seschrock 2206088e9d47Seschrock /* 2207fa9e4066Sahrens * Iterate over all pools to determine the maximum width 2208fa9e4066Sahrens * for the pool / device name column across all pools. 2209fa9e4066Sahrens */ 2210fa9e4066Sahrens cb.cb_namewidth = 0; 221199653d4eSeschrock (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 2212fa9e4066Sahrens 2213fa9e4066Sahrens /* 2214fa9e4066Sahrens * If it's the first time, or verbose mode, print the header. 2215fa9e4066Sahrens */ 2216fa9e4066Sahrens if (++cb.cb_iteration == 1 || verbose) 2217fa9e4066Sahrens print_iostat_header(&cb); 2218fa9e4066Sahrens 221999653d4eSeschrock (void) pool_list_iter(list, B_FALSE, print_iostat, &cb); 2220fa9e4066Sahrens 2221fa9e4066Sahrens /* 2222fa9e4066Sahrens * If there's more than one pool, and we're not in verbose mode 2223fa9e4066Sahrens * (which prints a separator for us), then print a separator. 2224fa9e4066Sahrens */ 2225fa9e4066Sahrens if (npools > 1 && !verbose) 2226fa9e4066Sahrens print_iostat_separator(&cb); 2227fa9e4066Sahrens 2228fa9e4066Sahrens if (verbose) 2229fa9e4066Sahrens (void) printf("\n"); 2230fa9e4066Sahrens 223139c23413Seschrock /* 223239c23413Seschrock * Flush the output so that redirection to a file isn't buffered 223339c23413Seschrock * indefinitely. 223439c23413Seschrock */ 223539c23413Seschrock (void) fflush(stdout); 223639c23413Seschrock 2237fa9e4066Sahrens if (interval == 0) 2238fa9e4066Sahrens break; 2239fa9e4066Sahrens 2240fa9e4066Sahrens if (count != 0 && --count == 0) 2241fa9e4066Sahrens break; 2242fa9e4066Sahrens 2243fa9e4066Sahrens (void) sleep(interval); 2244fa9e4066Sahrens } 2245fa9e4066Sahrens 2246fa9e4066Sahrens pool_list_free(list); 2247fa9e4066Sahrens 2248fa9e4066Sahrens return (ret); 2249fa9e4066Sahrens } 2250fa9e4066Sahrens 2251fa9e4066Sahrens typedef struct list_cbdata { 225299653d4eSeschrock boolean_t cb_scripted; 225399653d4eSeschrock boolean_t cb_first; 2254990b4856Slling zprop_list_t *cb_proplist; 2255fa9e4066Sahrens } list_cbdata_t; 2256fa9e4066Sahrens 2257fa9e4066Sahrens /* 2258fa9e4066Sahrens * Given a list of columns to display, output appropriate headers for each one. 2259fa9e4066Sahrens */ 2260990b4856Slling static void 2261990b4856Slling print_header(zprop_list_t *pl) 2262fa9e4066Sahrens { 2263990b4856Slling const char *header; 2264990b4856Slling boolean_t first = B_TRUE; 2265990b4856Slling boolean_t right_justify; 2266fa9e4066Sahrens 2267990b4856Slling for (; pl != NULL; pl = pl->pl_next) { 2268990b4856Slling if (pl->pl_prop == ZPROP_INVAL) 2269990b4856Slling continue; 2270990b4856Slling 2271990b4856Slling if (!first) 2272fa9e4066Sahrens (void) printf(" "); 2273fa9e4066Sahrens else 2274990b4856Slling first = B_FALSE; 2275fa9e4066Sahrens 2276990b4856Slling header = zpool_prop_column_name(pl->pl_prop); 2277990b4856Slling right_justify = zpool_prop_align_right(pl->pl_prop); 2278990b4856Slling 2279990b4856Slling if (pl->pl_next == NULL && !right_justify) 2280990b4856Slling (void) printf("%s", header); 2281990b4856Slling else if (right_justify) 2282990b4856Slling (void) printf("%*s", pl->pl_width, header); 2283990b4856Slling else 2284990b4856Slling (void) printf("%-*s", pl->pl_width, header); 2285fa9e4066Sahrens } 2286fa9e4066Sahrens 2287fa9e4066Sahrens (void) printf("\n"); 2288fa9e4066Sahrens } 2289fa9e4066Sahrens 2290990b4856Slling /* 2291990b4856Slling * Given a pool and a list of properties, print out all the properties according 2292990b4856Slling * to the described layout. 2293990b4856Slling */ 2294990b4856Slling static void 2295990b4856Slling print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted) 2296990b4856Slling { 2297990b4856Slling boolean_t first = B_TRUE; 2298990b4856Slling char property[ZPOOL_MAXPROPLEN]; 2299990b4856Slling char *propstr; 2300990b4856Slling boolean_t right_justify; 2301990b4856Slling int width; 2302990b4856Slling 2303990b4856Slling for (; pl != NULL; pl = pl->pl_next) { 2304990b4856Slling if (!first) { 2305990b4856Slling if (scripted) 2306990b4856Slling (void) printf("\t"); 2307990b4856Slling else 2308990b4856Slling (void) printf(" "); 2309990b4856Slling } else { 2310990b4856Slling first = B_FALSE; 2311990b4856Slling } 2312990b4856Slling 2313990b4856Slling right_justify = B_FALSE; 2314990b4856Slling if (pl->pl_prop != ZPROP_INVAL) { 2315990b4856Slling if (zpool_get_prop(zhp, pl->pl_prop, property, 2316990b4856Slling sizeof (property), NULL) != 0) 2317990b4856Slling propstr = "-"; 2318990b4856Slling else 2319990b4856Slling propstr = property; 2320990b4856Slling 2321990b4856Slling right_justify = zpool_prop_align_right(pl->pl_prop); 2322990b4856Slling } else { 2323990b4856Slling propstr = "-"; 2324990b4856Slling } 2325990b4856Slling 2326990b4856Slling width = pl->pl_width; 2327990b4856Slling 2328990b4856Slling /* 2329990b4856Slling * If this is being called in scripted mode, or if this is the 2330990b4856Slling * last column and it is left-justified, don't include a width 2331990b4856Slling * format specifier. 2332990b4856Slling */ 2333990b4856Slling if (scripted || (pl->pl_next == NULL && !right_justify)) 2334990b4856Slling (void) printf("%s", propstr); 2335990b4856Slling else if (right_justify) 2336990b4856Slling (void) printf("%*s", width, propstr); 2337990b4856Slling else 2338990b4856Slling (void) printf("%-*s", width, propstr); 2339990b4856Slling } 2340990b4856Slling 2341990b4856Slling (void) printf("\n"); 2342990b4856Slling } 2343990b4856Slling 2344990b4856Slling /* 2345990b4856Slling * Generic callback function to list a pool. 2346990b4856Slling */ 2347fa9e4066Sahrens int 2348fa9e4066Sahrens list_callback(zpool_handle_t *zhp, void *data) 2349fa9e4066Sahrens { 2350fa9e4066Sahrens list_cbdata_t *cbp = data; 2351fa9e4066Sahrens 2352fa9e4066Sahrens if (cbp->cb_first) { 2353fa9e4066Sahrens if (!cbp->cb_scripted) 2354990b4856Slling print_header(cbp->cb_proplist); 235599653d4eSeschrock cbp->cb_first = B_FALSE; 2356fa9e4066Sahrens } 2357fa9e4066Sahrens 2358990b4856Slling print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted); 2359fa9e4066Sahrens 2360fa9e4066Sahrens return (0); 2361fa9e4066Sahrens } 2362fa9e4066Sahrens 2363fa9e4066Sahrens /* 2364990b4856Slling * zpool list [-H] [-o prop[,prop]*] [pool] ... 2365fa9e4066Sahrens * 2366990b4856Slling * -H Scripted mode. Don't display headers, and separate properties 2367990b4856Slling * by a single tab. 2368990b4856Slling * -o List of properties to display. Defaults to 2369990b4856Slling * "name,size,used,available,capacity,health,altroot" 2370fa9e4066Sahrens * 2371fa9e4066Sahrens * List all pools in the system, whether or not they're healthy. Output space 2372fa9e4066Sahrens * statistics for each one, as well as health status summary. 2373fa9e4066Sahrens */ 2374fa9e4066Sahrens int 2375fa9e4066Sahrens zpool_do_list(int argc, char **argv) 2376fa9e4066Sahrens { 2377fa9e4066Sahrens int c; 2378fa9e4066Sahrens int ret; 2379fa9e4066Sahrens list_cbdata_t cb = { 0 }; 2380990b4856Slling static char default_props[] = 2381990b4856Slling "name,size,used,available,capacity,health,altroot"; 2382990b4856Slling char *props = default_props; 2383fa9e4066Sahrens 2384fa9e4066Sahrens /* check options */ 2385fa9e4066Sahrens while ((c = getopt(argc, argv, ":Ho:")) != -1) { 2386fa9e4066Sahrens switch (c) { 2387fa9e4066Sahrens case 'H': 238899653d4eSeschrock cb.cb_scripted = B_TRUE; 2389fa9e4066Sahrens break; 2390fa9e4066Sahrens case 'o': 2391990b4856Slling props = optarg; 2392fa9e4066Sahrens break; 2393fa9e4066Sahrens case ':': 2394fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 2395fa9e4066Sahrens "'%c' option\n"), optopt); 239699653d4eSeschrock usage(B_FALSE); 2397fa9e4066Sahrens break; 2398fa9e4066Sahrens case '?': 2399fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2400fa9e4066Sahrens optopt); 240199653d4eSeschrock usage(B_FALSE); 2402fa9e4066Sahrens } 2403fa9e4066Sahrens } 2404fa9e4066Sahrens 2405fa9e4066Sahrens argc -= optind; 2406fa9e4066Sahrens argv += optind; 2407fa9e4066Sahrens 2408990b4856Slling if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) 240999653d4eSeschrock usage(B_FALSE); 2410fa9e4066Sahrens 241199653d4eSeschrock cb.cb_first = B_TRUE; 2412fa9e4066Sahrens 2413990b4856Slling ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, 2414990b4856Slling list_callback, &cb); 2415990b4856Slling 2416990b4856Slling zprop_free_list(cb.cb_proplist); 2417fa9e4066Sahrens 2418fce7d82bSmmusante if (argc == 0 && cb.cb_first && !cb.cb_scripted) { 2419fa9e4066Sahrens (void) printf(gettext("no pools available\n")); 2420fa9e4066Sahrens return (0); 2421fa9e4066Sahrens } 2422fa9e4066Sahrens 2423fa9e4066Sahrens return (ret); 2424fa9e4066Sahrens } 2425fa9e4066Sahrens 2426fa9e4066Sahrens static nvlist_t * 2427fa9e4066Sahrens zpool_get_vdev_by_name(nvlist_t *nv, char *name) 2428fa9e4066Sahrens { 2429fa9e4066Sahrens nvlist_t **child; 2430fa9e4066Sahrens uint_t c, children; 2431fa9e4066Sahrens nvlist_t *match; 2432fa9e4066Sahrens char *path; 2433fa9e4066Sahrens 2434fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2435fa9e4066Sahrens &child, &children) != 0) { 2436fa9e4066Sahrens verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 2437fa9e4066Sahrens if (strncmp(name, "/dev/dsk/", 9) == 0) 2438fa9e4066Sahrens name += 9; 2439fa9e4066Sahrens if (strncmp(path, "/dev/dsk/", 9) == 0) 2440fa9e4066Sahrens path += 9; 2441fa9e4066Sahrens if (strcmp(name, path) == 0) 2442fa9e4066Sahrens return (nv); 2443fa9e4066Sahrens return (NULL); 2444fa9e4066Sahrens } 2445fa9e4066Sahrens 2446fa9e4066Sahrens for (c = 0; c < children; c++) 2447fa9e4066Sahrens if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL) 2448fa9e4066Sahrens return (match); 2449fa9e4066Sahrens 2450fa9e4066Sahrens return (NULL); 2451fa9e4066Sahrens } 2452fa9e4066Sahrens 2453fa9e4066Sahrens static int 2454fa9e4066Sahrens zpool_do_attach_or_replace(int argc, char **argv, int replacing) 2455fa9e4066Sahrens { 245699653d4eSeschrock boolean_t force = B_FALSE; 2457fa9e4066Sahrens int c; 2458fa9e4066Sahrens nvlist_t *nvroot; 2459fa9e4066Sahrens char *poolname, *old_disk, *new_disk; 2460fa9e4066Sahrens zpool_handle_t *zhp; 246199653d4eSeschrock int ret; 2462fa9e4066Sahrens 2463fa9e4066Sahrens /* check options */ 2464fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) { 2465fa9e4066Sahrens switch (c) { 2466fa9e4066Sahrens case 'f': 246799653d4eSeschrock force = B_TRUE; 2468fa9e4066Sahrens break; 2469fa9e4066Sahrens case '?': 2470fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2471fa9e4066Sahrens optopt); 247299653d4eSeschrock usage(B_FALSE); 2473fa9e4066Sahrens } 2474fa9e4066Sahrens } 2475fa9e4066Sahrens 2476fa9e4066Sahrens argc -= optind; 2477fa9e4066Sahrens argv += optind; 2478fa9e4066Sahrens 2479fa9e4066Sahrens /* get pool name and check number of arguments */ 2480fa9e4066Sahrens if (argc < 1) { 2481fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 248299653d4eSeschrock usage(B_FALSE); 2483fa9e4066Sahrens } 2484fa9e4066Sahrens 2485fa9e4066Sahrens poolname = argv[0]; 2486fa9e4066Sahrens 2487fa9e4066Sahrens if (argc < 2) { 2488fa9e4066Sahrens (void) fprintf(stderr, 2489fa9e4066Sahrens gettext("missing <device> specification\n")); 249099653d4eSeschrock usage(B_FALSE); 2491fa9e4066Sahrens } 2492fa9e4066Sahrens 2493fa9e4066Sahrens old_disk = argv[1]; 2494fa9e4066Sahrens 2495fa9e4066Sahrens if (argc < 3) { 2496fa9e4066Sahrens if (!replacing) { 2497fa9e4066Sahrens (void) fprintf(stderr, 2498fa9e4066Sahrens gettext("missing <new_device> specification\n")); 249999653d4eSeschrock usage(B_FALSE); 2500fa9e4066Sahrens } 2501fa9e4066Sahrens new_disk = old_disk; 2502fa9e4066Sahrens argc -= 1; 2503fa9e4066Sahrens argv += 1; 2504fa9e4066Sahrens } else { 2505fa9e4066Sahrens new_disk = argv[2]; 2506fa9e4066Sahrens argc -= 2; 2507fa9e4066Sahrens argv += 2; 2508fa9e4066Sahrens } 2509fa9e4066Sahrens 2510fa9e4066Sahrens if (argc > 1) { 2511fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 251299653d4eSeschrock usage(B_FALSE); 2513fa9e4066Sahrens } 2514fa9e4066Sahrens 251599653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2516fa9e4066Sahrens return (1); 2517fa9e4066Sahrens 25188488aeb5Staylor if (zpool_get_config(zhp, NULL) == NULL) { 2519fa9e4066Sahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 2520fa9e4066Sahrens poolname); 2521fa9e4066Sahrens zpool_close(zhp); 2522fa9e4066Sahrens return (1); 2523fa9e4066Sahrens } 2524fa9e4066Sahrens 2525705040edSEric Taylor nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE, 2526705040edSEric Taylor argc, argv); 2527fa9e4066Sahrens if (nvroot == NULL) { 2528fa9e4066Sahrens zpool_close(zhp); 2529fa9e4066Sahrens return (1); 2530fa9e4066Sahrens } 2531fa9e4066Sahrens 253299653d4eSeschrock ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); 253399653d4eSeschrock 253499653d4eSeschrock nvlist_free(nvroot); 253599653d4eSeschrock zpool_close(zhp); 253699653d4eSeschrock 253799653d4eSeschrock return (ret); 2538fa9e4066Sahrens } 2539fa9e4066Sahrens 2540fa9e4066Sahrens /* 2541fa9e4066Sahrens * zpool replace [-f] <pool> <device> <new_device> 2542fa9e4066Sahrens * 2543fa9e4066Sahrens * -f Force attach, even if <new_device> appears to be in use. 2544fa9e4066Sahrens * 2545fa9e4066Sahrens * Replace <device> with <new_device>. 2546fa9e4066Sahrens */ 2547fa9e4066Sahrens /* ARGSUSED */ 2548fa9e4066Sahrens int 2549fa9e4066Sahrens zpool_do_replace(int argc, char **argv) 2550fa9e4066Sahrens { 2551fa9e4066Sahrens return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 2552fa9e4066Sahrens } 2553fa9e4066Sahrens 2554fa9e4066Sahrens /* 2555fa9e4066Sahrens * zpool attach [-f] <pool> <device> <new_device> 2556fa9e4066Sahrens * 2557fa9e4066Sahrens * -f Force attach, even if <new_device> appears to be in use. 2558fa9e4066Sahrens * 2559fa9e4066Sahrens * Attach <new_device> to the mirror containing <device>. If <device> is not 2560fa9e4066Sahrens * part of a mirror, then <device> will be transformed into a mirror of 2561fa9e4066Sahrens * <device> and <new_device>. In either case, <new_device> will begin life 2562fa9e4066Sahrens * with a DTL of [0, now], and will immediately begin to resilver itself. 2563fa9e4066Sahrens */ 2564fa9e4066Sahrens int 2565fa9e4066Sahrens zpool_do_attach(int argc, char **argv) 2566fa9e4066Sahrens { 2567fa9e4066Sahrens return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 2568fa9e4066Sahrens } 2569fa9e4066Sahrens 2570fa9e4066Sahrens /* 2571fa9e4066Sahrens * zpool detach [-f] <pool> <device> 2572fa9e4066Sahrens * 2573fa9e4066Sahrens * -f Force detach of <device>, even if DTLs argue against it 2574fa9e4066Sahrens * (not supported yet) 2575fa9e4066Sahrens * 2576fa9e4066Sahrens * Detach a device from a mirror. The operation will be refused if <device> 2577fa9e4066Sahrens * is the last device in the mirror, or if the DTLs indicate that this device 2578fa9e4066Sahrens * has the only valid copy of some data. 2579fa9e4066Sahrens */ 2580fa9e4066Sahrens /* ARGSUSED */ 2581fa9e4066Sahrens int 2582fa9e4066Sahrens zpool_do_detach(int argc, char **argv) 2583fa9e4066Sahrens { 2584fa9e4066Sahrens int c; 2585fa9e4066Sahrens char *poolname, *path; 2586fa9e4066Sahrens zpool_handle_t *zhp; 258799653d4eSeschrock int ret; 2588fa9e4066Sahrens 2589fa9e4066Sahrens /* check options */ 2590fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) { 2591fa9e4066Sahrens switch (c) { 2592fa9e4066Sahrens case 'f': 2593fa9e4066Sahrens case '?': 2594fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2595fa9e4066Sahrens optopt); 259699653d4eSeschrock usage(B_FALSE); 2597fa9e4066Sahrens } 2598fa9e4066Sahrens } 2599fa9e4066Sahrens 2600fa9e4066Sahrens argc -= optind; 2601fa9e4066Sahrens argv += optind; 2602fa9e4066Sahrens 2603fa9e4066Sahrens /* get pool name and check number of arguments */ 2604fa9e4066Sahrens if (argc < 1) { 2605fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 260699653d4eSeschrock usage(B_FALSE); 2607fa9e4066Sahrens } 2608fa9e4066Sahrens 2609fa9e4066Sahrens if (argc < 2) { 2610fa9e4066Sahrens (void) fprintf(stderr, 2611fa9e4066Sahrens gettext("missing <device> specification\n")); 261299653d4eSeschrock usage(B_FALSE); 2613fa9e4066Sahrens } 2614fa9e4066Sahrens 2615fa9e4066Sahrens poolname = argv[0]; 2616fa9e4066Sahrens path = argv[1]; 2617fa9e4066Sahrens 261899653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2619fa9e4066Sahrens return (1); 2620fa9e4066Sahrens 262199653d4eSeschrock ret = zpool_vdev_detach(zhp, path); 262299653d4eSeschrock 262399653d4eSeschrock zpool_close(zhp); 262499653d4eSeschrock 262599653d4eSeschrock return (ret); 2626fa9e4066Sahrens } 2627fa9e4066Sahrens 2628fa9e4066Sahrens /* 2629441d80aaSlling * zpool online <pool> <device> ... 2630fa9e4066Sahrens */ 2631fa9e4066Sahrens int 2632fa9e4066Sahrens zpool_do_online(int argc, char **argv) 2633fa9e4066Sahrens { 2634fa9e4066Sahrens int c, i; 2635fa9e4066Sahrens char *poolname; 2636fa9e4066Sahrens zpool_handle_t *zhp; 2637fa9e4066Sahrens int ret = 0; 26383d7072f8Seschrock vdev_state_t newstate; 2639573ca77eSGeorge Wilson int flags = 0; 2640fa9e4066Sahrens 2641fa9e4066Sahrens /* check options */ 2642573ca77eSGeorge Wilson while ((c = getopt(argc, argv, "et")) != -1) { 2643fa9e4066Sahrens switch (c) { 2644573ca77eSGeorge Wilson case 'e': 2645573ca77eSGeorge Wilson flags |= ZFS_ONLINE_EXPAND; 2646573ca77eSGeorge Wilson break; 2647fa9e4066Sahrens case 't': 2648fa9e4066Sahrens case '?': 2649fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2650fa9e4066Sahrens optopt); 265199653d4eSeschrock usage(B_FALSE); 2652fa9e4066Sahrens } 2653fa9e4066Sahrens } 2654fa9e4066Sahrens 2655fa9e4066Sahrens argc -= optind; 2656fa9e4066Sahrens argv += optind; 2657fa9e4066Sahrens 2658fa9e4066Sahrens /* get pool name and check number of arguments */ 2659fa9e4066Sahrens if (argc < 1) { 2660fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name\n")); 266199653d4eSeschrock usage(B_FALSE); 2662fa9e4066Sahrens } 2663fa9e4066Sahrens if (argc < 2) { 2664fa9e4066Sahrens (void) fprintf(stderr, gettext("missing device name\n")); 266599653d4eSeschrock usage(B_FALSE); 2666fa9e4066Sahrens } 2667fa9e4066Sahrens 2668fa9e4066Sahrens poolname = argv[0]; 2669fa9e4066Sahrens 267099653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2671fa9e4066Sahrens return (1); 2672fa9e4066Sahrens 26733d7072f8Seschrock for (i = 1; i < argc; i++) { 2674573ca77eSGeorge Wilson if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) { 26753d7072f8Seschrock if (newstate != VDEV_STATE_HEALTHY) { 26763d7072f8Seschrock (void) printf(gettext("warning: device '%s' " 26773d7072f8Seschrock "onlined, but remains in faulted state\n"), 2678fa9e4066Sahrens argv[i]); 26793d7072f8Seschrock if (newstate == VDEV_STATE_FAULTED) 26803d7072f8Seschrock (void) printf(gettext("use 'zpool " 26813d7072f8Seschrock "clear' to restore a faulted " 26823d7072f8Seschrock "device\n")); 2683fa9e4066Sahrens else 26843d7072f8Seschrock (void) printf(gettext("use 'zpool " 26853d7072f8Seschrock "replace' to replace devices " 26863d7072f8Seschrock "that are no longer present\n")); 26873d7072f8Seschrock } 26883d7072f8Seschrock } else { 2689fa9e4066Sahrens ret = 1; 26903d7072f8Seschrock } 26913d7072f8Seschrock } 2692fa9e4066Sahrens 269399653d4eSeschrock zpool_close(zhp); 269499653d4eSeschrock 2695fa9e4066Sahrens return (ret); 2696fa9e4066Sahrens } 2697fa9e4066Sahrens 2698fa9e4066Sahrens /* 2699441d80aaSlling * zpool offline [-ft] <pool> <device> ... 2700fa9e4066Sahrens * 2701fa9e4066Sahrens * -f Force the device into the offline state, even if doing 2702fa9e4066Sahrens * so would appear to compromise pool availability. 2703fa9e4066Sahrens * (not supported yet) 2704fa9e4066Sahrens * 2705fa9e4066Sahrens * -t Only take the device off-line temporarily. The offline 2706fa9e4066Sahrens * state will not be persistent across reboots. 2707fa9e4066Sahrens */ 2708fa9e4066Sahrens /* ARGSUSED */ 2709fa9e4066Sahrens int 2710fa9e4066Sahrens zpool_do_offline(int argc, char **argv) 2711fa9e4066Sahrens { 2712fa9e4066Sahrens int c, i; 2713fa9e4066Sahrens char *poolname; 2714fa9e4066Sahrens zpool_handle_t *zhp; 271599653d4eSeschrock int ret = 0; 271699653d4eSeschrock boolean_t istmp = B_FALSE; 2717fa9e4066Sahrens 2718fa9e4066Sahrens /* check options */ 2719fa9e4066Sahrens while ((c = getopt(argc, argv, "ft")) != -1) { 2720fa9e4066Sahrens switch (c) { 2721fa9e4066Sahrens case 't': 272299653d4eSeschrock istmp = B_TRUE; 2723441d80aaSlling break; 2724441d80aaSlling case 'f': 2725fa9e4066Sahrens case '?': 2726fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2727fa9e4066Sahrens optopt); 272899653d4eSeschrock usage(B_FALSE); 2729fa9e4066Sahrens } 2730fa9e4066Sahrens } 2731fa9e4066Sahrens 2732fa9e4066Sahrens argc -= optind; 2733fa9e4066Sahrens argv += optind; 2734fa9e4066Sahrens 2735fa9e4066Sahrens /* get pool name and check number of arguments */ 2736fa9e4066Sahrens if (argc < 1) { 2737fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name\n")); 273899653d4eSeschrock usage(B_FALSE); 2739fa9e4066Sahrens } 2740fa9e4066Sahrens if (argc < 2) { 2741fa9e4066Sahrens (void) fprintf(stderr, gettext("missing device name\n")); 274299653d4eSeschrock usage(B_FALSE); 2743fa9e4066Sahrens } 2744fa9e4066Sahrens 2745fa9e4066Sahrens poolname = argv[0]; 2746fa9e4066Sahrens 274799653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 2748fa9e4066Sahrens return (1); 2749fa9e4066Sahrens 27503d7072f8Seschrock for (i = 1; i < argc; i++) { 27513d7072f8Seschrock if (zpool_vdev_offline(zhp, argv[i], istmp) != 0) 2752fa9e4066Sahrens ret = 1; 27533d7072f8Seschrock } 2754fa9e4066Sahrens 275599653d4eSeschrock zpool_close(zhp); 275699653d4eSeschrock 2757fa9e4066Sahrens return (ret); 2758fa9e4066Sahrens } 2759fa9e4066Sahrens 2760ea8dc4b6Seschrock /* 2761ea8dc4b6Seschrock * zpool clear <pool> [device] 2762ea8dc4b6Seschrock * 2763ea8dc4b6Seschrock * Clear all errors associated with a pool or a particular device. 2764ea8dc4b6Seschrock */ 2765ea8dc4b6Seschrock int 2766ea8dc4b6Seschrock zpool_do_clear(int argc, char **argv) 2767ea8dc4b6Seschrock { 2768ea8dc4b6Seschrock int ret = 0; 2769ea8dc4b6Seschrock zpool_handle_t *zhp; 2770ea8dc4b6Seschrock char *pool, *device; 2771ea8dc4b6Seschrock 2772ea8dc4b6Seschrock if (argc < 2) { 2773ea8dc4b6Seschrock (void) fprintf(stderr, gettext("missing pool name\n")); 277499653d4eSeschrock usage(B_FALSE); 2775ea8dc4b6Seschrock } 2776ea8dc4b6Seschrock 2777ea8dc4b6Seschrock if (argc > 3) { 2778ea8dc4b6Seschrock (void) fprintf(stderr, gettext("too many arguments\n")); 277999653d4eSeschrock usage(B_FALSE); 2780ea8dc4b6Seschrock } 2781ea8dc4b6Seschrock 2782ea8dc4b6Seschrock pool = argv[1]; 2783ea8dc4b6Seschrock device = argc == 3 ? argv[2] : NULL; 2784ea8dc4b6Seschrock 2785b87f3af3Sperrin if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) 2786ea8dc4b6Seschrock return (1); 2787ea8dc4b6Seschrock 2788ea8dc4b6Seschrock if (zpool_clear(zhp, device) != 0) 2789ea8dc4b6Seschrock ret = 1; 2790ea8dc4b6Seschrock 2791ea8dc4b6Seschrock zpool_close(zhp); 2792ea8dc4b6Seschrock 2793ea8dc4b6Seschrock return (ret); 2794ea8dc4b6Seschrock } 2795ea8dc4b6Seschrock 2796fa9e4066Sahrens typedef struct scrub_cbdata { 2797fa9e4066Sahrens int cb_type; 279806eeb2adSek110237 int cb_argc; 279906eeb2adSek110237 char **cb_argv; 2800fa9e4066Sahrens } scrub_cbdata_t; 2801fa9e4066Sahrens 2802fa9e4066Sahrens int 2803fa9e4066Sahrens scrub_callback(zpool_handle_t *zhp, void *data) 2804fa9e4066Sahrens { 2805fa9e4066Sahrens scrub_cbdata_t *cb = data; 280606eeb2adSek110237 int err; 2807fa9e4066Sahrens 2808ea8dc4b6Seschrock /* 2809ea8dc4b6Seschrock * Ignore faulted pools. 2810ea8dc4b6Seschrock */ 2811ea8dc4b6Seschrock if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 2812ea8dc4b6Seschrock (void) fprintf(stderr, gettext("cannot scrub '%s': pool is " 2813ea8dc4b6Seschrock "currently unavailable\n"), zpool_get_name(zhp)); 2814ea8dc4b6Seschrock return (1); 2815ea8dc4b6Seschrock } 2816ea8dc4b6Seschrock 281706eeb2adSek110237 err = zpool_scrub(zhp, cb->cb_type); 281806eeb2adSek110237 281906eeb2adSek110237 return (err != 0); 2820fa9e4066Sahrens } 2821fa9e4066Sahrens 2822fa9e4066Sahrens /* 2823fa9e4066Sahrens * zpool scrub [-s] <pool> ... 2824fa9e4066Sahrens * 2825fa9e4066Sahrens * -s Stop. Stops any in-progress scrub. 2826fa9e4066Sahrens */ 2827fa9e4066Sahrens int 2828fa9e4066Sahrens zpool_do_scrub(int argc, char **argv) 2829fa9e4066Sahrens { 2830fa9e4066Sahrens int c; 2831fa9e4066Sahrens scrub_cbdata_t cb; 2832fa9e4066Sahrens 2833fa9e4066Sahrens cb.cb_type = POOL_SCRUB_EVERYTHING; 2834fa9e4066Sahrens 2835fa9e4066Sahrens /* check options */ 2836fa9e4066Sahrens while ((c = getopt(argc, argv, "s")) != -1) { 2837fa9e4066Sahrens switch (c) { 2838fa9e4066Sahrens case 's': 2839fa9e4066Sahrens cb.cb_type = POOL_SCRUB_NONE; 2840fa9e4066Sahrens break; 2841fa9e4066Sahrens case '?': 2842fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2843fa9e4066Sahrens optopt); 284499653d4eSeschrock usage(B_FALSE); 2845fa9e4066Sahrens } 2846fa9e4066Sahrens } 2847fa9e4066Sahrens 284806eeb2adSek110237 cb.cb_argc = argc; 284906eeb2adSek110237 cb.cb_argv = argv; 2850fa9e4066Sahrens argc -= optind; 2851fa9e4066Sahrens argv += optind; 2852fa9e4066Sahrens 2853fa9e4066Sahrens if (argc < 1) { 2854fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 285599653d4eSeschrock usage(B_FALSE); 2856fa9e4066Sahrens } 2857fa9e4066Sahrens 2858b1b8ab34Slling return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 2859fa9e4066Sahrens } 2860fa9e4066Sahrens 2861fa9e4066Sahrens typedef struct status_cbdata { 2862fa9e4066Sahrens int cb_count; 2863e9dbad6fSeschrock boolean_t cb_allpools; 286499653d4eSeschrock boolean_t cb_verbose; 286599653d4eSeschrock boolean_t cb_explain; 286699653d4eSeschrock boolean_t cb_first; 2867fa9e4066Sahrens } status_cbdata_t; 2868fa9e4066Sahrens 2869fa9e4066Sahrens /* 2870fa9e4066Sahrens * Print out detailed scrub status. 2871fa9e4066Sahrens */ 2872fa9e4066Sahrens void 2873fa9e4066Sahrens print_scrub_status(nvlist_t *nvroot) 2874fa9e4066Sahrens { 2875fa9e4066Sahrens vdev_stat_t *vs; 2876fa9e4066Sahrens uint_t vsc; 2877fa9e4066Sahrens time_t start, end, now; 2878fa9e4066Sahrens double fraction_done; 287918ce54dfSek110237 uint64_t examined, total, minutes_left, minutes_taken; 2880fa9e4066Sahrens char *scrub_type; 2881fa9e4066Sahrens 2882fa9e4066Sahrens verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 2883fa9e4066Sahrens (uint64_t **)&vs, &vsc) == 0); 2884fa9e4066Sahrens 2885fa9e4066Sahrens /* 2886fa9e4066Sahrens * If there's never been a scrub, there's not much to say. 2887fa9e4066Sahrens */ 2888fa9e4066Sahrens if (vs->vs_scrub_end == 0 && vs->vs_scrub_type == POOL_SCRUB_NONE) { 2889fa9e4066Sahrens (void) printf(gettext("none requested\n")); 2890fa9e4066Sahrens return; 2891fa9e4066Sahrens } 2892fa9e4066Sahrens 2893fa9e4066Sahrens scrub_type = (vs->vs_scrub_type == POOL_SCRUB_RESILVER) ? 2894fa9e4066Sahrens "resilver" : "scrub"; 2895fa9e4066Sahrens 2896fa9e4066Sahrens start = vs->vs_scrub_start; 2897fa9e4066Sahrens end = vs->vs_scrub_end; 2898fa9e4066Sahrens now = time(NULL); 2899fa9e4066Sahrens examined = vs->vs_scrub_examined; 2900fa9e4066Sahrens total = vs->vs_alloc; 2901fa9e4066Sahrens 2902fa9e4066Sahrens if (end != 0) { 290318ce54dfSek110237 minutes_taken = (uint64_t)((end - start) / 60); 290418ce54dfSek110237 290518ce54dfSek110237 (void) printf(gettext("%s %s after %lluh%um with %llu errors " 290618ce54dfSek110237 "on %s"), 2907fa9e4066Sahrens scrub_type, vs->vs_scrub_complete ? "completed" : "stopped", 290818ce54dfSek110237 (u_longlong_t)(minutes_taken / 60), 290918ce54dfSek110237 (uint_t)(minutes_taken % 60), 2910fa9e4066Sahrens (u_longlong_t)vs->vs_scrub_errors, ctime(&end)); 2911fa9e4066Sahrens return; 2912fa9e4066Sahrens } 2913fa9e4066Sahrens 2914fa9e4066Sahrens if (examined == 0) 2915fa9e4066Sahrens examined = 1; 2916fa9e4066Sahrens if (examined > total) 2917fa9e4066Sahrens total = examined; 2918fa9e4066Sahrens 2919fa9e4066Sahrens fraction_done = (double)examined / total; 2920fa9e4066Sahrens minutes_left = (uint64_t)((now - start) * 2921fa9e4066Sahrens (1 - fraction_done) / fraction_done / 60); 292218ce54dfSek110237 minutes_taken = (uint64_t)((now - start) / 60); 2923fa9e4066Sahrens 292418ce54dfSek110237 (void) printf(gettext("%s in progress for %lluh%um, %.2f%% done, " 292518ce54dfSek110237 "%lluh%um to go\n"), 292618ce54dfSek110237 scrub_type, (u_longlong_t)(minutes_taken / 60), 292718ce54dfSek110237 (uint_t)(minutes_taken % 60), 100 * fraction_done, 2928fa9e4066Sahrens (u_longlong_t)(minutes_left / 60), (uint_t)(minutes_left % 60)); 2929fa9e4066Sahrens } 2930fa9e4066Sahrens 2931ea8dc4b6Seschrock static void 2932ea8dc4b6Seschrock print_error_log(zpool_handle_t *zhp) 2933ea8dc4b6Seschrock { 293475519f38Sek110237 nvlist_t *nverrlist = NULL; 293555434c77Sek110237 nvpair_t *elem; 293655434c77Sek110237 char *pathname; 293755434c77Sek110237 size_t len = MAXPATHLEN * 2; 2938ea8dc4b6Seschrock 293955434c77Sek110237 if (zpool_get_errlog(zhp, &nverrlist) != 0) { 2940ea8dc4b6Seschrock (void) printf("errors: List of errors unavailable " 2941ea8dc4b6Seschrock "(insufficient privileges)\n"); 2942ea8dc4b6Seschrock return; 2943ea8dc4b6Seschrock } 2944ea8dc4b6Seschrock 294555434c77Sek110237 (void) printf("errors: Permanent errors have been " 294655434c77Sek110237 "detected in the following files:\n\n"); 2947ea8dc4b6Seschrock 294855434c77Sek110237 pathname = safe_malloc(len); 294955434c77Sek110237 elem = NULL; 295055434c77Sek110237 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 295155434c77Sek110237 nvlist_t *nv; 295255434c77Sek110237 uint64_t dsobj, obj; 2953ea8dc4b6Seschrock 295455434c77Sek110237 verify(nvpair_value_nvlist(elem, &nv) == 0); 295555434c77Sek110237 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 295655434c77Sek110237 &dsobj) == 0); 295755434c77Sek110237 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 295855434c77Sek110237 &obj) == 0); 295955434c77Sek110237 zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 296055434c77Sek110237 (void) printf("%7s %s\n", "", pathname); 2961ea8dc4b6Seschrock } 296255434c77Sek110237 free(pathname); 296355434c77Sek110237 nvlist_free(nverrlist); 2964ea8dc4b6Seschrock } 2965ea8dc4b6Seschrock 296699653d4eSeschrock static void 296799653d4eSeschrock print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares, 296899653d4eSeschrock int namewidth) 296999653d4eSeschrock { 297099653d4eSeschrock uint_t i; 297199653d4eSeschrock char *name; 297299653d4eSeschrock 297399653d4eSeschrock if (nspares == 0) 297499653d4eSeschrock return; 297599653d4eSeschrock 297699653d4eSeschrock (void) printf(gettext("\tspares\n")); 297799653d4eSeschrock 297899653d4eSeschrock for (i = 0; i < nspares; i++) { 297999653d4eSeschrock name = zpool_vdev_name(g_zfs, zhp, spares[i]); 298099653d4eSeschrock print_status_config(zhp, name, spares[i], 2981aa8cf21aSNeil Perrin namewidth, 2, B_TRUE); 298299653d4eSeschrock free(name); 298399653d4eSeschrock } 298499653d4eSeschrock } 298599653d4eSeschrock 2986fa94a07fSbrendan static void 2987fa94a07fSbrendan print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache, 2988fa94a07fSbrendan int namewidth) 2989fa94a07fSbrendan { 2990fa94a07fSbrendan uint_t i; 2991fa94a07fSbrendan char *name; 2992fa94a07fSbrendan 2993fa94a07fSbrendan if (nl2cache == 0) 2994fa94a07fSbrendan return; 2995fa94a07fSbrendan 2996fa94a07fSbrendan (void) printf(gettext("\tcache\n")); 2997fa94a07fSbrendan 2998fa94a07fSbrendan for (i = 0; i < nl2cache; i++) { 2999fa94a07fSbrendan name = zpool_vdev_name(g_zfs, zhp, l2cache[i]); 3000fa94a07fSbrendan print_status_config(zhp, name, l2cache[i], 3001aa8cf21aSNeil Perrin namewidth, 2, B_FALSE); 3002aa8cf21aSNeil Perrin free(name); 3003aa8cf21aSNeil Perrin } 3004aa8cf21aSNeil Perrin } 3005aa8cf21aSNeil Perrin 3006aa8cf21aSNeil Perrin /* 3007fa9e4066Sahrens * Display a summary of pool status. Displays a summary such as: 3008fa9e4066Sahrens * 3009fa9e4066Sahrens * pool: tank 3010fa9e4066Sahrens * status: DEGRADED 3011fa9e4066Sahrens * reason: One or more devices ... 3012fa9e4066Sahrens * see: http://www.sun.com/msg/ZFS-xxxx-01 3013fa9e4066Sahrens * config: 3014fa9e4066Sahrens * mirror DEGRADED 3015fa9e4066Sahrens * c1t0d0 OK 3016ea8dc4b6Seschrock * c2t0d0 UNAVAIL 3017fa9e4066Sahrens * 3018fa9e4066Sahrens * When given the '-v' option, we print out the complete config. If the '-e' 3019fa9e4066Sahrens * option is specified, then we print out error rate information as well. 3020fa9e4066Sahrens */ 3021fa9e4066Sahrens int 3022fa9e4066Sahrens status_callback(zpool_handle_t *zhp, void *data) 3023fa9e4066Sahrens { 3024fa9e4066Sahrens status_cbdata_t *cbp = data; 3025fa9e4066Sahrens nvlist_t *config, *nvroot; 3026fa9e4066Sahrens char *msgid; 3027fa9e4066Sahrens int reason; 302846657f8dSmmusante const char *health; 302946657f8dSmmusante uint_t c; 303046657f8dSmmusante vdev_stat_t *vs; 3031fa9e4066Sahrens 3032088e9d47Seschrock config = zpool_get_config(zhp, NULL); 3033fa9e4066Sahrens reason = zpool_get_status(zhp, &msgid); 3034fa9e4066Sahrens 3035fa9e4066Sahrens cbp->cb_count++; 3036fa9e4066Sahrens 3037fa9e4066Sahrens /* 3038fa9e4066Sahrens * If we were given 'zpool status -x', only report those pools with 3039fa9e4066Sahrens * problems. 3040fa9e4066Sahrens */ 3041e9dbad6fSeschrock if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) { 3042e9dbad6fSeschrock if (!cbp->cb_allpools) { 3043e9dbad6fSeschrock (void) printf(gettext("pool '%s' is healthy\n"), 3044e9dbad6fSeschrock zpool_get_name(zhp)); 3045e9dbad6fSeschrock if (cbp->cb_first) 3046e9dbad6fSeschrock cbp->cb_first = B_FALSE; 3047e9dbad6fSeschrock } 3048fa9e4066Sahrens return (0); 3049e9dbad6fSeschrock } 3050fa9e4066Sahrens 3051fa9e4066Sahrens if (cbp->cb_first) 305299653d4eSeschrock cbp->cb_first = B_FALSE; 3053fa9e4066Sahrens else 3054fa9e4066Sahrens (void) printf("\n"); 3055fa9e4066Sahrens 305646657f8dSmmusante verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 305746657f8dSmmusante &nvroot) == 0); 305846657f8dSmmusante verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, 305946657f8dSmmusante (uint64_t **)&vs, &c) == 0); 3060990b4856Slling health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 3061fa9e4066Sahrens 3062fa9e4066Sahrens (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 3063fa9e4066Sahrens (void) printf(gettext(" state: %s\n"), health); 3064fa9e4066Sahrens 3065fa9e4066Sahrens switch (reason) { 3066fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_R: 3067fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 3068fa9e4066Sahrens "be opened. Sufficient replicas exist for\n\tthe pool to " 3069fa9e4066Sahrens "continue functioning in a degraded state.\n")); 3070fa9e4066Sahrens (void) printf(gettext("action: Attach the missing device and " 3071fa9e4066Sahrens "online it using 'zpool online'.\n")); 3072fa9e4066Sahrens break; 3073fa9e4066Sahrens 3074fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_NR: 3075fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 3076fa9e4066Sahrens "be opened. There are insufficient\n\treplicas for the " 3077fa9e4066Sahrens "pool to continue functioning.\n")); 3078fa9e4066Sahrens (void) printf(gettext("action: Attach the missing device and " 3079fa9e4066Sahrens "online it using 'zpool online'.\n")); 3080fa9e4066Sahrens break; 3081fa9e4066Sahrens 3082fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_R: 3083fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 3084fa9e4066Sahrens "be used because the label is missing or\n\tinvalid. " 3085fa9e4066Sahrens "Sufficient replicas exist for the pool to continue\n\t" 3086fa9e4066Sahrens "functioning in a degraded state.\n")); 3087fa9e4066Sahrens (void) printf(gettext("action: Replace the device using " 3088fa9e4066Sahrens "'zpool replace'.\n")); 3089fa9e4066Sahrens break; 3090fa9e4066Sahrens 3091fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_NR: 3092fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 3093b1b8ab34Slling "be used because the label is missing \n\tor invalid. " 3094fa9e4066Sahrens "There are insufficient replicas for the pool to " 3095fa9e4066Sahrens "continue\n\tfunctioning.\n")); 3096fa9e4066Sahrens (void) printf(gettext("action: Destroy and re-create the pool " 3097fa9e4066Sahrens "from a backup source.\n")); 3098fa9e4066Sahrens break; 3099fa9e4066Sahrens 3100fa9e4066Sahrens case ZPOOL_STATUS_FAILING_DEV: 3101fa9e4066Sahrens (void) printf(gettext("status: One or more devices has " 3102fa9e4066Sahrens "experienced an unrecoverable error. An\n\tattempt was " 3103fa9e4066Sahrens "made to correct the error. Applications are " 3104fa9e4066Sahrens "unaffected.\n")); 3105fa9e4066Sahrens (void) printf(gettext("action: Determine if the device needs " 3106fa9e4066Sahrens "to be replaced, and clear the errors\n\tusing " 3107ea8dc4b6Seschrock "'zpool clear' or replace the device with 'zpool " 3108fa9e4066Sahrens "replace'.\n")); 3109fa9e4066Sahrens break; 3110fa9e4066Sahrens 3111fa9e4066Sahrens case ZPOOL_STATUS_OFFLINE_DEV: 3112fa9e4066Sahrens (void) printf(gettext("status: One or more devices has " 3113d7d4af51Smmusante "been taken offline by the administrator.\n\tSufficient " 3114fa9e4066Sahrens "replicas exist for the pool to continue functioning in " 3115fa9e4066Sahrens "a\n\tdegraded state.\n")); 3116fa9e4066Sahrens (void) printf(gettext("action: Online the device using " 3117fa9e4066Sahrens "'zpool online' or replace the device with\n\t'zpool " 3118fa9e4066Sahrens "replace'.\n")); 3119fa9e4066Sahrens break; 3120fa9e4066Sahrens 3121fa9e4066Sahrens case ZPOOL_STATUS_RESILVERING: 3122fa9e4066Sahrens (void) printf(gettext("status: One or more devices is " 3123fa9e4066Sahrens "currently being resilvered. The pool will\n\tcontinue " 3124fa9e4066Sahrens "to function, possibly in a degraded state.\n")); 3125fa9e4066Sahrens (void) printf(gettext("action: Wait for the resilver to " 3126fa9e4066Sahrens "complete.\n")); 3127fa9e4066Sahrens break; 3128fa9e4066Sahrens 3129ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_DATA: 3130ea8dc4b6Seschrock (void) printf(gettext("status: One or more devices has " 3131ea8dc4b6Seschrock "experienced an error resulting in data\n\tcorruption. " 3132ea8dc4b6Seschrock "Applications may be affected.\n")); 3133ea8dc4b6Seschrock (void) printf(gettext("action: Restore the file in question " 3134ea8dc4b6Seschrock "if possible. Otherwise restore the\n\tentire pool from " 3135ea8dc4b6Seschrock "backup.\n")); 3136ea8dc4b6Seschrock break; 3137ea8dc4b6Seschrock 3138ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_POOL: 3139ea8dc4b6Seschrock (void) printf(gettext("status: The pool metadata is corrupted " 3140ea8dc4b6Seschrock "and the pool cannot be opened.\n")); 3141ea8dc4b6Seschrock (void) printf(gettext("action: Destroy and re-create the pool " 3142ea8dc4b6Seschrock "from a backup source.\n")); 3143ea8dc4b6Seschrock break; 3144ea8dc4b6Seschrock 3145eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_OLDER: 3146eaca9bbdSeschrock (void) printf(gettext("status: The pool is formatted using an " 3147eaca9bbdSeschrock "older on-disk format. The pool can\n\tstill be used, but " 3148eaca9bbdSeschrock "some features are unavailable.\n")); 3149eaca9bbdSeschrock (void) printf(gettext("action: Upgrade the pool using 'zpool " 3150eaca9bbdSeschrock "upgrade'. Once this is done, the\n\tpool will no longer " 3151eaca9bbdSeschrock "be accessible on older software versions.\n")); 3152eaca9bbdSeschrock break; 3153eaca9bbdSeschrock 3154eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 3155eaca9bbdSeschrock (void) printf(gettext("status: The pool has been upgraded to a " 3156eaca9bbdSeschrock "newer, incompatible on-disk version.\n\tThe pool cannot " 3157eaca9bbdSeschrock "be accessed on this system.\n")); 3158eaca9bbdSeschrock (void) printf(gettext("action: Access the pool from a system " 3159eaca9bbdSeschrock "running more recent software, or\n\trestore the pool from " 3160eaca9bbdSeschrock "backup.\n")); 3161eaca9bbdSeschrock break; 3162eaca9bbdSeschrock 31633d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_R: 31643d7072f8Seschrock (void) printf(gettext("status: One or more devices are " 31653d7072f8Seschrock "faulted in response to persistent errors.\n\tSufficient " 31663d7072f8Seschrock "replicas exist for the pool to continue functioning " 31673d7072f8Seschrock "in a\n\tdegraded state.\n")); 31683d7072f8Seschrock (void) printf(gettext("action: Replace the faulted device, " 31693d7072f8Seschrock "or use 'zpool clear' to mark the device\n\trepaired.\n")); 31703d7072f8Seschrock break; 31713d7072f8Seschrock 31723d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_NR: 31733d7072f8Seschrock (void) printf(gettext("status: One or more devices are " 31743d7072f8Seschrock "faulted in response to persistent errors. There are " 31753d7072f8Seschrock "insufficient replicas for the pool to\n\tcontinue " 31763d7072f8Seschrock "functioning.\n")); 31773d7072f8Seschrock (void) printf(gettext("action: Destroy and re-create the pool " 31783d7072f8Seschrock "from a backup source. Manually marking the device\n" 31793d7072f8Seschrock "\trepaired using 'zpool clear' may allow some data " 31803d7072f8Seschrock "to be recovered.\n")); 31813d7072f8Seschrock break; 31823d7072f8Seschrock 318332b87932Sek110237 case ZPOOL_STATUS_IO_FAILURE_WAIT: 318432b87932Sek110237 case ZPOOL_STATUS_IO_FAILURE_CONTINUE: 318532b87932Sek110237 (void) printf(gettext("status: One or more devices are " 31868a79c1b5Sek110237 "faulted in response to IO failures.\n")); 318732b87932Sek110237 (void) printf(gettext("action: Make sure the affected devices " 318832b87932Sek110237 "are connected, then run 'zpool clear'.\n")); 318932b87932Sek110237 break; 319032b87932Sek110237 3191b87f3af3Sperrin case ZPOOL_STATUS_BAD_LOG: 3192b87f3af3Sperrin (void) printf(gettext("status: An intent log record " 3193b87f3af3Sperrin "could not be read.\n" 3194b87f3af3Sperrin "\tWaiting for adminstrator intervention to fix the " 3195b87f3af3Sperrin "faulted pool.\n")); 3196b87f3af3Sperrin (void) printf(gettext("action: Either restore the affected " 3197b87f3af3Sperrin "device(s) and run 'zpool online',\n" 3198b87f3af3Sperrin "\tor ignore the intent log records by running " 3199b87f3af3Sperrin "'zpool clear'.\n")); 3200b87f3af3Sperrin break; 3201b87f3af3Sperrin 3202fa9e4066Sahrens default: 3203fa9e4066Sahrens /* 3204fa9e4066Sahrens * The remaining errors can't actually be generated, yet. 3205fa9e4066Sahrens */ 3206fa9e4066Sahrens assert(reason == ZPOOL_STATUS_OK); 3207fa9e4066Sahrens } 3208fa9e4066Sahrens 3209fa9e4066Sahrens if (msgid != NULL) 3210fa9e4066Sahrens (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), 3211fa9e4066Sahrens msgid); 3212fa9e4066Sahrens 3213fa9e4066Sahrens if (config != NULL) { 3214fa9e4066Sahrens int namewidth; 3215ea8dc4b6Seschrock uint64_t nerr; 3216fa94a07fSbrendan nvlist_t **spares, **l2cache; 3217fa94a07fSbrendan uint_t nspares, nl2cache; 3218fa9e4066Sahrens 3219fa9e4066Sahrens 3220fa9e4066Sahrens (void) printf(gettext(" scrub: ")); 3221fa9e4066Sahrens print_scrub_status(nvroot); 3222fa9e4066Sahrens 3223c67d9675Seschrock namewidth = max_width(zhp, nvroot, 0, 0); 3224fa9e4066Sahrens if (namewidth < 10) 3225fa9e4066Sahrens namewidth = 10; 3226fa9e4066Sahrens 3227fa9e4066Sahrens (void) printf(gettext("config:\n\n")); 3228fa9e4066Sahrens (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth, 3229fa9e4066Sahrens "NAME", "STATE", "READ", "WRITE", "CKSUM"); 3230c67d9675Seschrock print_status_config(zhp, zpool_get_name(zhp), nvroot, 3231aa8cf21aSNeil Perrin namewidth, 0, B_FALSE); 323299653d4eSeschrock 32334dea40f0SNeil Perrin if (num_logs(nvroot) > 0) 3234e6ca193dSGeorge Wilson print_logs(zhp, nvroot, namewidth, B_TRUE); 3235fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 3236fa94a07fSbrendan &l2cache, &nl2cache) == 0) 3237fa94a07fSbrendan print_l2cache(zhp, l2cache, nl2cache, namewidth); 3238fa94a07fSbrendan 323999653d4eSeschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 324099653d4eSeschrock &spares, &nspares) == 0) 324199653d4eSeschrock print_spares(zhp, spares, nspares, namewidth); 3242ea8dc4b6Seschrock 3243ea8dc4b6Seschrock if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 3244ea8dc4b6Seschrock &nerr) == 0) { 324555434c77Sek110237 nvlist_t *nverrlist = NULL; 324655434c77Sek110237 3247ea8dc4b6Seschrock /* 3248ea8dc4b6Seschrock * If the approximate error count is small, get a 3249ea8dc4b6Seschrock * precise count by fetching the entire log and 3250ea8dc4b6Seschrock * uniquifying the results. 3251ea8dc4b6Seschrock */ 325275519f38Sek110237 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose && 325355434c77Sek110237 zpool_get_errlog(zhp, &nverrlist) == 0) { 325455434c77Sek110237 nvpair_t *elem; 325555434c77Sek110237 325655434c77Sek110237 elem = NULL; 325755434c77Sek110237 nerr = 0; 325855434c77Sek110237 while ((elem = nvlist_next_nvpair(nverrlist, 325955434c77Sek110237 elem)) != NULL) { 326055434c77Sek110237 nerr++; 326155434c77Sek110237 } 326255434c77Sek110237 } 326355434c77Sek110237 nvlist_free(nverrlist); 3264ea8dc4b6Seschrock 3265ea8dc4b6Seschrock (void) printf("\n"); 326699653d4eSeschrock 3267ea8dc4b6Seschrock if (nerr == 0) 3268ea8dc4b6Seschrock (void) printf(gettext("errors: No known data " 3269ea8dc4b6Seschrock "errors\n")); 3270ea8dc4b6Seschrock else if (!cbp->cb_verbose) 3271e9dbad6fSeschrock (void) printf(gettext("errors: %llu data " 32725ad82045Snd150628 "errors, use '-v' for a list\n"), 32735ad82045Snd150628 (u_longlong_t)nerr); 3274ea8dc4b6Seschrock else 3275ea8dc4b6Seschrock print_error_log(zhp); 3276ea8dc4b6Seschrock } 3277fa9e4066Sahrens } else { 3278fa9e4066Sahrens (void) printf(gettext("config: The configuration cannot be " 3279fa9e4066Sahrens "determined.\n")); 3280fa9e4066Sahrens } 3281fa9e4066Sahrens 3282fa9e4066Sahrens return (0); 3283fa9e4066Sahrens } 3284fa9e4066Sahrens 3285fa9e4066Sahrens /* 3286fa9e4066Sahrens * zpool status [-vx] [pool] ... 3287fa9e4066Sahrens * 3288fa9e4066Sahrens * -v Display complete error logs 3289fa9e4066Sahrens * -x Display only pools with potential problems 3290fa9e4066Sahrens * 3291fa9e4066Sahrens * Describes the health status of all pools or some subset. 3292fa9e4066Sahrens */ 3293fa9e4066Sahrens int 3294fa9e4066Sahrens zpool_do_status(int argc, char **argv) 3295fa9e4066Sahrens { 3296fa9e4066Sahrens int c; 3297fa9e4066Sahrens int ret; 3298fa9e4066Sahrens status_cbdata_t cb = { 0 }; 3299fa9e4066Sahrens 3300fa9e4066Sahrens /* check options */ 3301fa9e4066Sahrens while ((c = getopt(argc, argv, "vx")) != -1) { 3302fa9e4066Sahrens switch (c) { 3303fa9e4066Sahrens case 'v': 330499653d4eSeschrock cb.cb_verbose = B_TRUE; 3305fa9e4066Sahrens break; 3306fa9e4066Sahrens case 'x': 330799653d4eSeschrock cb.cb_explain = B_TRUE; 3308fa9e4066Sahrens break; 3309fa9e4066Sahrens case '?': 3310fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3311fa9e4066Sahrens optopt); 331299653d4eSeschrock usage(B_FALSE); 3313fa9e4066Sahrens } 3314fa9e4066Sahrens } 3315fa9e4066Sahrens 3316fa9e4066Sahrens argc -= optind; 3317fa9e4066Sahrens argv += optind; 3318fa9e4066Sahrens 331999653d4eSeschrock cb.cb_first = B_TRUE; 3320fa9e4066Sahrens 3321e9dbad6fSeschrock if (argc == 0) 3322e9dbad6fSeschrock cb.cb_allpools = B_TRUE; 3323e9dbad6fSeschrock 3324b1b8ab34Slling ret = for_each_pool(argc, argv, B_TRUE, NULL, status_callback, &cb); 3325fa9e4066Sahrens 3326fa9e4066Sahrens if (argc == 0 && cb.cb_count == 0) 3327fa9e4066Sahrens (void) printf(gettext("no pools available\n")); 3328e9dbad6fSeschrock else if (cb.cb_explain && cb.cb_first && cb.cb_allpools) 3329fa9e4066Sahrens (void) printf(gettext("all pools are healthy\n")); 3330fa9e4066Sahrens 3331fa9e4066Sahrens return (ret); 3332fa9e4066Sahrens } 3333fa9e4066Sahrens 3334eaca9bbdSeschrock typedef struct upgrade_cbdata { 3335eaca9bbdSeschrock int cb_all; 3336eaca9bbdSeschrock int cb_first; 3337eaca9bbdSeschrock int cb_newer; 333806eeb2adSek110237 int cb_argc; 3339990b4856Slling uint64_t cb_version; 334006eeb2adSek110237 char **cb_argv; 3341eaca9bbdSeschrock } upgrade_cbdata_t; 3342eaca9bbdSeschrock 3343eaca9bbdSeschrock static int 3344eaca9bbdSeschrock upgrade_cb(zpool_handle_t *zhp, void *arg) 3345eaca9bbdSeschrock { 3346eaca9bbdSeschrock upgrade_cbdata_t *cbp = arg; 3347eaca9bbdSeschrock nvlist_t *config; 3348eaca9bbdSeschrock uint64_t version; 3349eaca9bbdSeschrock int ret = 0; 3350eaca9bbdSeschrock 3351eaca9bbdSeschrock config = zpool_get_config(zhp, NULL); 3352eaca9bbdSeschrock verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 3353eaca9bbdSeschrock &version) == 0); 3354eaca9bbdSeschrock 3355e7437265Sahrens if (!cbp->cb_newer && version < SPA_VERSION) { 3356eaca9bbdSeschrock if (!cbp->cb_all) { 3357eaca9bbdSeschrock if (cbp->cb_first) { 3358eaca9bbdSeschrock (void) printf(gettext("The following pools are " 3359eaca9bbdSeschrock "out of date, and can be upgraded. After " 3360eaca9bbdSeschrock "being\nupgraded, these pools will no " 3361eaca9bbdSeschrock "longer be accessible by older software " 3362eaca9bbdSeschrock "versions.\n\n")); 3363eaca9bbdSeschrock (void) printf(gettext("VER POOL\n")); 3364eaca9bbdSeschrock (void) printf(gettext("--- ------------\n")); 336599653d4eSeschrock cbp->cb_first = B_FALSE; 3366eaca9bbdSeschrock } 3367eaca9bbdSeschrock 33685ad82045Snd150628 (void) printf("%2llu %s\n", (u_longlong_t)version, 3369eaca9bbdSeschrock zpool_get_name(zhp)); 3370eaca9bbdSeschrock } else { 337199653d4eSeschrock cbp->cb_first = B_FALSE; 3372990b4856Slling ret = zpool_upgrade(zhp, cbp->cb_version); 337306eeb2adSek110237 if (!ret) { 3374eaca9bbdSeschrock (void) printf(gettext("Successfully upgraded " 3375990b4856Slling "'%s'\n\n"), zpool_get_name(zhp)); 3376eaca9bbdSeschrock } 337706eeb2adSek110237 } 3378e7437265Sahrens } else if (cbp->cb_newer && version > SPA_VERSION) { 3379eaca9bbdSeschrock assert(!cbp->cb_all); 3380eaca9bbdSeschrock 3381eaca9bbdSeschrock if (cbp->cb_first) { 3382eaca9bbdSeschrock (void) printf(gettext("The following pools are " 3383eaca9bbdSeschrock "formatted using a newer software version and\n" 3384eaca9bbdSeschrock "cannot be accessed on the current system.\n\n")); 3385eaca9bbdSeschrock (void) printf(gettext("VER POOL\n")); 3386eaca9bbdSeschrock (void) printf(gettext("--- ------------\n")); 338799653d4eSeschrock cbp->cb_first = B_FALSE; 3388eaca9bbdSeschrock } 3389eaca9bbdSeschrock 33905ad82045Snd150628 (void) printf("%2llu %s\n", (u_longlong_t)version, 3391eaca9bbdSeschrock zpool_get_name(zhp)); 3392eaca9bbdSeschrock } 3393eaca9bbdSeschrock 3394eaca9bbdSeschrock zpool_close(zhp); 3395eaca9bbdSeschrock return (ret); 3396eaca9bbdSeschrock } 3397eaca9bbdSeschrock 3398eaca9bbdSeschrock /* ARGSUSED */ 3399eaca9bbdSeschrock static int 340006eeb2adSek110237 upgrade_one(zpool_handle_t *zhp, void *data) 3401eaca9bbdSeschrock { 3402990b4856Slling upgrade_cbdata_t *cbp = data; 3403990b4856Slling uint64_t cur_version; 3404eaca9bbdSeschrock int ret; 3405eaca9bbdSeschrock 34068654d025Sperrin if (strcmp("log", zpool_get_name(zhp)) == 0) { 34078654d025Sperrin (void) printf(gettext("'log' is now a reserved word\n" 34088654d025Sperrin "Pool 'log' must be renamed using export and import" 34098654d025Sperrin " to upgrade.\n")); 34108654d025Sperrin return (1); 34118654d025Sperrin } 3412990b4856Slling 3413990b4856Slling cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 3414e6c728e1Sbrendan if (cur_version > cbp->cb_version) { 3415eaca9bbdSeschrock (void) printf(gettext("Pool '%s' is already formatted " 3416e6c728e1Sbrendan "using more current version '%llu'.\n"), 3417e6c728e1Sbrendan zpool_get_name(zhp), cur_version); 3418e6c728e1Sbrendan return (0); 3419e6c728e1Sbrendan } 3420e6c728e1Sbrendan if (cur_version == cbp->cb_version) { 3421e6c728e1Sbrendan (void) printf(gettext("Pool '%s' is already formatted " 3422e6c728e1Sbrendan "using the current version.\n"), zpool_get_name(zhp)); 3423eaca9bbdSeschrock return (0); 3424eaca9bbdSeschrock } 3425eaca9bbdSeschrock 3426990b4856Slling ret = zpool_upgrade(zhp, cbp->cb_version); 342706eeb2adSek110237 342806eeb2adSek110237 if (!ret) { 342944cd46caSbillm (void) printf(gettext("Successfully upgraded '%s' " 3430990b4856Slling "from version %llu to version %llu\n\n"), 3431990b4856Slling zpool_get_name(zhp), (u_longlong_t)cur_version, 3432990b4856Slling (u_longlong_t)cbp->cb_version); 343306eeb2adSek110237 } 3434eaca9bbdSeschrock 3435eaca9bbdSeschrock return (ret != 0); 3436eaca9bbdSeschrock } 3437eaca9bbdSeschrock 3438eaca9bbdSeschrock /* 3439eaca9bbdSeschrock * zpool upgrade 3440eaca9bbdSeschrock * zpool upgrade -v 3441990b4856Slling * zpool upgrade [-V version] <-a | pool ...> 3442eaca9bbdSeschrock * 3443eaca9bbdSeschrock * With no arguments, display downrev'd ZFS pool available for upgrade. 3444eaca9bbdSeschrock * Individual pools can be upgraded by specifying the pool, and '-a' will 3445eaca9bbdSeschrock * upgrade all pools. 3446eaca9bbdSeschrock */ 3447eaca9bbdSeschrock int 3448eaca9bbdSeschrock zpool_do_upgrade(int argc, char **argv) 3449eaca9bbdSeschrock { 3450eaca9bbdSeschrock int c; 3451eaca9bbdSeschrock upgrade_cbdata_t cb = { 0 }; 3452eaca9bbdSeschrock int ret = 0; 3453eaca9bbdSeschrock boolean_t showversions = B_FALSE; 3454990b4856Slling char *end; 3455990b4856Slling 3456eaca9bbdSeschrock 3457eaca9bbdSeschrock /* check options */ 3458478ed9adSEric Taylor while ((c = getopt(argc, argv, ":avV:")) != -1) { 3459eaca9bbdSeschrock switch (c) { 3460eaca9bbdSeschrock case 'a': 346199653d4eSeschrock cb.cb_all = B_TRUE; 3462eaca9bbdSeschrock break; 3463eaca9bbdSeschrock case 'v': 3464eaca9bbdSeschrock showversions = B_TRUE; 3465eaca9bbdSeschrock break; 3466990b4856Slling case 'V': 3467990b4856Slling cb.cb_version = strtoll(optarg, &end, 10); 3468351420b3Slling if (*end != '\0' || cb.cb_version > SPA_VERSION || 3469351420b3Slling cb.cb_version < SPA_VERSION_1) { 3470990b4856Slling (void) fprintf(stderr, 3471990b4856Slling gettext("invalid version '%s'\n"), optarg); 3472990b4856Slling usage(B_FALSE); 3473990b4856Slling } 3474990b4856Slling break; 3475478ed9adSEric Taylor case ':': 3476478ed9adSEric Taylor (void) fprintf(stderr, gettext("missing argument for " 3477478ed9adSEric Taylor "'%c' option\n"), optopt); 3478478ed9adSEric Taylor usage(B_FALSE); 3479478ed9adSEric Taylor break; 3480eaca9bbdSeschrock case '?': 3481eaca9bbdSeschrock (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3482eaca9bbdSeschrock optopt); 348399653d4eSeschrock usage(B_FALSE); 3484eaca9bbdSeschrock } 3485eaca9bbdSeschrock } 3486eaca9bbdSeschrock 348706eeb2adSek110237 cb.cb_argc = argc; 348806eeb2adSek110237 cb.cb_argv = argv; 3489eaca9bbdSeschrock argc -= optind; 3490eaca9bbdSeschrock argv += optind; 3491eaca9bbdSeschrock 3492351420b3Slling if (cb.cb_version == 0) { 3493351420b3Slling cb.cb_version = SPA_VERSION; 3494351420b3Slling } else if (!cb.cb_all && argc == 0) { 3495351420b3Slling (void) fprintf(stderr, gettext("-V option is " 3496351420b3Slling "incompatible with other arguments\n")); 3497351420b3Slling usage(B_FALSE); 3498351420b3Slling } 3499351420b3Slling 3500eaca9bbdSeschrock if (showversions) { 3501eaca9bbdSeschrock if (cb.cb_all || argc != 0) { 3502eaca9bbdSeschrock (void) fprintf(stderr, gettext("-v option is " 3503eaca9bbdSeschrock "incompatible with other arguments\n")); 350499653d4eSeschrock usage(B_FALSE); 3505eaca9bbdSeschrock } 3506eaca9bbdSeschrock } else if (cb.cb_all) { 3507eaca9bbdSeschrock if (argc != 0) { 3508351420b3Slling (void) fprintf(stderr, gettext("-a option should not " 3509351420b3Slling "be used along with a pool name\n")); 351099653d4eSeschrock usage(B_FALSE); 3511eaca9bbdSeschrock } 3512eaca9bbdSeschrock } 3513eaca9bbdSeschrock 3514e7437265Sahrens (void) printf(gettext("This system is currently running " 3515e7437265Sahrens "ZFS pool version %llu.\n\n"), SPA_VERSION); 351699653d4eSeschrock cb.cb_first = B_TRUE; 3517eaca9bbdSeschrock if (showversions) { 3518eaca9bbdSeschrock (void) printf(gettext("The following versions are " 3519d7d4af51Smmusante "supported:\n\n")); 3520eaca9bbdSeschrock (void) printf(gettext("VER DESCRIPTION\n")); 3521eaca9bbdSeschrock (void) printf("--- -----------------------------------------" 3522eaca9bbdSeschrock "---------------\n"); 352399653d4eSeschrock (void) printf(gettext(" 1 Initial ZFS version\n")); 352444cd46caSbillm (void) printf(gettext(" 2 Ditto blocks " 352544cd46caSbillm "(replicated metadata)\n")); 352699653d4eSeschrock (void) printf(gettext(" 3 Hot spares and double parity " 352799653d4eSeschrock "RAID-Z\n")); 3528d7306b64Sek110237 (void) printf(gettext(" 4 zpool history\n")); 3529c9431fa1Sahl (void) printf(gettext(" 5 Compression using the gzip " 3530c9431fa1Sahl "algorithm\n")); 3531990b4856Slling (void) printf(gettext(" 6 bootfs pool property\n")); 35328654d025Sperrin (void) printf(gettext(" 7 Separate intent log devices\n")); 3533ecd6cf80Smarks (void) printf(gettext(" 8 Delegated administration\n")); 3534a9799022Sck153898 (void) printf(gettext(" 9 refquota and refreservation " 3535a9799022Sck153898 "properties\n")); 3536fa94a07fSbrendan (void) printf(gettext(" 10 Cache devices\n")); 3537088f3894Sahrens (void) printf(gettext(" 11 Improved scrub performance\n")); 3538bb0ade09Sahrens (void) printf(gettext(" 12 Snapshot properties\n")); 353974e7dc98SMatthew Ahrens (void) printf(gettext(" 13 snapused property\n")); 354014843421SMatthew Ahrens (void) printf(gettext(" 14 passthrough-x aclinherit\n")); 354114843421SMatthew Ahrens (void) printf(gettext(" 15 user/group space accounting\n")); 3542478ed9adSEric Taylor (void) printf(gettext(" 16 stmf property support\n")); 35438654d025Sperrin (void) printf(gettext("For more information on a particular " 3544eaca9bbdSeschrock "version, including supported releases, see:\n\n")); 3545eaca9bbdSeschrock (void) printf("http://www.opensolaris.org/os/community/zfs/" 3546eaca9bbdSeschrock "version/N\n\n"); 3547eaca9bbdSeschrock (void) printf(gettext("Where 'N' is the version number.\n")); 3548eaca9bbdSeschrock } else if (argc == 0) { 3549eaca9bbdSeschrock int notfound; 3550eaca9bbdSeschrock 355199653d4eSeschrock ret = zpool_iter(g_zfs, upgrade_cb, &cb); 3552eaca9bbdSeschrock notfound = cb.cb_first; 3553eaca9bbdSeschrock 3554eaca9bbdSeschrock if (!cb.cb_all && ret == 0) { 3555eaca9bbdSeschrock if (!cb.cb_first) 3556eaca9bbdSeschrock (void) printf("\n"); 3557eaca9bbdSeschrock cb.cb_first = B_TRUE; 3558eaca9bbdSeschrock cb.cb_newer = B_TRUE; 355999653d4eSeschrock ret = zpool_iter(g_zfs, upgrade_cb, &cb); 3560eaca9bbdSeschrock if (!cb.cb_first) { 3561eaca9bbdSeschrock notfound = B_FALSE; 3562eaca9bbdSeschrock (void) printf("\n"); 3563eaca9bbdSeschrock } 3564eaca9bbdSeschrock } 3565eaca9bbdSeschrock 3566eaca9bbdSeschrock if (ret == 0) { 3567eaca9bbdSeschrock if (notfound) 3568eaca9bbdSeschrock (void) printf(gettext("All pools are formatted " 3569eaca9bbdSeschrock "using this version.\n")); 3570eaca9bbdSeschrock else if (!cb.cb_all) 3571eaca9bbdSeschrock (void) printf(gettext("Use 'zpool upgrade -v' " 3572eaca9bbdSeschrock "for a list of available versions and " 3573eaca9bbdSeschrock "their associated\nfeatures.\n")); 3574eaca9bbdSeschrock } 3575eaca9bbdSeschrock } else { 3576b1b8ab34Slling ret = for_each_pool(argc, argv, B_FALSE, NULL, 3577b1b8ab34Slling upgrade_one, &cb); 357806eeb2adSek110237 } 357906eeb2adSek110237 358006eeb2adSek110237 return (ret); 358106eeb2adSek110237 } 358206eeb2adSek110237 3583ecd6cf80Smarks typedef struct hist_cbdata { 3584ecd6cf80Smarks boolean_t first; 3585ecd6cf80Smarks int longfmt; 3586ecd6cf80Smarks int internal; 3587ecd6cf80Smarks } hist_cbdata_t; 3588ecd6cf80Smarks 3589ecd6cf80Smarks char *hist_event_table[LOG_END] = { 3590ecd6cf80Smarks "invalid event", 3591ecd6cf80Smarks "pool create", 3592ecd6cf80Smarks "vdev add", 3593ecd6cf80Smarks "pool remove", 3594ecd6cf80Smarks "pool destroy", 3595ecd6cf80Smarks "pool export", 3596ecd6cf80Smarks "pool import", 3597ecd6cf80Smarks "vdev attach", 3598ecd6cf80Smarks "vdev replace", 3599ecd6cf80Smarks "vdev detach", 3600ecd6cf80Smarks "vdev online", 3601ecd6cf80Smarks "vdev offline", 3602ecd6cf80Smarks "vdev upgrade", 3603ecd6cf80Smarks "pool clear", 3604ecd6cf80Smarks "pool scrub", 3605ecd6cf80Smarks "pool property set", 3606ecd6cf80Smarks "create", 3607ecd6cf80Smarks "clone", 3608ecd6cf80Smarks "destroy", 3609ecd6cf80Smarks "destroy_begin_sync", 3610ecd6cf80Smarks "inherit", 3611ecd6cf80Smarks "property set", 3612ecd6cf80Smarks "quota set", 3613ecd6cf80Smarks "permission update", 3614ecd6cf80Smarks "permission remove", 3615ecd6cf80Smarks "permission who remove", 3616ecd6cf80Smarks "promote", 3617ecd6cf80Smarks "receive", 3618ecd6cf80Smarks "rename", 3619ecd6cf80Smarks "reservation set", 3620ecd6cf80Smarks "replay_inc_sync", 3621ecd6cf80Smarks "replay_full_sync", 3622ecd6cf80Smarks "rollback", 3623ecd6cf80Smarks "snapshot", 3624e7437265Sahrens "filesystem version upgrade", 3625a9799022Sck153898 "refquota set", 3626a9799022Sck153898 "refreservation set", 3627088f3894Sahrens "pool scrub done", 3628ecd6cf80Smarks }; 3629ecd6cf80Smarks 363006eeb2adSek110237 /* 363106eeb2adSek110237 * Print out the command history for a specific pool. 363206eeb2adSek110237 */ 363306eeb2adSek110237 static int 363406eeb2adSek110237 get_history_one(zpool_handle_t *zhp, void *data) 363506eeb2adSek110237 { 363606eeb2adSek110237 nvlist_t *nvhis; 363706eeb2adSek110237 nvlist_t **records; 363806eeb2adSek110237 uint_t numrecords; 363906eeb2adSek110237 char *cmdstr; 3640ecd6cf80Smarks char *pathstr; 364106eeb2adSek110237 uint64_t dst_time; 364206eeb2adSek110237 time_t tsec; 364306eeb2adSek110237 struct tm t; 364406eeb2adSek110237 char tbuf[30]; 364506eeb2adSek110237 int ret, i; 3646ecd6cf80Smarks uint64_t who; 3647ecd6cf80Smarks struct passwd *pwd; 3648ecd6cf80Smarks char *hostname; 3649ecd6cf80Smarks char *zonename; 3650ecd6cf80Smarks char internalstr[MAXPATHLEN]; 3651ecd6cf80Smarks hist_cbdata_t *cb = (hist_cbdata_t *)data; 3652ecd6cf80Smarks uint64_t txg; 3653ecd6cf80Smarks uint64_t ievent; 365406eeb2adSek110237 3655ecd6cf80Smarks cb->first = B_FALSE; 365606eeb2adSek110237 365706eeb2adSek110237 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); 365806eeb2adSek110237 365906eeb2adSek110237 if ((ret = zpool_get_history(zhp, &nvhis)) != 0) 366006eeb2adSek110237 return (ret); 366106eeb2adSek110237 366206eeb2adSek110237 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, 366306eeb2adSek110237 &records, &numrecords) == 0); 366406eeb2adSek110237 for (i = 0; i < numrecords; i++) { 366506eeb2adSek110237 if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME, 3666ecd6cf80Smarks &dst_time) != 0) 3667ecd6cf80Smarks continue; 3668ecd6cf80Smarks 3669ecd6cf80Smarks /* is it an internal event or a standard event? */ 3670ecd6cf80Smarks if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD, 3671ecd6cf80Smarks &cmdstr) != 0) { 3672ecd6cf80Smarks if (cb->internal == 0) 3673ecd6cf80Smarks continue; 3674ecd6cf80Smarks 3675ecd6cf80Smarks if (nvlist_lookup_uint64(records[i], 3676ecd6cf80Smarks ZPOOL_HIST_INT_EVENT, &ievent) != 0) 3677ecd6cf80Smarks continue; 3678ecd6cf80Smarks verify(nvlist_lookup_uint64(records[i], 3679ecd6cf80Smarks ZPOOL_HIST_TXG, &txg) == 0); 3680ecd6cf80Smarks verify(nvlist_lookup_string(records[i], 3681ecd6cf80Smarks ZPOOL_HIST_INT_STR, &pathstr) == 0); 3682088f3894Sahrens if (ievent >= LOG_END) 3683ecd6cf80Smarks continue; 3684ecd6cf80Smarks (void) snprintf(internalstr, 3685ecd6cf80Smarks sizeof (internalstr), 3686ecd6cf80Smarks "[internal %s txg:%lld] %s", 3687ecd6cf80Smarks hist_event_table[ievent], txg, 3688ecd6cf80Smarks pathstr); 3689ecd6cf80Smarks cmdstr = internalstr; 3690ecd6cf80Smarks } 369106eeb2adSek110237 tsec = dst_time; 369206eeb2adSek110237 (void) localtime_r(&tsec, &t); 369306eeb2adSek110237 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 3694ecd6cf80Smarks (void) printf("%s %s", tbuf, cmdstr); 3695ecd6cf80Smarks 3696ecd6cf80Smarks if (!cb->longfmt) { 3697ecd6cf80Smarks (void) printf("\n"); 3698ecd6cf80Smarks continue; 369906eeb2adSek110237 } 3700ecd6cf80Smarks (void) printf(" ["); 3701ecd6cf80Smarks if (nvlist_lookup_uint64(records[i], 3702ecd6cf80Smarks ZPOOL_HIST_WHO, &who) == 0) { 3703ecd6cf80Smarks pwd = getpwuid((uid_t)who); 3704ecd6cf80Smarks if (pwd) 3705ecd6cf80Smarks (void) printf("user %s on", 3706ecd6cf80Smarks pwd->pw_name); 3707ecd6cf80Smarks else 3708ecd6cf80Smarks (void) printf("user %d on", 3709ecd6cf80Smarks (int)who); 3710ecd6cf80Smarks } else { 3711ecd6cf80Smarks (void) printf(gettext("no info]\n")); 3712ecd6cf80Smarks continue; 3713ecd6cf80Smarks } 3714ecd6cf80Smarks if (nvlist_lookup_string(records[i], 3715ecd6cf80Smarks ZPOOL_HIST_HOST, &hostname) == 0) { 3716ecd6cf80Smarks (void) printf(" %s", hostname); 3717ecd6cf80Smarks } 3718ecd6cf80Smarks if (nvlist_lookup_string(records[i], 3719ecd6cf80Smarks ZPOOL_HIST_ZONE, &zonename) == 0) { 3720ecd6cf80Smarks (void) printf(":%s", zonename); 3721ecd6cf80Smarks } 3722ecd6cf80Smarks 3723ecd6cf80Smarks (void) printf("]"); 3724ecd6cf80Smarks (void) printf("\n"); 372506eeb2adSek110237 } 372606eeb2adSek110237 (void) printf("\n"); 372706eeb2adSek110237 nvlist_free(nvhis); 372806eeb2adSek110237 372906eeb2adSek110237 return (ret); 373006eeb2adSek110237 } 373106eeb2adSek110237 373206eeb2adSek110237 /* 373306eeb2adSek110237 * zpool history <pool> 373406eeb2adSek110237 * 373506eeb2adSek110237 * Displays the history of commands that modified pools. 373606eeb2adSek110237 */ 3737ecd6cf80Smarks 3738ecd6cf80Smarks 373906eeb2adSek110237 int 374006eeb2adSek110237 zpool_do_history(int argc, char **argv) 374106eeb2adSek110237 { 3742ecd6cf80Smarks hist_cbdata_t cbdata = { 0 }; 374306eeb2adSek110237 int ret; 3744ecd6cf80Smarks int c; 374506eeb2adSek110237 3746ecd6cf80Smarks cbdata.first = B_TRUE; 3747ecd6cf80Smarks /* check options */ 3748ecd6cf80Smarks while ((c = getopt(argc, argv, "li")) != -1) { 3749ecd6cf80Smarks switch (c) { 3750ecd6cf80Smarks case 'l': 3751ecd6cf80Smarks cbdata.longfmt = 1; 3752ecd6cf80Smarks break; 3753ecd6cf80Smarks case 'i': 3754ecd6cf80Smarks cbdata.internal = 1; 3755ecd6cf80Smarks break; 3756ecd6cf80Smarks case '?': 3757ecd6cf80Smarks (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3758ecd6cf80Smarks optopt); 3759ecd6cf80Smarks usage(B_FALSE); 3760ecd6cf80Smarks } 3761ecd6cf80Smarks } 376206eeb2adSek110237 argc -= optind; 376306eeb2adSek110237 argv += optind; 376406eeb2adSek110237 3765b1b8ab34Slling ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one, 3766ecd6cf80Smarks &cbdata); 376706eeb2adSek110237 3768ecd6cf80Smarks if (argc == 0 && cbdata.first == B_TRUE) { 376906eeb2adSek110237 (void) printf(gettext("no pools available\n")); 377006eeb2adSek110237 return (0); 3771eaca9bbdSeschrock } 3772eaca9bbdSeschrock 3773eaca9bbdSeschrock return (ret); 3774eaca9bbdSeschrock } 3775eaca9bbdSeschrock 3776b1b8ab34Slling static int 3777b1b8ab34Slling get_callback(zpool_handle_t *zhp, void *data) 3778b1b8ab34Slling { 3779990b4856Slling zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; 3780b1b8ab34Slling char value[MAXNAMELEN]; 3781990b4856Slling zprop_source_t srctype; 3782990b4856Slling zprop_list_t *pl; 3783b1b8ab34Slling 3784b1b8ab34Slling for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 3785b1b8ab34Slling 3786b1b8ab34Slling /* 3787990b4856Slling * Skip the special fake placeholder. This will also skip 3788990b4856Slling * over the name property when 'all' is specified. 3789b1b8ab34Slling */ 3790990b4856Slling if (pl->pl_prop == ZPOOL_PROP_NAME && 3791b1b8ab34Slling pl == cbp->cb_proplist) 3792b1b8ab34Slling continue; 3793b1b8ab34Slling 3794b1b8ab34Slling if (zpool_get_prop(zhp, pl->pl_prop, 3795b1b8ab34Slling value, sizeof (value), &srctype) != 0) 3796b1b8ab34Slling continue; 3797b1b8ab34Slling 3798990b4856Slling zprop_print_one_property(zpool_get_name(zhp), cbp, 3799b1b8ab34Slling zpool_prop_to_name(pl->pl_prop), value, srctype, NULL); 3800b1b8ab34Slling } 3801b1b8ab34Slling return (0); 3802b1b8ab34Slling } 3803b1b8ab34Slling 3804b1b8ab34Slling int 3805b1b8ab34Slling zpool_do_get(int argc, char **argv) 3806b1b8ab34Slling { 3807990b4856Slling zprop_get_cbdata_t cb = { 0 }; 3808990b4856Slling zprop_list_t fake_name = { 0 }; 3809b1b8ab34Slling int ret; 3810b1b8ab34Slling 3811b1b8ab34Slling if (argc < 3) 3812b1b8ab34Slling usage(B_FALSE); 3813b1b8ab34Slling 3814b1b8ab34Slling cb.cb_first = B_TRUE; 3815990b4856Slling cb.cb_sources = ZPROP_SRC_ALL; 3816b1b8ab34Slling cb.cb_columns[0] = GET_COL_NAME; 3817b1b8ab34Slling cb.cb_columns[1] = GET_COL_PROPERTY; 3818b1b8ab34Slling cb.cb_columns[2] = GET_COL_VALUE; 3819b1b8ab34Slling cb.cb_columns[3] = GET_COL_SOURCE; 3820990b4856Slling cb.cb_type = ZFS_TYPE_POOL; 3821b1b8ab34Slling 3822990b4856Slling if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist, 3823990b4856Slling ZFS_TYPE_POOL) != 0) 3824b1b8ab34Slling usage(B_FALSE); 3825b1b8ab34Slling 3826b1b8ab34Slling if (cb.cb_proplist != NULL) { 3827990b4856Slling fake_name.pl_prop = ZPOOL_PROP_NAME; 3828b1b8ab34Slling fake_name.pl_width = strlen(gettext("NAME")); 3829b1b8ab34Slling fake_name.pl_next = cb.cb_proplist; 3830b1b8ab34Slling cb.cb_proplist = &fake_name; 3831b1b8ab34Slling } 3832b1b8ab34Slling 3833b1b8ab34Slling ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist, 3834b1b8ab34Slling get_callback, &cb); 3835b1b8ab34Slling 3836b1b8ab34Slling if (cb.cb_proplist == &fake_name) 3837990b4856Slling zprop_free_list(fake_name.pl_next); 3838b1b8ab34Slling else 3839990b4856Slling zprop_free_list(cb.cb_proplist); 3840b1b8ab34Slling 3841b1b8ab34Slling return (ret); 3842b1b8ab34Slling } 3843b1b8ab34Slling 3844b1b8ab34Slling typedef struct set_cbdata { 3845b1b8ab34Slling char *cb_propname; 3846b1b8ab34Slling char *cb_value; 3847b1b8ab34Slling boolean_t cb_any_successful; 3848b1b8ab34Slling } set_cbdata_t; 3849b1b8ab34Slling 3850b1b8ab34Slling int 3851b1b8ab34Slling set_callback(zpool_handle_t *zhp, void *data) 3852b1b8ab34Slling { 3853b1b8ab34Slling int error; 3854b1b8ab34Slling set_cbdata_t *cb = (set_cbdata_t *)data; 3855b1b8ab34Slling 3856b1b8ab34Slling error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value); 3857b1b8ab34Slling 3858b1b8ab34Slling if (!error) 3859b1b8ab34Slling cb->cb_any_successful = B_TRUE; 3860b1b8ab34Slling 3861b1b8ab34Slling return (error); 3862b1b8ab34Slling } 3863b1b8ab34Slling 3864b1b8ab34Slling int 3865b1b8ab34Slling zpool_do_set(int argc, char **argv) 3866b1b8ab34Slling { 3867b1b8ab34Slling set_cbdata_t cb = { 0 }; 3868b1b8ab34Slling int error; 3869b1b8ab34Slling 3870b1b8ab34Slling if (argc > 1 && argv[1][0] == '-') { 3871b1b8ab34Slling (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3872b1b8ab34Slling argv[1][1]); 3873b1b8ab34Slling usage(B_FALSE); 3874b1b8ab34Slling } 3875b1b8ab34Slling 3876b1b8ab34Slling if (argc < 2) { 3877b1b8ab34Slling (void) fprintf(stderr, gettext("missing property=value " 3878b1b8ab34Slling "argument\n")); 3879b1b8ab34Slling usage(B_FALSE); 3880b1b8ab34Slling } 3881b1b8ab34Slling 3882b1b8ab34Slling if (argc < 3) { 3883b1b8ab34Slling (void) fprintf(stderr, gettext("missing pool name\n")); 3884b1b8ab34Slling usage(B_FALSE); 3885b1b8ab34Slling } 3886b1b8ab34Slling 3887b1b8ab34Slling if (argc > 3) { 3888b1b8ab34Slling (void) fprintf(stderr, gettext("too many pool names\n")); 3889b1b8ab34Slling usage(B_FALSE); 3890b1b8ab34Slling } 3891b1b8ab34Slling 3892b1b8ab34Slling cb.cb_propname = argv[1]; 3893b1b8ab34Slling cb.cb_value = strchr(cb.cb_propname, '='); 3894b1b8ab34Slling if (cb.cb_value == NULL) { 3895b1b8ab34Slling (void) fprintf(stderr, gettext("missing value in " 3896b1b8ab34Slling "property=value argument\n")); 3897b1b8ab34Slling usage(B_FALSE); 3898b1b8ab34Slling } 3899b1b8ab34Slling 3900b1b8ab34Slling *(cb.cb_value) = '\0'; 3901b1b8ab34Slling cb.cb_value++; 3902b1b8ab34Slling 3903b1b8ab34Slling error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, 3904b1b8ab34Slling set_callback, &cb); 3905b1b8ab34Slling 3906b1b8ab34Slling return (error); 3907b1b8ab34Slling } 3908b1b8ab34Slling 3909b1b8ab34Slling static int 3910b1b8ab34Slling find_command_idx(char *command, int *idx) 3911b1b8ab34Slling { 3912b1b8ab34Slling int i; 3913b1b8ab34Slling 3914b1b8ab34Slling for (i = 0; i < NCOMMAND; i++) { 3915b1b8ab34Slling if (command_table[i].name == NULL) 3916b1b8ab34Slling continue; 3917b1b8ab34Slling 3918b1b8ab34Slling if (strcmp(command, command_table[i].name) == 0) { 3919b1b8ab34Slling *idx = i; 3920b1b8ab34Slling return (0); 3921b1b8ab34Slling } 3922b1b8ab34Slling } 3923b1b8ab34Slling return (1); 3924b1b8ab34Slling } 3925b1b8ab34Slling 3926fa9e4066Sahrens int 3927fa9e4066Sahrens main(int argc, char **argv) 3928fa9e4066Sahrens { 3929fa9e4066Sahrens int ret; 3930fa9e4066Sahrens int i; 3931fa9e4066Sahrens char *cmdname; 3932fa9e4066Sahrens 3933fa9e4066Sahrens (void) setlocale(LC_ALL, ""); 3934fa9e4066Sahrens (void) textdomain(TEXT_DOMAIN); 3935fa9e4066Sahrens 393699653d4eSeschrock if ((g_zfs = libzfs_init()) == NULL) { 393799653d4eSeschrock (void) fprintf(stderr, gettext("internal error: failed to " 3938203a47d8Snd150628 "initialize ZFS library\n")); 393999653d4eSeschrock return (1); 394099653d4eSeschrock } 394199653d4eSeschrock 394299653d4eSeschrock libzfs_print_on_error(g_zfs, B_TRUE); 394399653d4eSeschrock 3944fa9e4066Sahrens opterr = 0; 3945fa9e4066Sahrens 3946fa9e4066Sahrens /* 3947fa9e4066Sahrens * Make sure the user has specified some command. 3948fa9e4066Sahrens */ 3949fa9e4066Sahrens if (argc < 2) { 3950fa9e4066Sahrens (void) fprintf(stderr, gettext("missing command\n")); 395199653d4eSeschrock usage(B_FALSE); 3952fa9e4066Sahrens } 3953fa9e4066Sahrens 3954fa9e4066Sahrens cmdname = argv[1]; 3955fa9e4066Sahrens 3956fa9e4066Sahrens /* 3957fa9e4066Sahrens * Special case '-?' 3958fa9e4066Sahrens */ 3959fa9e4066Sahrens if (strcmp(cmdname, "-?") == 0) 396099653d4eSeschrock usage(B_TRUE); 3961fa9e4066Sahrens 39622a6b87f0Sek110237 zpool_set_history_str("zpool", argc, argv, history_str); 39632a6b87f0Sek110237 verify(zpool_stage_history(g_zfs, history_str) == 0); 39642a6b87f0Sek110237 3965fa9e4066Sahrens /* 3966fa9e4066Sahrens * Run the appropriate command. 3967fa9e4066Sahrens */ 3968b1b8ab34Slling if (find_command_idx(cmdname, &i) == 0) { 3969fa9e4066Sahrens current_command = &command_table[i]; 3970fa9e4066Sahrens ret = command_table[i].func(argc - 1, argv + 1); 397191ebeef5Sahrens } else if (strchr(cmdname, '=')) { 397291ebeef5Sahrens verify(find_command_idx("set", &i) == 0); 397391ebeef5Sahrens current_command = &command_table[i]; 397491ebeef5Sahrens ret = command_table[i].func(argc, argv); 397591ebeef5Sahrens } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 3976fa9e4066Sahrens /* 397791ebeef5Sahrens * 'freeze' is a vile debugging abomination, so we treat 397891ebeef5Sahrens * it as such. 3979fa9e4066Sahrens */ 3980ea8dc4b6Seschrock char buf[16384]; 3981ea8dc4b6Seschrock int fd = open(ZFS_DEV, O_RDWR); 3982fa9e4066Sahrens (void) strcpy((void *)buf, argv[2]); 3983fa9e4066Sahrens return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf)); 398491ebeef5Sahrens } else { 3985fa9e4066Sahrens (void) fprintf(stderr, gettext("unrecognized " 3986fa9e4066Sahrens "command '%s'\n"), cmdname); 398799653d4eSeschrock usage(B_FALSE); 3988fa9e4066Sahrens } 3989fa9e4066Sahrens 399099653d4eSeschrock libzfs_fini(g_zfs); 399199653d4eSeschrock 3992fa9e4066Sahrens /* 3993fa9e4066Sahrens * The 'ZFS_ABORT' environment variable causes us to dump core on exit 3994fa9e4066Sahrens * for the purposes of running ::findleaks. 3995fa9e4066Sahrens */ 3996fa9e4066Sahrens if (getenv("ZFS_ABORT") != NULL) { 3997fa9e4066Sahrens (void) printf("dumping core by request\n"); 3998fa9e4066Sahrens abort(); 3999fa9e4066Sahrens } 4000fa9e4066Sahrens 4001fa9e4066Sahrens return (ret); 4002fa9e4066Sahrens } 4003