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 /* 233f9d6ad7SLin Ling * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 245cabbc6bSPrashanth Sreenivasa * Copyright (c) 2011, 2018 by Delphix. All rights reserved. 25e1d5e507SFrederik Wessels * Copyright (c) 2012 by Frederik Wessels. All rights reserved. 269edf9ebdSPrasad Joshi * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved. 27b327cd3fSIgor Kozhukhov * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>. 286401734dSWill Andrews * Copyright 2016 Nexenta Systems, Inc. 291702cce7SAlek Pinchuk * Copyright (c) 2017 Datto Inc. 30fa9e4066Sahrens */ 31fa9e4066Sahrens 32fa9e4066Sahrens #include <assert.h> 33fa9e4066Sahrens #include <ctype.h> 34fa9e4066Sahrens #include <dirent.h> 35fa9e4066Sahrens #include <errno.h> 36fa9e4066Sahrens #include <fcntl.h> 37*86714001SSerapheim Dimitropoulos #include <getopt.h> 38fa9e4066Sahrens #include <libgen.h> 39fa9e4066Sahrens #include <libintl.h> 40fa9e4066Sahrens #include <libuutil.h> 41fa9e4066Sahrens #include <locale.h> 42fa9e4066Sahrens #include <stdio.h> 43fa9e4066Sahrens #include <stdlib.h> 44fa9e4066Sahrens #include <string.h> 45fa9e4066Sahrens #include <strings.h> 46fa9e4066Sahrens #include <unistd.h> 47fa9e4066Sahrens #include <priv.h> 48ecd6cf80Smarks #include <pwd.h> 49ecd6cf80Smarks #include <zone.h> 504263d13fSGeorge Wilson #include <zfs_prop.h> 51b1b8ab34Slling #include <sys/fs/zfs.h> 52fa9e4066Sahrens #include <sys/stat.h> 53fa9e4066Sahrens 54fa9e4066Sahrens #include <libzfs.h> 55fa9e4066Sahrens 56fa9e4066Sahrens #include "zpool_util.h" 57b7b97454Sperrin #include "zfs_comutil.h" 58ad135b5dSChristopher Siden #include "zfeature_common.h" 59fa9e4066Sahrens 6026fd7700SKrishnendu Sadhukhan - Sun Microsystems #include "statcommon.h" 6126fd7700SKrishnendu Sadhukhan - Sun Microsystems 62fa9e4066Sahrens static int zpool_do_create(int, char **); 63fa9e4066Sahrens static int zpool_do_destroy(int, char **); 64fa9e4066Sahrens 65fa9e4066Sahrens static int zpool_do_add(int, char **); 6699653d4eSeschrock static int zpool_do_remove(int, char **); 676401734dSWill Andrews static int zpool_do_labelclear(int, char **); 68fa9e4066Sahrens 69*86714001SSerapheim Dimitropoulos static int zpool_do_checkpoint(int, char **); 70*86714001SSerapheim Dimitropoulos 71fa9e4066Sahrens static int zpool_do_list(int, char **); 72fa9e4066Sahrens static int zpool_do_iostat(int, char **); 73fa9e4066Sahrens static int zpool_do_status(int, char **); 74fa9e4066Sahrens 75fa9e4066Sahrens static int zpool_do_online(int, char **); 76fa9e4066Sahrens static int zpool_do_offline(int, char **); 77ea8dc4b6Seschrock static int zpool_do_clear(int, char **); 784263d13fSGeorge Wilson static int zpool_do_reopen(int, char **); 79fa9e4066Sahrens 80e9103aaeSGarrett D'Amore static int zpool_do_reguid(int, char **); 81e9103aaeSGarrett D'Amore 82fa9e4066Sahrens static int zpool_do_attach(int, char **); 83fa9e4066Sahrens static int zpool_do_detach(int, char **); 84fa9e4066Sahrens static int zpool_do_replace(int, char **); 851195e687SMark J Musante static int zpool_do_split(int, char **); 86fa9e4066Sahrens 87fa9e4066Sahrens static int zpool_do_scrub(int, char **); 88fa9e4066Sahrens 89fa9e4066Sahrens static int zpool_do_import(int, char **); 90fa9e4066Sahrens static int zpool_do_export(int, char **); 91fa9e4066Sahrens 92eaca9bbdSeschrock static int zpool_do_upgrade(int, char **); 93eaca9bbdSeschrock 9406eeb2adSek static int zpool_do_history(int, char **); 9506eeb2adSek 96b1b8ab34Slling static int zpool_do_get(int, char **); 97b1b8ab34Slling static int zpool_do_set(int, char **); 98b1b8ab34Slling 99fa9e4066Sahrens /* 100fa9e4066Sahrens * These libumem hooks provide a reasonable set of defaults for the allocator's 101fa9e4066Sahrens * debugging facilities. 102fa9e4066Sahrens */ 10329ab75c9Srm 10429ab75c9Srm #ifdef DEBUG 105fa9e4066Sahrens const char * 10699653d4eSeschrock _umem_debug_init(void) 107fa9e4066Sahrens { 108fa9e4066Sahrens return ("default,verbose"); /* $UMEM_DEBUG setting */ 109fa9e4066Sahrens } 110fa9e4066Sahrens 111fa9e4066Sahrens const char * 112fa9e4066Sahrens _umem_logging_init(void) 113fa9e4066Sahrens { 114fa9e4066Sahrens return ("fail,contents"); /* $UMEM_LOGGING setting */ 115fa9e4066Sahrens } 11629ab75c9Srm #endif 117fa9e4066Sahrens 11865cd9f28Seschrock typedef enum { 11965cd9f28Seschrock HELP_ADD, 12065cd9f28Seschrock HELP_ATTACH, 121ea8dc4b6Seschrock HELP_CLEAR, 12265cd9f28Seschrock HELP_CREATE, 123*86714001SSerapheim Dimitropoulos HELP_CHECKPOINT, 12465cd9f28Seschrock HELP_DESTROY, 12565cd9f28Seschrock HELP_DETACH, 12665cd9f28Seschrock HELP_EXPORT, 12706eeb2adSek HELP_HISTORY, 12865cd9f28Seschrock HELP_IMPORT, 12965cd9f28Seschrock HELP_IOSTAT, 1306401734dSWill Andrews HELP_LABELCLEAR, 13165cd9f28Seschrock HELP_LIST, 13265cd9f28Seschrock HELP_OFFLINE, 13365cd9f28Seschrock HELP_ONLINE, 13465cd9f28Seschrock HELP_REPLACE, 13599653d4eSeschrock HELP_REMOVE, 13665cd9f28Seschrock HELP_SCRUB, 137eaca9bbdSeschrock HELP_STATUS, 138b1b8ab34Slling HELP_UPGRADE, 139b1b8ab34Slling HELP_GET, 1401195e687SMark J Musante HELP_SET, 141e9103aaeSGarrett D'Amore HELP_SPLIT, 1424263d13fSGeorge Wilson HELP_REGUID, 1434263d13fSGeorge Wilson HELP_REOPEN 14465cd9f28Seschrock } zpool_help_t; 14565cd9f28Seschrock 14665cd9f28Seschrock 147fa9e4066Sahrens typedef struct zpool_command { 148fa9e4066Sahrens const char *name; 149fa9e4066Sahrens int (*func)(int, char **); 15065cd9f28Seschrock zpool_help_t usage; 151fa9e4066Sahrens } zpool_command_t; 152fa9e4066Sahrens 153fa9e4066Sahrens /* 154fa9e4066Sahrens * Master command table. Each ZFS command has a name, associated function, and 155ea8dc4b6Seschrock * usage message. The usage messages need to be internationalized, so we have 156ea8dc4b6Seschrock * to have a function to return the usage message based on a command index. 15765cd9f28Seschrock * 15865cd9f28Seschrock * These commands are organized according to how they are displayed in the usage 15965cd9f28Seschrock * message. An empty command (one with a NULL name) indicates an empty line in 16065cd9f28Seschrock * the generic usage message. 161fa9e4066Sahrens */ 162fa9e4066Sahrens static zpool_command_t command_table[] = { 16365cd9f28Seschrock { "create", zpool_do_create, HELP_CREATE }, 16465cd9f28Seschrock { "destroy", zpool_do_destroy, HELP_DESTROY }, 165fa9e4066Sahrens { NULL }, 16665cd9f28Seschrock { "add", zpool_do_add, HELP_ADD }, 16799653d4eSeschrock { "remove", zpool_do_remove, HELP_REMOVE }, 168fa9e4066Sahrens { NULL }, 1696401734dSWill Andrews { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR }, 1706401734dSWill Andrews { NULL }, 171*86714001SSerapheim Dimitropoulos { "checkpoint", zpool_do_checkpoint, HELP_CHECKPOINT }, 172*86714001SSerapheim Dimitropoulos { NULL }, 17365cd9f28Seschrock { "list", zpool_do_list, HELP_LIST }, 17465cd9f28Seschrock { "iostat", zpool_do_iostat, HELP_IOSTAT }, 17565cd9f28Seschrock { "status", zpool_do_status, HELP_STATUS }, 176fa9e4066Sahrens { NULL }, 17765cd9f28Seschrock { "online", zpool_do_online, HELP_ONLINE }, 17865cd9f28Seschrock { "offline", zpool_do_offline, HELP_OFFLINE }, 179ea8dc4b6Seschrock { "clear", zpool_do_clear, HELP_CLEAR }, 1804263d13fSGeorge Wilson { "reopen", zpool_do_reopen, HELP_REOPEN }, 181fa9e4066Sahrens { NULL }, 18265cd9f28Seschrock { "attach", zpool_do_attach, HELP_ATTACH }, 18365cd9f28Seschrock { "detach", zpool_do_detach, HELP_DETACH }, 18465cd9f28Seschrock { "replace", zpool_do_replace, HELP_REPLACE }, 1851195e687SMark J Musante { "split", zpool_do_split, HELP_SPLIT }, 186fa9e4066Sahrens { NULL }, 18765cd9f28Seschrock { "scrub", zpool_do_scrub, HELP_SCRUB }, 188fa9e4066Sahrens { NULL }, 18965cd9f28Seschrock { "import", zpool_do_import, HELP_IMPORT }, 19065cd9f28Seschrock { "export", zpool_do_export, HELP_EXPORT }, 19106eeb2adSek { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, 192e9103aaeSGarrett D'Amore { "reguid", zpool_do_reguid, HELP_REGUID }, 19306eeb2adSek { NULL }, 194b1b8ab34Slling { "history", zpool_do_history, HELP_HISTORY }, 195b1b8ab34Slling { "get", zpool_do_get, HELP_GET }, 196b1b8ab34Slling { "set", zpool_do_set, HELP_SET }, 197fa9e4066Sahrens }; 198fa9e4066Sahrens 199fa9e4066Sahrens #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 200fa9e4066Sahrens 2014445fffbSMatthew Ahrens static zpool_command_t *current_command; 2022a6b87f0Sek static char history_str[HIS_MAX_RECORD_LEN]; 2034445fffbSMatthew Ahrens static boolean_t log_history = B_TRUE; 20426fd7700SKrishnendu Sadhukhan - Sun Microsystems static uint_t timestamp_fmt = NODATE; 20526fd7700SKrishnendu Sadhukhan - Sun Microsystems 20665cd9f28Seschrock static const char * 2079a686fbcSPaul Dagnelie get_usage(zpool_help_t idx) 2089a686fbcSPaul Dagnelie { 20965cd9f28Seschrock switch (idx) { 21065cd9f28Seschrock case HELP_ADD: 21165cd9f28Seschrock return (gettext("\tadd [-fn] <pool> <vdev> ...\n")); 21265cd9f28Seschrock case HELP_ATTACH: 21365cd9f28Seschrock return (gettext("\tattach [-f] <pool> <device> " 214e45ce728Sahrens "<new-device>\n")); 215ea8dc4b6Seschrock case HELP_CLEAR: 216468c413aSTim Haley return (gettext("\tclear [-nF] <pool> [device]\n")); 21765cd9f28Seschrock case HELP_CREATE: 2187855d95bSToomas Soome return (gettext("\tcreate [-fnd] [-B] " 2197855d95bSToomas Soome "[-o property=value] ... \n" 2200a48a24eStimh "\t [-O file-system-property=value] ... \n" 221990b4856Slling "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n")); 222*86714001SSerapheim Dimitropoulos case HELP_CHECKPOINT: 223*86714001SSerapheim Dimitropoulos return (gettext("\tcheckpoint [--discard] <pool> ...\n")); 22465cd9f28Seschrock case HELP_DESTROY: 22565cd9f28Seschrock return (gettext("\tdestroy [-f] <pool>\n")); 22665cd9f28Seschrock case HELP_DETACH: 22765cd9f28Seschrock return (gettext("\tdetach <pool> <device>\n")); 22865cd9f28Seschrock case HELP_EXPORT: 22965cd9f28Seschrock return (gettext("\texport [-f] <pool> ...\n")); 23006eeb2adSek case HELP_HISTORY: 231ecd6cf80Smarks return (gettext("\thistory [-il] [<pool>] ...\n")); 23265cd9f28Seschrock case HELP_IMPORT: 2334c58d714Sdarrenm return (gettext("\timport [-d dir] [-D]\n" 2342f8aaab3Seschrock "\timport [-o mntopts] [-o property=value] ... \n" 235f9af39baSGeorge Wilson "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] " 236f9af39baSGeorge Wilson "[-R root] [-F [-n]] -a\n" 2372f8aaab3Seschrock "\timport [-o mntopts] [-o property=value] ... \n" 238f9af39baSGeorge Wilson "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] " 239f9af39baSGeorge Wilson "[-R root] [-F [-n]]\n" 240*86714001SSerapheim Dimitropoulos "\t [--rewind-to-checkpoint] <pool | id> [newpool]\n")); 24165cd9f28Seschrock case HELP_IOSTAT: 24226fd7700SKrishnendu Sadhukhan - Sun Microsystems return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval " 24365cd9f28Seschrock "[count]]\n")); 2446401734dSWill Andrews case HELP_LABELCLEAR: 2456401734dSWill Andrews return (gettext("\tlabelclear [-f] <vdev>\n")); 24665cd9f28Seschrock case HELP_LIST: 247c58b3526SAdam Stevko return (gettext("\tlist [-Hp] [-o property[,...]] " 2483f9d6ad7SLin Ling "[-T d|u] [pool] ... [interval [count]]\n")); 24965cd9f28Seschrock case HELP_OFFLINE: 250441d80aaSlling return (gettext("\toffline [-t] <pool> <device> ...\n")); 25165cd9f28Seschrock case HELP_ONLINE: 252441d80aaSlling return (gettext("\tonline <pool> <device> ...\n")); 25365cd9f28Seschrock case HELP_REPLACE: 25465cd9f28Seschrock return (gettext("\treplace [-f] <pool> <device> " 255e45ce728Sahrens "[new-device]\n")); 25699653d4eSeschrock case HELP_REMOVE: 2575cabbc6bSPrashanth Sreenivasa return (gettext("\tremove [-nps] <pool> <device> ...\n")); 2584263d13fSGeorge Wilson case HELP_REOPEN: 25931d7e8faSGeorge Wilson return (gettext("\treopen <pool>\n")); 26065cd9f28Seschrock case HELP_SCRUB: 2611702cce7SAlek Pinchuk return (gettext("\tscrub [-s | -p] <pool> ...\n")); 26265cd9f28Seschrock case HELP_STATUS: 2633f9d6ad7SLin Ling return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval " 2643f9d6ad7SLin Ling "[count]]\n")); 265eaca9bbdSeschrock case HELP_UPGRADE: 266eaca9bbdSeschrock return (gettext("\tupgrade\n" 267eaca9bbdSeschrock "\tupgrade -v\n" 268990b4856Slling "\tupgrade [-V version] <-a | pool ...>\n")); 269b1b8ab34Slling case HELP_GET: 270c58b3526SAdam Stevko return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] " 271c58b3526SAdam Stevko "<\"all\" | property[,...]> <pool> ...\n")); 272b1b8ab34Slling case HELP_SET: 273b1b8ab34Slling return (gettext("\tset <property=value> <pool> \n")); 2741195e687SMark J Musante case HELP_SPLIT: 2751195e687SMark J Musante return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n" 2761195e687SMark J Musante "\t [-o property=value] <pool> <newpool> " 2771195e687SMark J Musante "[<device> ...]\n")); 278e9103aaeSGarrett D'Amore case HELP_REGUID: 279e9103aaeSGarrett D'Amore return (gettext("\treguid <pool>\n")); 28065cd9f28Seschrock } 28165cd9f28Seschrock 28265cd9f28Seschrock abort(); 28365cd9f28Seschrock /* NOTREACHED */ 28465cd9f28Seschrock } 28565cd9f28Seschrock 286fa9e4066Sahrens 287b1b8ab34Slling /* 288b1b8ab34Slling * Callback routine that will print out a pool property value. 289b1b8ab34Slling */ 290990b4856Slling static int 291990b4856Slling print_prop_cb(int prop, void *cb) 292b1b8ab34Slling { 293b1b8ab34Slling FILE *fp = cb; 294b1b8ab34Slling 295b24ab676SJeff Bonwick (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop)); 296b1b8ab34Slling 297990b4856Slling if (zpool_prop_readonly(prop)) 298990b4856Slling (void) fprintf(fp, " NO "); 299990b4856Slling else 300b24ab676SJeff Bonwick (void) fprintf(fp, " YES "); 301990b4856Slling 302b1b8ab34Slling if (zpool_prop_values(prop) == NULL) 303b1b8ab34Slling (void) fprintf(fp, "-\n"); 304b1b8ab34Slling else 305b1b8ab34Slling (void) fprintf(fp, "%s\n", zpool_prop_values(prop)); 306b1b8ab34Slling 307990b4856Slling return (ZPROP_CONT); 308b1b8ab34Slling } 309b1b8ab34Slling 310fa9e4066Sahrens /* 311fa9e4066Sahrens * Display usage message. If we're inside a command, display only the usage for 312fa9e4066Sahrens * that command. Otherwise, iterate over the entire command table and display 313fa9e4066Sahrens * a complete usage message. 314fa9e4066Sahrens */ 315fa9e4066Sahrens void 31699653d4eSeschrock usage(boolean_t requested) 317fa9e4066Sahrens { 318fa9e4066Sahrens FILE *fp = requested ? stdout : stderr; 319fa9e4066Sahrens 320fa9e4066Sahrens if (current_command == NULL) { 321fa9e4066Sahrens int i; 322fa9e4066Sahrens 323fa9e4066Sahrens (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 324fa9e4066Sahrens (void) fprintf(fp, 325fa9e4066Sahrens gettext("where 'command' is one of the following:\n\n")); 326fa9e4066Sahrens 327fa9e4066Sahrens for (i = 0; i < NCOMMAND; i++) { 328fa9e4066Sahrens if (command_table[i].name == NULL) 329fa9e4066Sahrens (void) fprintf(fp, "\n"); 330fa9e4066Sahrens else 331fa9e4066Sahrens (void) fprintf(fp, "%s", 33265cd9f28Seschrock get_usage(command_table[i].usage)); 333fa9e4066Sahrens } 334fa9e4066Sahrens } else { 335fa9e4066Sahrens (void) fprintf(fp, gettext("usage:\n")); 33665cd9f28Seschrock (void) fprintf(fp, "%s", get_usage(current_command->usage)); 337fa9e4066Sahrens } 338fa9e4066Sahrens 339b1b8ab34Slling if (current_command != NULL && 340b1b8ab34Slling ((strcmp(current_command->name, "set") == 0) || 341990b4856Slling (strcmp(current_command->name, "get") == 0) || 342990b4856Slling (strcmp(current_command->name, "list") == 0))) { 343b1b8ab34Slling 344b1b8ab34Slling (void) fprintf(fp, 345b1b8ab34Slling gettext("\nthe following properties are supported:\n")); 346b1b8ab34Slling 347b24ab676SJeff Bonwick (void) fprintf(fp, "\n\t%-15s %s %s\n\n", 348990b4856Slling "PROPERTY", "EDIT", "VALUES"); 349b1b8ab34Slling 350b1b8ab34Slling /* Iterate over all properties */ 351990b4856Slling (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, 352990b4856Slling ZFS_TYPE_POOL); 353ad135b5dSChristopher Siden 354ad135b5dSChristopher Siden (void) fprintf(fp, "\t%-15s ", "feature@..."); 355ad135b5dSChristopher Siden (void) fprintf(fp, "YES disabled | enabled | active\n"); 356ad135b5dSChristopher Siden 357ad135b5dSChristopher Siden (void) fprintf(fp, gettext("\nThe feature@ properties must be " 358ad135b5dSChristopher Siden "appended with a feature name.\nSee zpool-features(5).\n")); 359b1b8ab34Slling } 360b1b8ab34Slling 361e9dbad6fSeschrock /* 362e9dbad6fSeschrock * See comments at end of main(). 363e9dbad6fSeschrock */ 364e9dbad6fSeschrock if (getenv("ZFS_ABORT") != NULL) { 365e9dbad6fSeschrock (void) printf("dumping core by request\n"); 366e9dbad6fSeschrock abort(); 367e9dbad6fSeschrock } 368e9dbad6fSeschrock 369fa9e4066Sahrens exit(requested ? 0 : 2); 370fa9e4066Sahrens } 371fa9e4066Sahrens 372fa9e4066Sahrens void 3738654d025Sperrin print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, 3748654d025Sperrin boolean_t print_logs) 375fa9e4066Sahrens { 376fa9e4066Sahrens nvlist_t **child; 377fa9e4066Sahrens uint_t c, children; 378afefbcddSeschrock char *vname; 379fa9e4066Sahrens 380fa9e4066Sahrens if (name != NULL) 381fa9e4066Sahrens (void) printf("\t%*s%s\n", indent, "", name); 382fa9e4066Sahrens 383fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 384fa9e4066Sahrens &child, &children) != 0) 385fa9e4066Sahrens return; 386fa9e4066Sahrens 387afefbcddSeschrock for (c = 0; c < children; c++) { 3888654d025Sperrin uint64_t is_log = B_FALSE; 3898654d025Sperrin 3908654d025Sperrin (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 3918654d025Sperrin &is_log); 3928654d025Sperrin if ((is_log && !print_logs) || (!is_log && print_logs)) 3938654d025Sperrin continue; 3948654d025Sperrin 39588ecc943SGeorge Wilson vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 3968654d025Sperrin print_vdev_tree(zhp, vname, child[c], indent + 2, 3978654d025Sperrin B_FALSE); 398afefbcddSeschrock free(vname); 399afefbcddSeschrock } 400fa9e4066Sahrens } 401fa9e4066Sahrens 40257221772SChristopher Siden static boolean_t 40357221772SChristopher Siden prop_list_contains_feature(nvlist_t *proplist) 40457221772SChristopher Siden { 40557221772SChristopher Siden nvpair_t *nvp; 40657221772SChristopher Siden for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp; 40757221772SChristopher Siden nvp = nvlist_next_nvpair(proplist, nvp)) { 40857221772SChristopher Siden if (zpool_prop_feature(nvpair_name(nvp))) 40957221772SChristopher Siden return (B_TRUE); 41057221772SChristopher Siden } 41157221772SChristopher Siden return (B_FALSE); 41257221772SChristopher Siden } 41357221772SChristopher Siden 414990b4856Slling /* 415990b4856Slling * Add a property pair (name, string-value) into a property nvlist. 416990b4856Slling */ 417990b4856Slling static int 4180a48a24eStimh add_prop_list(const char *propname, char *propval, nvlist_t **props, 4190a48a24eStimh boolean_t poolprop) 420990b4856Slling { 421d2aa06e8SAndrew Stormont zpool_prop_t prop = ZPOOL_PROP_INVAL; 4220a48a24eStimh zfs_prop_t fprop; 423990b4856Slling nvlist_t *proplist; 4240a48a24eStimh const char *normnm; 4250a48a24eStimh char *strval; 426990b4856Slling 427990b4856Slling if (*props == NULL && 428990b4856Slling nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) { 429990b4856Slling (void) fprintf(stderr, 430990b4856Slling gettext("internal error: out of memory\n")); 431990b4856Slling return (1); 432990b4856Slling } 433990b4856Slling 434990b4856Slling proplist = *props; 435990b4856Slling 4360a48a24eStimh if (poolprop) { 43757221772SChristopher Siden const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION); 43857221772SChristopher Siden 439d2aa06e8SAndrew Stormont if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL && 440ad135b5dSChristopher Siden !zpool_prop_feature(propname)) { 4410a48a24eStimh (void) fprintf(stderr, gettext("property '%s' is " 4420a48a24eStimh "not a valid pool property\n"), propname); 4430a48a24eStimh return (2); 4440a48a24eStimh } 44557221772SChristopher Siden 44657221772SChristopher Siden /* 44757221772SChristopher Siden * feature@ properties and version should not be specified 44857221772SChristopher Siden * at the same time. 44957221772SChristopher Siden */ 4504ae5f5f0SAlan Somers if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) && 45157221772SChristopher Siden nvlist_exists(proplist, vname)) || 45257221772SChristopher Siden (prop == ZPOOL_PROP_VERSION && 45357221772SChristopher Siden prop_list_contains_feature(proplist))) { 45457221772SChristopher Siden (void) fprintf(stderr, gettext("'feature@' and " 45557221772SChristopher Siden "'version' properties cannot be specified " 45657221772SChristopher Siden "together\n")); 45757221772SChristopher Siden return (2); 45857221772SChristopher Siden } 45957221772SChristopher Siden 46057221772SChristopher Siden 461ad135b5dSChristopher Siden if (zpool_prop_feature(propname)) 462ad135b5dSChristopher Siden normnm = propname; 463ad135b5dSChristopher Siden else 464ad135b5dSChristopher Siden normnm = zpool_prop_to_name(prop); 4650a48a24eStimh } else { 46614843421SMatthew Ahrens if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) { 46714843421SMatthew Ahrens normnm = zfs_prop_to_name(fprop); 46814843421SMatthew Ahrens } else { 46914843421SMatthew Ahrens normnm = propname; 4700a48a24eStimh } 471990b4856Slling } 472990b4856Slling 4730a48a24eStimh if (nvlist_lookup_string(proplist, normnm, &strval) == 0 && 4740a48a24eStimh prop != ZPOOL_PROP_CACHEFILE) { 475990b4856Slling (void) fprintf(stderr, gettext("property '%s' " 476990b4856Slling "specified multiple times\n"), propname); 477990b4856Slling return (2); 478990b4856Slling } 479990b4856Slling 4800a48a24eStimh if (nvlist_add_string(proplist, normnm, propval) != 0) { 481990b4856Slling (void) fprintf(stderr, gettext("internal " 482990b4856Slling "error: out of memory\n")); 483990b4856Slling return (1); 484990b4856Slling } 485990b4856Slling 486990b4856Slling return (0); 487990b4856Slling } 488990b4856Slling 489fa9e4066Sahrens /* 490fa9e4066Sahrens * zpool add [-fn] <pool> <vdev> ... 491fa9e4066Sahrens * 492fa9e4066Sahrens * -f Force addition of devices, even if they appear in use 493fa9e4066Sahrens * -n Do not add the devices, but display the resulting layout if 494fa9e4066Sahrens * they were to be added. 495fa9e4066Sahrens * 496fa9e4066Sahrens * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 497fa9e4066Sahrens * handled by get_vdev_spec(), which constructs the nvlist needed to pass to 498fa9e4066Sahrens * libzfs. 499fa9e4066Sahrens */ 500fa9e4066Sahrens int 501fa9e4066Sahrens zpool_do_add(int argc, char **argv) 502fa9e4066Sahrens { 50399653d4eSeschrock boolean_t force = B_FALSE; 50499653d4eSeschrock boolean_t dryrun = B_FALSE; 505fa9e4066Sahrens int c; 506fa9e4066Sahrens nvlist_t *nvroot; 507fa9e4066Sahrens char *poolname; 5087855d95bSToomas Soome zpool_boot_label_t boot_type; 5097855d95bSToomas Soome uint64_t boot_size; 510fa9e4066Sahrens int ret; 511fa9e4066Sahrens zpool_handle_t *zhp; 512fa9e4066Sahrens nvlist_t *config; 513fa9e4066Sahrens 514fa9e4066Sahrens /* check options */ 515fa9e4066Sahrens while ((c = getopt(argc, argv, "fn")) != -1) { 516fa9e4066Sahrens switch (c) { 517fa9e4066Sahrens case 'f': 51899653d4eSeschrock force = B_TRUE; 519fa9e4066Sahrens break; 520fa9e4066Sahrens case 'n': 52199653d4eSeschrock dryrun = B_TRUE; 522fa9e4066Sahrens break; 523fa9e4066Sahrens case '?': 524fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 525fa9e4066Sahrens optopt); 52699653d4eSeschrock usage(B_FALSE); 527fa9e4066Sahrens } 528fa9e4066Sahrens } 529fa9e4066Sahrens 530fa9e4066Sahrens argc -= optind; 531fa9e4066Sahrens argv += optind; 532fa9e4066Sahrens 533fa9e4066Sahrens /* get pool name and check number of arguments */ 534fa9e4066Sahrens if (argc < 1) { 535fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 53699653d4eSeschrock usage(B_FALSE); 537fa9e4066Sahrens } 538fa9e4066Sahrens if (argc < 2) { 539fa9e4066Sahrens (void) fprintf(stderr, gettext("missing vdev specification\n")); 54099653d4eSeschrock usage(B_FALSE); 541fa9e4066Sahrens } 542fa9e4066Sahrens 543fa9e4066Sahrens poolname = argv[0]; 544fa9e4066Sahrens 545fa9e4066Sahrens argc--; 546fa9e4066Sahrens argv++; 547fa9e4066Sahrens 54899653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 549fa9e4066Sahrens return (1); 550fa9e4066Sahrens 551088e9d47Seschrock if ((config = zpool_get_config(zhp, NULL)) == NULL) { 552fa9e4066Sahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 553fa9e4066Sahrens poolname); 554fa9e4066Sahrens zpool_close(zhp); 555fa9e4066Sahrens return (1); 556fa9e4066Sahrens } 557fa9e4066Sahrens 5587855d95bSToomas Soome if (zpool_is_bootable(zhp)) 5597855d95bSToomas Soome boot_type = ZPOOL_COPY_BOOT_LABEL; 5607855d95bSToomas Soome else 5617855d95bSToomas Soome boot_type = ZPOOL_NO_BOOT_LABEL; 5627855d95bSToomas Soome 563fa9e4066Sahrens /* pass off to get_vdev_spec for processing */ 5647855d95bSToomas Soome boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 565705040edSEric Taylor nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun, 5667855d95bSToomas Soome boot_type, boot_size, argc, argv); 567fa9e4066Sahrens if (nvroot == NULL) { 568fa9e4066Sahrens zpool_close(zhp); 569fa9e4066Sahrens return (1); 570fa9e4066Sahrens } 571fa9e4066Sahrens 572fa9e4066Sahrens if (dryrun) { 573fa9e4066Sahrens nvlist_t *poolnvroot; 574fa9e4066Sahrens 575fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 576fa9e4066Sahrens &poolnvroot) == 0); 577fa9e4066Sahrens 578fa9e4066Sahrens (void) printf(gettext("would update '%s' to the following " 579fa9e4066Sahrens "configuration:\n"), zpool_get_name(zhp)); 580fa9e4066Sahrens 5818654d025Sperrin /* print original main pool and new tree */ 5828654d025Sperrin print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE); 5838654d025Sperrin print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE); 5848654d025Sperrin 5858654d025Sperrin /* Do the same for the logs */ 5868654d025Sperrin if (num_logs(poolnvroot) > 0) { 5878654d025Sperrin print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE); 5888654d025Sperrin print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE); 5898654d025Sperrin } else if (num_logs(nvroot) > 0) { 5908654d025Sperrin print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE); 5918654d025Sperrin } 592fa9e4066Sahrens 593fa9e4066Sahrens ret = 0; 594fa9e4066Sahrens } else { 595fa9e4066Sahrens ret = (zpool_add(zhp, nvroot) != 0); 596fa9e4066Sahrens } 597fa9e4066Sahrens 59899653d4eSeschrock nvlist_free(nvroot); 59999653d4eSeschrock zpool_close(zhp); 60099653d4eSeschrock 60199653d4eSeschrock return (ret); 60299653d4eSeschrock } 60399653d4eSeschrock 60499653d4eSeschrock /* 6053f9d6ad7SLin Ling * zpool remove <pool> <vdev> ... 60699653d4eSeschrock * 6075cabbc6bSPrashanth Sreenivasa * Removes the given vdev from the pool. 60899653d4eSeschrock */ 60999653d4eSeschrock int 61099653d4eSeschrock zpool_do_remove(int argc, char **argv) 61199653d4eSeschrock { 61299653d4eSeschrock char *poolname; 613fa94a07fSbrendan int i, ret = 0; 61499653d4eSeschrock zpool_handle_t *zhp; 6155cabbc6bSPrashanth Sreenivasa boolean_t stop = B_FALSE; 6165cabbc6bSPrashanth Sreenivasa boolean_t noop = B_FALSE; 6175cabbc6bSPrashanth Sreenivasa boolean_t parsable = B_FALSE; 6185cabbc6bSPrashanth Sreenivasa char c; 61999653d4eSeschrock 6205cabbc6bSPrashanth Sreenivasa /* check options */ 6215cabbc6bSPrashanth Sreenivasa while ((c = getopt(argc, argv, "nps")) != -1) { 6225cabbc6bSPrashanth Sreenivasa switch (c) { 6235cabbc6bSPrashanth Sreenivasa case 'n': 6245cabbc6bSPrashanth Sreenivasa noop = B_TRUE; 6255cabbc6bSPrashanth Sreenivasa break; 6265cabbc6bSPrashanth Sreenivasa case 'p': 6275cabbc6bSPrashanth Sreenivasa parsable = B_TRUE; 6285cabbc6bSPrashanth Sreenivasa break; 6295cabbc6bSPrashanth Sreenivasa case 's': 6305cabbc6bSPrashanth Sreenivasa stop = B_TRUE; 6315cabbc6bSPrashanth Sreenivasa break; 6325cabbc6bSPrashanth Sreenivasa case '?': 6335cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6345cabbc6bSPrashanth Sreenivasa optopt); 6355cabbc6bSPrashanth Sreenivasa usage(B_FALSE); 6365cabbc6bSPrashanth Sreenivasa } 6375cabbc6bSPrashanth Sreenivasa } 6385cabbc6bSPrashanth Sreenivasa 6395cabbc6bSPrashanth Sreenivasa argc -= optind; 6405cabbc6bSPrashanth Sreenivasa argv += optind; 64199653d4eSeschrock 64299653d4eSeschrock /* get pool name and check number of arguments */ 64399653d4eSeschrock if (argc < 1) { 64499653d4eSeschrock (void) fprintf(stderr, gettext("missing pool name argument\n")); 64599653d4eSeschrock usage(B_FALSE); 64699653d4eSeschrock } 64799653d4eSeschrock 64899653d4eSeschrock poolname = argv[0]; 64999653d4eSeschrock 65099653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 65199653d4eSeschrock return (1); 65299653d4eSeschrock 6535cabbc6bSPrashanth Sreenivasa if (stop && noop) { 6545cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("stop request ignored\n")); 6555cabbc6bSPrashanth Sreenivasa return (0); 6565cabbc6bSPrashanth Sreenivasa } 6575cabbc6bSPrashanth Sreenivasa 6585cabbc6bSPrashanth Sreenivasa if (stop) { 6595cabbc6bSPrashanth Sreenivasa if (argc > 1) { 6605cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("too many arguments\n")); 6615cabbc6bSPrashanth Sreenivasa usage(B_FALSE); 6625cabbc6bSPrashanth Sreenivasa } 6635cabbc6bSPrashanth Sreenivasa if (zpool_vdev_remove_cancel(zhp) != 0) 664fa94a07fSbrendan ret = 1; 6655cabbc6bSPrashanth Sreenivasa } else { 6665cabbc6bSPrashanth Sreenivasa if (argc < 2) { 6675cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("missing device\n")); 6685cabbc6bSPrashanth Sreenivasa usage(B_FALSE); 6695cabbc6bSPrashanth Sreenivasa } 6705cabbc6bSPrashanth Sreenivasa 6715cabbc6bSPrashanth Sreenivasa for (i = 1; i < argc; i++) { 6725cabbc6bSPrashanth Sreenivasa if (noop) { 6735cabbc6bSPrashanth Sreenivasa uint64_t size; 6745cabbc6bSPrashanth Sreenivasa 6755cabbc6bSPrashanth Sreenivasa if (zpool_vdev_indirect_size(zhp, argv[i], 6765cabbc6bSPrashanth Sreenivasa &size) != 0) { 6775cabbc6bSPrashanth Sreenivasa ret = 1; 6785cabbc6bSPrashanth Sreenivasa break; 6795cabbc6bSPrashanth Sreenivasa } 6805cabbc6bSPrashanth Sreenivasa if (parsable) { 6815cabbc6bSPrashanth Sreenivasa (void) printf("%s %llu\n", 6825cabbc6bSPrashanth Sreenivasa argv[i], size); 6835cabbc6bSPrashanth Sreenivasa } else { 6845cabbc6bSPrashanth Sreenivasa char valstr[32]; 6855cabbc6bSPrashanth Sreenivasa zfs_nicenum(size, valstr, 6865cabbc6bSPrashanth Sreenivasa sizeof (valstr)); 6875cabbc6bSPrashanth Sreenivasa (void) printf("Memory that will be " 6885cabbc6bSPrashanth Sreenivasa "used after removing %s: %s\n", 6895cabbc6bSPrashanth Sreenivasa argv[i], valstr); 6905cabbc6bSPrashanth Sreenivasa } 6915cabbc6bSPrashanth Sreenivasa } else { 6925cabbc6bSPrashanth Sreenivasa if (zpool_vdev_remove(zhp, argv[i]) != 0) 6935cabbc6bSPrashanth Sreenivasa ret = 1; 6945cabbc6bSPrashanth Sreenivasa } 6955cabbc6bSPrashanth Sreenivasa } 696fa94a07fSbrendan } 69799653d4eSeschrock 698fa9e4066Sahrens return (ret); 699fa9e4066Sahrens } 700fa9e4066Sahrens 7016401734dSWill Andrews /* 7026401734dSWill Andrews * zpool labelclear [-f] <vdev> 7036401734dSWill Andrews * 7046401734dSWill Andrews * -f Force clearing the label for the vdevs which are members of 7056401734dSWill Andrews * the exported or foreign pools. 7066401734dSWill Andrews * 7076401734dSWill Andrews * Verifies that the vdev is not active and zeros out the label information 7086401734dSWill Andrews * on the device. 7096401734dSWill Andrews */ 7106401734dSWill Andrews int 7116401734dSWill Andrews zpool_do_labelclear(int argc, char **argv) 7126401734dSWill Andrews { 7136401734dSWill Andrews char vdev[MAXPATHLEN]; 7146401734dSWill Andrews char *name = NULL; 7156401734dSWill Andrews struct stat st; 7166401734dSWill Andrews int c, fd, ret = 0; 7176401734dSWill Andrews nvlist_t *config; 7186401734dSWill Andrews pool_state_t state; 7196401734dSWill Andrews boolean_t inuse = B_FALSE; 7206401734dSWill Andrews boolean_t force = B_FALSE; 7216401734dSWill Andrews 7226401734dSWill Andrews /* check options */ 7236401734dSWill Andrews while ((c = getopt(argc, argv, "f")) != -1) { 7246401734dSWill Andrews switch (c) { 7256401734dSWill Andrews case 'f': 7266401734dSWill Andrews force = B_TRUE; 7276401734dSWill Andrews break; 7286401734dSWill Andrews default: 7296401734dSWill Andrews (void) fprintf(stderr, gettext("invalid option '%c'\n"), 7306401734dSWill Andrews optopt); 7316401734dSWill Andrews usage(B_FALSE); 7326401734dSWill Andrews } 7336401734dSWill Andrews } 7346401734dSWill Andrews 7356401734dSWill Andrews argc -= optind; 7366401734dSWill Andrews argv += optind; 7376401734dSWill Andrews 7386401734dSWill Andrews /* get vdev name */ 7396401734dSWill Andrews if (argc < 1) { 7406401734dSWill Andrews (void) fprintf(stderr, gettext("missing vdev name\n")); 7416401734dSWill Andrews usage(B_FALSE); 7426401734dSWill Andrews } 7436401734dSWill Andrews if (argc > 1) { 7446401734dSWill Andrews (void) fprintf(stderr, gettext("too many arguments\n")); 7456401734dSWill Andrews usage(B_FALSE); 7466401734dSWill Andrews } 7476401734dSWill Andrews 7486401734dSWill Andrews /* 7496401734dSWill Andrews * Check if we were given absolute path and use it as is. 7506401734dSWill Andrews * Otherwise if the provided vdev name doesn't point to a file, 7516401734dSWill Andrews * try prepending dsk path and appending s0. 7526401734dSWill Andrews */ 7536401734dSWill Andrews (void) strlcpy(vdev, argv[0], sizeof (vdev)); 7546401734dSWill Andrews if (vdev[0] != '/' && stat(vdev, &st) != 0) { 7556401734dSWill Andrews char *s; 7566401734dSWill Andrews 7576401734dSWill Andrews (void) snprintf(vdev, sizeof (vdev), "%s/%s", 7586401734dSWill Andrews ZFS_DISK_ROOT, argv[0]); 7596401734dSWill Andrews if ((s = strrchr(argv[0], 's')) == NULL || 7606401734dSWill Andrews !isdigit(*(s + 1))) 7616401734dSWill Andrews (void) strlcat(vdev, "s0", sizeof (vdev)); 7626401734dSWill Andrews if (stat(vdev, &st) != 0) { 7636401734dSWill Andrews (void) fprintf(stderr, gettext( 7646401734dSWill Andrews "failed to find device %s, try specifying absolute " 7656401734dSWill Andrews "path instead\n"), argv[0]); 7666401734dSWill Andrews return (1); 7676401734dSWill Andrews } 7686401734dSWill Andrews } 7696401734dSWill Andrews 7706401734dSWill Andrews if ((fd = open(vdev, O_RDWR)) < 0) { 7716401734dSWill Andrews (void) fprintf(stderr, gettext("failed to open %s: %s\n"), 7726401734dSWill Andrews vdev, strerror(errno)); 7736401734dSWill Andrews return (1); 7746401734dSWill Andrews } 7756401734dSWill Andrews 776c861bfbdSAlan Somers if (zpool_read_label(fd, &config) != 0) { 7776401734dSWill Andrews (void) fprintf(stderr, 7786401734dSWill Andrews gettext("failed to read label from %s\n"), vdev); 7796401734dSWill Andrews return (1); 7806401734dSWill Andrews } 7816401734dSWill Andrews nvlist_free(config); 7826401734dSWill Andrews 7836401734dSWill Andrews ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse); 7846401734dSWill Andrews if (ret != 0) { 7856401734dSWill Andrews (void) fprintf(stderr, 7866401734dSWill Andrews gettext("failed to check state for %s\n"), vdev); 7876401734dSWill Andrews return (1); 7886401734dSWill Andrews } 7896401734dSWill Andrews 7906401734dSWill Andrews if (!inuse) 7916401734dSWill Andrews goto wipe_label; 7926401734dSWill Andrews 7936401734dSWill Andrews switch (state) { 7946401734dSWill Andrews default: 7956401734dSWill Andrews case POOL_STATE_ACTIVE: 7966401734dSWill Andrews case POOL_STATE_SPARE: 7976401734dSWill Andrews case POOL_STATE_L2CACHE: 7986401734dSWill Andrews (void) fprintf(stderr, gettext( 7996401734dSWill Andrews "%s is a member (%s) of pool \"%s\"\n"), 8006401734dSWill Andrews vdev, zpool_pool_state_to_name(state), name); 8016401734dSWill Andrews ret = 1; 8026401734dSWill Andrews goto errout; 8036401734dSWill Andrews 8046401734dSWill Andrews case POOL_STATE_EXPORTED: 8056401734dSWill Andrews if (force) 8066401734dSWill Andrews break; 8076401734dSWill Andrews (void) fprintf(stderr, gettext( 8086401734dSWill Andrews "use '-f' to override the following error:\n" 8096401734dSWill Andrews "%s is a member of exported pool \"%s\"\n"), 8106401734dSWill Andrews vdev, name); 8116401734dSWill Andrews ret = 1; 8126401734dSWill Andrews goto errout; 8136401734dSWill Andrews 8146401734dSWill Andrews case POOL_STATE_POTENTIALLY_ACTIVE: 8156401734dSWill Andrews if (force) 8166401734dSWill Andrews break; 8176401734dSWill Andrews (void) fprintf(stderr, gettext( 8186401734dSWill Andrews "use '-f' to override the following error:\n" 8196401734dSWill Andrews "%s is a member of potentially active pool \"%s\"\n"), 8206401734dSWill Andrews vdev, name); 8216401734dSWill Andrews ret = 1; 8226401734dSWill Andrews goto errout; 8236401734dSWill Andrews 8246401734dSWill Andrews case POOL_STATE_DESTROYED: 8256401734dSWill Andrews /* inuse should never be set for a destroyed pool */ 8266401734dSWill Andrews assert(0); 8276401734dSWill Andrews break; 8286401734dSWill Andrews } 8296401734dSWill Andrews 8306401734dSWill Andrews wipe_label: 8316401734dSWill Andrews ret = zpool_clear_label(fd); 8326401734dSWill Andrews if (ret != 0) { 8336401734dSWill Andrews (void) fprintf(stderr, 8346401734dSWill Andrews gettext("failed to clear label for %s\n"), vdev); 8356401734dSWill Andrews } 8366401734dSWill Andrews 8376401734dSWill Andrews errout: 8386401734dSWill Andrews free(name); 8396401734dSWill Andrews (void) close(fd); 8406401734dSWill Andrews 8416401734dSWill Andrews return (ret); 8426401734dSWill Andrews } 8436401734dSWill Andrews 844fa9e4066Sahrens /* 8457855d95bSToomas Soome * zpool create [-fnd] [-B] [-o property=value] ... 8460a48a24eStimh * [-O file-system-property=value] ... 8470a48a24eStimh * [-R root] [-m mountpoint] <pool> <dev> ... 848fa9e4066Sahrens * 8497855d95bSToomas Soome * -B Create boot partition. 850fa9e4066Sahrens * -f Force creation, even if devices appear in use 851fa9e4066Sahrens * -n Do not create the pool, but display the resulting layout if it 852fa9e4066Sahrens * were to be created. 853fa9e4066Sahrens * -R Create a pool under an alternate root 854fa9e4066Sahrens * -m Set default mountpoint for the root dataset. By default it's 855ad135b5dSChristopher Siden * '/<pool>' 856990b4856Slling * -o Set property=value. 857ad135b5dSChristopher Siden * -d Don't automatically enable all supported pool features 858ad135b5dSChristopher Siden * (individual features can be enabled with -o). 8590a48a24eStimh * -O Set fsproperty=value in the pool's root file system 860fa9e4066Sahrens * 861b1b8ab34Slling * Creates the named pool according to the given vdev specification. The 862fa9e4066Sahrens * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once 863fa9e4066Sahrens * we get the nvlist back from get_vdev_spec(), we either print out the contents 864fa9e4066Sahrens * (if '-n' was specified), or pass it to libzfs to do the creation. 865fa9e4066Sahrens */ 8667855d95bSToomas Soome 8677855d95bSToomas Soome #define SYSTEM256 (256 * 1024 * 1024) 868fa9e4066Sahrens int 869fa9e4066Sahrens zpool_do_create(int argc, char **argv) 870fa9e4066Sahrens { 87199653d4eSeschrock boolean_t force = B_FALSE; 87299653d4eSeschrock boolean_t dryrun = B_FALSE; 873ad135b5dSChristopher Siden boolean_t enable_all_pool_feat = B_TRUE; 8747855d95bSToomas Soome zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL; 8757855d95bSToomas Soome uint64_t boot_size = 0; 876fa9e4066Sahrens int c; 877990b4856Slling nvlist_t *nvroot = NULL; 878fa9e4066Sahrens char *poolname; 879990b4856Slling int ret = 1; 880fa9e4066Sahrens char *altroot = NULL; 881fa9e4066Sahrens char *mountpoint = NULL; 8820a48a24eStimh nvlist_t *fsprops = NULL; 883990b4856Slling nvlist_t *props = NULL; 8842f8aaab3Seschrock char *propval; 885fa9e4066Sahrens 886fa9e4066Sahrens /* check options */ 8877855d95bSToomas Soome while ((c = getopt(argc, argv, ":fndBR:m:o:O:")) != -1) { 888fa9e4066Sahrens switch (c) { 889fa9e4066Sahrens case 'f': 89099653d4eSeschrock force = B_TRUE; 891fa9e4066Sahrens break; 892fa9e4066Sahrens case 'n': 89399653d4eSeschrock dryrun = B_TRUE; 894fa9e4066Sahrens break; 895ad135b5dSChristopher Siden case 'd': 896ad135b5dSChristopher Siden enable_all_pool_feat = B_FALSE; 897ad135b5dSChristopher Siden break; 8987855d95bSToomas Soome case 'B': 8997855d95bSToomas Soome /* 9007855d95bSToomas Soome * We should create the system partition. 9017855d95bSToomas Soome * Also make sure the size is set. 9027855d95bSToomas Soome */ 9037855d95bSToomas Soome boot_type = ZPOOL_CREATE_BOOT_LABEL; 9047855d95bSToomas Soome if (boot_size == 0) 9057855d95bSToomas Soome boot_size = SYSTEM256; 9067855d95bSToomas Soome break; 907fa9e4066Sahrens case 'R': 908fa9e4066Sahrens altroot = optarg; 909990b4856Slling if (add_prop_list(zpool_prop_to_name( 9100a48a24eStimh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 911990b4856Slling goto errout; 9122f8aaab3Seschrock if (nvlist_lookup_string(props, 9132f8aaab3Seschrock zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 9142f8aaab3Seschrock &propval) == 0) 9152f8aaab3Seschrock break; 916990b4856Slling if (add_prop_list(zpool_prop_to_name( 9170a48a24eStimh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 918990b4856Slling goto errout; 919fa9e4066Sahrens break; 920fa9e4066Sahrens case 'm': 9218b713775SWill Andrews /* Equivalent to -O mountpoint=optarg */ 922fa9e4066Sahrens mountpoint = optarg; 923fa9e4066Sahrens break; 924990b4856Slling case 'o': 925990b4856Slling if ((propval = strchr(optarg, '=')) == NULL) { 926990b4856Slling (void) fprintf(stderr, gettext("missing " 927990b4856Slling "'=' for -o option\n")); 928990b4856Slling goto errout; 929990b4856Slling } 930990b4856Slling *propval = '\0'; 931990b4856Slling propval++; 932990b4856Slling 9330a48a24eStimh if (add_prop_list(optarg, propval, &props, B_TRUE)) 9340a48a24eStimh goto errout; 935ad135b5dSChristopher Siden 9367855d95bSToomas Soome /* 9377855d95bSToomas Soome * Get bootsize value for make_root_vdev(). 9387855d95bSToomas Soome */ 9397855d95bSToomas Soome if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) { 9407855d95bSToomas Soome if (zfs_nicestrtonum(g_zfs, propval, 9417855d95bSToomas Soome &boot_size) < 0 || boot_size == 0) { 9427855d95bSToomas Soome (void) fprintf(stderr, 9437855d95bSToomas Soome gettext("bad boot partition size " 9447855d95bSToomas Soome "'%s': %s\n"), propval, 9457855d95bSToomas Soome libzfs_error_description(g_zfs)); 9467855d95bSToomas Soome goto errout; 9477855d95bSToomas Soome } 9487855d95bSToomas Soome } 9497855d95bSToomas Soome 950ad135b5dSChristopher Siden /* 951ad135b5dSChristopher Siden * If the user is creating a pool that doesn't support 952ad135b5dSChristopher Siden * feature flags, don't enable any features. 953ad135b5dSChristopher Siden */ 954ad135b5dSChristopher Siden if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) { 955ad135b5dSChristopher Siden char *end; 956ad135b5dSChristopher Siden u_longlong_t ver; 957ad135b5dSChristopher Siden 958ad135b5dSChristopher Siden ver = strtoull(propval, &end, 10); 959ad135b5dSChristopher Siden if (*end == '\0' && 960ad135b5dSChristopher Siden ver < SPA_VERSION_FEATURES) { 961ad135b5dSChristopher Siden enable_all_pool_feat = B_FALSE; 962ad135b5dSChristopher Siden } 963ad135b5dSChristopher Siden } 964c423721fSXin Li if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT) 965c423721fSXin Li altroot = propval; 9660a48a24eStimh break; 9670a48a24eStimh case 'O': 9680a48a24eStimh if ((propval = strchr(optarg, '=')) == NULL) { 9690a48a24eStimh (void) fprintf(stderr, gettext("missing " 9700a48a24eStimh "'=' for -O option\n")); 9710a48a24eStimh goto errout; 9720a48a24eStimh } 9730a48a24eStimh *propval = '\0'; 9740a48a24eStimh propval++; 9750a48a24eStimh 9768b713775SWill Andrews /* 9778b713775SWill Andrews * Mountpoints are checked and then added later. 9788b713775SWill Andrews * Uniquely among properties, they can be specified 9798b713775SWill Andrews * more than once, to avoid conflict with -m. 9808b713775SWill Andrews */ 9818b713775SWill Andrews if (0 == strcmp(optarg, 9828b713775SWill Andrews zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) { 9838b713775SWill Andrews mountpoint = propval; 9848b713775SWill Andrews } else if (add_prop_list(optarg, propval, &fsprops, 9858b713775SWill Andrews B_FALSE)) { 986990b4856Slling goto errout; 9878b713775SWill Andrews } 988990b4856Slling break; 989fa9e4066Sahrens case ':': 990fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 991fa9e4066Sahrens "'%c' option\n"), optopt); 992990b4856Slling goto badusage; 993fa9e4066Sahrens case '?': 994fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 995fa9e4066Sahrens optopt); 996990b4856Slling goto badusage; 997fa9e4066Sahrens } 998fa9e4066Sahrens } 999fa9e4066Sahrens 1000fa9e4066Sahrens argc -= optind; 1001fa9e4066Sahrens argv += optind; 1002fa9e4066Sahrens 1003fa9e4066Sahrens /* get pool name and check number of arguments */ 1004fa9e4066Sahrens if (argc < 1) { 1005fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 1006990b4856Slling goto badusage; 1007fa9e4066Sahrens } 1008fa9e4066Sahrens if (argc < 2) { 1009fa9e4066Sahrens (void) fprintf(stderr, gettext("missing vdev specification\n")); 1010990b4856Slling goto badusage; 1011fa9e4066Sahrens } 1012fa9e4066Sahrens 1013fa9e4066Sahrens poolname = argv[0]; 1014fa9e4066Sahrens 1015fa9e4066Sahrens /* 1016fa9e4066Sahrens * As a special case, check for use of '/' in the name, and direct the 1017fa9e4066Sahrens * user to use 'zfs create' instead. 1018fa9e4066Sahrens */ 1019fa9e4066Sahrens if (strchr(poolname, '/') != NULL) { 1020fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot create '%s': invalid " 1021fa9e4066Sahrens "character '/' in pool name\n"), poolname); 1022fa9e4066Sahrens (void) fprintf(stderr, gettext("use 'zfs create' to " 1023fa9e4066Sahrens "create a dataset\n")); 1024990b4856Slling goto errout; 1025fa9e4066Sahrens } 1026fa9e4066Sahrens 10277855d95bSToomas Soome /* 10287855d95bSToomas Soome * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used, 10297855d95bSToomas Soome * and not set otherwise. 10307855d95bSToomas Soome */ 10317855d95bSToomas Soome if (boot_type == ZPOOL_CREATE_BOOT_LABEL) { 10327855d95bSToomas Soome const char *propname; 10337855d95bSToomas Soome char *strptr, *buf = NULL; 10347855d95bSToomas Soome int rv; 10357855d95bSToomas Soome 10367855d95bSToomas Soome propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 10377855d95bSToomas Soome if (nvlist_lookup_string(props, propname, &strptr) != 0) { 10387855d95bSToomas Soome (void) asprintf(&buf, "%" PRIu64, boot_size); 10397855d95bSToomas Soome if (buf == NULL) { 10407855d95bSToomas Soome (void) fprintf(stderr, 10417855d95bSToomas Soome gettext("internal error: out of memory\n")); 10427855d95bSToomas Soome goto errout; 10437855d95bSToomas Soome } 10447855d95bSToomas Soome rv = add_prop_list(propname, buf, &props, B_TRUE); 10457855d95bSToomas Soome free(buf); 10467855d95bSToomas Soome if (rv != 0) 10477855d95bSToomas Soome goto errout; 10487855d95bSToomas Soome } 10497855d95bSToomas Soome } else { 10507855d95bSToomas Soome const char *propname; 10517855d95bSToomas Soome char *strptr; 10527855d95bSToomas Soome 10537855d95bSToomas Soome propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 10547855d95bSToomas Soome if (nvlist_lookup_string(props, propname, &strptr) == 0) { 10557855d95bSToomas Soome (void) fprintf(stderr, gettext("error: setting boot " 10567855d95bSToomas Soome "partition size requires option '-B'\n")); 10577855d95bSToomas Soome goto errout; 10587855d95bSToomas Soome } 10597855d95bSToomas Soome } 10607855d95bSToomas Soome 1061fa9e4066Sahrens /* pass off to get_vdev_spec for bulk processing */ 1062705040edSEric Taylor nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun, 10637855d95bSToomas Soome boot_type, boot_size, argc - 1, argv + 1); 1064fa9e4066Sahrens if (nvroot == NULL) 10650a48a24eStimh goto errout; 1066fa9e4066Sahrens 106799653d4eSeschrock /* make_root_vdev() allows 0 toplevel children if there are spares */ 1068b7b97454Sperrin if (!zfs_allocatable_devs(nvroot)) { 106999653d4eSeschrock (void) fprintf(stderr, gettext("invalid vdev " 107099653d4eSeschrock "specification: at least one toplevel vdev must be " 107199653d4eSeschrock "specified\n")); 1072990b4856Slling goto errout; 107399653d4eSeschrock } 107499653d4eSeschrock 1075fa9e4066Sahrens if (altroot != NULL && altroot[0] != '/') { 1076fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid alternate root '%s': " 1077e9dbad6fSeschrock "must be an absolute path\n"), altroot); 1078990b4856Slling goto errout; 1079fa9e4066Sahrens } 1080fa9e4066Sahrens 1081fa9e4066Sahrens /* 1082fa9e4066Sahrens * Check the validity of the mountpoint and direct the user to use the 1083fa9e4066Sahrens * '-m' mountpoint option if it looks like its in use. 1084fa9e4066Sahrens */ 1085fa9e4066Sahrens if (mountpoint == NULL || 1086fa9e4066Sahrens (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 1087fa9e4066Sahrens strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) { 1088fa9e4066Sahrens char buf[MAXPATHLEN]; 108911022c7cStimh DIR *dirp; 1090fa9e4066Sahrens 1091fa9e4066Sahrens if (mountpoint && mountpoint[0] != '/') { 1092fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid mountpoint " 1093fa9e4066Sahrens "'%s': must be an absolute path, 'legacy', or " 1094fa9e4066Sahrens "'none'\n"), mountpoint); 1095990b4856Slling goto errout; 1096fa9e4066Sahrens } 1097fa9e4066Sahrens 1098fa9e4066Sahrens if (mountpoint == NULL) { 1099fa9e4066Sahrens if (altroot != NULL) 1100fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s/%s", 1101fa9e4066Sahrens altroot, poolname); 1102fa9e4066Sahrens else 1103fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "/%s", 1104fa9e4066Sahrens poolname); 1105fa9e4066Sahrens } else { 1106fa9e4066Sahrens if (altroot != NULL) 1107fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s%s", 1108fa9e4066Sahrens altroot, mountpoint); 1109fa9e4066Sahrens else 1110fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s", 1111fa9e4066Sahrens mountpoint); 1112fa9e4066Sahrens } 1113fa9e4066Sahrens 111411022c7cStimh if ((dirp = opendir(buf)) == NULL && errno != ENOENT) { 111511022c7cStimh (void) fprintf(stderr, gettext("mountpoint '%s' : " 111611022c7cStimh "%s\n"), buf, strerror(errno)); 1117fa9e4066Sahrens (void) fprintf(stderr, gettext("use '-m' " 1118fa9e4066Sahrens "option to provide a different default\n")); 1119990b4856Slling goto errout; 112011022c7cStimh } else if (dirp) { 112111022c7cStimh int count = 0; 112211022c7cStimh 112311022c7cStimh while (count < 3 && readdir(dirp) != NULL) 112411022c7cStimh count++; 112511022c7cStimh (void) closedir(dirp); 112611022c7cStimh 112711022c7cStimh if (count > 2) { 112811022c7cStimh (void) fprintf(stderr, gettext("mountpoint " 112911022c7cStimh "'%s' exists and is not empty\n"), buf); 113011022c7cStimh (void) fprintf(stderr, gettext("use '-m' " 113111022c7cStimh "option to provide a " 113211022c7cStimh "different default\n")); 113311022c7cStimh goto errout; 113411022c7cStimh } 1135fa9e4066Sahrens } 1136fa9e4066Sahrens } 1137fa9e4066Sahrens 11388b713775SWill Andrews /* 11398b713775SWill Andrews * Now that the mountpoint's validity has been checked, ensure that 11408b713775SWill Andrews * the property is set appropriately prior to creating the pool. 11418b713775SWill Andrews */ 11428b713775SWill Andrews if (mountpoint != NULL) { 11438b713775SWill Andrews ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 11448b713775SWill Andrews mountpoint, &fsprops, B_FALSE); 11458b713775SWill Andrews if (ret != 0) 11468b713775SWill Andrews goto errout; 11478b713775SWill Andrews } 11488b713775SWill Andrews 11498b713775SWill Andrews ret = 1; 1150fa9e4066Sahrens if (dryrun) { 1151fa9e4066Sahrens /* 1152fa9e4066Sahrens * For a dry run invocation, print out a basic message and run 1153fa9e4066Sahrens * through all the vdevs in the list and print out in an 1154fa9e4066Sahrens * appropriate hierarchy. 1155fa9e4066Sahrens */ 1156fa9e4066Sahrens (void) printf(gettext("would create '%s' with the " 1157fa9e4066Sahrens "following layout:\n\n"), poolname); 1158fa9e4066Sahrens 11598654d025Sperrin print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE); 11608654d025Sperrin if (num_logs(nvroot) > 0) 11618654d025Sperrin print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE); 1162fa9e4066Sahrens 1163fa9e4066Sahrens ret = 0; 1164fa9e4066Sahrens } else { 1165fa9e4066Sahrens /* 1166fa9e4066Sahrens * Hand off to libzfs. 1167fa9e4066Sahrens */ 1168ad135b5dSChristopher Siden if (enable_all_pool_feat) { 11692acef22dSMatthew Ahrens spa_feature_t i; 1170ad135b5dSChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 1171ad135b5dSChristopher Siden char propname[MAXPATHLEN]; 1172ad135b5dSChristopher Siden zfeature_info_t *feat = &spa_feature_table[i]; 1173ad135b5dSChristopher Siden 1174ad135b5dSChristopher Siden (void) snprintf(propname, sizeof (propname), 1175ad135b5dSChristopher Siden "feature@%s", feat->fi_uname); 1176ad135b5dSChristopher Siden 1177ad135b5dSChristopher Siden /* 1178ad135b5dSChristopher Siden * Skip feature if user specified it manually 1179ad135b5dSChristopher Siden * on the command line. 1180ad135b5dSChristopher Siden */ 1181ad135b5dSChristopher Siden if (nvlist_exists(props, propname)) 1182ad135b5dSChristopher Siden continue; 1183ad135b5dSChristopher Siden 11848b713775SWill Andrews ret = add_prop_list(propname, 11858b713775SWill Andrews ZFS_FEATURE_ENABLED, &props, B_TRUE); 11868b713775SWill Andrews if (ret != 0) 1187ad135b5dSChristopher Siden goto errout; 1188ad135b5dSChristopher Siden } 1189ad135b5dSChristopher Siden } 11908b713775SWill Andrews 11918b713775SWill Andrews ret = 1; 11920a48a24eStimh if (zpool_create(g_zfs, poolname, 11930a48a24eStimh nvroot, props, fsprops) == 0) { 119499653d4eSeschrock zfs_handle_t *pool = zfs_open(g_zfs, poolname, 1195fa9e4066Sahrens ZFS_TYPE_FILESYSTEM); 1196fa9e4066Sahrens if (pool != NULL) { 1197fa9e4066Sahrens if (zfs_mount(pool, NULL, 0) == 0) 1198da6c28aaSamw ret = zfs_shareall(pool); 1199fa9e4066Sahrens zfs_close(pool); 1200fa9e4066Sahrens } 120199653d4eSeschrock } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { 120299653d4eSeschrock (void) fprintf(stderr, gettext("pool name may have " 120399653d4eSeschrock "been omitted\n")); 1204fa9e4066Sahrens } 1205fa9e4066Sahrens } 1206fa9e4066Sahrens 1207990b4856Slling errout: 12082f8aaab3Seschrock nvlist_free(nvroot); 12090a48a24eStimh nvlist_free(fsprops); 12102f8aaab3Seschrock nvlist_free(props); 1211fa9e4066Sahrens return (ret); 1212990b4856Slling badusage: 12130a48a24eStimh nvlist_free(fsprops); 1214990b4856Slling nvlist_free(props); 1215990b4856Slling usage(B_FALSE); 1216990b4856Slling return (2); 1217fa9e4066Sahrens } 1218fa9e4066Sahrens 1219fa9e4066Sahrens /* 1220fa9e4066Sahrens * zpool destroy <pool> 1221fa9e4066Sahrens * 1222fa9e4066Sahrens * -f Forcefully unmount any datasets 1223fa9e4066Sahrens * 1224fa9e4066Sahrens * Destroy the given pool. Automatically unmounts any datasets in the pool. 1225fa9e4066Sahrens */ 1226fa9e4066Sahrens int 1227fa9e4066Sahrens zpool_do_destroy(int argc, char **argv) 1228fa9e4066Sahrens { 122999653d4eSeschrock boolean_t force = B_FALSE; 1230fa9e4066Sahrens int c; 1231fa9e4066Sahrens char *pool; 1232fa9e4066Sahrens zpool_handle_t *zhp; 1233fa9e4066Sahrens int ret; 1234fa9e4066Sahrens 1235fa9e4066Sahrens /* check options */ 1236fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) { 1237fa9e4066Sahrens switch (c) { 1238fa9e4066Sahrens case 'f': 123999653d4eSeschrock force = B_TRUE; 1240fa9e4066Sahrens break; 1241fa9e4066Sahrens case '?': 1242fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1243fa9e4066Sahrens optopt); 124499653d4eSeschrock usage(B_FALSE); 1245fa9e4066Sahrens } 1246fa9e4066Sahrens } 1247fa9e4066Sahrens 1248fa9e4066Sahrens argc -= optind; 1249fa9e4066Sahrens argv += optind; 1250fa9e4066Sahrens 1251fa9e4066Sahrens /* check arguments */ 1252fa9e4066Sahrens if (argc < 1) { 1253fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool argument\n")); 125499653d4eSeschrock usage(B_FALSE); 1255fa9e4066Sahrens } 1256fa9e4066Sahrens if (argc > 1) { 1257fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 125899653d4eSeschrock usage(B_FALSE); 1259fa9e4066Sahrens } 1260fa9e4066Sahrens 1261fa9e4066Sahrens pool = argv[0]; 1262fa9e4066Sahrens 126399653d4eSeschrock if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 1264fa9e4066Sahrens /* 1265fa9e4066Sahrens * As a special case, check for use of '/' in the name, and 1266fa9e4066Sahrens * direct the user to use 'zfs destroy' instead. 1267fa9e4066Sahrens */ 1268fa9e4066Sahrens if (strchr(pool, '/') != NULL) 1269fa9e4066Sahrens (void) fprintf(stderr, gettext("use 'zfs destroy' to " 1270fa9e4066Sahrens "destroy a dataset\n")); 1271fa9e4066Sahrens return (1); 1272fa9e4066Sahrens } 1273fa9e4066Sahrens 1274f3861e1aSahl if (zpool_disable_datasets(zhp, force) != 0) { 1275fa9e4066Sahrens (void) fprintf(stderr, gettext("could not destroy '%s': " 1276fa9e4066Sahrens "could not unmount datasets\n"), zpool_get_name(zhp)); 1277fa9e4066Sahrens return (1); 1278fa9e4066Sahrens } 1279fa9e4066Sahrens 12804445fffbSMatthew Ahrens /* The history must be logged as part of the export */ 12814445fffbSMatthew Ahrens log_history = B_FALSE; 12824445fffbSMatthew Ahrens 12834445fffbSMatthew Ahrens ret = (zpool_destroy(zhp, history_str) != 0); 1284fa9e4066Sahrens 1285fa9e4066Sahrens zpool_close(zhp); 1286fa9e4066Sahrens 1287fa9e4066Sahrens return (ret); 1288fa9e4066Sahrens } 1289fa9e4066Sahrens 1290fa9e4066Sahrens /* 1291fa9e4066Sahrens * zpool export [-f] <pool> ... 1292fa9e4066Sahrens * 1293fa9e4066Sahrens * -f Forcefully unmount datasets 1294fa9e4066Sahrens * 1295b1b8ab34Slling * Export the given pools. By default, the command will attempt to cleanly 1296fa9e4066Sahrens * unmount any active datasets within the pool. If the '-f' flag is specified, 1297fa9e4066Sahrens * then the datasets will be forcefully unmounted. 1298fa9e4066Sahrens */ 1299fa9e4066Sahrens int 1300fa9e4066Sahrens zpool_do_export(int argc, char **argv) 1301fa9e4066Sahrens { 130299653d4eSeschrock boolean_t force = B_FALSE; 1303394ab0cbSGeorge Wilson boolean_t hardforce = B_FALSE; 1304fa9e4066Sahrens int c; 1305fa9e4066Sahrens zpool_handle_t *zhp; 1306fa9e4066Sahrens int ret; 1307fa9e4066Sahrens int i; 1308fa9e4066Sahrens 1309fa9e4066Sahrens /* check options */ 1310394ab0cbSGeorge Wilson while ((c = getopt(argc, argv, "fF")) != -1) { 1311fa9e4066Sahrens switch (c) { 1312fa9e4066Sahrens case 'f': 131399653d4eSeschrock force = B_TRUE; 1314fa9e4066Sahrens break; 1315394ab0cbSGeorge Wilson case 'F': 1316394ab0cbSGeorge Wilson hardforce = B_TRUE; 1317394ab0cbSGeorge Wilson break; 1318fa9e4066Sahrens case '?': 1319fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1320fa9e4066Sahrens optopt); 132199653d4eSeschrock usage(B_FALSE); 1322fa9e4066Sahrens } 1323fa9e4066Sahrens } 1324fa9e4066Sahrens 1325fa9e4066Sahrens argc -= optind; 1326fa9e4066Sahrens argv += optind; 1327fa9e4066Sahrens 1328fa9e4066Sahrens /* check arguments */ 1329fa9e4066Sahrens if (argc < 1) { 1330fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool argument\n")); 133199653d4eSeschrock usage(B_FALSE); 1332fa9e4066Sahrens } 1333fa9e4066Sahrens 1334fa9e4066Sahrens ret = 0; 1335fa9e4066Sahrens for (i = 0; i < argc; i++) { 133699653d4eSeschrock if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) { 1337fa9e4066Sahrens ret = 1; 1338fa9e4066Sahrens continue; 1339fa9e4066Sahrens } 1340fa9e4066Sahrens 1341f3861e1aSahl if (zpool_disable_datasets(zhp, force) != 0) { 1342fa9e4066Sahrens ret = 1; 1343fa9e4066Sahrens zpool_close(zhp); 1344fa9e4066Sahrens continue; 1345fa9e4066Sahrens } 1346fa9e4066Sahrens 13474445fffbSMatthew Ahrens /* The history must be logged as part of the export */ 13484445fffbSMatthew Ahrens log_history = B_FALSE; 13494445fffbSMatthew Ahrens 1350394ab0cbSGeorge Wilson if (hardforce) { 13514445fffbSMatthew Ahrens if (zpool_export_force(zhp, history_str) != 0) 1352394ab0cbSGeorge Wilson ret = 1; 13534445fffbSMatthew Ahrens } else if (zpool_export(zhp, force, history_str) != 0) { 1354fa9e4066Sahrens ret = 1; 1355394ab0cbSGeorge Wilson } 1356fa9e4066Sahrens 1357fa9e4066Sahrens zpool_close(zhp); 1358fa9e4066Sahrens } 1359fa9e4066Sahrens 1360fa9e4066Sahrens return (ret); 1361fa9e4066Sahrens } 1362fa9e4066Sahrens 1363fa9e4066Sahrens /* 1364fa9e4066Sahrens * Given a vdev configuration, determine the maximum width needed for the device 1365fa9e4066Sahrens * name column. 1366fa9e4066Sahrens */ 1367fa9e4066Sahrens static int 1368c67d9675Seschrock max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max) 1369fa9e4066Sahrens { 137088ecc943SGeorge Wilson char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE); 1371fa9e4066Sahrens nvlist_t **child; 1372fa9e4066Sahrens uint_t c, children; 1373fa9e4066Sahrens int ret; 1374fa9e4066Sahrens 1375fa9e4066Sahrens if (strlen(name) + depth > max) 1376fa9e4066Sahrens max = strlen(name) + depth; 1377fa9e4066Sahrens 1378afefbcddSeschrock free(name); 1379afefbcddSeschrock 138099653d4eSeschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 138199653d4eSeschrock &child, &children) == 0) { 138299653d4eSeschrock for (c = 0; c < children; c++) 138399653d4eSeschrock if ((ret = max_width(zhp, child[c], depth + 2, 138499653d4eSeschrock max)) > max) 138599653d4eSeschrock max = ret; 138699653d4eSeschrock } 138799653d4eSeschrock 1388fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1389fa94a07fSbrendan &child, &children) == 0) { 1390fa94a07fSbrendan for (c = 0; c < children; c++) 1391fa94a07fSbrendan if ((ret = max_width(zhp, child[c], depth + 2, 1392fa94a07fSbrendan max)) > max) 1393fa94a07fSbrendan max = ret; 1394fa94a07fSbrendan } 1395fa94a07fSbrendan 1396fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 139799653d4eSeschrock &child, &children) == 0) { 139899653d4eSeschrock for (c = 0; c < children; c++) 139999653d4eSeschrock if ((ret = max_width(zhp, child[c], depth + 2, 140099653d4eSeschrock max)) > max) 140199653d4eSeschrock max = ret; 140299653d4eSeschrock } 1403fa9e4066Sahrens 1404fa9e4066Sahrens 1405fa9e4066Sahrens return (max); 1406fa9e4066Sahrens } 1407fa9e4066Sahrens 1408e6ca193dSGeorge Wilson typedef struct spare_cbdata { 1409e6ca193dSGeorge Wilson uint64_t cb_guid; 1410e6ca193dSGeorge Wilson zpool_handle_t *cb_zhp; 1411e6ca193dSGeorge Wilson } spare_cbdata_t; 1412e6ca193dSGeorge Wilson 1413e6ca193dSGeorge Wilson static boolean_t 1414e6ca193dSGeorge Wilson find_vdev(nvlist_t *nv, uint64_t search) 1415e6ca193dSGeorge Wilson { 1416e6ca193dSGeorge Wilson uint64_t guid; 1417e6ca193dSGeorge Wilson nvlist_t **child; 1418e6ca193dSGeorge Wilson uint_t c, children; 1419e6ca193dSGeorge Wilson 1420e6ca193dSGeorge Wilson if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 1421e6ca193dSGeorge Wilson search == guid) 1422e6ca193dSGeorge Wilson return (B_TRUE); 1423e6ca193dSGeorge Wilson 1424e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1425e6ca193dSGeorge Wilson &child, &children) == 0) { 1426e6ca193dSGeorge Wilson for (c = 0; c < children; c++) 1427e6ca193dSGeorge Wilson if (find_vdev(child[c], search)) 1428e6ca193dSGeorge Wilson return (B_TRUE); 1429e6ca193dSGeorge Wilson } 1430e6ca193dSGeorge Wilson 1431e6ca193dSGeorge Wilson return (B_FALSE); 1432e6ca193dSGeorge Wilson } 1433e6ca193dSGeorge Wilson 1434e6ca193dSGeorge Wilson static int 1435e6ca193dSGeorge Wilson find_spare(zpool_handle_t *zhp, void *data) 1436e6ca193dSGeorge Wilson { 1437e6ca193dSGeorge Wilson spare_cbdata_t *cbp = data; 1438e6ca193dSGeorge Wilson nvlist_t *config, *nvroot; 1439e6ca193dSGeorge Wilson 1440e6ca193dSGeorge Wilson config = zpool_get_config(zhp, NULL); 1441e6ca193dSGeorge Wilson verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1442e6ca193dSGeorge Wilson &nvroot) == 0); 1443e6ca193dSGeorge Wilson 1444e6ca193dSGeorge Wilson if (find_vdev(nvroot, cbp->cb_guid)) { 1445e6ca193dSGeorge Wilson cbp->cb_zhp = zhp; 1446e6ca193dSGeorge Wilson return (1); 1447e6ca193dSGeorge Wilson } 1448e6ca193dSGeorge Wilson 1449e6ca193dSGeorge Wilson zpool_close(zhp); 1450e6ca193dSGeorge Wilson return (0); 1451e6ca193dSGeorge Wilson } 1452e6ca193dSGeorge Wilson 1453e6ca193dSGeorge Wilson /* 1454e6ca193dSGeorge Wilson * Print out configuration state as requested by status_callback. 1455e6ca193dSGeorge Wilson */ 1456e6ca193dSGeorge Wilson void 1457e6ca193dSGeorge Wilson print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 1458e6ca193dSGeorge Wilson int namewidth, int depth, boolean_t isspare) 1459e6ca193dSGeorge Wilson { 1460e6ca193dSGeorge Wilson nvlist_t **child; 1461e6ca193dSGeorge Wilson uint_t c, children; 14623f9d6ad7SLin Ling pool_scan_stat_t *ps = NULL; 1463e6ca193dSGeorge Wilson vdev_stat_t *vs; 14643f9d6ad7SLin Ling char rbuf[6], wbuf[6], cbuf[6]; 1465e6ca193dSGeorge Wilson char *vname; 1466e6ca193dSGeorge Wilson uint64_t notpresent; 1467e6ca193dSGeorge Wilson spare_cbdata_t cb; 14686401734dSWill Andrews const char *state; 14695cabbc6bSPrashanth Sreenivasa char *type; 1470e6ca193dSGeorge Wilson 1471e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1472e6ca193dSGeorge Wilson &child, &children) != 0) 1473e6ca193dSGeorge Wilson children = 0; 1474e6ca193dSGeorge Wilson 14753f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 14763f9d6ad7SLin Ling (uint64_t **)&vs, &c) == 0); 14773f9d6ad7SLin Ling 14785cabbc6bSPrashanth Sreenivasa verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 14795cabbc6bSPrashanth Sreenivasa 14805cabbc6bSPrashanth Sreenivasa if (strcmp(type, VDEV_TYPE_INDIRECT) == 0) 14815cabbc6bSPrashanth Sreenivasa return; 14825cabbc6bSPrashanth Sreenivasa 1483e6ca193dSGeorge Wilson state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1484e6ca193dSGeorge Wilson if (isspare) { 1485e6ca193dSGeorge Wilson /* 1486e6ca193dSGeorge Wilson * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 1487e6ca193dSGeorge Wilson * online drives. 1488e6ca193dSGeorge Wilson */ 1489e6ca193dSGeorge Wilson if (vs->vs_aux == VDEV_AUX_SPARED) 1490e6ca193dSGeorge Wilson state = "INUSE"; 1491e6ca193dSGeorge Wilson else if (vs->vs_state == VDEV_STATE_HEALTHY) 1492e6ca193dSGeorge Wilson state = "AVAIL"; 1493e6ca193dSGeorge Wilson } 1494e6ca193dSGeorge Wilson 1495e6ca193dSGeorge Wilson (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, 1496e6ca193dSGeorge Wilson name, state); 1497e6ca193dSGeorge Wilson 1498e6ca193dSGeorge Wilson if (!isspare) { 1499e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 1500e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 1501e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 1502e6ca193dSGeorge Wilson (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 1503e6ca193dSGeorge Wilson } 1504e6ca193dSGeorge Wilson 1505e6ca193dSGeorge Wilson if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1506e6ca193dSGeorge Wilson ¬present) == 0) { 1507e6ca193dSGeorge Wilson char *path; 1508e6ca193dSGeorge Wilson verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 1509e6ca193dSGeorge Wilson (void) printf(" was %s", path); 1510e6ca193dSGeorge Wilson } else if (vs->vs_aux != 0) { 1511e6ca193dSGeorge Wilson (void) printf(" "); 1512e6ca193dSGeorge Wilson 1513e6ca193dSGeorge Wilson switch (vs->vs_aux) { 1514e6ca193dSGeorge Wilson case VDEV_AUX_OPEN_FAILED: 1515e6ca193dSGeorge Wilson (void) printf(gettext("cannot open")); 1516e6ca193dSGeorge Wilson break; 1517e6ca193dSGeorge Wilson 1518e6ca193dSGeorge Wilson case VDEV_AUX_BAD_GUID_SUM: 1519e6ca193dSGeorge Wilson (void) printf(gettext("missing device")); 1520e6ca193dSGeorge Wilson break; 1521e6ca193dSGeorge Wilson 1522e6ca193dSGeorge Wilson case VDEV_AUX_NO_REPLICAS: 1523e6ca193dSGeorge Wilson (void) printf(gettext("insufficient replicas")); 1524e6ca193dSGeorge Wilson break; 1525e6ca193dSGeorge Wilson 1526e6ca193dSGeorge Wilson case VDEV_AUX_VERSION_NEWER: 1527e6ca193dSGeorge Wilson (void) printf(gettext("newer version")); 1528e6ca193dSGeorge Wilson break; 1529e6ca193dSGeorge Wilson 1530ad135b5dSChristopher Siden case VDEV_AUX_UNSUP_FEAT: 1531ad135b5dSChristopher Siden (void) printf(gettext("unsupported feature(s)")); 1532ad135b5dSChristopher Siden break; 1533ad135b5dSChristopher Siden 1534e6ca193dSGeorge Wilson case VDEV_AUX_SPARED: 1535e6ca193dSGeorge Wilson verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 1536e6ca193dSGeorge Wilson &cb.cb_guid) == 0); 1537e6ca193dSGeorge Wilson if (zpool_iter(g_zfs, find_spare, &cb) == 1) { 1538e6ca193dSGeorge Wilson if (strcmp(zpool_get_name(cb.cb_zhp), 1539e6ca193dSGeorge Wilson zpool_get_name(zhp)) == 0) 1540e6ca193dSGeorge Wilson (void) printf(gettext("currently in " 1541e6ca193dSGeorge Wilson "use")); 1542e6ca193dSGeorge Wilson else 1543e6ca193dSGeorge Wilson (void) printf(gettext("in use by " 1544e6ca193dSGeorge Wilson "pool '%s'"), 1545e6ca193dSGeorge Wilson zpool_get_name(cb.cb_zhp)); 1546e6ca193dSGeorge Wilson zpool_close(cb.cb_zhp); 1547e6ca193dSGeorge Wilson } else { 1548e6ca193dSGeorge Wilson (void) printf(gettext("currently in use")); 1549e6ca193dSGeorge Wilson } 1550e6ca193dSGeorge Wilson break; 1551e6ca193dSGeorge Wilson 1552e6ca193dSGeorge Wilson case VDEV_AUX_ERR_EXCEEDED: 1553e6ca193dSGeorge Wilson (void) printf(gettext("too many errors")); 1554e6ca193dSGeorge Wilson break; 1555e6ca193dSGeorge Wilson 1556e6ca193dSGeorge Wilson case VDEV_AUX_IO_FAILURE: 1557e6ca193dSGeorge Wilson (void) printf(gettext("experienced I/O failures")); 1558e6ca193dSGeorge Wilson break; 1559e6ca193dSGeorge Wilson 1560e6ca193dSGeorge Wilson case VDEV_AUX_BAD_LOG: 1561e6ca193dSGeorge Wilson (void) printf(gettext("bad intent log")); 1562e6ca193dSGeorge Wilson break; 1563e6ca193dSGeorge Wilson 1564069f55e2SEric Schrock case VDEV_AUX_EXTERNAL: 1565069f55e2SEric Schrock (void) printf(gettext("external device fault")); 1566069f55e2SEric Schrock break; 1567069f55e2SEric Schrock 15681195e687SMark J Musante case VDEV_AUX_SPLIT_POOL: 15691195e687SMark J Musante (void) printf(gettext("split into new pool")); 15701195e687SMark J Musante break; 15711195e687SMark J Musante 15726f793812SPavel Zakharov case VDEV_AUX_CHILDREN_OFFLINE: 15736f793812SPavel Zakharov (void) printf(gettext("all children offline")); 15746f793812SPavel Zakharov break; 15756f793812SPavel Zakharov 1576e6ca193dSGeorge Wilson default: 1577e6ca193dSGeorge Wilson (void) printf(gettext("corrupted data")); 1578e6ca193dSGeorge Wilson break; 1579e6ca193dSGeorge Wilson } 15803f9d6ad7SLin Ling } 15813f9d6ad7SLin Ling 15823f9d6ad7SLin Ling (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS, 15833f9d6ad7SLin Ling (uint64_t **)&ps, &c); 15843f9d6ad7SLin Ling 15853f9d6ad7SLin Ling if (ps && ps->pss_state == DSS_SCANNING && 15863f9d6ad7SLin Ling vs->vs_scan_processed != 0 && children == 0) { 15873f9d6ad7SLin Ling (void) printf(gettext(" (%s)"), 15883f9d6ad7SLin Ling (ps->pss_func == POOL_SCAN_RESILVER) ? 15893f9d6ad7SLin Ling "resilvering" : "repairing"); 1590e6ca193dSGeorge Wilson } 1591e6ca193dSGeorge Wilson 1592e6ca193dSGeorge Wilson (void) printf("\n"); 1593e6ca193dSGeorge Wilson 1594e6ca193dSGeorge Wilson for (c = 0; c < children; c++) { 159588ecc943SGeorge Wilson uint64_t islog = B_FALSE, ishole = B_FALSE; 1596e6ca193dSGeorge Wilson 159788ecc943SGeorge Wilson /* Don't print logs or holes here */ 1598e6ca193dSGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 159988ecc943SGeorge Wilson &islog); 160088ecc943SGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, 160188ecc943SGeorge Wilson &ishole); 160288ecc943SGeorge Wilson if (islog || ishole) 1603e6ca193dSGeorge Wilson continue; 160488ecc943SGeorge Wilson vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE); 1605e6ca193dSGeorge Wilson print_status_config(zhp, vname, child[c], 1606e6ca193dSGeorge Wilson namewidth, depth + 2, isspare); 1607e6ca193dSGeorge Wilson free(vname); 1608e6ca193dSGeorge Wilson } 1609e6ca193dSGeorge Wilson } 1610e6ca193dSGeorge Wilson 1611fa9e4066Sahrens 1612fa9e4066Sahrens /* 1613fa9e4066Sahrens * Print the configuration of an exported pool. Iterate over all vdevs in the 1614fa9e4066Sahrens * pool, printing out the name and status for each one. 1615fa9e4066Sahrens */ 1616fa9e4066Sahrens void 1617e6ca193dSGeorge Wilson print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) 1618fa9e4066Sahrens { 1619fa9e4066Sahrens nvlist_t **child; 1620fa9e4066Sahrens uint_t c, children; 1621fa9e4066Sahrens vdev_stat_t *vs; 1622afefbcddSeschrock char *type, *vname; 1623fa9e4066Sahrens 1624fa9e4066Sahrens verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 162588ecc943SGeorge Wilson if (strcmp(type, VDEV_TYPE_MISSING) == 0 || 162688ecc943SGeorge Wilson strcmp(type, VDEV_TYPE_HOLE) == 0) 1627fa9e4066Sahrens return; 1628fa9e4066Sahrens 16293f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 1630fa9e4066Sahrens (uint64_t **)&vs, &c) == 0); 1631fa9e4066Sahrens 1632fa9e4066Sahrens (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name); 1633990b4856Slling (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); 1634fa9e4066Sahrens 1635fa9e4066Sahrens if (vs->vs_aux != 0) { 16363d7072f8Seschrock (void) printf(" "); 1637fa9e4066Sahrens 1638fa9e4066Sahrens switch (vs->vs_aux) { 1639fa9e4066Sahrens case VDEV_AUX_OPEN_FAILED: 1640fa9e4066Sahrens (void) printf(gettext("cannot open")); 1641fa9e4066Sahrens break; 1642fa9e4066Sahrens 1643fa9e4066Sahrens case VDEV_AUX_BAD_GUID_SUM: 1644fa9e4066Sahrens (void) printf(gettext("missing device")); 1645fa9e4066Sahrens break; 1646fa9e4066Sahrens 1647fa9e4066Sahrens case VDEV_AUX_NO_REPLICAS: 1648fa9e4066Sahrens (void) printf(gettext("insufficient replicas")); 1649fa9e4066Sahrens break; 1650fa9e4066Sahrens 1651eaca9bbdSeschrock case VDEV_AUX_VERSION_NEWER: 1652eaca9bbdSeschrock (void) printf(gettext("newer version")); 1653eaca9bbdSeschrock break; 1654eaca9bbdSeschrock 1655ad135b5dSChristopher Siden case VDEV_AUX_UNSUP_FEAT: 1656ad135b5dSChristopher Siden (void) printf(gettext("unsupported feature(s)")); 1657ad135b5dSChristopher Siden break; 1658ad135b5dSChristopher Siden 16593d7072f8Seschrock case VDEV_AUX_ERR_EXCEEDED: 16603d7072f8Seschrock (void) printf(gettext("too many errors")); 16613d7072f8Seschrock break; 16623d7072f8Seschrock 16636f793812SPavel Zakharov case VDEV_AUX_CHILDREN_OFFLINE: 16646f793812SPavel Zakharov (void) printf(gettext("all children offline")); 16656f793812SPavel Zakharov break; 16666f793812SPavel Zakharov 1667fa9e4066Sahrens default: 1668fa9e4066Sahrens (void) printf(gettext("corrupted data")); 1669fa9e4066Sahrens break; 1670fa9e4066Sahrens } 1671fa9e4066Sahrens } 1672fa9e4066Sahrens (void) printf("\n"); 1673fa9e4066Sahrens 1674fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1675fa9e4066Sahrens &child, &children) != 0) 1676fa9e4066Sahrens return; 1677fa9e4066Sahrens 1678afefbcddSeschrock for (c = 0; c < children; c++) { 16798654d025Sperrin uint64_t is_log = B_FALSE; 16808654d025Sperrin 16818654d025Sperrin (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 16828654d025Sperrin &is_log); 1683e6ca193dSGeorge Wilson if (is_log) 16848654d025Sperrin continue; 16858654d025Sperrin 168688ecc943SGeorge Wilson vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE); 1687e6ca193dSGeorge Wilson print_import_config(vname, child[c], namewidth, depth + 2); 1688afefbcddSeschrock free(vname); 1689afefbcddSeschrock } 169099653d4eSeschrock 1691fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1692fa94a07fSbrendan &child, &children) == 0) { 1693fa94a07fSbrendan (void) printf(gettext("\tcache\n")); 1694fa94a07fSbrendan for (c = 0; c < children; c++) { 169588ecc943SGeorge Wilson vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE); 1696fa94a07fSbrendan (void) printf("\t %s\n", vname); 1697fa94a07fSbrendan free(vname); 1698fa94a07fSbrendan } 1699fa94a07fSbrendan } 170099653d4eSeschrock 1701fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1702fa94a07fSbrendan &child, &children) == 0) { 1703fa94a07fSbrendan (void) printf(gettext("\tspares\n")); 1704fa94a07fSbrendan for (c = 0; c < children; c++) { 170588ecc943SGeorge Wilson vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE); 1706fa94a07fSbrendan (void) printf("\t %s\n", vname); 1707fa94a07fSbrendan free(vname); 1708fa94a07fSbrendan } 170999653d4eSeschrock } 1710fa9e4066Sahrens } 1711fa9e4066Sahrens 1712e6ca193dSGeorge Wilson /* 1713e6ca193dSGeorge Wilson * Print log vdevs. 1714e6ca193dSGeorge Wilson * Logs are recorded as top level vdevs in the main pool child array 1715e6ca193dSGeorge Wilson * but with "is_log" set to 1. We use either print_status_config() or 1716e6ca193dSGeorge Wilson * print_import_config() to print the top level logs then any log 1717e6ca193dSGeorge Wilson * children (eg mirrored slogs) are printed recursively - which 1718e6ca193dSGeorge Wilson * works because only the top level vdev is marked "is_log" 1719e6ca193dSGeorge Wilson */ 1720e6ca193dSGeorge Wilson static void 1721e6ca193dSGeorge Wilson print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose) 1722e6ca193dSGeorge Wilson { 1723e6ca193dSGeorge Wilson uint_t c, children; 1724e6ca193dSGeorge Wilson nvlist_t **child; 1725e6ca193dSGeorge Wilson 1726e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, 1727e6ca193dSGeorge Wilson &children) != 0) 1728e6ca193dSGeorge Wilson return; 1729e6ca193dSGeorge Wilson 1730e6ca193dSGeorge Wilson (void) printf(gettext("\tlogs\n")); 1731e6ca193dSGeorge Wilson 1732e6ca193dSGeorge Wilson for (c = 0; c < children; c++) { 1733e6ca193dSGeorge Wilson uint64_t is_log = B_FALSE; 1734e6ca193dSGeorge Wilson char *name; 1735e6ca193dSGeorge Wilson 1736e6ca193dSGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1737e6ca193dSGeorge Wilson &is_log); 1738e6ca193dSGeorge Wilson if (!is_log) 1739e6ca193dSGeorge Wilson continue; 174088ecc943SGeorge Wilson name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE); 1741e6ca193dSGeorge Wilson if (verbose) 1742e6ca193dSGeorge Wilson print_status_config(zhp, name, child[c], namewidth, 1743e6ca193dSGeorge Wilson 2, B_FALSE); 1744e6ca193dSGeorge Wilson else 1745e6ca193dSGeorge Wilson print_import_config(name, child[c], namewidth, 2); 1746e6ca193dSGeorge Wilson free(name); 1747e6ca193dSGeorge Wilson } 1748e6ca193dSGeorge Wilson } 1749468c413aSTim Haley 1750fa9e4066Sahrens /* 1751fa9e4066Sahrens * Display the status for the given pool. 1752fa9e4066Sahrens */ 1753fa9e4066Sahrens static void 1754fa9e4066Sahrens show_import(nvlist_t *config) 1755fa9e4066Sahrens { 1756fa9e4066Sahrens uint64_t pool_state; 1757fa9e4066Sahrens vdev_stat_t *vs; 1758fa9e4066Sahrens char *name; 1759fa9e4066Sahrens uint64_t guid; 1760fa9e4066Sahrens char *msgid; 1761fa9e4066Sahrens nvlist_t *nvroot; 1762fa9e4066Sahrens int reason; 176346657f8dSmmusante const char *health; 1764fa9e4066Sahrens uint_t vsc; 1765fa9e4066Sahrens int namewidth; 17668704186eSDan McDonald char *comment; 1767fa9e4066Sahrens 1768fa9e4066Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1769fa9e4066Sahrens &name) == 0); 1770fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 1771fa9e4066Sahrens &guid) == 0); 1772fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 1773fa9e4066Sahrens &pool_state) == 0); 1774fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1775fa9e4066Sahrens &nvroot) == 0); 1776fa9e4066Sahrens 17773f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 1778fa9e4066Sahrens (uint64_t **)&vs, &vsc) == 0); 1779990b4856Slling health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1780fa9e4066Sahrens 1781fa9e4066Sahrens reason = zpool_import_status(config, &msgid); 1782fa9e4066Sahrens 17838704186eSDan McDonald (void) printf(gettext(" pool: %s\n"), name); 17848704186eSDan McDonald (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); 17858704186eSDan McDonald (void) printf(gettext(" state: %s"), health); 17864c58d714Sdarrenm if (pool_state == POOL_STATE_DESTROYED) 1787b1b8ab34Slling (void) printf(gettext(" (DESTROYED)")); 17884c58d714Sdarrenm (void) printf("\n"); 1789fa9e4066Sahrens 1790fa9e4066Sahrens switch (reason) { 1791fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_R: 1792fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_NR: 1793fa9e4066Sahrens case ZPOOL_STATUS_BAD_GUID_SUM: 17948704186eSDan McDonald (void) printf(gettext(" status: One or more devices are " 17958704186eSDan McDonald "missing from the system.\n")); 1796fa9e4066Sahrens break; 1797fa9e4066Sahrens 1798fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_R: 1799fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_NR: 18008704186eSDan McDonald (void) printf(gettext(" status: One or more devices contains " 1801fa9e4066Sahrens "corrupted data.\n")); 1802fa9e4066Sahrens break; 1803fa9e4066Sahrens 1804fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_DATA: 18058704186eSDan McDonald (void) printf( 18068704186eSDan McDonald gettext(" status: The pool data is corrupted.\n")); 1807fa9e4066Sahrens break; 1808fa9e4066Sahrens 1809441d80aaSlling case ZPOOL_STATUS_OFFLINE_DEV: 18108704186eSDan McDonald (void) printf(gettext(" status: One or more devices " 1811441d80aaSlling "are offlined.\n")); 1812441d80aaSlling break; 1813441d80aaSlling 1814ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_POOL: 18158704186eSDan McDonald (void) printf(gettext(" status: The pool metadata is " 1816ea8dc4b6Seschrock "corrupted.\n")); 1817ea8dc4b6Seschrock break; 1818ea8dc4b6Seschrock 1819eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_OLDER: 182057221772SChristopher Siden (void) printf(gettext(" status: The pool is formatted using a " 182157221772SChristopher Siden "legacy on-disk version.\n")); 1822eaca9bbdSeschrock break; 1823eaca9bbdSeschrock 1824eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 18258704186eSDan McDonald (void) printf(gettext(" status: The pool is formatted using an " 1826eaca9bbdSeschrock "incompatible version.\n")); 1827eaca9bbdSeschrock break; 1828b87f3af3Sperrin 182957221772SChristopher Siden case ZPOOL_STATUS_FEAT_DISABLED: 183057221772SChristopher Siden (void) printf(gettext(" status: Some supported features are " 183157221772SChristopher Siden "not enabled on the pool.\n")); 183257221772SChristopher Siden break; 183357221772SChristopher Siden 1834ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ: 1835ad135b5dSChristopher Siden (void) printf(gettext("status: The pool uses the following " 1836edc8ef7dSToomas Soome "feature(s) not supported on this system:\n")); 1837ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 1838ad135b5dSChristopher Siden break; 1839ad135b5dSChristopher Siden 1840ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 1841ad135b5dSChristopher Siden (void) printf(gettext("status: The pool can only be accessed " 1842ad135b5dSChristopher Siden "in read-only mode on this system. It\n\tcannot be " 1843ad135b5dSChristopher Siden "accessed in read-write mode because it uses the " 1844ad135b5dSChristopher Siden "following\n\tfeature(s) not supported on this system:\n")); 1845ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 1846ad135b5dSChristopher Siden break; 1847ad135b5dSChristopher Siden 184895173954Sek case ZPOOL_STATUS_HOSTID_MISMATCH: 18498704186eSDan McDonald (void) printf(gettext(" status: The pool was last accessed by " 185095173954Sek "another system.\n")); 185195173954Sek break; 1852b87f3af3Sperrin 18533d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_R: 18543d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_NR: 18558704186eSDan McDonald (void) printf(gettext(" status: One or more devices are " 18563d7072f8Seschrock "faulted.\n")); 18573d7072f8Seschrock break; 18583d7072f8Seschrock 1859b87f3af3Sperrin case ZPOOL_STATUS_BAD_LOG: 18608704186eSDan McDonald (void) printf(gettext(" status: An intent log record cannot be " 1861b87f3af3Sperrin "read.\n")); 1862b87f3af3Sperrin break; 1863b87f3af3Sperrin 18643f9d6ad7SLin Ling case ZPOOL_STATUS_RESILVERING: 18658704186eSDan McDonald (void) printf(gettext(" status: One or more devices were being " 18663f9d6ad7SLin Ling "resilvered.\n")); 18673f9d6ad7SLin Ling break; 18683f9d6ad7SLin Ling 1869fa9e4066Sahrens default: 1870fa9e4066Sahrens /* 1871fa9e4066Sahrens * No other status can be seen when importing pools. 1872fa9e4066Sahrens */ 1873fa9e4066Sahrens assert(reason == ZPOOL_STATUS_OK); 1874fa9e4066Sahrens } 1875fa9e4066Sahrens 1876fa9e4066Sahrens /* 1877fa9e4066Sahrens * Print out an action according to the overall state of the pool. 1878fa9e4066Sahrens */ 187946657f8dSmmusante if (vs->vs_state == VDEV_STATE_HEALTHY) { 188057221772SChristopher Siden if (reason == ZPOOL_STATUS_VERSION_OLDER || 188157221772SChristopher Siden reason == ZPOOL_STATUS_FEAT_DISABLED) { 18828704186eSDan McDonald (void) printf(gettext(" action: The pool can be " 1883eaca9bbdSeschrock "imported using its name or numeric identifier, " 1884eaca9bbdSeschrock "though\n\tsome features will not be available " 1885eaca9bbdSeschrock "without an explicit 'zpool upgrade'.\n")); 188657221772SChristopher Siden } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) { 18878704186eSDan McDonald (void) printf(gettext(" action: The pool can be " 188895173954Sek "imported using its name or numeric " 188995173954Sek "identifier and\n\tthe '-f' flag.\n")); 189057221772SChristopher Siden } else { 18918704186eSDan McDonald (void) printf(gettext(" action: The pool can be " 1892eaca9bbdSeschrock "imported using its name or numeric " 1893eaca9bbdSeschrock "identifier.\n")); 189457221772SChristopher Siden } 189546657f8dSmmusante } else if (vs->vs_state == VDEV_STATE_DEGRADED) { 18968704186eSDan McDonald (void) printf(gettext(" action: The pool can be imported " 1897fa9e4066Sahrens "despite missing or damaged devices. The\n\tfault " 1898eaca9bbdSeschrock "tolerance of the pool may be compromised if imported.\n")); 1899fa9e4066Sahrens } else { 1900eaca9bbdSeschrock switch (reason) { 1901eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 19028704186eSDan McDonald (void) printf(gettext(" action: The pool cannot be " 1903eaca9bbdSeschrock "imported. Access the pool on a system running " 1904eaca9bbdSeschrock "newer\n\tsoftware, or recreate the pool from " 1905eaca9bbdSeschrock "backup.\n")); 1906eaca9bbdSeschrock break; 1907ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ: 1908ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be " 1909ad135b5dSChristopher Siden "imported. Access the pool on a system that " 1910ad135b5dSChristopher Siden "supports\n\tthe required feature(s), or recreate " 1911ad135b5dSChristopher Siden "the pool from backup.\n")); 1912ad135b5dSChristopher Siden break; 1913ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 1914ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be " 1915ad135b5dSChristopher Siden "imported in read-write mode. Import the pool " 1916ad135b5dSChristopher Siden "with\n" 1917ad135b5dSChristopher Siden "\t\"-o readonly=on\", access the pool on a system " 1918ad135b5dSChristopher Siden "that supports the\n\trequired feature(s), or " 1919ad135b5dSChristopher Siden "recreate the pool from backup.\n")); 1920ad135b5dSChristopher Siden break; 1921eaca9bbdSeschrock case ZPOOL_STATUS_MISSING_DEV_R: 1922eaca9bbdSeschrock case ZPOOL_STATUS_MISSING_DEV_NR: 1923eaca9bbdSeschrock case ZPOOL_STATUS_BAD_GUID_SUM: 19248704186eSDan McDonald (void) printf(gettext(" action: The pool cannot be " 1925fa9e4066Sahrens "imported. Attach the missing\n\tdevices and try " 1926fa9e4066Sahrens "again.\n")); 1927eaca9bbdSeschrock break; 1928eaca9bbdSeschrock default: 19298704186eSDan McDonald (void) printf(gettext(" action: The pool cannot be " 1930fa9e4066Sahrens "imported due to damaged devices or data.\n")); 1931eaca9bbdSeschrock } 1932eaca9bbdSeschrock } 1933eaca9bbdSeschrock 19348704186eSDan McDonald /* Print the comment attached to the pool. */ 19358704186eSDan McDonald if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0) 19368704186eSDan McDonald (void) printf(gettext("comment: %s\n"), comment); 19378704186eSDan McDonald 193846657f8dSmmusante /* 193946657f8dSmmusante * If the state is "closed" or "can't open", and the aux state 194046657f8dSmmusante * is "corrupt data": 194146657f8dSmmusante */ 194246657f8dSmmusante if (((vs->vs_state == VDEV_STATE_CLOSED) || 194346657f8dSmmusante (vs->vs_state == VDEV_STATE_CANT_OPEN)) && 194446657f8dSmmusante (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) { 1945eaca9bbdSeschrock if (pool_state == POOL_STATE_DESTROYED) 1946eaca9bbdSeschrock (void) printf(gettext("\tThe pool was destroyed, " 1947eaca9bbdSeschrock "but can be imported using the '-Df' flags.\n")); 1948eaca9bbdSeschrock else if (pool_state != POOL_STATE_EXPORTED) 1949eaca9bbdSeschrock (void) printf(gettext("\tThe pool may be active on " 195018ce54dfSek "another system, but can be imported using\n\t" 1951eaca9bbdSeschrock "the '-f' flag.\n")); 1952fa9e4066Sahrens } 1953fa9e4066Sahrens 1954fa9e4066Sahrens if (msgid != NULL) 1955654b400cSJoshua M. Clulow (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 1956fa9e4066Sahrens msgid); 1957fa9e4066Sahrens 19588704186eSDan McDonald (void) printf(gettext(" config:\n\n")); 1959fa9e4066Sahrens 1960c67d9675Seschrock namewidth = max_width(NULL, nvroot, 0, 0); 1961fa9e4066Sahrens if (namewidth < 10) 1962fa9e4066Sahrens namewidth = 10; 19638654d025Sperrin 1964e6ca193dSGeorge Wilson print_import_config(name, nvroot, namewidth, 0); 1965e6ca193dSGeorge Wilson if (num_logs(nvroot) > 0) 1966e6ca193dSGeorge Wilson print_logs(NULL, nvroot, namewidth, B_FALSE); 1967fa9e4066Sahrens 1968fa9e4066Sahrens if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 196946657f8dSmmusante (void) printf(gettext("\n\tAdditional devices are known to " 1970fa9e4066Sahrens "be part of this pool, though their\n\texact " 197146657f8dSmmusante "configuration cannot be determined.\n")); 1972fa9e4066Sahrens } 1973fa9e4066Sahrens } 1974fa9e4066Sahrens 1975fa9e4066Sahrens /* 1976fa9e4066Sahrens * Perform the import for the given configuration. This passes the heavy 1977990b4856Slling * lifting off to zpool_import_props(), and then mounts the datasets contained 1978990b4856Slling * within the pool. 1979fa9e4066Sahrens */ 1980fa9e4066Sahrens static int 1981fa9e4066Sahrens do_import(nvlist_t *config, const char *newname, const char *mntopts, 19824b964adaSGeorge Wilson nvlist_t *props, int flags) 1983fa9e4066Sahrens { 1984fa9e4066Sahrens zpool_handle_t *zhp; 1985fa9e4066Sahrens char *name; 1986fa9e4066Sahrens uint64_t state; 1987eaca9bbdSeschrock uint64_t version; 1988fa9e4066Sahrens 1989fa9e4066Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1990fa9e4066Sahrens &name) == 0); 1991fa9e4066Sahrens 1992fa9e4066Sahrens verify(nvlist_lookup_uint64(config, 1993fa9e4066Sahrens ZPOOL_CONFIG_POOL_STATE, &state) == 0); 1994eaca9bbdSeschrock verify(nvlist_lookup_uint64(config, 1995eaca9bbdSeschrock ZPOOL_CONFIG_VERSION, &version) == 0); 1996ad135b5dSChristopher Siden if (!SPA_VERSION_IS_SUPPORTED(version)) { 1997eaca9bbdSeschrock (void) fprintf(stderr, gettext("cannot import '%s': pool " 1998ad135b5dSChristopher Siden "is formatted using an unsupported ZFS version\n"), name); 1999eaca9bbdSeschrock return (1); 20004b964adaSGeorge Wilson } else if (state != POOL_STATE_EXPORTED && 20014b964adaSGeorge Wilson !(flags & ZFS_IMPORT_ANY_HOST)) { 200295173954Sek uint64_t hostid; 200395173954Sek 200495173954Sek if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, 200595173954Sek &hostid) == 0) { 200695173954Sek if ((unsigned long)hostid != gethostid()) { 200795173954Sek char *hostname; 200895173954Sek uint64_t timestamp; 200995173954Sek time_t t; 201095173954Sek 201195173954Sek verify(nvlist_lookup_string(config, 201295173954Sek ZPOOL_CONFIG_HOSTNAME, &hostname) == 0); 201395173954Sek verify(nvlist_lookup_uint64(config, 201495173954Sek ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0); 201595173954Sek t = timestamp; 201695173954Sek (void) fprintf(stderr, gettext("cannot import " 201795173954Sek "'%s': pool may be in use from other " 201895173954Sek "system, it was last accessed by %s " 201995173954Sek "(hostid: 0x%lx) on %s"), name, hostname, 202095173954Sek (unsigned long)hostid, 202195173954Sek asctime(localtime(&t))); 202295173954Sek (void) fprintf(stderr, gettext("use '-f' to " 202395173954Sek "import anyway\n")); 202495173954Sek return (1); 202595173954Sek } 202695173954Sek } else { 202795173954Sek (void) fprintf(stderr, gettext("cannot import '%s': " 202895173954Sek "pool may be in use from other system\n"), name); 202995173954Sek (void) fprintf(stderr, gettext("use '-f' to import " 203095173954Sek "anyway\n")); 203195173954Sek return (1); 203295173954Sek } 2033fa9e4066Sahrens } 2034fa9e4066Sahrens 20354b964adaSGeorge Wilson if (zpool_import_props(g_zfs, config, newname, props, flags) != 0) 2036fa9e4066Sahrens return (1); 2037fa9e4066Sahrens 2038fa9e4066Sahrens if (newname != NULL) 2039fa9e4066Sahrens name = (char *)newname; 2040fa9e4066Sahrens 20414f0f5e5bSVictor Latushkin if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL) 20424f0f5e5bSVictor Latushkin return (1); 2043fa9e4066Sahrens 2044379c004dSEric Schrock if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 2045f9af39baSGeorge Wilson !(flags & ZFS_IMPORT_ONLY) && 2046379c004dSEric Schrock zpool_enable_datasets(zhp, mntopts, 0) != 0) { 2047fa9e4066Sahrens zpool_close(zhp); 2048fa9e4066Sahrens return (1); 2049fa9e4066Sahrens } 2050fa9e4066Sahrens 2051fa9e4066Sahrens zpool_close(zhp); 2052468c413aSTim Haley return (0); 2053fa9e4066Sahrens } 2054fa9e4066Sahrens 2055*86714001SSerapheim Dimitropoulos /* 2056*86714001SSerapheim Dimitropoulos * zpool checkpoint <pool> 2057*86714001SSerapheim Dimitropoulos * checkpoint --discard <pool> 2058*86714001SSerapheim Dimitropoulos * 2059*86714001SSerapheim Dimitropoulos * -d Discard the checkpoint from a checkpointed 2060*86714001SSerapheim Dimitropoulos * --discard pool. 2061*86714001SSerapheim Dimitropoulos * 2062*86714001SSerapheim Dimitropoulos * Checkpoints the specified pool, by taking a "snapshot" of its 2063*86714001SSerapheim Dimitropoulos * current state. A pool can only have one checkpoint at a time. 2064*86714001SSerapheim Dimitropoulos */ 2065*86714001SSerapheim Dimitropoulos int 2066*86714001SSerapheim Dimitropoulos zpool_do_checkpoint(int argc, char **argv) 2067*86714001SSerapheim Dimitropoulos { 2068*86714001SSerapheim Dimitropoulos boolean_t discard; 2069*86714001SSerapheim Dimitropoulos char *pool; 2070*86714001SSerapheim Dimitropoulos zpool_handle_t *zhp; 2071*86714001SSerapheim Dimitropoulos int c, err; 2072*86714001SSerapheim Dimitropoulos 2073*86714001SSerapheim Dimitropoulos struct option long_options[] = { 2074*86714001SSerapheim Dimitropoulos {"discard", no_argument, NULL, 'd'}, 2075*86714001SSerapheim Dimitropoulos {0, 0, 0, 0} 2076*86714001SSerapheim Dimitropoulos }; 2077*86714001SSerapheim Dimitropoulos 2078*86714001SSerapheim Dimitropoulos discard = B_FALSE; 2079*86714001SSerapheim Dimitropoulos while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) { 2080*86714001SSerapheim Dimitropoulos switch (c) { 2081*86714001SSerapheim Dimitropoulos case 'd': 2082*86714001SSerapheim Dimitropoulos discard = B_TRUE; 2083*86714001SSerapheim Dimitropoulos break; 2084*86714001SSerapheim Dimitropoulos case '?': 2085*86714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2086*86714001SSerapheim Dimitropoulos optopt); 2087*86714001SSerapheim Dimitropoulos usage(B_FALSE); 2088*86714001SSerapheim Dimitropoulos } 2089*86714001SSerapheim Dimitropoulos } 2090*86714001SSerapheim Dimitropoulos 2091*86714001SSerapheim Dimitropoulos argc -= optind; 2092*86714001SSerapheim Dimitropoulos argv += optind; 2093*86714001SSerapheim Dimitropoulos 2094*86714001SSerapheim Dimitropoulos if (argc < 1) { 2095*86714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("missing pool argument\n")); 2096*86714001SSerapheim Dimitropoulos usage(B_FALSE); 2097*86714001SSerapheim Dimitropoulos } 2098*86714001SSerapheim Dimitropoulos 2099*86714001SSerapheim Dimitropoulos if (argc > 1) { 2100*86714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("too many arguments\n")); 2101*86714001SSerapheim Dimitropoulos usage(B_FALSE); 2102*86714001SSerapheim Dimitropoulos } 2103*86714001SSerapheim Dimitropoulos 2104*86714001SSerapheim Dimitropoulos pool = argv[0]; 2105*86714001SSerapheim Dimitropoulos 2106*86714001SSerapheim Dimitropoulos if ((zhp = zpool_open(g_zfs, pool)) == NULL) { 2107*86714001SSerapheim Dimitropoulos /* As a special case, check for use of '/' in the name */ 2108*86714001SSerapheim Dimitropoulos if (strchr(pool, '/') != NULL) 2109*86714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("'zpool checkpoint' " 2110*86714001SSerapheim Dimitropoulos "doesn't work on datasets. To save the state " 2111*86714001SSerapheim Dimitropoulos "of a dataset from a specific point in time " 2112*86714001SSerapheim Dimitropoulos "please use 'zfs snapshot'\n")); 2113*86714001SSerapheim Dimitropoulos return (1); 2114*86714001SSerapheim Dimitropoulos } 2115*86714001SSerapheim Dimitropoulos 2116*86714001SSerapheim Dimitropoulos if (discard) 2117*86714001SSerapheim Dimitropoulos err = (zpool_discard_checkpoint(zhp) != 0); 2118*86714001SSerapheim Dimitropoulos else 2119*86714001SSerapheim Dimitropoulos err = (zpool_checkpoint(zhp) != 0); 2120*86714001SSerapheim Dimitropoulos 2121*86714001SSerapheim Dimitropoulos zpool_close(zhp); 2122*86714001SSerapheim Dimitropoulos 2123*86714001SSerapheim Dimitropoulos return (err); 2124*86714001SSerapheim Dimitropoulos } 2125*86714001SSerapheim Dimitropoulos 2126*86714001SSerapheim Dimitropoulos #define CHECKPOINT_OPT 1024 2127*86714001SSerapheim Dimitropoulos 2128fa9e4066Sahrens /* 21294c58d714Sdarrenm * zpool import [-d dir] [-D] 21302f8aaab3Seschrock * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 21312f8aaab3Seschrock * [-d dir | -c cachefile] [-f] -a 21322f8aaab3Seschrock * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 2133468c413aSTim Haley * [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool] 21342f8aaab3Seschrock * 21352f8aaab3Seschrock * -c Read pool information from a cachefile instead of searching 21362f8aaab3Seschrock * devices. 2137fa9e4066Sahrens * 2138fa9e4066Sahrens * -d Scan in a specific directory, other than /dev/dsk. More than 2139fa9e4066Sahrens * one directory can be specified using multiple '-d' options. 2140fa9e4066Sahrens * 21414c58d714Sdarrenm * -D Scan for previously destroyed pools or import all or only 21424c58d714Sdarrenm * specified destroyed pools. 21434c58d714Sdarrenm * 2144fa9e4066Sahrens * -R Temporarily import the pool, with all mountpoints relative to 2145fa9e4066Sahrens * the given root. The pool will remain exported when the machine 2146fa9e4066Sahrens * is rebooted. 2147fa9e4066Sahrens * 2148468c413aSTim Haley * -V Import even in the presence of faulted vdevs. This is an 2149c5904d13Seschrock * intentionally undocumented option for testing purposes, and 2150c5904d13Seschrock * treats the pool configuration as complete, leaving any bad 21514f0f5e5bSVictor Latushkin * vdevs in the FAULTED state. In other words, it does verbatim 21524f0f5e5bSVictor Latushkin * import. 2153c5904d13Seschrock * 2154468c413aSTim Haley * -f Force import, even if it appears that the pool is active. 2155468c413aSTim Haley * 2156468c413aSTim Haley * -F Attempt rewind if necessary. 2157468c413aSTim Haley * 2158468c413aSTim Haley * -n See if rewind would work, but don't actually rewind. 2159468c413aSTim Haley * 2160f9af39baSGeorge Wilson * -N Import the pool but don't mount datasets. 2161f9af39baSGeorge Wilson * 2162f9af39baSGeorge Wilson * -T Specify a starting txg to use for import. This option is 2163f9af39baSGeorge Wilson * intentionally undocumented option for testing purposes. 2164f9af39baSGeorge Wilson * 2165fa9e4066Sahrens * -a Import all pools found. 2166fa9e4066Sahrens * 2167990b4856Slling * -o Set property=value and/or temporary mount options (without '='). 2168ecd6cf80Smarks * 2169*86714001SSerapheim Dimitropoulos * --rewind-to-checkpoint 2170*86714001SSerapheim Dimitropoulos * Import the pool and revert back to the checkpoint. 2171*86714001SSerapheim Dimitropoulos * 2172fa9e4066Sahrens * The import command scans for pools to import, and import pools based on pool 2173fa9e4066Sahrens * name and GUID. The pool can also be renamed as part of the import process. 2174fa9e4066Sahrens */ 2175fa9e4066Sahrens int 2176fa9e4066Sahrens zpool_do_import(int argc, char **argv) 2177fa9e4066Sahrens { 2178fa9e4066Sahrens char **searchdirs = NULL; 2179fa9e4066Sahrens int nsearch = 0; 2180fa9e4066Sahrens int c; 2181d41c4376SMark J Musante int err = 0; 21822f8aaab3Seschrock nvlist_t *pools = NULL; 218399653d4eSeschrock boolean_t do_all = B_FALSE; 218499653d4eSeschrock boolean_t do_destroyed = B_FALSE; 2185fa9e4066Sahrens char *mntopts = NULL; 2186fa9e4066Sahrens nvpair_t *elem; 2187fa9e4066Sahrens nvlist_t *config; 218824e697d4Sck uint64_t searchguid = 0; 218924e697d4Sck char *searchname = NULL; 2190990b4856Slling char *propval; 2191fa9e4066Sahrens nvlist_t *found_config; 2192468c413aSTim Haley nvlist_t *policy = NULL; 2193ecd6cf80Smarks nvlist_t *props = NULL; 219499653d4eSeschrock boolean_t first; 21954b964adaSGeorge Wilson int flags = ZFS_IMPORT_NORMAL; 2196468c413aSTim Haley uint32_t rewind_policy = ZPOOL_NO_REWIND; 2197468c413aSTim Haley boolean_t dryrun = B_FALSE; 2198468c413aSTim Haley boolean_t do_rewind = B_FALSE; 2199468c413aSTim Haley boolean_t xtreme_rewind = B_FALSE; 2200f9af39baSGeorge Wilson uint64_t pool_state, txg = -1ULL; 22012f8aaab3Seschrock char *cachefile = NULL; 2202d41c4376SMark J Musante importargs_t idata = { 0 }; 2203f9af39baSGeorge Wilson char *endptr; 2204fa9e4066Sahrens 2205*86714001SSerapheim Dimitropoulos 2206*86714001SSerapheim Dimitropoulos struct option long_options[] = { 2207*86714001SSerapheim Dimitropoulos {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT}, 2208*86714001SSerapheim Dimitropoulos {0, 0, 0, 0} 2209*86714001SSerapheim Dimitropoulos }; 2210*86714001SSerapheim Dimitropoulos 2211fa9e4066Sahrens /* check options */ 2212*86714001SSerapheim Dimitropoulos while ((c = getopt_long(argc, argv, ":aCc:d:DEfFmnNo:rR:T:VX", 2213*86714001SSerapheim Dimitropoulos long_options, NULL)) != -1) { 2214fa9e4066Sahrens switch (c) { 2215fa9e4066Sahrens case 'a': 221699653d4eSeschrock do_all = B_TRUE; 2217fa9e4066Sahrens break; 22182f8aaab3Seschrock case 'c': 22192f8aaab3Seschrock cachefile = optarg; 22202f8aaab3Seschrock break; 2221fa9e4066Sahrens case 'd': 2222fa9e4066Sahrens if (searchdirs == NULL) { 2223fa9e4066Sahrens searchdirs = safe_malloc(sizeof (char *)); 2224fa9e4066Sahrens } else { 2225fa9e4066Sahrens char **tmp = safe_malloc((nsearch + 1) * 2226fa9e4066Sahrens sizeof (char *)); 2227fa9e4066Sahrens bcopy(searchdirs, tmp, nsearch * 2228fa9e4066Sahrens sizeof (char *)); 2229fa9e4066Sahrens free(searchdirs); 2230fa9e4066Sahrens searchdirs = tmp; 2231fa9e4066Sahrens } 2232fa9e4066Sahrens searchdirs[nsearch++] = optarg; 2233fa9e4066Sahrens break; 22344c58d714Sdarrenm case 'D': 223599653d4eSeschrock do_destroyed = B_TRUE; 22364c58d714Sdarrenm break; 2237fa9e4066Sahrens case 'f': 22384b964adaSGeorge Wilson flags |= ZFS_IMPORT_ANY_HOST; 2239fa9e4066Sahrens break; 2240c5904d13Seschrock case 'F': 2241468c413aSTim Haley do_rewind = B_TRUE; 2242468c413aSTim Haley break; 22434b964adaSGeorge Wilson case 'm': 22444b964adaSGeorge Wilson flags |= ZFS_IMPORT_MISSING_LOG; 22454b964adaSGeorge Wilson break; 2246468c413aSTim Haley case 'n': 2247468c413aSTim Haley dryrun = B_TRUE; 2248c5904d13Seschrock break; 2249f9af39baSGeorge Wilson case 'N': 2250f9af39baSGeorge Wilson flags |= ZFS_IMPORT_ONLY; 2251f9af39baSGeorge Wilson break; 2252fa9e4066Sahrens case 'o': 2253990b4856Slling if ((propval = strchr(optarg, '=')) != NULL) { 2254990b4856Slling *propval = '\0'; 2255990b4856Slling propval++; 22560a48a24eStimh if (add_prop_list(optarg, propval, 22570a48a24eStimh &props, B_TRUE)) 2258990b4856Slling goto error; 2259990b4856Slling } else { 2260990b4856Slling mntopts = optarg; 2261990b4856Slling } 2262fa9e4066Sahrens break; 2263fa9e4066Sahrens case 'R': 2264990b4856Slling if (add_prop_list(zpool_prop_to_name( 22650a48a24eStimh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 2266990b4856Slling goto error; 22672f8aaab3Seschrock if (nvlist_lookup_string(props, 22682f8aaab3Seschrock zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 22692f8aaab3Seschrock &propval) == 0) 22702f8aaab3Seschrock break; 2271990b4856Slling if (add_prop_list(zpool_prop_to_name( 22720a48a24eStimh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 2273990b4856Slling goto error; 2274fa9e4066Sahrens break; 2275f9af39baSGeorge Wilson case 'T': 2276f9af39baSGeorge Wilson errno = 0; 2277e42d2059SMatthew Ahrens txg = strtoull(optarg, &endptr, 0); 2278f9af39baSGeorge Wilson if (errno != 0 || *endptr != '\0') { 2279f9af39baSGeorge Wilson (void) fprintf(stderr, 2280f9af39baSGeorge Wilson gettext("invalid txg value\n")); 2281f9af39baSGeorge Wilson usage(B_FALSE); 2282f9af39baSGeorge Wilson } 2283f9af39baSGeorge Wilson rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND; 2284f9af39baSGeorge Wilson break; 2285468c413aSTim Haley case 'V': 22864b964adaSGeorge Wilson flags |= ZFS_IMPORT_VERBATIM; 2287468c413aSTim Haley break; 2288468c413aSTim Haley case 'X': 2289468c413aSTim Haley xtreme_rewind = B_TRUE; 2290468c413aSTim Haley break; 2291*86714001SSerapheim Dimitropoulos case CHECKPOINT_OPT: 2292*86714001SSerapheim Dimitropoulos flags |= ZFS_IMPORT_CHECKPOINT; 2293*86714001SSerapheim Dimitropoulos break; 2294fa9e4066Sahrens case ':': 2295fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 2296fa9e4066Sahrens "'%c' option\n"), optopt); 229799653d4eSeschrock usage(B_FALSE); 2298fa9e4066Sahrens break; 2299fa9e4066Sahrens case '?': 2300fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2301fa9e4066Sahrens optopt); 230299653d4eSeschrock usage(B_FALSE); 2303fa9e4066Sahrens } 2304fa9e4066Sahrens } 2305fa9e4066Sahrens 2306fa9e4066Sahrens argc -= optind; 2307fa9e4066Sahrens argv += optind; 2308fa9e4066Sahrens 23092f8aaab3Seschrock if (cachefile && nsearch != 0) { 23102f8aaab3Seschrock (void) fprintf(stderr, gettext("-c is incompatible with -d\n")); 23112f8aaab3Seschrock usage(B_FALSE); 23122f8aaab3Seschrock } 23132f8aaab3Seschrock 2314468c413aSTim Haley if ((dryrun || xtreme_rewind) && !do_rewind) { 2315468c413aSTim Haley (void) fprintf(stderr, 2316468c413aSTim Haley gettext("-n or -X only meaningful with -F\n")); 2317468c413aSTim Haley usage(B_FALSE); 2318468c413aSTim Haley } 2319468c413aSTim Haley if (dryrun) 2320468c413aSTim Haley rewind_policy = ZPOOL_TRY_REWIND; 2321468c413aSTim Haley else if (do_rewind) 2322468c413aSTim Haley rewind_policy = ZPOOL_DO_REWIND; 2323468c413aSTim Haley if (xtreme_rewind) 2324468c413aSTim Haley rewind_policy |= ZPOOL_EXTREME_REWIND; 2325468c413aSTim Haley 2326468c413aSTim Haley /* In the future, we can capture further policy and include it here */ 2327468c413aSTim Haley if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 2328f9af39baSGeorge Wilson nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 || 2329468c413aSTim Haley nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0) 2330468c413aSTim Haley goto error; 2331468c413aSTim Haley 2332fa9e4066Sahrens if (searchdirs == NULL) { 2333fa9e4066Sahrens searchdirs = safe_malloc(sizeof (char *)); 23346401734dSWill Andrews searchdirs[0] = ZFS_DISK_ROOT; 2335fa9e4066Sahrens nsearch = 1; 2336fa9e4066Sahrens } 2337fa9e4066Sahrens 2338fa9e4066Sahrens /* check argument count */ 2339fa9e4066Sahrens if (do_all) { 2340fa9e4066Sahrens if (argc != 0) { 2341fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 234299653d4eSeschrock usage(B_FALSE); 2343fa9e4066Sahrens } 2344fa9e4066Sahrens } else { 2345fa9e4066Sahrens if (argc > 2) { 2346fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 234799653d4eSeschrock usage(B_FALSE); 2348fa9e4066Sahrens } 2349fa9e4066Sahrens 2350fa9e4066Sahrens /* 2351fa9e4066Sahrens * Check for the SYS_CONFIG privilege. We do this explicitly 2352fa9e4066Sahrens * here because otherwise any attempt to discover pools will 2353fa9e4066Sahrens * silently fail. 2354fa9e4066Sahrens */ 2355fa9e4066Sahrens if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 2356fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot " 2357fa9e4066Sahrens "discover pools: permission denied\n")); 235899653d4eSeschrock free(searchdirs); 2359468c413aSTim Haley nvlist_free(policy); 2360fa9e4066Sahrens return (1); 2361fa9e4066Sahrens } 2362fa9e4066Sahrens } 2363fa9e4066Sahrens 2364fa9e4066Sahrens /* 2365fa9e4066Sahrens * Depending on the arguments given, we do one of the following: 2366fa9e4066Sahrens * 2367fa9e4066Sahrens * <none> Iterate through all pools and display information about 2368fa9e4066Sahrens * each one. 2369fa9e4066Sahrens * 2370fa9e4066Sahrens * -a Iterate through all pools and try to import each one. 2371fa9e4066Sahrens * 2372fa9e4066Sahrens * <id> Find the pool that corresponds to the given GUID/pool 2373fa9e4066Sahrens * name and import that one. 23744c58d714Sdarrenm * 23754c58d714Sdarrenm * -D Above options applies only to destroyed pools. 2376fa9e4066Sahrens */ 2377fa9e4066Sahrens if (argc != 0) { 2378fa9e4066Sahrens char *endptr; 2379fa9e4066Sahrens 2380fa9e4066Sahrens errno = 0; 2381fa9e4066Sahrens searchguid = strtoull(argv[0], &endptr, 10); 23829edf9ebdSPrasad Joshi if (errno != 0 || *endptr != '\0') { 2383fa9e4066Sahrens searchname = argv[0]; 23849edf9ebdSPrasad Joshi searchguid = 0; 23859edf9ebdSPrasad Joshi } 2386fa9e4066Sahrens found_config = NULL; 2387fa9e4066Sahrens 238824e697d4Sck /* 2389d41c4376SMark J Musante * User specified a name or guid. Ensure it's unique. 239024e697d4Sck */ 2391d41c4376SMark J Musante idata.unique = B_TRUE; 239224e697d4Sck } 239324e697d4Sck 2394d41c4376SMark J Musante 2395d41c4376SMark J Musante idata.path = searchdirs; 2396d41c4376SMark J Musante idata.paths = nsearch; 2397d41c4376SMark J Musante idata.poolname = searchname; 2398d41c4376SMark J Musante idata.guid = searchguid; 2399d41c4376SMark J Musante idata.cachefile = cachefile; 24006f793812SPavel Zakharov idata.policy = policy; 2401d41c4376SMark J Musante 2402d41c4376SMark J Musante pools = zpool_search_import(g_zfs, &idata); 2403d41c4376SMark J Musante 2404d41c4376SMark J Musante if (pools != NULL && idata.exists && 2405d41c4376SMark J Musante (argc == 1 || strcmp(argv[0], argv[1]) == 0)) { 2406d41c4376SMark J Musante (void) fprintf(stderr, gettext("cannot import '%s': " 2407d41c4376SMark J Musante "a pool with that name already exists\n"), 2408d41c4376SMark J Musante argv[0]); 2409d41c4376SMark J Musante (void) fprintf(stderr, gettext("use the form '%s " 2410d41c4376SMark J Musante "<pool | id> <newpool>' to give it a new name\n"), 2411d41c4376SMark J Musante "zpool import"); 2412d41c4376SMark J Musante err = 1; 2413d41c4376SMark J Musante } else if (pools == NULL && idata.exists) { 2414d41c4376SMark J Musante (void) fprintf(stderr, gettext("cannot import '%s': " 2415d41c4376SMark J Musante "a pool with that name is already created/imported,\n"), 2416d41c4376SMark J Musante argv[0]); 2417d41c4376SMark J Musante (void) fprintf(stderr, gettext("and no additional pools " 2418d41c4376SMark J Musante "with that name were found\n")); 2419d41c4376SMark J Musante err = 1; 2420d41c4376SMark J Musante } else if (pools == NULL) { 242124e697d4Sck if (argc != 0) { 242224e697d4Sck (void) fprintf(stderr, gettext("cannot import '%s': " 242324e697d4Sck "no such pool available\n"), argv[0]); 242424e697d4Sck } 2425d41c4376SMark J Musante err = 1; 2426d41c4376SMark J Musante } 2427d41c4376SMark J Musante 2428d41c4376SMark J Musante if (err == 1) { 242924e697d4Sck free(searchdirs); 2430468c413aSTim Haley nvlist_free(policy); 243124e697d4Sck return (1); 243224e697d4Sck } 243324e697d4Sck 243424e697d4Sck /* 243524e697d4Sck * At this point we have a list of import candidate configs. Even if 243624e697d4Sck * we were searching by pool name or guid, we still need to 243724e697d4Sck * post-process the list to deal with pool state and possible 243824e697d4Sck * duplicate names. 243924e697d4Sck */ 2440fa9e4066Sahrens err = 0; 2441fa9e4066Sahrens elem = NULL; 244299653d4eSeschrock first = B_TRUE; 2443fa9e4066Sahrens while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 2444fa9e4066Sahrens 2445fa9e4066Sahrens verify(nvpair_value_nvlist(elem, &config) == 0); 2446fa9e4066Sahrens 24474c58d714Sdarrenm verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 24484c58d714Sdarrenm &pool_state) == 0); 24494c58d714Sdarrenm if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) 24504c58d714Sdarrenm continue; 24514c58d714Sdarrenm if (do_destroyed && pool_state != POOL_STATE_DESTROYED) 24524c58d714Sdarrenm continue; 24534c58d714Sdarrenm 2454468c413aSTim Haley verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY, 2455468c413aSTim Haley policy) == 0); 2456468c413aSTim Haley 2457fa9e4066Sahrens if (argc == 0) { 2458fa9e4066Sahrens if (first) 245999653d4eSeschrock first = B_FALSE; 24603bb79becSeschrock else if (!do_all) 2461fa9e4066Sahrens (void) printf("\n"); 2462fa9e4066Sahrens 2463468c413aSTim Haley if (do_all) { 2464fa9e4066Sahrens err |= do_import(config, NULL, mntopts, 24654b964adaSGeorge Wilson props, flags); 2466468c413aSTim Haley } else { 2467fa9e4066Sahrens show_import(config); 2468468c413aSTim Haley } 2469fa9e4066Sahrens } else if (searchname != NULL) { 2470fa9e4066Sahrens char *name; 2471fa9e4066Sahrens 2472fa9e4066Sahrens /* 2473fa9e4066Sahrens * We are searching for a pool based on name. 2474fa9e4066Sahrens */ 2475fa9e4066Sahrens verify(nvlist_lookup_string(config, 2476fa9e4066Sahrens ZPOOL_CONFIG_POOL_NAME, &name) == 0); 2477fa9e4066Sahrens 2478fa9e4066Sahrens if (strcmp(name, searchname) == 0) { 2479fa9e4066Sahrens if (found_config != NULL) { 2480fa9e4066Sahrens (void) fprintf(stderr, gettext( 2481fa9e4066Sahrens "cannot import '%s': more than " 2482fa9e4066Sahrens "one matching pool\n"), searchname); 2483fa9e4066Sahrens (void) fprintf(stderr, gettext( 2484fa9e4066Sahrens "import by numeric ID instead\n")); 248599653d4eSeschrock err = B_TRUE; 2486fa9e4066Sahrens } 2487fa9e4066Sahrens found_config = config; 2488fa9e4066Sahrens } 2489fa9e4066Sahrens } else { 2490fa9e4066Sahrens uint64_t guid; 2491fa9e4066Sahrens 2492fa9e4066Sahrens /* 2493fa9e4066Sahrens * Search for a pool by guid. 2494fa9e4066Sahrens */ 2495fa9e4066Sahrens verify(nvlist_lookup_uint64(config, 2496fa9e4066Sahrens ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 2497fa9e4066Sahrens 2498fa9e4066Sahrens if (guid == searchguid) 2499fa9e4066Sahrens found_config = config; 2500fa9e4066Sahrens } 2501fa9e4066Sahrens } 2502fa9e4066Sahrens 2503fa9e4066Sahrens /* 2504fa9e4066Sahrens * If we were searching for a specific pool, verify that we found a 2505fa9e4066Sahrens * pool, and then do the import. 2506fa9e4066Sahrens */ 2507fa9e4066Sahrens if (argc != 0 && err == 0) { 2508fa9e4066Sahrens if (found_config == NULL) { 2509fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot import '%s': " 2510fa9e4066Sahrens "no such pool available\n"), argv[0]); 251199653d4eSeschrock err = B_TRUE; 2512fa9e4066Sahrens } else { 2513fa9e4066Sahrens err |= do_import(found_config, argc == 1 ? NULL : 25144b964adaSGeorge Wilson argv[1], mntopts, props, flags); 2515fa9e4066Sahrens } 2516fa9e4066Sahrens } 2517fa9e4066Sahrens 2518fa9e4066Sahrens /* 2519fa9e4066Sahrens * If we were just looking for pools, report an error if none were 2520fa9e4066Sahrens * found. 2521fa9e4066Sahrens */ 2522fa9e4066Sahrens if (argc == 0 && first) 2523fa9e4066Sahrens (void) fprintf(stderr, 2524fa9e4066Sahrens gettext("no pools available to import\n")); 2525fa9e4066Sahrens 2526ecd6cf80Smarks error: 25272f8aaab3Seschrock nvlist_free(props); 2528fa9e4066Sahrens nvlist_free(pools); 2529468c413aSTim Haley nvlist_free(policy); 253099653d4eSeschrock free(searchdirs); 2531fa9e4066Sahrens 2532fa9e4066Sahrens return (err ? 1 : 0); 2533fa9e4066Sahrens } 2534fa9e4066Sahrens 2535fa9e4066Sahrens typedef struct iostat_cbdata { 25364263d13fSGeorge Wilson boolean_t cb_verbose; 2537fa9e4066Sahrens int cb_namewidth; 25384263d13fSGeorge Wilson int cb_iteration; 25394263d13fSGeorge Wilson zpool_list_t *cb_list; 2540fa9e4066Sahrens } iostat_cbdata_t; 2541fa9e4066Sahrens 2542fa9e4066Sahrens static void 2543fa9e4066Sahrens print_iostat_separator(iostat_cbdata_t *cb) 2544fa9e4066Sahrens { 2545fa9e4066Sahrens int i = 0; 2546fa9e4066Sahrens 2547fa9e4066Sahrens for (i = 0; i < cb->cb_namewidth; i++) 2548fa9e4066Sahrens (void) printf("-"); 2549fa9e4066Sahrens (void) printf(" ----- ----- ----- ----- ----- -----\n"); 2550fa9e4066Sahrens } 2551fa9e4066Sahrens 2552fa9e4066Sahrens static void 2553fa9e4066Sahrens print_iostat_header(iostat_cbdata_t *cb) 2554fa9e4066Sahrens { 2555fa9e4066Sahrens (void) printf("%*s capacity operations bandwidth\n", 2556fa9e4066Sahrens cb->cb_namewidth, ""); 2557485bbbf5SGeorge Wilson (void) printf("%-*s alloc free read write read write\n", 2558fa9e4066Sahrens cb->cb_namewidth, "pool"); 2559fa9e4066Sahrens print_iostat_separator(cb); 2560fa9e4066Sahrens } 2561fa9e4066Sahrens 2562fa9e4066Sahrens /* 2563fa9e4066Sahrens * Display a single statistic. 2564fa9e4066Sahrens */ 2565990b4856Slling static void 2566fa9e4066Sahrens print_one_stat(uint64_t value) 2567fa9e4066Sahrens { 2568fa9e4066Sahrens char buf[64]; 2569fa9e4066Sahrens 2570fa9e4066Sahrens zfs_nicenum(value, buf, sizeof (buf)); 2571fa9e4066Sahrens (void) printf(" %5s", buf); 2572fa9e4066Sahrens } 2573fa9e4066Sahrens 2574fa9e4066Sahrens /* 2575fa9e4066Sahrens * Print out all the statistics for the given vdev. This can either be the 2576fa9e4066Sahrens * toplevel configuration, or called recursively. If 'name' is NULL, then this 2577fa9e4066Sahrens * is a verbose output, and we don't want to display the toplevel pool stats. 2578fa9e4066Sahrens */ 2579fa9e4066Sahrens void 2580c67d9675Seschrock print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 2581c67d9675Seschrock nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 2582fa9e4066Sahrens { 2583fa9e4066Sahrens nvlist_t **oldchild, **newchild; 2584fa9e4066Sahrens uint_t c, children; 2585fa9e4066Sahrens vdev_stat_t *oldvs, *newvs; 2586fa9e4066Sahrens vdev_stat_t zerovs = { 0 }; 2587fa9e4066Sahrens uint64_t tdelta; 2588fa9e4066Sahrens double scale; 2589afefbcddSeschrock char *vname; 2590fa9e4066Sahrens 25915cabbc6bSPrashanth Sreenivasa if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 25925cabbc6bSPrashanth Sreenivasa return; 25935cabbc6bSPrashanth Sreenivasa 2594fa9e4066Sahrens if (oldnv != NULL) { 25953f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(oldnv, 25963f9d6ad7SLin Ling ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0); 2597fa9e4066Sahrens } else { 2598fa9e4066Sahrens oldvs = &zerovs; 2599fa9e4066Sahrens } 2600fa9e4066Sahrens 26013f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS, 2602fa9e4066Sahrens (uint64_t **)&newvs, &c) == 0); 2603fa9e4066Sahrens 2604fa9e4066Sahrens if (strlen(name) + depth > cb->cb_namewidth) 2605fa9e4066Sahrens (void) printf("%*s%s", depth, "", name); 2606fa9e4066Sahrens else 2607fa9e4066Sahrens (void) printf("%*s%s%*s", depth, "", name, 2608fa9e4066Sahrens (int)(cb->cb_namewidth - strlen(name) - depth), ""); 2609fa9e4066Sahrens 2610fa9e4066Sahrens tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 2611fa9e4066Sahrens 2612fa9e4066Sahrens if (tdelta == 0) 2613fa9e4066Sahrens scale = 1.0; 2614fa9e4066Sahrens else 2615fa9e4066Sahrens scale = (double)NANOSEC / tdelta; 2616fa9e4066Sahrens 2617fa9e4066Sahrens /* only toplevel vdevs have capacity stats */ 2618fa9e4066Sahrens if (newvs->vs_space == 0) { 2619fa9e4066Sahrens (void) printf(" - -"); 2620fa9e4066Sahrens } else { 2621fa9e4066Sahrens print_one_stat(newvs->vs_alloc); 2622fa9e4066Sahrens print_one_stat(newvs->vs_space - newvs->vs_alloc); 2623fa9e4066Sahrens } 2624fa9e4066Sahrens 2625fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] - 2626fa9e4066Sahrens oldvs->vs_ops[ZIO_TYPE_READ]))); 2627fa9e4066Sahrens 2628fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] - 2629fa9e4066Sahrens oldvs->vs_ops[ZIO_TYPE_WRITE]))); 2630fa9e4066Sahrens 2631fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] - 2632fa9e4066Sahrens oldvs->vs_bytes[ZIO_TYPE_READ]))); 2633fa9e4066Sahrens 2634fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] - 2635fa9e4066Sahrens oldvs->vs_bytes[ZIO_TYPE_WRITE]))); 2636fa9e4066Sahrens 2637fa9e4066Sahrens (void) printf("\n"); 2638fa9e4066Sahrens 2639fa9e4066Sahrens if (!cb->cb_verbose) 2640fa9e4066Sahrens return; 2641fa9e4066Sahrens 2642fa9e4066Sahrens if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 2643fa9e4066Sahrens &newchild, &children) != 0) 2644fa9e4066Sahrens return; 2645fa9e4066Sahrens 2646fa9e4066Sahrens if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 2647fa9e4066Sahrens &oldchild, &c) != 0) 2648fa9e4066Sahrens return; 2649fa9e4066Sahrens 2650afefbcddSeschrock for (c = 0; c < children; c++) { 26519d439f90SMike Harsch uint64_t ishole = B_FALSE, islog = B_FALSE; 26523f9d6ad7SLin Ling 26539d439f90SMike Harsch (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE, 26549d439f90SMike Harsch &ishole); 26559d439f90SMike Harsch 26569d439f90SMike Harsch (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG, 26579d439f90SMike Harsch &islog); 26589d439f90SMike Harsch 26599d439f90SMike Harsch if (ishole || islog) 26603f9d6ad7SLin Ling continue; 26613f9d6ad7SLin Ling 266288ecc943SGeorge Wilson vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE); 2663c67d9675Seschrock print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 2664afefbcddSeschrock newchild[c], cb, depth + 2); 2665afefbcddSeschrock free(vname); 2666afefbcddSeschrock } 2667fa94a07fSbrendan 26689d439f90SMike Harsch /* 26699d439f90SMike Harsch * Log device section 26709d439f90SMike Harsch */ 26719d439f90SMike Harsch 26729d439f90SMike Harsch if (num_logs(newnv) > 0) { 26739d439f90SMike Harsch (void) printf("%-*s - - - - - " 26749d439f90SMike Harsch "-\n", cb->cb_namewidth, "logs"); 26759d439f90SMike Harsch 26769d439f90SMike Harsch for (c = 0; c < children; c++) { 26779d439f90SMike Harsch uint64_t islog = B_FALSE; 26789d439f90SMike Harsch (void) nvlist_lookup_uint64(newchild[c], 26799d439f90SMike Harsch ZPOOL_CONFIG_IS_LOG, &islog); 26809d439f90SMike Harsch 26819d439f90SMike Harsch if (islog) { 26829d439f90SMike Harsch vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 26839d439f90SMike Harsch B_FALSE); 26849d439f90SMike Harsch print_vdev_stats(zhp, vname, oldnv ? 26859d439f90SMike Harsch oldchild[c] : NULL, newchild[c], 26869d439f90SMike Harsch cb, depth + 2); 26879d439f90SMike Harsch free(vname); 26889d439f90SMike Harsch } 26899d439f90SMike Harsch } 26909d439f90SMike Harsch 26919d439f90SMike Harsch } 26929d439f90SMike Harsch 2693fa94a07fSbrendan /* 2694fa94a07fSbrendan * Include level 2 ARC devices in iostat output 2695fa94a07fSbrendan */ 2696fa94a07fSbrendan if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, 2697fa94a07fSbrendan &newchild, &children) != 0) 2698fa94a07fSbrendan return; 2699fa94a07fSbrendan 2700fa94a07fSbrendan if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, 2701fa94a07fSbrendan &oldchild, &c) != 0) 2702fa94a07fSbrendan return; 2703fa94a07fSbrendan 2704fa94a07fSbrendan if (children > 0) { 2705fa94a07fSbrendan (void) printf("%-*s - - - - - " 2706fa94a07fSbrendan "-\n", cb->cb_namewidth, "cache"); 2707fa94a07fSbrendan for (c = 0; c < children; c++) { 270888ecc943SGeorge Wilson vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 270988ecc943SGeorge Wilson B_FALSE); 2710fa94a07fSbrendan print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 2711fa94a07fSbrendan newchild[c], cb, depth + 2); 2712fa94a07fSbrendan free(vname); 2713fa94a07fSbrendan } 2714fa94a07fSbrendan } 2715fa9e4066Sahrens } 2716fa9e4066Sahrens 2717088e9d47Seschrock static int 2718088e9d47Seschrock refresh_iostat(zpool_handle_t *zhp, void *data) 2719088e9d47Seschrock { 2720088e9d47Seschrock iostat_cbdata_t *cb = data; 272194de1d4cSeschrock boolean_t missing; 2722088e9d47Seschrock 2723088e9d47Seschrock /* 2724088e9d47Seschrock * If the pool has disappeared, remove it from the list and continue. 2725088e9d47Seschrock */ 272694de1d4cSeschrock if (zpool_refresh_stats(zhp, &missing) != 0) 272794de1d4cSeschrock return (-1); 272894de1d4cSeschrock 272994de1d4cSeschrock if (missing) 2730088e9d47Seschrock pool_list_remove(cb->cb_list, zhp); 2731088e9d47Seschrock 2732088e9d47Seschrock return (0); 2733088e9d47Seschrock } 2734088e9d47Seschrock 2735fa9e4066Sahrens /* 2736fa9e4066Sahrens * Callback to print out the iostats for the given pool. 2737fa9e4066Sahrens */ 2738fa9e4066Sahrens int 2739fa9e4066Sahrens print_iostat(zpool_handle_t *zhp, void *data) 2740fa9e4066Sahrens { 2741fa9e4066Sahrens iostat_cbdata_t *cb = data; 2742fa9e4066Sahrens nvlist_t *oldconfig, *newconfig; 2743fa9e4066Sahrens nvlist_t *oldnvroot, *newnvroot; 2744fa9e4066Sahrens 2745088e9d47Seschrock newconfig = zpool_get_config(zhp, &oldconfig); 2746fa9e4066Sahrens 2747088e9d47Seschrock if (cb->cb_iteration == 1) 2748fa9e4066Sahrens oldconfig = NULL; 2749fa9e4066Sahrens 2750fa9e4066Sahrens verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 2751fa9e4066Sahrens &newnvroot) == 0); 2752fa9e4066Sahrens 2753088e9d47Seschrock if (oldconfig == NULL) 2754fa9e4066Sahrens oldnvroot = NULL; 2755088e9d47Seschrock else 2756088e9d47Seschrock verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 2757088e9d47Seschrock &oldnvroot) == 0); 2758fa9e4066Sahrens 2759fa9e4066Sahrens /* 2760fa9e4066Sahrens * Print out the statistics for the pool. 2761fa9e4066Sahrens */ 2762c67d9675Seschrock print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 2763fa9e4066Sahrens 2764fa9e4066Sahrens if (cb->cb_verbose) 2765fa9e4066Sahrens print_iostat_separator(cb); 2766fa9e4066Sahrens 2767fa9e4066Sahrens return (0); 2768fa9e4066Sahrens } 2769fa9e4066Sahrens 2770fa9e4066Sahrens int 2771fa9e4066Sahrens get_namewidth(zpool_handle_t *zhp, void *data) 2772fa9e4066Sahrens { 2773fa9e4066Sahrens iostat_cbdata_t *cb = data; 2774fa9e4066Sahrens nvlist_t *config, *nvroot; 2775fa9e4066Sahrens 2776088e9d47Seschrock if ((config = zpool_get_config(zhp, NULL)) != NULL) { 2777fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2778fa9e4066Sahrens &nvroot) == 0); 2779fa9e4066Sahrens if (!cb->cb_verbose) 2780fa9e4066Sahrens cb->cb_namewidth = strlen(zpool_get_name(zhp)); 2781fa9e4066Sahrens else 2782e1d5e507SFrederik Wessels cb->cb_namewidth = max_width(zhp, nvroot, 0, 2783e1d5e507SFrederik Wessels cb->cb_namewidth); 2784fa9e4066Sahrens } 2785fa9e4066Sahrens 2786fa9e4066Sahrens /* 2787fa9e4066Sahrens * The width must fall into the range [10,38]. The upper limit is the 2788fa9e4066Sahrens * maximum we can have and still fit in 80 columns. 2789fa9e4066Sahrens */ 2790fa9e4066Sahrens if (cb->cb_namewidth < 10) 2791fa9e4066Sahrens cb->cb_namewidth = 10; 2792fa9e4066Sahrens if (cb->cb_namewidth > 38) 2793fa9e4066Sahrens cb->cb_namewidth = 38; 2794fa9e4066Sahrens 2795fa9e4066Sahrens return (0); 2796fa9e4066Sahrens } 2797fa9e4066Sahrens 2798fa9e4066Sahrens /* 27993f9d6ad7SLin Ling * Parse the input string, get the 'interval' and 'count' value if there is one. 2800fa9e4066Sahrens */ 28013f9d6ad7SLin Ling static void 28023f9d6ad7SLin Ling get_interval_count(int *argcp, char **argv, unsigned long *iv, 28033f9d6ad7SLin Ling unsigned long *cnt) 2804fa9e4066Sahrens { 2805fa9e4066Sahrens unsigned long interval = 0, count = 0; 28063f9d6ad7SLin Ling int argc = *argcp, errno; 2807fa9e4066Sahrens 2808fa9e4066Sahrens /* 2809fa9e4066Sahrens * Determine if the last argument is an integer or a pool name 2810fa9e4066Sahrens */ 2811fa9e4066Sahrens if (argc > 0 && isdigit(argv[argc - 1][0])) { 2812fa9e4066Sahrens char *end; 2813fa9e4066Sahrens 2814fa9e4066Sahrens errno = 0; 2815fa9e4066Sahrens interval = strtoul(argv[argc - 1], &end, 10); 2816fa9e4066Sahrens 2817fa9e4066Sahrens if (*end == '\0' && errno == 0) { 2818fa9e4066Sahrens if (interval == 0) { 2819fa9e4066Sahrens (void) fprintf(stderr, gettext("interval " 2820fa9e4066Sahrens "cannot be zero\n")); 282199653d4eSeschrock usage(B_FALSE); 2822fa9e4066Sahrens } 2823fa9e4066Sahrens /* 2824fa9e4066Sahrens * Ignore the last parameter 2825fa9e4066Sahrens */ 2826fa9e4066Sahrens argc--; 2827fa9e4066Sahrens } else { 2828fa9e4066Sahrens /* 2829fa9e4066Sahrens * If this is not a valid number, just plow on. The 2830fa9e4066Sahrens * user will get a more informative error message later 2831fa9e4066Sahrens * on. 2832fa9e4066Sahrens */ 2833fa9e4066Sahrens interval = 0; 2834fa9e4066Sahrens } 2835fa9e4066Sahrens } 2836fa9e4066Sahrens 2837fa9e4066Sahrens /* 2838fa9e4066Sahrens * If the last argument is also an integer, then we have both a count 28393f9d6ad7SLin Ling * and an interval. 2840fa9e4066Sahrens */ 2841fa9e4066Sahrens if (argc > 0 && isdigit(argv[argc - 1][0])) { 2842fa9e4066Sahrens char *end; 2843fa9e4066Sahrens 2844fa9e4066Sahrens errno = 0; 2845fa9e4066Sahrens count = interval; 2846fa9e4066Sahrens interval = strtoul(argv[argc - 1], &end, 10); 2847fa9e4066Sahrens 2848fa9e4066Sahrens if (*end == '\0' && errno == 0) { 2849fa9e4066Sahrens if (interval == 0) { 2850fa9e4066Sahrens (void) fprintf(stderr, gettext("interval " 2851fa9e4066Sahrens "cannot be zero\n")); 285299653d4eSeschrock usage(B_FALSE); 2853fa9e4066Sahrens } 2854fa9e4066Sahrens 2855fa9e4066Sahrens /* 2856fa9e4066Sahrens * Ignore the last parameter 2857fa9e4066Sahrens */ 2858fa9e4066Sahrens argc--; 2859fa9e4066Sahrens } else { 2860fa9e4066Sahrens interval = 0; 2861fa9e4066Sahrens } 2862fa9e4066Sahrens } 2863fa9e4066Sahrens 28643f9d6ad7SLin Ling *iv = interval; 28653f9d6ad7SLin Ling *cnt = count; 28663f9d6ad7SLin Ling *argcp = argc; 28673f9d6ad7SLin Ling } 28683f9d6ad7SLin Ling 28693f9d6ad7SLin Ling static void 28703f9d6ad7SLin Ling get_timestamp_arg(char c) 28713f9d6ad7SLin Ling { 28723f9d6ad7SLin Ling if (c == 'u') 28733f9d6ad7SLin Ling timestamp_fmt = UDATE; 28743f9d6ad7SLin Ling else if (c == 'd') 28753f9d6ad7SLin Ling timestamp_fmt = DDATE; 28763f9d6ad7SLin Ling else 28773f9d6ad7SLin Ling usage(B_FALSE); 28783f9d6ad7SLin Ling } 28793f9d6ad7SLin Ling 28803f9d6ad7SLin Ling /* 28813f9d6ad7SLin Ling * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]] 28823f9d6ad7SLin Ling * 28833f9d6ad7SLin Ling * -v Display statistics for individual vdevs 28843f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format 28853f9d6ad7SLin Ling * 28863f9d6ad7SLin Ling * This command can be tricky because we want to be able to deal with pool 28873f9d6ad7SLin Ling * creation/destruction as well as vdev configuration changes. The bulk of this 28883f9d6ad7SLin Ling * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 28893f9d6ad7SLin Ling * on pool_list_update() to detect the addition of new pools. Configuration 28903f9d6ad7SLin Ling * changes are all handled within libzfs. 28913f9d6ad7SLin Ling */ 28923f9d6ad7SLin Ling int 28933f9d6ad7SLin Ling zpool_do_iostat(int argc, char **argv) 28943f9d6ad7SLin Ling { 28953f9d6ad7SLin Ling int c; 28963f9d6ad7SLin Ling int ret; 28973f9d6ad7SLin Ling int npools; 28983f9d6ad7SLin Ling unsigned long interval = 0, count = 0; 28993f9d6ad7SLin Ling zpool_list_t *list; 29003f9d6ad7SLin Ling boolean_t verbose = B_FALSE; 29013f9d6ad7SLin Ling iostat_cbdata_t cb; 29023f9d6ad7SLin Ling 29033f9d6ad7SLin Ling /* check options */ 29043f9d6ad7SLin Ling while ((c = getopt(argc, argv, "T:v")) != -1) { 29053f9d6ad7SLin Ling switch (c) { 29063f9d6ad7SLin Ling case 'T': 29073f9d6ad7SLin Ling get_timestamp_arg(*optarg); 29083f9d6ad7SLin Ling break; 29093f9d6ad7SLin Ling case 'v': 29103f9d6ad7SLin Ling verbose = B_TRUE; 29113f9d6ad7SLin Ling break; 29123f9d6ad7SLin Ling case '?': 29133f9d6ad7SLin Ling (void) fprintf(stderr, gettext("invalid option '%c'\n"), 29143f9d6ad7SLin Ling optopt); 29153f9d6ad7SLin Ling usage(B_FALSE); 29163f9d6ad7SLin Ling } 29173f9d6ad7SLin Ling } 29183f9d6ad7SLin Ling 29193f9d6ad7SLin Ling argc -= optind; 29203f9d6ad7SLin Ling argv += optind; 29213f9d6ad7SLin Ling 29223f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count); 29233f9d6ad7SLin Ling 2924fa9e4066Sahrens /* 2925fa9e4066Sahrens * Construct the list of all interesting pools. 2926fa9e4066Sahrens */ 2927fa9e4066Sahrens ret = 0; 2928b1b8ab34Slling if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL) 2929fa9e4066Sahrens return (1); 2930fa9e4066Sahrens 293199653d4eSeschrock if (pool_list_count(list) == 0 && argc != 0) { 293299653d4eSeschrock pool_list_free(list); 2933fa9e4066Sahrens return (1); 293499653d4eSeschrock } 2935fa9e4066Sahrens 2936fa9e4066Sahrens if (pool_list_count(list) == 0 && interval == 0) { 293799653d4eSeschrock pool_list_free(list); 2938fa9e4066Sahrens (void) fprintf(stderr, gettext("no pools available\n")); 2939fa9e4066Sahrens return (1); 2940fa9e4066Sahrens } 2941fa9e4066Sahrens 2942fa9e4066Sahrens /* 2943fa9e4066Sahrens * Enter the main iostat loop. 2944fa9e4066Sahrens */ 2945fa9e4066Sahrens cb.cb_list = list; 2946fa9e4066Sahrens cb.cb_verbose = verbose; 2947fa9e4066Sahrens cb.cb_iteration = 0; 2948fa9e4066Sahrens cb.cb_namewidth = 0; 2949fa9e4066Sahrens 2950fa9e4066Sahrens for (;;) { 2951fa9e4066Sahrens pool_list_update(list); 2952fa9e4066Sahrens 2953fa9e4066Sahrens if ((npools = pool_list_count(list)) == 0) 2954fa9e4066Sahrens break; 2955fa9e4066Sahrens 2956088e9d47Seschrock /* 2957088e9d47Seschrock * Refresh all statistics. This is done as an explicit step 2958088e9d47Seschrock * before calculating the maximum name width, so that any 2959088e9d47Seschrock * configuration changes are properly accounted for. 2960088e9d47Seschrock */ 296199653d4eSeschrock (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb); 2962088e9d47Seschrock 2963fa9e4066Sahrens /* 2964fa9e4066Sahrens * Iterate over all pools to determine the maximum width 2965fa9e4066Sahrens * for the pool / device name column across all pools. 2966fa9e4066Sahrens */ 2967fa9e4066Sahrens cb.cb_namewidth = 0; 296899653d4eSeschrock (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 2969fa9e4066Sahrens 297026fd7700SKrishnendu Sadhukhan - Sun Microsystems if (timestamp_fmt != NODATE) 297126fd7700SKrishnendu Sadhukhan - Sun Microsystems print_timestamp(timestamp_fmt); 297226fd7700SKrishnendu Sadhukhan - Sun Microsystems 2973fa9e4066Sahrens /* 2974fa9e4066Sahrens * If it's the first time, or verbose mode, print the header. 2975fa9e4066Sahrens */ 2976fa9e4066Sahrens if (++cb.cb_iteration == 1 || verbose) 2977fa9e4066Sahrens print_iostat_header(&cb); 2978fa9e4066Sahrens 297999653d4eSeschrock (void) pool_list_iter(list, B_FALSE, print_iostat, &cb); 2980fa9e4066Sahrens 2981fa9e4066Sahrens /* 2982fa9e4066Sahrens * If there's more than one pool, and we're not in verbose mode 2983fa9e4066Sahrens * (which prints a separator for us), then print a separator. 2984fa9e4066Sahrens */ 2985fa9e4066Sahrens if (npools > 1 && !verbose) 2986fa9e4066Sahrens print_iostat_separator(&cb); 2987fa9e4066Sahrens 2988fa9e4066Sahrens if (verbose) 2989fa9e4066Sahrens (void) printf("\n"); 2990fa9e4066Sahrens 299139c23413Seschrock /* 299239c23413Seschrock * Flush the output so that redirection to a file isn't buffered 299339c23413Seschrock * indefinitely. 299439c23413Seschrock */ 299539c23413Seschrock (void) fflush(stdout); 299639c23413Seschrock 2997fa9e4066Sahrens if (interval == 0) 2998fa9e4066Sahrens break; 2999fa9e4066Sahrens 3000fa9e4066Sahrens if (count != 0 && --count == 0) 3001fa9e4066Sahrens break; 3002fa9e4066Sahrens 3003fa9e4066Sahrens (void) sleep(interval); 3004fa9e4066Sahrens } 3005fa9e4066Sahrens 3006fa9e4066Sahrens pool_list_free(list); 3007fa9e4066Sahrens 3008fa9e4066Sahrens return (ret); 3009fa9e4066Sahrens } 3010fa9e4066Sahrens 3011fa9e4066Sahrens typedef struct list_cbdata { 30124263d13fSGeorge Wilson boolean_t cb_verbose; 30134263d13fSGeorge Wilson int cb_namewidth; 301499653d4eSeschrock boolean_t cb_scripted; 3015990b4856Slling zprop_list_t *cb_proplist; 3016c58b3526SAdam Stevko boolean_t cb_literal; 3017fa9e4066Sahrens } list_cbdata_t; 3018fa9e4066Sahrens 3019fa9e4066Sahrens /* 3020fa9e4066Sahrens * Given a list of columns to display, output appropriate headers for each one. 3021fa9e4066Sahrens */ 3022990b4856Slling static void 30234263d13fSGeorge Wilson print_header(list_cbdata_t *cb) 3024fa9e4066Sahrens { 30254263d13fSGeorge Wilson zprop_list_t *pl = cb->cb_proplist; 3026ad135b5dSChristopher Siden char headerbuf[ZPOOL_MAXPROPLEN]; 3027990b4856Slling const char *header; 3028990b4856Slling boolean_t first = B_TRUE; 3029990b4856Slling boolean_t right_justify; 30304263d13fSGeorge Wilson size_t width = 0; 3031990b4856Slling 3032990b4856Slling for (; pl != NULL; pl = pl->pl_next) { 30334263d13fSGeorge Wilson width = pl->pl_width; 30344263d13fSGeorge Wilson if (first && cb->cb_verbose) { 30354263d13fSGeorge Wilson /* 30364263d13fSGeorge Wilson * Reset the width to accommodate the verbose listing 30374263d13fSGeorge Wilson * of devices. 30384263d13fSGeorge Wilson */ 30394263d13fSGeorge Wilson width = cb->cb_namewidth; 30404263d13fSGeorge Wilson } 30414263d13fSGeorge Wilson 3042990b4856Slling if (!first) 3043fa9e4066Sahrens (void) printf(" "); 3044fa9e4066Sahrens else 3045990b4856Slling first = B_FALSE; 3046990b4856Slling 3047ad135b5dSChristopher Siden right_justify = B_FALSE; 3048ad135b5dSChristopher Siden if (pl->pl_prop != ZPROP_INVAL) { 3049ad135b5dSChristopher Siden header = zpool_prop_column_name(pl->pl_prop); 3050ad135b5dSChristopher Siden right_justify = zpool_prop_align_right(pl->pl_prop); 3051ad135b5dSChristopher Siden } else { 3052ad135b5dSChristopher Siden int i; 3053ad135b5dSChristopher Siden 3054ad135b5dSChristopher Siden for (i = 0; pl->pl_user_prop[i] != '\0'; i++) 3055ad135b5dSChristopher Siden headerbuf[i] = toupper(pl->pl_user_prop[i]); 3056ad135b5dSChristopher Siden headerbuf[i] = '\0'; 3057ad135b5dSChristopher Siden header = headerbuf; 3058ad135b5dSChristopher Siden } 3059fa9e4066Sahrens 3060990b4856Slling if (pl->pl_next == NULL && !right_justify) 3061990b4856Slling (void) printf("%s", header); 3062990b4856Slling else if (right_justify) 30634263d13fSGeorge Wilson (void) printf("%*s", width, header); 3064990b4856Slling else 30654263d13fSGeorge Wilson (void) printf("%-*s", width, header); 30664263d13fSGeorge Wilson 3067fa9e4066Sahrens } 3068fa9e4066Sahrens 3069fa9e4066Sahrens (void) printf("\n"); 3070fa9e4066Sahrens } 3071fa9e4066Sahrens 3072990b4856Slling /* 3073990b4856Slling * Given a pool and a list of properties, print out all the properties according 3074990b4856Slling * to the described layout. 3075990b4856Slling */ 3076990b4856Slling static void 30774263d13fSGeorge Wilson print_pool(zpool_handle_t *zhp, list_cbdata_t *cb) 3078fa9e4066Sahrens { 30794263d13fSGeorge Wilson zprop_list_t *pl = cb->cb_proplist; 3080990b4856Slling boolean_t first = B_TRUE; 3081990b4856Slling char property[ZPOOL_MAXPROPLEN]; 3082990b4856Slling char *propstr; 3083990b4856Slling boolean_t right_justify; 30844263d13fSGeorge Wilson size_t width; 3085990b4856Slling 3086990b4856Slling for (; pl != NULL; pl = pl->pl_next) { 30874263d13fSGeorge Wilson 30884263d13fSGeorge Wilson width = pl->pl_width; 30894263d13fSGeorge Wilson if (first && cb->cb_verbose) { 30904263d13fSGeorge Wilson /* 30914263d13fSGeorge Wilson * Reset the width to accommodate the verbose listing 30924263d13fSGeorge Wilson * of devices. 30934263d13fSGeorge Wilson */ 30944263d13fSGeorge Wilson width = cb->cb_namewidth; 30954263d13fSGeorge Wilson } 30964263d13fSGeorge Wilson 3097990b4856Slling if (!first) { 30984263d13fSGeorge Wilson if (cb->cb_scripted) 3099fa9e4066Sahrens (void) printf("\t"); 3100fa9e4066Sahrens else 3101fa9e4066Sahrens (void) printf(" "); 3102990b4856Slling } else { 3103990b4856Slling first = B_FALSE; 3104fa9e4066Sahrens } 3105fa9e4066Sahrens 3106990b4856Slling right_justify = B_FALSE; 3107990b4856Slling if (pl->pl_prop != ZPROP_INVAL) { 31087a09f97bSGeorge Wilson if (zpool_get_prop(zhp, pl->pl_prop, property, 3109c58b3526SAdam Stevko sizeof (property), NULL, cb->cb_literal) != 0) 3110990b4856Slling propstr = "-"; 3111fa9e4066Sahrens else 3112990b4856Slling propstr = property; 3113fa9e4066Sahrens 3114990b4856Slling right_justify = zpool_prop_align_right(pl->pl_prop); 3115ad135b5dSChristopher Siden } else if ((zpool_prop_feature(pl->pl_user_prop) || 3116ad135b5dSChristopher Siden zpool_prop_unsupported(pl->pl_user_prop)) && 3117ad135b5dSChristopher Siden zpool_prop_get_feature(zhp, pl->pl_user_prop, property, 3118ad135b5dSChristopher Siden sizeof (property)) == 0) { 3119ad135b5dSChristopher Siden propstr = property; 3120990b4856Slling } else { 3121990b4856Slling propstr = "-"; 3122990b4856Slling } 3123fa9e4066Sahrens 3124fa9e4066Sahrens 3125990b4856Slling /* 3126990b4856Slling * If this is being called in scripted mode, or if this is the 3127990b4856Slling * last column and it is left-justified, don't include a width 3128990b4856Slling * format specifier. 3129990b4856Slling */ 31304263d13fSGeorge Wilson if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify)) 3131990b4856Slling (void) printf("%s", propstr); 3132990b4856Slling else if (right_justify) 3133990b4856Slling (void) printf("%*s", width, propstr); 3134990b4856Slling else 3135990b4856Slling (void) printf("%-*s", width, propstr); 3136990b4856Slling } 3137fa9e4066Sahrens 3138990b4856Slling (void) printf("\n"); 3139990b4856Slling } 3140fa9e4066Sahrens 31414263d13fSGeorge Wilson static void 31427a09f97bSGeorge Wilson print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted, 31437a09f97bSGeorge Wilson boolean_t valid) 31444263d13fSGeorge Wilson { 31454263d13fSGeorge Wilson char propval[64]; 31464263d13fSGeorge Wilson boolean_t fixed; 31474263d13fSGeorge Wilson size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL); 31484263d13fSGeorge Wilson 31497a09f97bSGeorge Wilson switch (prop) { 31507a09f97bSGeorge Wilson case ZPOOL_PROP_EXPANDSZ: 3151*86714001SSerapheim Dimitropoulos case ZPOOL_PROP_CHECKPOINT: 31527a09f97bSGeorge Wilson if (value == 0) 31537a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval)); 31547a09f97bSGeorge Wilson else 31557a09f97bSGeorge Wilson zfs_nicenum(value, propval, sizeof (propval)); 31567a09f97bSGeorge Wilson break; 31577a09f97bSGeorge Wilson case ZPOOL_PROP_FRAGMENTATION: 31587a09f97bSGeorge Wilson if (value == ZFS_FRAG_INVALID) { 31597a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval)); 31607a09f97bSGeorge Wilson } else { 31617a09f97bSGeorge Wilson (void) snprintf(propval, sizeof (propval), "%llu%%", 31627a09f97bSGeorge Wilson value); 31637a09f97bSGeorge Wilson } 31647a09f97bSGeorge Wilson break; 31657a09f97bSGeorge Wilson case ZPOOL_PROP_CAPACITY: 31662e4c9986SGeorge Wilson (void) snprintf(propval, sizeof (propval), "%llu%%", value); 31677a09f97bSGeorge Wilson break; 31687a09f97bSGeorge Wilson default: 31692e4c9986SGeorge Wilson zfs_nicenum(value, propval, sizeof (propval)); 31707a09f97bSGeorge Wilson } 31717a09f97bSGeorge Wilson 31727a09f97bSGeorge Wilson if (!valid) 31737a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval)); 31744263d13fSGeorge Wilson 31754263d13fSGeorge Wilson if (scripted) 31764263d13fSGeorge Wilson (void) printf("\t%s", propval); 31774263d13fSGeorge Wilson else 31784263d13fSGeorge Wilson (void) printf(" %*s", width, propval); 31794263d13fSGeorge Wilson } 31804263d13fSGeorge Wilson 31814263d13fSGeorge Wilson void 31824263d13fSGeorge Wilson print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 31834263d13fSGeorge Wilson list_cbdata_t *cb, int depth) 31844263d13fSGeorge Wilson { 31854263d13fSGeorge Wilson nvlist_t **child; 31864263d13fSGeorge Wilson vdev_stat_t *vs; 31874263d13fSGeorge Wilson uint_t c, children; 31884263d13fSGeorge Wilson char *vname; 31894263d13fSGeorge Wilson boolean_t scripted = cb->cb_scripted; 319052244c09SJohn Wren Kennedy uint64_t islog = B_FALSE; 319152244c09SJohn Wren Kennedy boolean_t haslog = B_FALSE; 319252244c09SJohn Wren Kennedy char *dashes = "%-*s - - - - - -\n"; 31934263d13fSGeorge Wilson 31944263d13fSGeorge Wilson verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 31954263d13fSGeorge Wilson (uint64_t **)&vs, &c) == 0); 31964263d13fSGeorge Wilson 31974263d13fSGeorge Wilson if (name != NULL) { 31987a09f97bSGeorge Wilson boolean_t toplevel = (vs->vs_space != 0); 31997a09f97bSGeorge Wilson uint64_t cap; 32007a09f97bSGeorge Wilson 32015cabbc6bSPrashanth Sreenivasa if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 32025cabbc6bSPrashanth Sreenivasa return; 32035cabbc6bSPrashanth Sreenivasa 32044263d13fSGeorge Wilson if (scripted) 32054263d13fSGeorge Wilson (void) printf("\t%s", name); 32064263d13fSGeorge Wilson else if (strlen(name) + depth > cb->cb_namewidth) 32074263d13fSGeorge Wilson (void) printf("%*s%s", depth, "", name); 32084263d13fSGeorge Wilson else 32094263d13fSGeorge Wilson (void) printf("%*s%s%*s", depth, "", name, 32104263d13fSGeorge Wilson (int)(cb->cb_namewidth - strlen(name) - depth), ""); 32114263d13fSGeorge Wilson 32127a09f97bSGeorge Wilson /* 32137a09f97bSGeorge Wilson * Print the properties for the individual vdevs. Some 32147a09f97bSGeorge Wilson * properties are only applicable to toplevel vdevs. The 32157a09f97bSGeorge Wilson * 'toplevel' boolean value is passed to the print_one_column() 32167a09f97bSGeorge Wilson * to indicate that the value is valid. 32177a09f97bSGeorge Wilson */ 32187a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted, 32197a09f97bSGeorge Wilson toplevel); 32207a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted, 32217a09f97bSGeorge Wilson toplevel); 32227a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc, 32237a09f97bSGeorge Wilson scripted, toplevel); 3224*86714001SSerapheim Dimitropoulos print_one_column(ZPOOL_PROP_CHECKPOINT, 3225*86714001SSerapheim Dimitropoulos vs->vs_checkpoint_space, scripted, toplevel); 32267a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted, 32277a09f97bSGeorge Wilson B_TRUE); 32287a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_FRAGMENTATION, 32297a09f97bSGeorge Wilson vs->vs_fragmentation, scripted, 32307a09f97bSGeorge Wilson (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel)); 32317a09f97bSGeorge Wilson cap = (vs->vs_space == 0) ? 0 : 32327a09f97bSGeorge Wilson (vs->vs_alloc * 100 / vs->vs_space); 32337a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel); 32344263d13fSGeorge Wilson (void) printf("\n"); 32354263d13fSGeorge Wilson } 32364263d13fSGeorge Wilson 32374263d13fSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 32384263d13fSGeorge Wilson &child, &children) != 0) 32394263d13fSGeorge Wilson return; 32404263d13fSGeorge Wilson 32414263d13fSGeorge Wilson for (c = 0; c < children; c++) { 32424263d13fSGeorge Wilson uint64_t ishole = B_FALSE; 32434263d13fSGeorge Wilson 32444263d13fSGeorge Wilson if (nvlist_lookup_uint64(child[c], 32454263d13fSGeorge Wilson ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole) 32464263d13fSGeorge Wilson continue; 32474263d13fSGeorge Wilson 324852244c09SJohn Wren Kennedy if (nvlist_lookup_uint64(child[c], 324952244c09SJohn Wren Kennedy ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) { 325052244c09SJohn Wren Kennedy haslog = B_TRUE; 325152244c09SJohn Wren Kennedy continue; 325252244c09SJohn Wren Kennedy } 325352244c09SJohn Wren Kennedy 32544263d13fSGeorge Wilson vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 32554263d13fSGeorge Wilson print_list_stats(zhp, vname, child[c], cb, depth + 2); 32564263d13fSGeorge Wilson free(vname); 32574263d13fSGeorge Wilson } 32584263d13fSGeorge Wilson 325952244c09SJohn Wren Kennedy if (haslog == B_TRUE) { 326052244c09SJohn Wren Kennedy /* LINTED E_SEC_PRINTF_VAR_FMT */ 326152244c09SJohn Wren Kennedy (void) printf(dashes, cb->cb_namewidth, "log"); 326252244c09SJohn Wren Kennedy for (c = 0; c < children; c++) { 326352244c09SJohn Wren Kennedy if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 326452244c09SJohn Wren Kennedy &islog) != 0 || !islog) 326552244c09SJohn Wren Kennedy continue; 326652244c09SJohn Wren Kennedy vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 326752244c09SJohn Wren Kennedy print_list_stats(zhp, vname, child[c], cb, depth + 2); 326852244c09SJohn Wren Kennedy free(vname); 326952244c09SJohn Wren Kennedy } 327052244c09SJohn Wren Kennedy } 327152244c09SJohn Wren Kennedy 32724263d13fSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 327352244c09SJohn Wren Kennedy &child, &children) == 0 && children > 0) { 327452244c09SJohn Wren Kennedy /* LINTED E_SEC_PRINTF_VAR_FMT */ 327552244c09SJohn Wren Kennedy (void) printf(dashes, cb->cb_namewidth, "cache"); 327652244c09SJohn Wren Kennedy for (c = 0; c < children; c++) { 327752244c09SJohn Wren Kennedy vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 327852244c09SJohn Wren Kennedy print_list_stats(zhp, vname, child[c], cb, depth + 2); 327952244c09SJohn Wren Kennedy free(vname); 328052244c09SJohn Wren Kennedy } 328152244c09SJohn Wren Kennedy } 32824263d13fSGeorge Wilson 328352244c09SJohn Wren Kennedy if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child, 328452244c09SJohn Wren Kennedy &children) == 0 && children > 0) { 328552244c09SJohn Wren Kennedy /* LINTED E_SEC_PRINTF_VAR_FMT */ 328652244c09SJohn Wren Kennedy (void) printf(dashes, cb->cb_namewidth, "spare"); 32874263d13fSGeorge Wilson for (c = 0; c < children; c++) { 328852244c09SJohn Wren Kennedy vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 32894263d13fSGeorge Wilson print_list_stats(zhp, vname, child[c], cb, depth + 2); 32904263d13fSGeorge Wilson free(vname); 32914263d13fSGeorge Wilson } 32924263d13fSGeorge Wilson } 32934263d13fSGeorge Wilson } 32944263d13fSGeorge Wilson 32954263d13fSGeorge Wilson 3296990b4856Slling /* 3297990b4856Slling * Generic callback function to list a pool. 3298990b4856Slling */ 3299990b4856Slling int 3300990b4856Slling list_callback(zpool_handle_t *zhp, void *data) 3301990b4856Slling { 3302990b4856Slling list_cbdata_t *cbp = data; 33034263d13fSGeorge Wilson nvlist_t *config; 33044263d13fSGeorge Wilson nvlist_t *nvroot; 3305fa9e4066Sahrens 33064263d13fSGeorge Wilson config = zpool_get_config(zhp, NULL); 3307fa9e4066Sahrens 33084263d13fSGeorge Wilson print_pool(zhp, cbp); 33094263d13fSGeorge Wilson if (!cbp->cb_verbose) 33104263d13fSGeorge Wilson return (0); 33114263d13fSGeorge Wilson 33124263d13fSGeorge Wilson verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 33134263d13fSGeorge Wilson &nvroot) == 0); 33144263d13fSGeorge Wilson print_list_stats(zhp, NULL, nvroot, cbp, 0); 3315fa9e4066Sahrens 3316fa9e4066Sahrens return (0); 3317fa9e4066Sahrens } 3318fa9e4066Sahrens 3319fa9e4066Sahrens /* 3320c58b3526SAdam Stevko * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]] 3321fa9e4066Sahrens * 3322990b4856Slling * -H Scripted mode. Don't display headers, and separate properties 3323990b4856Slling * by a single tab. 3324990b4856Slling * -o List of properties to display. Defaults to 33257a09f97bSGeorge Wilson * "name,size,allocated,free,expandsize,fragmentation,capacity," 33267a09f97bSGeorge Wilson * "dedupratio,health,altroot" 3327c58b3526SAdam Stevko * -p Diplay values in parsable (exact) format. 33283f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format 3329fa9e4066Sahrens * 3330fa9e4066Sahrens * List all pools in the system, whether or not they're healthy. Output space 3331fa9e4066Sahrens * statistics for each one, as well as health status summary. 3332fa9e4066Sahrens */ 3333fa9e4066Sahrens int 3334fa9e4066Sahrens zpool_do_list(int argc, char **argv) 3335fa9e4066Sahrens { 3336fa9e4066Sahrens int c; 3337fa9e4066Sahrens int ret; 3338fa9e4066Sahrens list_cbdata_t cb = { 0 }; 3339990b4856Slling static char default_props[] = 3340*86714001SSerapheim Dimitropoulos "name,size,allocated,free,checkpoint,expandsize,fragmentation," 3341*86714001SSerapheim Dimitropoulos "capacity,dedupratio,health,altroot"; 3342990b4856Slling char *props = default_props; 33433f9d6ad7SLin Ling unsigned long interval = 0, count = 0; 33444263d13fSGeorge Wilson zpool_list_t *list; 33454263d13fSGeorge Wilson boolean_t first = B_TRUE; 3346fa9e4066Sahrens 3347fa9e4066Sahrens /* check options */ 3348c58b3526SAdam Stevko while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) { 3349fa9e4066Sahrens switch (c) { 3350fa9e4066Sahrens case 'H': 335199653d4eSeschrock cb.cb_scripted = B_TRUE; 3352fa9e4066Sahrens break; 3353fa9e4066Sahrens case 'o': 3354990b4856Slling props = optarg; 3355fa9e4066Sahrens break; 3356c58b3526SAdam Stevko case 'p': 3357c58b3526SAdam Stevko cb.cb_literal = B_TRUE; 3358c58b3526SAdam Stevko break; 33593f9d6ad7SLin Ling case 'T': 33603f9d6ad7SLin Ling get_timestamp_arg(*optarg); 33613f9d6ad7SLin Ling break; 33624263d13fSGeorge Wilson case 'v': 33634263d13fSGeorge Wilson cb.cb_verbose = B_TRUE; 33644263d13fSGeorge Wilson break; 3365fa9e4066Sahrens case ':': 3366fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 3367fa9e4066Sahrens "'%c' option\n"), optopt); 336899653d4eSeschrock usage(B_FALSE); 3369fa9e4066Sahrens break; 3370fa9e4066Sahrens case '?': 3371fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3372fa9e4066Sahrens optopt); 337399653d4eSeschrock usage(B_FALSE); 3374fa9e4066Sahrens } 3375fa9e4066Sahrens } 3376fa9e4066Sahrens 3377fa9e4066Sahrens argc -= optind; 3378fa9e4066Sahrens argv += optind; 3379fa9e4066Sahrens 33803f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count); 33813f9d6ad7SLin Ling 3382990b4856Slling if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) 3383990b4856Slling usage(B_FALSE); 3384fa9e4066Sahrens 33853f9d6ad7SLin Ling for (;;) { 3386cd67d23dSGeorge Wilson if ((list = pool_list_get(argc, argv, &cb.cb_proplist, 3387cd67d23dSGeorge Wilson &ret)) == NULL) 3388cd67d23dSGeorge Wilson return (1); 33894263d13fSGeorge Wilson 33904263d13fSGeorge Wilson if (pool_list_count(list) == 0) 33914263d13fSGeorge Wilson break; 33924263d13fSGeorge Wilson 33934263d13fSGeorge Wilson cb.cb_namewidth = 0; 33944263d13fSGeorge Wilson (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 3395990b4856Slling 33963f9d6ad7SLin Ling if (timestamp_fmt != NODATE) 33973f9d6ad7SLin Ling print_timestamp(timestamp_fmt); 3398fa9e4066Sahrens 33994263d13fSGeorge Wilson if (!cb.cb_scripted && (first || cb.cb_verbose)) { 34004263d13fSGeorge Wilson print_header(&cb); 34014263d13fSGeorge Wilson first = B_FALSE; 34023f9d6ad7SLin Ling } 34034263d13fSGeorge Wilson ret = pool_list_iter(list, B_TRUE, list_callback, &cb); 34043f9d6ad7SLin Ling 34053f9d6ad7SLin Ling if (interval == 0) 34063f9d6ad7SLin Ling break; 34073f9d6ad7SLin Ling 34083f9d6ad7SLin Ling if (count != 0 && --count == 0) 34093f9d6ad7SLin Ling break; 34103f9d6ad7SLin Ling 3411cd67d23dSGeorge Wilson pool_list_free(list); 34123f9d6ad7SLin Ling (void) sleep(interval); 3413fa9e4066Sahrens } 3414fa9e4066Sahrens 3415cd67d23dSGeorge Wilson if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) { 3416cd67d23dSGeorge Wilson (void) printf(gettext("no pools available\n")); 3417cd67d23dSGeorge Wilson ret = 0; 3418cd67d23dSGeorge Wilson } 3419cd67d23dSGeorge Wilson 3420cd67d23dSGeorge Wilson pool_list_free(list); 34213f9d6ad7SLin Ling zprop_free_list(cb.cb_proplist); 3422fa9e4066Sahrens return (ret); 3423fa9e4066Sahrens } 3424fa9e4066Sahrens 3425fa9e4066Sahrens static int 3426fa9e4066Sahrens zpool_do_attach_or_replace(int argc, char **argv, int replacing) 3427fa9e4066Sahrens { 342899653d4eSeschrock boolean_t force = B_FALSE; 3429fa9e4066Sahrens int c; 3430fa9e4066Sahrens nvlist_t *nvroot; 3431fa9e4066Sahrens char *poolname, *old_disk, *new_disk; 3432fa9e4066Sahrens zpool_handle_t *zhp; 34337855d95bSToomas Soome zpool_boot_label_t boot_type; 34347855d95bSToomas Soome uint64_t boot_size; 343599653d4eSeschrock int ret; 3436fa9e4066Sahrens 3437fa9e4066Sahrens /* check options */ 3438fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) { 3439fa9e4066Sahrens switch (c) { 3440fa9e4066Sahrens case 'f': 344199653d4eSeschrock force = B_TRUE; 3442fa9e4066Sahrens break; 3443fa9e4066Sahrens case '?': 3444fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3445fa9e4066Sahrens optopt); 344699653d4eSeschrock usage(B_FALSE); 3447fa9e4066Sahrens } 3448fa9e4066Sahrens } 3449fa9e4066Sahrens 3450fa9e4066Sahrens argc -= optind; 3451fa9e4066Sahrens argv += optind; 3452fa9e4066Sahrens 3453fa9e4066Sahrens /* get pool name and check number of arguments */ 3454fa9e4066Sahrens if (argc < 1) { 3455fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 345699653d4eSeschrock usage(B_FALSE); 3457fa9e4066Sahrens } 3458fa9e4066Sahrens 3459fa9e4066Sahrens poolname = argv[0]; 3460fa9e4066Sahrens 3461fa9e4066Sahrens if (argc < 2) { 3462fa9e4066Sahrens (void) fprintf(stderr, 3463fa9e4066Sahrens gettext("missing <device> specification\n")); 346499653d4eSeschrock usage(B_FALSE); 3465fa9e4066Sahrens } 3466fa9e4066Sahrens 3467fa9e4066Sahrens old_disk = argv[1]; 3468fa9e4066Sahrens 3469fa9e4066Sahrens if (argc < 3) { 3470fa9e4066Sahrens if (!replacing) { 3471fa9e4066Sahrens (void) fprintf(stderr, 3472fa9e4066Sahrens gettext("missing <new_device> specification\n")); 347399653d4eSeschrock usage(B_FALSE); 3474fa9e4066Sahrens } 3475fa9e4066Sahrens new_disk = old_disk; 3476fa9e4066Sahrens argc -= 1; 3477fa9e4066Sahrens argv += 1; 3478fa9e4066Sahrens } else { 3479fa9e4066Sahrens new_disk = argv[2]; 3480fa9e4066Sahrens argc -= 2; 3481fa9e4066Sahrens argv += 2; 3482fa9e4066Sahrens } 3483fa9e4066Sahrens 3484fa9e4066Sahrens if (argc > 1) { 3485fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 348699653d4eSeschrock usage(B_FALSE); 3487fa9e4066Sahrens } 3488fa9e4066Sahrens 348999653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3490fa9e4066Sahrens return (1); 3491fa9e4066Sahrens 34928488aeb5Staylor if (zpool_get_config(zhp, NULL) == NULL) { 3493fa9e4066Sahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 3494fa9e4066Sahrens poolname); 3495fa9e4066Sahrens zpool_close(zhp); 3496fa9e4066Sahrens return (1); 3497fa9e4066Sahrens } 3498fa9e4066Sahrens 34997855d95bSToomas Soome if (zpool_is_bootable(zhp)) 35007855d95bSToomas Soome boot_type = ZPOOL_COPY_BOOT_LABEL; 35017855d95bSToomas Soome else 35027855d95bSToomas Soome boot_type = ZPOOL_NO_BOOT_LABEL; 35037855d95bSToomas Soome 35047855d95bSToomas Soome boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 3505705040edSEric Taylor nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE, 35067855d95bSToomas Soome boot_type, boot_size, argc, argv); 3507fa9e4066Sahrens if (nvroot == NULL) { 3508fa9e4066Sahrens zpool_close(zhp); 3509fa9e4066Sahrens return (1); 3510fa9e4066Sahrens } 3511fa9e4066Sahrens 351299653d4eSeschrock ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); 351399653d4eSeschrock 351499653d4eSeschrock nvlist_free(nvroot); 351599653d4eSeschrock zpool_close(zhp); 351699653d4eSeschrock 351799653d4eSeschrock return (ret); 3518fa9e4066Sahrens } 3519fa9e4066Sahrens 3520fa9e4066Sahrens /* 3521fa9e4066Sahrens * zpool replace [-f] <pool> <device> <new_device> 3522fa9e4066Sahrens * 3523fa9e4066Sahrens * -f Force attach, even if <new_device> appears to be in use. 3524fa9e4066Sahrens * 3525fa9e4066Sahrens * Replace <device> with <new_device>. 3526fa9e4066Sahrens */ 3527fa9e4066Sahrens /* ARGSUSED */ 3528fa9e4066Sahrens int 3529fa9e4066Sahrens zpool_do_replace(int argc, char **argv) 3530fa9e4066Sahrens { 3531fa9e4066Sahrens return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 3532fa9e4066Sahrens } 3533fa9e4066Sahrens 3534fa9e4066Sahrens /* 3535fa9e4066Sahrens * zpool attach [-f] <pool> <device> <new_device> 3536fa9e4066Sahrens * 3537fa9e4066Sahrens * -f Force attach, even if <new_device> appears to be in use. 3538fa9e4066Sahrens * 3539fa9e4066Sahrens * Attach <new_device> to the mirror containing <device>. If <device> is not 3540fa9e4066Sahrens * part of a mirror, then <device> will be transformed into a mirror of 3541fa9e4066Sahrens * <device> and <new_device>. In either case, <new_device> will begin life 3542fa9e4066Sahrens * with a DTL of [0, now], and will immediately begin to resilver itself. 3543fa9e4066Sahrens */ 3544fa9e4066Sahrens int 3545fa9e4066Sahrens zpool_do_attach(int argc, char **argv) 3546fa9e4066Sahrens { 3547fa9e4066Sahrens return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 3548fa9e4066Sahrens } 3549fa9e4066Sahrens 3550fa9e4066Sahrens /* 3551fa9e4066Sahrens * zpool detach [-f] <pool> <device> 3552fa9e4066Sahrens * 3553fa9e4066Sahrens * -f Force detach of <device>, even if DTLs argue against it 3554fa9e4066Sahrens * (not supported yet) 3555fa9e4066Sahrens * 3556fa9e4066Sahrens * Detach a device from a mirror. The operation will be refused if <device> 3557fa9e4066Sahrens * is the last device in the mirror, or if the DTLs indicate that this device 3558fa9e4066Sahrens * has the only valid copy of some data. 3559fa9e4066Sahrens */ 3560fa9e4066Sahrens /* ARGSUSED */ 3561fa9e4066Sahrens int 3562fa9e4066Sahrens zpool_do_detach(int argc, char **argv) 3563fa9e4066Sahrens { 3564fa9e4066Sahrens int c; 3565fa9e4066Sahrens char *poolname, *path; 3566fa9e4066Sahrens zpool_handle_t *zhp; 356799653d4eSeschrock int ret; 3568fa9e4066Sahrens 3569fa9e4066Sahrens /* check options */ 3570fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) { 3571fa9e4066Sahrens switch (c) { 3572fa9e4066Sahrens case 'f': 3573fa9e4066Sahrens case '?': 3574fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3575fa9e4066Sahrens optopt); 357699653d4eSeschrock usage(B_FALSE); 3577fa9e4066Sahrens } 3578fa9e4066Sahrens } 3579fa9e4066Sahrens 3580fa9e4066Sahrens argc -= optind; 3581fa9e4066Sahrens argv += optind; 3582fa9e4066Sahrens 3583fa9e4066Sahrens /* get pool name and check number of arguments */ 3584fa9e4066Sahrens if (argc < 1) { 3585fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 358699653d4eSeschrock usage(B_FALSE); 3587fa9e4066Sahrens } 3588fa9e4066Sahrens 3589fa9e4066Sahrens if (argc < 2) { 3590fa9e4066Sahrens (void) fprintf(stderr, 3591fa9e4066Sahrens gettext("missing <device> specification\n")); 359299653d4eSeschrock usage(B_FALSE); 3593fa9e4066Sahrens } 3594fa9e4066Sahrens 3595fa9e4066Sahrens poolname = argv[0]; 3596fa9e4066Sahrens path = argv[1]; 3597fa9e4066Sahrens 359899653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3599fa9e4066Sahrens return (1); 3600fa9e4066Sahrens 360199653d4eSeschrock ret = zpool_vdev_detach(zhp, path); 360299653d4eSeschrock 360399653d4eSeschrock zpool_close(zhp); 360499653d4eSeschrock 360599653d4eSeschrock return (ret); 3606fa9e4066Sahrens } 3607fa9e4066Sahrens 36081195e687SMark J Musante /* 36091195e687SMark J Musante * zpool split [-n] [-o prop=val] ... 36101195e687SMark J Musante * [-o mntopt] ... 36111195e687SMark J Musante * [-R altroot] <pool> <newpool> [<device> ...] 36121195e687SMark J Musante * 36131195e687SMark J Musante * -n Do not split the pool, but display the resulting layout if 36141195e687SMark J Musante * it were to be split. 36151195e687SMark J Musante * -o Set property=value, or set mount options. 36161195e687SMark J Musante * -R Mount the split-off pool under an alternate root. 36171195e687SMark J Musante * 36181195e687SMark J Musante * Splits the named pool and gives it the new pool name. Devices to be split 36191195e687SMark J Musante * off may be listed, provided that no more than one device is specified 36201195e687SMark J Musante * per top-level vdev mirror. The newly split pool is left in an exported 36211195e687SMark J Musante * state unless -R is specified. 36221195e687SMark J Musante * 36231195e687SMark J Musante * Restrictions: the top-level of the pool pool must only be made up of 36241195e687SMark J Musante * mirrors; all devices in the pool must be healthy; no device may be 36251195e687SMark J Musante * undergoing a resilvering operation. 36261195e687SMark J Musante */ 36271195e687SMark J Musante int 36281195e687SMark J Musante zpool_do_split(int argc, char **argv) 36291195e687SMark J Musante { 36301195e687SMark J Musante char *srcpool, *newpool, *propval; 36311195e687SMark J Musante char *mntopts = NULL; 36321195e687SMark J Musante splitflags_t flags; 36331195e687SMark J Musante int c, ret = 0; 36341195e687SMark J Musante zpool_handle_t *zhp; 36351195e687SMark J Musante nvlist_t *config, *props = NULL; 36361195e687SMark J Musante 36371195e687SMark J Musante flags.dryrun = B_FALSE; 36381195e687SMark J Musante flags.import = B_FALSE; 36391195e687SMark J Musante 36401195e687SMark J Musante /* check options */ 36411195e687SMark J Musante while ((c = getopt(argc, argv, ":R:no:")) != -1) { 36421195e687SMark J Musante switch (c) { 36431195e687SMark J Musante case 'R': 36441195e687SMark J Musante flags.import = B_TRUE; 36451195e687SMark J Musante if (add_prop_list( 36461195e687SMark J Musante zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg, 36471195e687SMark J Musante &props, B_TRUE) != 0) { 3648aab83bb8SJosef 'Jeff' Sipek nvlist_free(props); 36491195e687SMark J Musante usage(B_FALSE); 36501195e687SMark J Musante } 36511195e687SMark J Musante break; 36521195e687SMark J Musante case 'n': 36531195e687SMark J Musante flags.dryrun = B_TRUE; 36541195e687SMark J Musante break; 36551195e687SMark J Musante case 'o': 36561195e687SMark J Musante if ((propval = strchr(optarg, '=')) != NULL) { 36571195e687SMark J Musante *propval = '\0'; 36581195e687SMark J Musante propval++; 36591195e687SMark J Musante if (add_prop_list(optarg, propval, 36601195e687SMark J Musante &props, B_TRUE) != 0) { 3661aab83bb8SJosef 'Jeff' Sipek nvlist_free(props); 36621195e687SMark J Musante usage(B_FALSE); 36631195e687SMark J Musante } 36641195e687SMark J Musante } else { 36651195e687SMark J Musante mntopts = optarg; 36661195e687SMark J Musante } 36671195e687SMark J Musante break; 36681195e687SMark J Musante case ':': 36691195e687SMark J Musante (void) fprintf(stderr, gettext("missing argument for " 36701195e687SMark J Musante "'%c' option\n"), optopt); 36711195e687SMark J Musante usage(B_FALSE); 36721195e687SMark J Musante break; 36731195e687SMark J Musante case '?': 36741195e687SMark J Musante (void) fprintf(stderr, gettext("invalid option '%c'\n"), 36751195e687SMark J Musante optopt); 36761195e687SMark J Musante usage(B_FALSE); 36771195e687SMark J Musante break; 36781195e687SMark J Musante } 36791195e687SMark J Musante } 36801195e687SMark J Musante 36811195e687SMark J Musante if (!flags.import && mntopts != NULL) { 36821195e687SMark J Musante (void) fprintf(stderr, gettext("setting mntopts is only " 36831195e687SMark J Musante "valid when importing the pool\n")); 36841195e687SMark J Musante usage(B_FALSE); 36851195e687SMark J Musante } 36861195e687SMark J Musante 36871195e687SMark J Musante argc -= optind; 36881195e687SMark J Musante argv += optind; 36891195e687SMark J Musante 36901195e687SMark J Musante if (argc < 1) { 36911195e687SMark J Musante (void) fprintf(stderr, gettext("Missing pool name\n")); 36921195e687SMark J Musante usage(B_FALSE); 36931195e687SMark J Musante } 36941195e687SMark J Musante if (argc < 2) { 36951195e687SMark J Musante (void) fprintf(stderr, gettext("Missing new pool name\n")); 36961195e687SMark J Musante usage(B_FALSE); 36971195e687SMark J Musante } 36981195e687SMark J Musante 36991195e687SMark J Musante srcpool = argv[0]; 37001195e687SMark J Musante newpool = argv[1]; 37011195e687SMark J Musante 37021195e687SMark J Musante argc -= 2; 37031195e687SMark J Musante argv += 2; 37041195e687SMark J Musante 37051195e687SMark J Musante if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) 37061195e687SMark J Musante return (1); 37071195e687SMark J Musante 37081195e687SMark J Musante config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv); 37091195e687SMark J Musante if (config == NULL) { 37101195e687SMark J Musante ret = 1; 37111195e687SMark J Musante } else { 37121195e687SMark J Musante if (flags.dryrun) { 37131195e687SMark J Musante (void) printf(gettext("would create '%s' with the " 37141195e687SMark J Musante "following layout:\n\n"), newpool); 37151195e687SMark J Musante print_vdev_tree(NULL, newpool, config, 0, B_FALSE); 37161195e687SMark J Musante } 37171195e687SMark J Musante nvlist_free(config); 37181195e687SMark J Musante } 37191195e687SMark J Musante 37201195e687SMark J Musante zpool_close(zhp); 37211195e687SMark J Musante 37221195e687SMark J Musante if (ret != 0 || flags.dryrun || !flags.import) 37231195e687SMark J Musante return (ret); 37241195e687SMark J Musante 37251195e687SMark J Musante /* 37261195e687SMark J Musante * The split was successful. Now we need to open the new 37271195e687SMark J Musante * pool and import it. 37281195e687SMark J Musante */ 37291195e687SMark J Musante if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) 37301195e687SMark J Musante return (1); 37311195e687SMark J Musante if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 37321195e687SMark J Musante zpool_enable_datasets(zhp, mntopts, 0) != 0) { 37331195e687SMark J Musante ret = 1; 3734fe7cd8aaSCyril Plisko (void) fprintf(stderr, gettext("Split was successful, but " 37351195e687SMark J Musante "the datasets could not all be mounted\n")); 37361195e687SMark J Musante (void) fprintf(stderr, gettext("Try doing '%s' with a " 37371195e687SMark J Musante "different altroot\n"), "zpool import"); 37381195e687SMark J Musante } 37391195e687SMark J Musante zpool_close(zhp); 37401195e687SMark J Musante 37411195e687SMark J Musante return (ret); 37421195e687SMark J Musante } 37431195e687SMark J Musante 37441195e687SMark J Musante 37451195e687SMark J Musante 3746fa9e4066Sahrens /* 3747441d80aaSlling * zpool online <pool> <device> ... 3748fa9e4066Sahrens */ 3749fa9e4066Sahrens int 3750fa9e4066Sahrens zpool_do_online(int argc, char **argv) 3751fa9e4066Sahrens { 3752fa9e4066Sahrens int c, i; 3753fa9e4066Sahrens char *poolname; 3754fa9e4066Sahrens zpool_handle_t *zhp; 3755fa9e4066Sahrens int ret = 0; 37563d7072f8Seschrock vdev_state_t newstate; 3757573ca77eSGeorge Wilson int flags = 0; 3758fa9e4066Sahrens 3759fa9e4066Sahrens /* check options */ 3760573ca77eSGeorge Wilson while ((c = getopt(argc, argv, "et")) != -1) { 3761fa9e4066Sahrens switch (c) { 3762573ca77eSGeorge Wilson case 'e': 3763573ca77eSGeorge Wilson flags |= ZFS_ONLINE_EXPAND; 3764573ca77eSGeorge Wilson break; 3765fa9e4066Sahrens case 't': 3766fa9e4066Sahrens case '?': 3767fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3768fa9e4066Sahrens optopt); 376999653d4eSeschrock usage(B_FALSE); 3770fa9e4066Sahrens } 3771fa9e4066Sahrens } 3772fa9e4066Sahrens 3773fa9e4066Sahrens argc -= optind; 3774fa9e4066Sahrens argv += optind; 3775fa9e4066Sahrens 3776fa9e4066Sahrens /* get pool name and check number of arguments */ 3777fa9e4066Sahrens if (argc < 1) { 3778fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name\n")); 377999653d4eSeschrock usage(B_FALSE); 3780fa9e4066Sahrens } 3781fa9e4066Sahrens if (argc < 2) { 3782fa9e4066Sahrens (void) fprintf(stderr, gettext("missing device name\n")); 378399653d4eSeschrock usage(B_FALSE); 3784fa9e4066Sahrens } 3785fa9e4066Sahrens 3786fa9e4066Sahrens poolname = argv[0]; 3787fa9e4066Sahrens 378899653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3789fa9e4066Sahrens return (1); 3790fa9e4066Sahrens 37913d7072f8Seschrock for (i = 1; i < argc; i++) { 3792573ca77eSGeorge Wilson if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) { 37933d7072f8Seschrock if (newstate != VDEV_STATE_HEALTHY) { 37943d7072f8Seschrock (void) printf(gettext("warning: device '%s' " 37953d7072f8Seschrock "onlined, but remains in faulted state\n"), 37963d7072f8Seschrock argv[i]); 37973d7072f8Seschrock if (newstate == VDEV_STATE_FAULTED) 37983d7072f8Seschrock (void) printf(gettext("use 'zpool " 37993d7072f8Seschrock "clear' to restore a faulted " 38003d7072f8Seschrock "device\n")); 38013d7072f8Seschrock else 38023d7072f8Seschrock (void) printf(gettext("use 'zpool " 38033d7072f8Seschrock "replace' to replace devices " 38043d7072f8Seschrock "that are no longer present\n")); 38053d7072f8Seschrock } 38063d7072f8Seschrock } else { 3807fa9e4066Sahrens ret = 1; 38083d7072f8Seschrock } 38093d7072f8Seschrock } 3810fa9e4066Sahrens 381199653d4eSeschrock zpool_close(zhp); 381299653d4eSeschrock 3813fa9e4066Sahrens return (ret); 3814fa9e4066Sahrens } 3815fa9e4066Sahrens 3816fa9e4066Sahrens /* 3817441d80aaSlling * zpool offline [-ft] <pool> <device> ... 3818fa9e4066Sahrens * 3819fa9e4066Sahrens * -f Force the device into the offline state, even if doing 3820fa9e4066Sahrens * so would appear to compromise pool availability. 3821fa9e4066Sahrens * (not supported yet) 3822fa9e4066Sahrens * 3823fa9e4066Sahrens * -t Only take the device off-line temporarily. The offline 3824fa9e4066Sahrens * state will not be persistent across reboots. 3825fa9e4066Sahrens */ 3826fa9e4066Sahrens /* ARGSUSED */ 3827fa9e4066Sahrens int 3828fa9e4066Sahrens zpool_do_offline(int argc, char **argv) 3829fa9e4066Sahrens { 3830fa9e4066Sahrens int c, i; 3831fa9e4066Sahrens char *poolname; 3832fa9e4066Sahrens zpool_handle_t *zhp; 383399653d4eSeschrock int ret = 0; 383499653d4eSeschrock boolean_t istmp = B_FALSE; 3835fa9e4066Sahrens 3836fa9e4066Sahrens /* check options */ 3837fa9e4066Sahrens while ((c = getopt(argc, argv, "ft")) != -1) { 3838fa9e4066Sahrens switch (c) { 3839fa9e4066Sahrens case 't': 384099653d4eSeschrock istmp = B_TRUE; 3841441d80aaSlling break; 3842441d80aaSlling case 'f': 3843fa9e4066Sahrens case '?': 3844fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3845fa9e4066Sahrens optopt); 384699653d4eSeschrock usage(B_FALSE); 3847fa9e4066Sahrens } 3848fa9e4066Sahrens } 3849fa9e4066Sahrens 3850fa9e4066Sahrens argc -= optind; 3851fa9e4066Sahrens argv += optind; 3852fa9e4066Sahrens 3853fa9e4066Sahrens /* get pool name and check number of arguments */ 3854fa9e4066Sahrens if (argc < 1) { 3855fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name\n")); 385699653d4eSeschrock usage(B_FALSE); 3857fa9e4066Sahrens } 3858fa9e4066Sahrens if (argc < 2) { 3859fa9e4066Sahrens (void) fprintf(stderr, gettext("missing device name\n")); 386099653d4eSeschrock usage(B_FALSE); 3861fa9e4066Sahrens } 3862fa9e4066Sahrens 3863fa9e4066Sahrens poolname = argv[0]; 3864fa9e4066Sahrens 386599653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3866fa9e4066Sahrens return (1); 3867fa9e4066Sahrens 38683d7072f8Seschrock for (i = 1; i < argc; i++) { 38693d7072f8Seschrock if (zpool_vdev_offline(zhp, argv[i], istmp) != 0) 3870fa9e4066Sahrens ret = 1; 38713d7072f8Seschrock } 3872fa9e4066Sahrens 387399653d4eSeschrock zpool_close(zhp); 387499653d4eSeschrock 3875fa9e4066Sahrens return (ret); 3876fa9e4066Sahrens } 3877fa9e4066Sahrens 3878ea8dc4b6Seschrock /* 3879ea8dc4b6Seschrock * zpool clear <pool> [device] 3880ea8dc4b6Seschrock * 3881ea8dc4b6Seschrock * Clear all errors associated with a pool or a particular device. 3882ea8dc4b6Seschrock */ 3883ea8dc4b6Seschrock int 3884ea8dc4b6Seschrock zpool_do_clear(int argc, char **argv) 3885ea8dc4b6Seschrock { 3886468c413aSTim Haley int c; 3887ea8dc4b6Seschrock int ret = 0; 3888468c413aSTim Haley boolean_t dryrun = B_FALSE; 3889468c413aSTim Haley boolean_t do_rewind = B_FALSE; 3890468c413aSTim Haley boolean_t xtreme_rewind = B_FALSE; 3891468c413aSTim Haley uint32_t rewind_policy = ZPOOL_NO_REWIND; 3892468c413aSTim Haley nvlist_t *policy = NULL; 3893ea8dc4b6Seschrock zpool_handle_t *zhp; 3894ea8dc4b6Seschrock char *pool, *device; 3895ea8dc4b6Seschrock 3896468c413aSTim Haley /* check options */ 3897468c413aSTim Haley while ((c = getopt(argc, argv, "FnX")) != -1) { 3898468c413aSTim Haley switch (c) { 3899468c413aSTim Haley case 'F': 3900468c413aSTim Haley do_rewind = B_TRUE; 3901468c413aSTim Haley break; 3902468c413aSTim Haley case 'n': 3903468c413aSTim Haley dryrun = B_TRUE; 3904468c413aSTim Haley break; 3905468c413aSTim Haley case 'X': 3906468c413aSTim Haley xtreme_rewind = B_TRUE; 3907468c413aSTim Haley break; 3908468c413aSTim Haley case '?': 3909468c413aSTim Haley (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3910468c413aSTim Haley optopt); 3911468c413aSTim Haley usage(B_FALSE); 3912468c413aSTim Haley } 3913468c413aSTim Haley } 3914468c413aSTim Haley 3915468c413aSTim Haley argc -= optind; 3916468c413aSTim Haley argv += optind; 3917468c413aSTim Haley 3918468c413aSTim Haley if (argc < 1) { 3919ea8dc4b6Seschrock (void) fprintf(stderr, gettext("missing pool name\n")); 392099653d4eSeschrock usage(B_FALSE); 3921ea8dc4b6Seschrock } 3922ea8dc4b6Seschrock 3923468c413aSTim Haley if (argc > 2) { 3924ea8dc4b6Seschrock (void) fprintf(stderr, gettext("too many arguments\n")); 392599653d4eSeschrock usage(B_FALSE); 3926ea8dc4b6Seschrock } 3927ea8dc4b6Seschrock 3928468c413aSTim Haley if ((dryrun || xtreme_rewind) && !do_rewind) { 3929468c413aSTim Haley (void) fprintf(stderr, 3930468c413aSTim Haley gettext("-n or -X only meaningful with -F\n")); 3931468c413aSTim Haley usage(B_FALSE); 3932468c413aSTim Haley } 3933468c413aSTim Haley if (dryrun) 3934468c413aSTim Haley rewind_policy = ZPOOL_TRY_REWIND; 3935468c413aSTim Haley else if (do_rewind) 3936468c413aSTim Haley rewind_policy = ZPOOL_DO_REWIND; 3937468c413aSTim Haley if (xtreme_rewind) 3938468c413aSTim Haley rewind_policy |= ZPOOL_EXTREME_REWIND; 3939468c413aSTim Haley 3940468c413aSTim Haley /* In future, further rewind policy choices can be passed along here */ 3941468c413aSTim Haley if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 3942468c413aSTim Haley nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0) 3943468c413aSTim Haley return (1); 3944468c413aSTim Haley 3945468c413aSTim Haley pool = argv[0]; 3946468c413aSTim Haley device = argc == 2 ? argv[1] : NULL; 3947ea8dc4b6Seschrock 3948468c413aSTim Haley if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 3949468c413aSTim Haley nvlist_free(policy); 3950ea8dc4b6Seschrock return (1); 3951468c413aSTim Haley } 3952ea8dc4b6Seschrock 3953468c413aSTim Haley if (zpool_clear(zhp, device, policy) != 0) 3954ea8dc4b6Seschrock ret = 1; 3955ea8dc4b6Seschrock 3956ea8dc4b6Seschrock zpool_close(zhp); 3957ea8dc4b6Seschrock 3958468c413aSTim Haley nvlist_free(policy); 3959468c413aSTim Haley 3960ea8dc4b6Seschrock return (ret); 3961ea8dc4b6Seschrock } 3962ea8dc4b6Seschrock 3963e9103aaeSGarrett D'Amore /* 3964e9103aaeSGarrett D'Amore * zpool reguid <pool> 3965e9103aaeSGarrett D'Amore */ 3966e9103aaeSGarrett D'Amore int 3967e9103aaeSGarrett D'Amore zpool_do_reguid(int argc, char **argv) 3968e9103aaeSGarrett D'Amore { 3969e9103aaeSGarrett D'Amore int c; 3970e9103aaeSGarrett D'Amore char *poolname; 3971e9103aaeSGarrett D'Amore zpool_handle_t *zhp; 3972e9103aaeSGarrett D'Amore int ret = 0; 3973e9103aaeSGarrett D'Amore 3974e9103aaeSGarrett D'Amore /* check options */ 3975e9103aaeSGarrett D'Amore while ((c = getopt(argc, argv, "")) != -1) { 3976e9103aaeSGarrett D'Amore switch (c) { 3977e9103aaeSGarrett D'Amore case '?': 3978e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3979e9103aaeSGarrett D'Amore optopt); 3980e9103aaeSGarrett D'Amore usage(B_FALSE); 3981e9103aaeSGarrett D'Amore } 3982e9103aaeSGarrett D'Amore } 3983e9103aaeSGarrett D'Amore 3984e9103aaeSGarrett D'Amore argc -= optind; 3985e9103aaeSGarrett D'Amore argv += optind; 3986e9103aaeSGarrett D'Amore 3987e9103aaeSGarrett D'Amore /* get pool name and check number of arguments */ 3988e9103aaeSGarrett D'Amore if (argc < 1) { 3989e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("missing pool name\n")); 3990e9103aaeSGarrett D'Amore usage(B_FALSE); 3991e9103aaeSGarrett D'Amore } 3992e9103aaeSGarrett D'Amore 3993e9103aaeSGarrett D'Amore if (argc > 1) { 3994e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("too many arguments\n")); 3995e9103aaeSGarrett D'Amore usage(B_FALSE); 3996e9103aaeSGarrett D'Amore } 3997e9103aaeSGarrett D'Amore 3998e9103aaeSGarrett D'Amore poolname = argv[0]; 3999e9103aaeSGarrett D'Amore if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 4000e9103aaeSGarrett D'Amore return (1); 4001e9103aaeSGarrett D'Amore 4002e9103aaeSGarrett D'Amore ret = zpool_reguid(zhp); 4003e9103aaeSGarrett D'Amore 4004e9103aaeSGarrett D'Amore zpool_close(zhp); 4005e9103aaeSGarrett D'Amore return (ret); 4006e9103aaeSGarrett D'Amore } 4007e9103aaeSGarrett D'Amore 4008e9103aaeSGarrett D'Amore 40094263d13fSGeorge Wilson /* 40104263d13fSGeorge Wilson * zpool reopen <pool> 40114263d13fSGeorge Wilson * 40124263d13fSGeorge Wilson * Reopen the pool so that the kernel can update the sizes of all vdevs. 40134263d13fSGeorge Wilson */ 40144263d13fSGeorge Wilson int 40154263d13fSGeorge Wilson zpool_do_reopen(int argc, char **argv) 40164263d13fSGeorge Wilson { 401731d7e8faSGeorge Wilson int c; 40184263d13fSGeorge Wilson int ret = 0; 40194263d13fSGeorge Wilson zpool_handle_t *zhp; 40204263d13fSGeorge Wilson char *pool; 40214263d13fSGeorge Wilson 402231d7e8faSGeorge Wilson /* check options */ 402331d7e8faSGeorge Wilson while ((c = getopt(argc, argv, "")) != -1) { 402431d7e8faSGeorge Wilson switch (c) { 402531d7e8faSGeorge Wilson case '?': 402631d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("invalid option '%c'\n"), 402731d7e8faSGeorge Wilson optopt); 402831d7e8faSGeorge Wilson usage(B_FALSE); 402931d7e8faSGeorge Wilson } 403031d7e8faSGeorge Wilson } 403131d7e8faSGeorge Wilson 40324263d13fSGeorge Wilson argc--; 40334263d13fSGeorge Wilson argv++; 40344263d13fSGeorge Wilson 403531d7e8faSGeorge Wilson if (argc < 1) { 403631d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("missing pool name\n")); 403731d7e8faSGeorge Wilson usage(B_FALSE); 403831d7e8faSGeorge Wilson } 403931d7e8faSGeorge Wilson 404031d7e8faSGeorge Wilson if (argc > 1) { 404131d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("too many arguments\n")); 404231d7e8faSGeorge Wilson usage(B_FALSE); 404331d7e8faSGeorge Wilson } 40444263d13fSGeorge Wilson 40454263d13fSGeorge Wilson pool = argv[0]; 40464263d13fSGeorge Wilson if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) 40474263d13fSGeorge Wilson return (1); 40484263d13fSGeorge Wilson 40494263d13fSGeorge Wilson ret = zpool_reopen(zhp); 40504263d13fSGeorge Wilson zpool_close(zhp); 40514263d13fSGeorge Wilson return (ret); 40524263d13fSGeorge Wilson } 40534263d13fSGeorge Wilson 4054fa9e4066Sahrens typedef struct scrub_cbdata { 4055fa9e4066Sahrens int cb_type; 405606eeb2adSek int cb_argc; 405706eeb2adSek char **cb_argv; 40581702cce7SAlek Pinchuk pool_scrub_cmd_t cb_scrub_cmd; 4059fa9e4066Sahrens } scrub_cbdata_t; 4060fa9e4066Sahrens 4061*86714001SSerapheim Dimitropoulos static boolean_t 4062*86714001SSerapheim Dimitropoulos zpool_has_checkpoint(zpool_handle_t *zhp) 4063*86714001SSerapheim Dimitropoulos { 4064*86714001SSerapheim Dimitropoulos nvlist_t *config, *nvroot; 4065*86714001SSerapheim Dimitropoulos 4066*86714001SSerapheim Dimitropoulos config = zpool_get_config(zhp, NULL); 4067*86714001SSerapheim Dimitropoulos 4068*86714001SSerapheim Dimitropoulos if (config != NULL) { 4069*86714001SSerapheim Dimitropoulos pool_checkpoint_stat_t *pcs = NULL; 4070*86714001SSerapheim Dimitropoulos uint_t c; 4071*86714001SSerapheim Dimitropoulos 4072*86714001SSerapheim Dimitropoulos nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 4073*86714001SSerapheim Dimitropoulos (void) nvlist_lookup_uint64_array(nvroot, 4074*86714001SSerapheim Dimitropoulos ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 4075*86714001SSerapheim Dimitropoulos 4076*86714001SSerapheim Dimitropoulos if (pcs == NULL || pcs->pcs_state == CS_NONE) 4077*86714001SSerapheim Dimitropoulos return (B_FALSE); 4078*86714001SSerapheim Dimitropoulos 4079*86714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS || 4080*86714001SSerapheim Dimitropoulos pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 4081*86714001SSerapheim Dimitropoulos return (B_TRUE); 4082*86714001SSerapheim Dimitropoulos } 4083*86714001SSerapheim Dimitropoulos 4084*86714001SSerapheim Dimitropoulos return (B_FALSE); 4085*86714001SSerapheim Dimitropoulos } 4086*86714001SSerapheim Dimitropoulos 4087fa9e4066Sahrens int 4088fa9e4066Sahrens scrub_callback(zpool_handle_t *zhp, void *data) 4089fa9e4066Sahrens { 4090fa9e4066Sahrens scrub_cbdata_t *cb = data; 409106eeb2adSek int err; 4092fa9e4066Sahrens 4093ea8dc4b6Seschrock /* 4094ea8dc4b6Seschrock * Ignore faulted pools. 4095ea8dc4b6Seschrock */ 4096ea8dc4b6Seschrock if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 4097ea8dc4b6Seschrock (void) fprintf(stderr, gettext("cannot scrub '%s': pool is " 4098ea8dc4b6Seschrock "currently unavailable\n"), zpool_get_name(zhp)); 4099ea8dc4b6Seschrock return (1); 4100ea8dc4b6Seschrock } 4101ea8dc4b6Seschrock 41021702cce7SAlek Pinchuk err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd); 410306eeb2adSek 4104*86714001SSerapheim Dimitropoulos if (err == 0 && zpool_has_checkpoint(zhp) && 4105*86714001SSerapheim Dimitropoulos cb->cb_type == POOL_SCAN_SCRUB) { 4106*86714001SSerapheim Dimitropoulos (void) printf(gettext("warning: will not scrub state that " 4107*86714001SSerapheim Dimitropoulos "belongs to the checkpoint of pool '%s'\n"), 4108*86714001SSerapheim Dimitropoulos zpool_get_name(zhp)); 4109*86714001SSerapheim Dimitropoulos } 4110*86714001SSerapheim Dimitropoulos 411106eeb2adSek return (err != 0); 4112fa9e4066Sahrens } 4113fa9e4066Sahrens 4114fa9e4066Sahrens /* 41151702cce7SAlek Pinchuk * zpool scrub [-s | -p] <pool> ... 4116fa9e4066Sahrens * 4117fa9e4066Sahrens * -s Stop. Stops any in-progress scrub. 41181702cce7SAlek Pinchuk * -p Pause. Pause in-progress scrub. 4119fa9e4066Sahrens */ 4120fa9e4066Sahrens int 4121fa9e4066Sahrens zpool_do_scrub(int argc, char **argv) 4122fa9e4066Sahrens { 4123fa9e4066Sahrens int c; 4124fa9e4066Sahrens scrub_cbdata_t cb; 4125fa9e4066Sahrens 41263f9d6ad7SLin Ling cb.cb_type = POOL_SCAN_SCRUB; 41271702cce7SAlek Pinchuk cb.cb_scrub_cmd = POOL_SCRUB_NORMAL; 4128fa9e4066Sahrens 4129fa9e4066Sahrens /* check options */ 41301702cce7SAlek Pinchuk while ((c = getopt(argc, argv, "sp")) != -1) { 4131fa9e4066Sahrens switch (c) { 4132fa9e4066Sahrens case 's': 41333f9d6ad7SLin Ling cb.cb_type = POOL_SCAN_NONE; 4134fa9e4066Sahrens break; 41351702cce7SAlek Pinchuk case 'p': 41361702cce7SAlek Pinchuk cb.cb_scrub_cmd = POOL_SCRUB_PAUSE; 41371702cce7SAlek Pinchuk break; 4138fa9e4066Sahrens case '?': 4139fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4140fa9e4066Sahrens optopt); 414199653d4eSeschrock usage(B_FALSE); 4142fa9e4066Sahrens } 4143fa9e4066Sahrens } 4144fa9e4066Sahrens 41451702cce7SAlek Pinchuk if (cb.cb_type == POOL_SCAN_NONE && 41461702cce7SAlek Pinchuk cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) { 41471702cce7SAlek Pinchuk (void) fprintf(stderr, gettext("invalid option combination: " 41481702cce7SAlek Pinchuk "-s and -p are mutually exclusive\n")); 41491702cce7SAlek Pinchuk usage(B_FALSE); 41501702cce7SAlek Pinchuk } 41511702cce7SAlek Pinchuk 415206eeb2adSek cb.cb_argc = argc; 415306eeb2adSek cb.cb_argv = argv; 4154fa9e4066Sahrens argc -= optind; 4155fa9e4066Sahrens argv += optind; 4156fa9e4066Sahrens 4157fa9e4066Sahrens if (argc < 1) { 4158fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 415999653d4eSeschrock usage(B_FALSE); 4160fa9e4066Sahrens } 4161fa9e4066Sahrens 4162b1b8ab34Slling return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 4163fa9e4066Sahrens } 4164fa9e4066Sahrens 4165fa9e4066Sahrens typedef struct status_cbdata { 416699653d4eSeschrock int cb_count; 4167e9dbad6fSeschrock boolean_t cb_allpools; 416899653d4eSeschrock boolean_t cb_verbose; 416999653d4eSeschrock boolean_t cb_explain; 417099653d4eSeschrock boolean_t cb_first; 41719eb19f4dSGeorge Wilson boolean_t cb_dedup_stats; 4172fa9e4066Sahrens } status_cbdata_t; 4173fa9e4066Sahrens 4174fa9e4066Sahrens /* 4175fa9e4066Sahrens * Print out detailed scrub status. 4176fa9e4066Sahrens */ 41775cabbc6bSPrashanth Sreenivasa static void 41783f9d6ad7SLin Ling print_scan_status(pool_scan_stat_t *ps) 4179fa9e4066Sahrens { 41801702cce7SAlek Pinchuk time_t start, end, pause; 418173d314ceSLin Ling uint64_t elapsed, mins_left, hours_left; 41823f9d6ad7SLin Ling uint64_t pass_exam, examined, total; 41833f9d6ad7SLin Ling uint_t rate; 4184fa9e4066Sahrens double fraction_done; 41853f9d6ad7SLin Ling char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7]; 4186fa9e4066Sahrens 4187ce72e614SYuri Pankov (void) printf(gettext(" scan: ")); 4188fa9e4066Sahrens 41893f9d6ad7SLin Ling /* If there's never been a scan, there's not much to say. */ 41903f9d6ad7SLin Ling if (ps == NULL || ps->pss_func == POOL_SCAN_NONE || 41913f9d6ad7SLin Ling ps->pss_func >= POOL_SCAN_FUNCS) { 4192fa9e4066Sahrens (void) printf(gettext("none requested\n")); 4193fa9e4066Sahrens return; 4194fa9e4066Sahrens } 4195fa9e4066Sahrens 41963f9d6ad7SLin Ling start = ps->pss_start_time; 41973f9d6ad7SLin Ling end = ps->pss_end_time; 41981702cce7SAlek Pinchuk pause = ps->pss_pass_scrub_pause; 41993f9d6ad7SLin Ling zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf)); 4200fa9e4066Sahrens 42013f9d6ad7SLin Ling assert(ps->pss_func == POOL_SCAN_SCRUB || 42023f9d6ad7SLin Ling ps->pss_func == POOL_SCAN_RESILVER); 42033f9d6ad7SLin Ling /* 42043f9d6ad7SLin Ling * Scan is finished or canceled. 42053f9d6ad7SLin Ling */ 42063f9d6ad7SLin Ling if (ps->pss_state == DSS_FINISHED) { 42073f9d6ad7SLin Ling uint64_t minutes_taken = (end - start) / 60; 4208b327cd3fSIgor Kozhukhov char *fmt = NULL; 42093f9d6ad7SLin Ling 42103f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) { 42113f9d6ad7SLin Ling fmt = gettext("scrub repaired %s in %lluh%um with " 42123f9d6ad7SLin Ling "%llu errors on %s"); 42133f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) { 42143f9d6ad7SLin Ling fmt = gettext("resilvered %s in %lluh%um with " 42153f9d6ad7SLin Ling "%llu errors on %s"); 42163f9d6ad7SLin Ling } 42173f9d6ad7SLin Ling /* LINTED */ 42183f9d6ad7SLin Ling (void) printf(fmt, processed_buf, 421918ce54dfSek (u_longlong_t)(minutes_taken / 60), 422018ce54dfSek (uint_t)(minutes_taken % 60), 42213f9d6ad7SLin Ling (u_longlong_t)ps->pss_errors, 42223f9d6ad7SLin Ling ctime((time_t *)&end)); 42233f9d6ad7SLin Ling return; 42243f9d6ad7SLin Ling } else if (ps->pss_state == DSS_CANCELED) { 42253f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) { 42263f9d6ad7SLin Ling (void) printf(gettext("scrub canceled on %s"), 42273f9d6ad7SLin Ling ctime(&end)); 42283f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) { 42293f9d6ad7SLin Ling (void) printf(gettext("resilver canceled on %s"), 42303f9d6ad7SLin Ling ctime(&end)); 42313f9d6ad7SLin Ling } 4232fa9e4066Sahrens return; 4233fa9e4066Sahrens } 4234fa9e4066Sahrens 42353f9d6ad7SLin Ling assert(ps->pss_state == DSS_SCANNING); 42363f9d6ad7SLin Ling 42373f9d6ad7SLin Ling /* 42383f9d6ad7SLin Ling * Scan is in progress. 42393f9d6ad7SLin Ling */ 42403f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) { 42411702cce7SAlek Pinchuk if (pause == 0) { 42421702cce7SAlek Pinchuk (void) printf(gettext("scrub in progress since %s"), 42431702cce7SAlek Pinchuk ctime(&start)); 42441702cce7SAlek Pinchuk } else { 42451702cce7SAlek Pinchuk char buf[32]; 42461702cce7SAlek Pinchuk struct tm *p = localtime(&pause); 42471702cce7SAlek Pinchuk (void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p); 42481702cce7SAlek Pinchuk (void) printf(gettext("scrub paused since %s\n"), buf); 42491702cce7SAlek Pinchuk (void) printf(gettext("\tscrub started on %s"), 42501702cce7SAlek Pinchuk ctime(&start)); 42511702cce7SAlek Pinchuk } 42523f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) { 42533f9d6ad7SLin Ling (void) printf(gettext("resilver in progress since %s"), 42543f9d6ad7SLin Ling ctime(&start)); 42553f9d6ad7SLin Ling } 4256fa9e4066Sahrens 42573f9d6ad7SLin Ling examined = ps->pss_examined ? ps->pss_examined : 1; 42583f9d6ad7SLin Ling total = ps->pss_to_examine; 4259fa9e4066Sahrens fraction_done = (double)examined / total; 42603f9d6ad7SLin Ling 42613f9d6ad7SLin Ling /* elapsed time for this pass */ 42623f9d6ad7SLin Ling elapsed = time(NULL) - ps->pss_pass_start; 42631702cce7SAlek Pinchuk elapsed -= ps->pss_pass_scrub_spent_paused; 42643f9d6ad7SLin Ling elapsed = elapsed ? elapsed : 1; 42653f9d6ad7SLin Ling pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1; 42663f9d6ad7SLin Ling rate = pass_exam / elapsed; 42673f9d6ad7SLin Ling rate = rate ? rate : 1; 42683f9d6ad7SLin Ling mins_left = ((total - examined) / rate) / 60; 426973d314ceSLin Ling hours_left = mins_left / 60; 42703f9d6ad7SLin Ling 42713f9d6ad7SLin Ling zfs_nicenum(examined, examined_buf, sizeof (examined_buf)); 42723f9d6ad7SLin Ling zfs_nicenum(total, total_buf, sizeof (total_buf)); 42733f9d6ad7SLin Ling 427473d314ceSLin Ling /* 427573d314ceSLin Ling * do not print estimated time if hours_left is more than 30 days 42761702cce7SAlek Pinchuk * or we have a paused scrub 427773d314ceSLin Ling */ 42781702cce7SAlek Pinchuk if (pause == 0) { 42791702cce7SAlek Pinchuk zfs_nicenum(rate, rate_buf, sizeof (rate_buf)); 42801702cce7SAlek Pinchuk (void) printf(gettext("\t%s scanned out of %s at %s/s"), 42811702cce7SAlek Pinchuk examined_buf, total_buf, rate_buf); 42821702cce7SAlek Pinchuk if (hours_left < (30 * 24)) { 42831702cce7SAlek Pinchuk (void) printf(gettext(", %lluh%um to go\n"), 42841702cce7SAlek Pinchuk (u_longlong_t)hours_left, (uint_t)(mins_left % 60)); 42851702cce7SAlek Pinchuk } else { 42861702cce7SAlek Pinchuk (void) printf(gettext( 42871702cce7SAlek Pinchuk ", (scan is slow, no estimated time)\n")); 42881702cce7SAlek Pinchuk } 428973d314ceSLin Ling } else { 42901702cce7SAlek Pinchuk (void) printf(gettext("\t%s scanned out of %s\n"), 42911702cce7SAlek Pinchuk examined_buf, total_buf); 429273d314ceSLin Ling } 42933f9d6ad7SLin Ling 42943f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_RESILVER) { 42953f9d6ad7SLin Ling (void) printf(gettext(" %s resilvered, %.2f%% done\n"), 42963f9d6ad7SLin Ling processed_buf, 100 * fraction_done); 42973f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_SCRUB) { 42983f9d6ad7SLin Ling (void) printf(gettext(" %s repaired, %.2f%% done\n"), 42993f9d6ad7SLin Ling processed_buf, 100 * fraction_done); 43003f9d6ad7SLin Ling } 4301fa9e4066Sahrens } 4302fa9e4066Sahrens 4303*86714001SSerapheim Dimitropoulos /* 4304*86714001SSerapheim Dimitropoulos * As we don't scrub checkpointed blocks, we want to warn the 4305*86714001SSerapheim Dimitropoulos * user that we skipped scanning some blocks if a checkpoint exists 4306*86714001SSerapheim Dimitropoulos * or existed at any time during the scan. 4307*86714001SSerapheim Dimitropoulos */ 4308*86714001SSerapheim Dimitropoulos static void 4309*86714001SSerapheim Dimitropoulos print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs) 4310*86714001SSerapheim Dimitropoulos { 4311*86714001SSerapheim Dimitropoulos if (ps == NULL || pcs == NULL) 4312*86714001SSerapheim Dimitropoulos return; 4313*86714001SSerapheim Dimitropoulos 4314*86714001SSerapheim Dimitropoulos if (pcs->pcs_state == CS_NONE || 4315*86714001SSerapheim Dimitropoulos pcs->pcs_state == CS_CHECKPOINT_DISCARDING) 4316*86714001SSerapheim Dimitropoulos return; 4317*86714001SSerapheim Dimitropoulos 4318*86714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS); 4319*86714001SSerapheim Dimitropoulos 4320*86714001SSerapheim Dimitropoulos if (ps->pss_state == DSS_NONE) 4321*86714001SSerapheim Dimitropoulos return; 4322*86714001SSerapheim Dimitropoulos 4323*86714001SSerapheim Dimitropoulos if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) && 4324*86714001SSerapheim Dimitropoulos ps->pss_end_time < pcs->pcs_start_time) 4325*86714001SSerapheim Dimitropoulos return; 4326*86714001SSerapheim Dimitropoulos 4327*86714001SSerapheim Dimitropoulos if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) { 4328*86714001SSerapheim Dimitropoulos (void) printf(gettext(" scan warning: skipped blocks " 4329*86714001SSerapheim Dimitropoulos "that are only referenced by the checkpoint.\n")); 4330*86714001SSerapheim Dimitropoulos } else { 4331*86714001SSerapheim Dimitropoulos assert(ps->pss_state == DSS_SCANNING); 4332*86714001SSerapheim Dimitropoulos (void) printf(gettext(" scan warning: skipping blocks " 4333*86714001SSerapheim Dimitropoulos "that are only referenced by the checkpoint.\n")); 4334*86714001SSerapheim Dimitropoulos } 4335*86714001SSerapheim Dimitropoulos } 4336*86714001SSerapheim Dimitropoulos 43375cabbc6bSPrashanth Sreenivasa /* 43385cabbc6bSPrashanth Sreenivasa * Print out detailed removal status. 43395cabbc6bSPrashanth Sreenivasa */ 43405cabbc6bSPrashanth Sreenivasa static void 43415cabbc6bSPrashanth Sreenivasa print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs) 43425cabbc6bSPrashanth Sreenivasa { 43435cabbc6bSPrashanth Sreenivasa char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7]; 43445cabbc6bSPrashanth Sreenivasa time_t start, end; 43455cabbc6bSPrashanth Sreenivasa nvlist_t *config, *nvroot; 43465cabbc6bSPrashanth Sreenivasa nvlist_t **child; 43475cabbc6bSPrashanth Sreenivasa uint_t children; 43485cabbc6bSPrashanth Sreenivasa char *vdev_name; 43495cabbc6bSPrashanth Sreenivasa 43505cabbc6bSPrashanth Sreenivasa if (prs == NULL || prs->prs_state == DSS_NONE) 43515cabbc6bSPrashanth Sreenivasa return; 43525cabbc6bSPrashanth Sreenivasa 43535cabbc6bSPrashanth Sreenivasa /* 43545cabbc6bSPrashanth Sreenivasa * Determine name of vdev. 43555cabbc6bSPrashanth Sreenivasa */ 43565cabbc6bSPrashanth Sreenivasa config = zpool_get_config(zhp, NULL); 43575cabbc6bSPrashanth Sreenivasa nvroot = fnvlist_lookup_nvlist(config, 43585cabbc6bSPrashanth Sreenivasa ZPOOL_CONFIG_VDEV_TREE); 43595cabbc6bSPrashanth Sreenivasa verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 43605cabbc6bSPrashanth Sreenivasa &child, &children) == 0); 43615cabbc6bSPrashanth Sreenivasa assert(prs->prs_removing_vdev < children); 43625cabbc6bSPrashanth Sreenivasa vdev_name = zpool_vdev_name(g_zfs, zhp, 43635cabbc6bSPrashanth Sreenivasa child[prs->prs_removing_vdev], B_TRUE); 43645cabbc6bSPrashanth Sreenivasa 43655cabbc6bSPrashanth Sreenivasa (void) printf(gettext("remove: ")); 43665cabbc6bSPrashanth Sreenivasa 43675cabbc6bSPrashanth Sreenivasa start = prs->prs_start_time; 43685cabbc6bSPrashanth Sreenivasa end = prs->prs_end_time; 43695cabbc6bSPrashanth Sreenivasa zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf)); 43705cabbc6bSPrashanth Sreenivasa 43715cabbc6bSPrashanth Sreenivasa /* 43725cabbc6bSPrashanth Sreenivasa * Removal is finished or canceled. 43735cabbc6bSPrashanth Sreenivasa */ 43745cabbc6bSPrashanth Sreenivasa if (prs->prs_state == DSS_FINISHED) { 43755cabbc6bSPrashanth Sreenivasa uint64_t minutes_taken = (end - start) / 60; 43765cabbc6bSPrashanth Sreenivasa 43775cabbc6bSPrashanth Sreenivasa (void) printf(gettext("Removal of vdev %llu copied %s " 43785cabbc6bSPrashanth Sreenivasa "in %lluh%um, completed on %s"), 43795cabbc6bSPrashanth Sreenivasa (longlong_t)prs->prs_removing_vdev, 43805cabbc6bSPrashanth Sreenivasa copied_buf, 43815cabbc6bSPrashanth Sreenivasa (u_longlong_t)(minutes_taken / 60), 43825cabbc6bSPrashanth Sreenivasa (uint_t)(minutes_taken % 60), 43835cabbc6bSPrashanth Sreenivasa ctime((time_t *)&end)); 43845cabbc6bSPrashanth Sreenivasa } else if (prs->prs_state == DSS_CANCELED) { 43855cabbc6bSPrashanth Sreenivasa (void) printf(gettext("Removal of %s canceled on %s"), 43865cabbc6bSPrashanth Sreenivasa vdev_name, ctime(&end)); 43875cabbc6bSPrashanth Sreenivasa } else { 43885cabbc6bSPrashanth Sreenivasa uint64_t copied, total, elapsed, mins_left, hours_left; 43895cabbc6bSPrashanth Sreenivasa double fraction_done; 43905cabbc6bSPrashanth Sreenivasa uint_t rate; 43915cabbc6bSPrashanth Sreenivasa 43925cabbc6bSPrashanth Sreenivasa assert(prs->prs_state == DSS_SCANNING); 43935cabbc6bSPrashanth Sreenivasa 43945cabbc6bSPrashanth Sreenivasa /* 43955cabbc6bSPrashanth Sreenivasa * Removal is in progress. 43965cabbc6bSPrashanth Sreenivasa */ 43975cabbc6bSPrashanth Sreenivasa (void) printf(gettext( 43985cabbc6bSPrashanth Sreenivasa "Evacuation of %s in progress since %s"), 43995cabbc6bSPrashanth Sreenivasa vdev_name, ctime(&start)); 44005cabbc6bSPrashanth Sreenivasa 44015cabbc6bSPrashanth Sreenivasa copied = prs->prs_copied > 0 ? prs->prs_copied : 1; 44025cabbc6bSPrashanth Sreenivasa total = prs->prs_to_copy; 44035cabbc6bSPrashanth Sreenivasa fraction_done = (double)copied / total; 44045cabbc6bSPrashanth Sreenivasa 44055cabbc6bSPrashanth Sreenivasa /* elapsed time for this pass */ 44065cabbc6bSPrashanth Sreenivasa elapsed = time(NULL) - prs->prs_start_time; 44075cabbc6bSPrashanth Sreenivasa elapsed = elapsed > 0 ? elapsed : 1; 44085cabbc6bSPrashanth Sreenivasa rate = copied / elapsed; 44095cabbc6bSPrashanth Sreenivasa rate = rate > 0 ? rate : 1; 44105cabbc6bSPrashanth Sreenivasa mins_left = ((total - copied) / rate) / 60; 44115cabbc6bSPrashanth Sreenivasa hours_left = mins_left / 60; 44125cabbc6bSPrashanth Sreenivasa 44135cabbc6bSPrashanth Sreenivasa zfs_nicenum(copied, examined_buf, sizeof (examined_buf)); 44145cabbc6bSPrashanth Sreenivasa zfs_nicenum(total, total_buf, sizeof (total_buf)); 44155cabbc6bSPrashanth Sreenivasa zfs_nicenum(rate, rate_buf, sizeof (rate_buf)); 44165cabbc6bSPrashanth Sreenivasa 44175cabbc6bSPrashanth Sreenivasa /* 44185cabbc6bSPrashanth Sreenivasa * do not print estimated time if hours_left is more than 44195cabbc6bSPrashanth Sreenivasa * 30 days 44205cabbc6bSPrashanth Sreenivasa */ 44215cabbc6bSPrashanth Sreenivasa (void) printf(gettext(" %s copied out of %s at %s/s, " 44225cabbc6bSPrashanth Sreenivasa "%.2f%% done"), 44235cabbc6bSPrashanth Sreenivasa examined_buf, total_buf, rate_buf, 100 * fraction_done); 44245cabbc6bSPrashanth Sreenivasa if (hours_left < (30 * 24)) { 44255cabbc6bSPrashanth Sreenivasa (void) printf(gettext(", %lluh%um to go\n"), 44265cabbc6bSPrashanth Sreenivasa (u_longlong_t)hours_left, (uint_t)(mins_left % 60)); 44275cabbc6bSPrashanth Sreenivasa } else { 44285cabbc6bSPrashanth Sreenivasa (void) printf(gettext( 44295cabbc6bSPrashanth Sreenivasa ", (copy is slow, no estimated time)\n")); 44305cabbc6bSPrashanth Sreenivasa } 44315cabbc6bSPrashanth Sreenivasa } 44325cabbc6bSPrashanth Sreenivasa 44335cabbc6bSPrashanth Sreenivasa if (prs->prs_mapping_memory > 0) { 44345cabbc6bSPrashanth Sreenivasa char mem_buf[7]; 44355cabbc6bSPrashanth Sreenivasa zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf)); 44365cabbc6bSPrashanth Sreenivasa (void) printf(gettext(" %s memory used for " 44375cabbc6bSPrashanth Sreenivasa "removed device mappings\n"), 44385cabbc6bSPrashanth Sreenivasa mem_buf); 44395cabbc6bSPrashanth Sreenivasa } 44405cabbc6bSPrashanth Sreenivasa } 44415cabbc6bSPrashanth Sreenivasa 4442*86714001SSerapheim Dimitropoulos static void 4443*86714001SSerapheim Dimitropoulos print_checkpoint_status(pool_checkpoint_stat_t *pcs) 4444*86714001SSerapheim Dimitropoulos { 4445*86714001SSerapheim Dimitropoulos time_t start; 4446*86714001SSerapheim Dimitropoulos char space_buf[7]; 4447*86714001SSerapheim Dimitropoulos 4448*86714001SSerapheim Dimitropoulos if (pcs == NULL || pcs->pcs_state == CS_NONE) 4449*86714001SSerapheim Dimitropoulos return; 4450*86714001SSerapheim Dimitropoulos 4451*86714001SSerapheim Dimitropoulos (void) printf(gettext("checkpoint: ")); 4452*86714001SSerapheim Dimitropoulos 4453*86714001SSerapheim Dimitropoulos start = pcs->pcs_start_time; 4454*86714001SSerapheim Dimitropoulos zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf)); 4455*86714001SSerapheim Dimitropoulos 4456*86714001SSerapheim Dimitropoulos if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) { 4457*86714001SSerapheim Dimitropoulos char *date = ctime(&start); 4458*86714001SSerapheim Dimitropoulos 4459*86714001SSerapheim Dimitropoulos /* 4460*86714001SSerapheim Dimitropoulos * ctime() adds a newline at the end of the generated 4461*86714001SSerapheim Dimitropoulos * string, thus the weird format specifier and the 4462*86714001SSerapheim Dimitropoulos * strlen() call used to chop it off from the output. 4463*86714001SSerapheim Dimitropoulos */ 4464*86714001SSerapheim Dimitropoulos (void) printf(gettext("created %.*s, consumes %s\n"), 4465*86714001SSerapheim Dimitropoulos strlen(date) - 1, date, space_buf); 4466*86714001SSerapheim Dimitropoulos return; 4467*86714001SSerapheim Dimitropoulos } 4468*86714001SSerapheim Dimitropoulos 4469*86714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 4470*86714001SSerapheim Dimitropoulos 4471*86714001SSerapheim Dimitropoulos (void) printf(gettext("discarding, %s remaining.\n"), 4472*86714001SSerapheim Dimitropoulos space_buf); 4473*86714001SSerapheim Dimitropoulos } 4474*86714001SSerapheim Dimitropoulos 4475ea8dc4b6Seschrock static void 4476ea8dc4b6Seschrock print_error_log(zpool_handle_t *zhp) 4477ea8dc4b6Seschrock { 447875519f38Sek nvlist_t *nverrlist = NULL; 447955434c77Sek nvpair_t *elem; 448055434c77Sek char *pathname; 448155434c77Sek size_t len = MAXPATHLEN * 2; 4482ea8dc4b6Seschrock 448355434c77Sek if (zpool_get_errlog(zhp, &nverrlist) != 0) { 4484ea8dc4b6Seschrock (void) printf("errors: List of errors unavailable " 4485ea8dc4b6Seschrock "(insufficient privileges)\n"); 4486ea8dc4b6Seschrock return; 4487ea8dc4b6Seschrock } 4488ea8dc4b6Seschrock 448955434c77Sek (void) printf("errors: Permanent errors have been " 449055434c77Sek "detected in the following files:\n\n"); 4491ea8dc4b6Seschrock 449255434c77Sek pathname = safe_malloc(len); 449355434c77Sek elem = NULL; 449455434c77Sek while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 449555434c77Sek nvlist_t *nv; 449655434c77Sek uint64_t dsobj, obj; 449755434c77Sek 449855434c77Sek verify(nvpair_value_nvlist(elem, &nv) == 0); 449955434c77Sek verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 450055434c77Sek &dsobj) == 0); 450155434c77Sek verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 450255434c77Sek &obj) == 0); 450355434c77Sek zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 450455434c77Sek (void) printf("%7s %s\n", "", pathname); 450555434c77Sek } 450655434c77Sek free(pathname); 450755434c77Sek nvlist_free(nverrlist); 4508ea8dc4b6Seschrock } 4509ea8dc4b6Seschrock 451099653d4eSeschrock static void 451199653d4eSeschrock print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares, 451299653d4eSeschrock int namewidth) 451399653d4eSeschrock { 451499653d4eSeschrock uint_t i; 451599653d4eSeschrock char *name; 451699653d4eSeschrock 451799653d4eSeschrock if (nspares == 0) 451899653d4eSeschrock return; 451999653d4eSeschrock 452099653d4eSeschrock (void) printf(gettext("\tspares\n")); 452199653d4eSeschrock 452299653d4eSeschrock for (i = 0; i < nspares; i++) { 452388ecc943SGeorge Wilson name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE); 452499653d4eSeschrock print_status_config(zhp, name, spares[i], 4525aa8cf21aSNeil Perrin namewidth, 2, B_TRUE); 452699653d4eSeschrock free(name); 452799653d4eSeschrock } 452899653d4eSeschrock } 452999653d4eSeschrock 4530fa94a07fSbrendan static void 4531fa94a07fSbrendan print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache, 4532fa94a07fSbrendan int namewidth) 4533fa94a07fSbrendan { 4534fa94a07fSbrendan uint_t i; 4535fa94a07fSbrendan char *name; 4536fa94a07fSbrendan 4537fa94a07fSbrendan if (nl2cache == 0) 4538fa94a07fSbrendan return; 4539fa94a07fSbrendan 4540fa94a07fSbrendan (void) printf(gettext("\tcache\n")); 4541fa94a07fSbrendan 4542fa94a07fSbrendan for (i = 0; i < nl2cache; i++) { 454388ecc943SGeorge Wilson name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE); 4544fa94a07fSbrendan print_status_config(zhp, name, l2cache[i], 4545aa8cf21aSNeil Perrin namewidth, 2, B_FALSE); 4546aa8cf21aSNeil Perrin free(name); 4547aa8cf21aSNeil Perrin } 4548aa8cf21aSNeil Perrin } 4549aa8cf21aSNeil Perrin 45509eb19f4dSGeorge Wilson static void 45519eb19f4dSGeorge Wilson print_dedup_stats(nvlist_t *config) 45529eb19f4dSGeorge Wilson { 45539eb19f4dSGeorge Wilson ddt_histogram_t *ddh; 45549eb19f4dSGeorge Wilson ddt_stat_t *dds; 45559eb19f4dSGeorge Wilson ddt_object_t *ddo; 45569eb19f4dSGeorge Wilson uint_t c; 45579eb19f4dSGeorge Wilson 45589eb19f4dSGeorge Wilson /* 45599eb19f4dSGeorge Wilson * If the pool was faulted then we may not have been able to 45602384d9f8SGeorge Wilson * obtain the config. Otherwise, if we have anything in the dedup 45619eb19f4dSGeorge Wilson * table continue processing the stats. 45629eb19f4dSGeorge Wilson */ 45639eb19f4dSGeorge Wilson if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS, 4564ce72e614SYuri Pankov (uint64_t **)&ddo, &c) != 0) 45659eb19f4dSGeorge Wilson return; 45669eb19f4dSGeorge Wilson 45679eb19f4dSGeorge Wilson (void) printf("\n"); 4568ce72e614SYuri Pankov (void) printf(gettext(" dedup: ")); 4569ce72e614SYuri Pankov if (ddo->ddo_count == 0) { 4570ce72e614SYuri Pankov (void) printf(gettext("no DDT entries\n")); 4571ce72e614SYuri Pankov return; 4572ce72e614SYuri Pankov } 4573ce72e614SYuri Pankov 45749eb19f4dSGeorge Wilson (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n", 45759eb19f4dSGeorge Wilson (u_longlong_t)ddo->ddo_count, 45769eb19f4dSGeorge Wilson (u_longlong_t)ddo->ddo_dspace, 45779eb19f4dSGeorge Wilson (u_longlong_t)ddo->ddo_mspace); 45789eb19f4dSGeorge Wilson 45799eb19f4dSGeorge Wilson verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS, 45809eb19f4dSGeorge Wilson (uint64_t **)&dds, &c) == 0); 45819eb19f4dSGeorge Wilson verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM, 45829eb19f4dSGeorge Wilson (uint64_t **)&ddh, &c) == 0); 45839eb19f4dSGeorge Wilson zpool_dump_ddt(dds, ddh); 45849eb19f4dSGeorge Wilson } 45859eb19f4dSGeorge Wilson 4586fa9e4066Sahrens /* 4587fa9e4066Sahrens * Display a summary of pool status. Displays a summary such as: 4588fa9e4066Sahrens * 4589fa9e4066Sahrens * pool: tank 4590fa9e4066Sahrens * status: DEGRADED 4591fa9e4066Sahrens * reason: One or more devices ... 4592654b400cSJoshua M. Clulow * see: http://illumos.org/msg/ZFS-xxxx-01 4593fa9e4066Sahrens * config: 4594fa9e4066Sahrens * mirror DEGRADED 4595fa9e4066Sahrens * c1t0d0 OK 4596ea8dc4b6Seschrock * c2t0d0 UNAVAIL 4597fa9e4066Sahrens * 4598fa9e4066Sahrens * When given the '-v' option, we print out the complete config. If the '-e' 4599fa9e4066Sahrens * option is specified, then we print out error rate information as well. 4600fa9e4066Sahrens */ 4601fa9e4066Sahrens int 4602fa9e4066Sahrens status_callback(zpool_handle_t *zhp, void *data) 4603fa9e4066Sahrens { 4604fa9e4066Sahrens status_cbdata_t *cbp = data; 4605fa9e4066Sahrens nvlist_t *config, *nvroot; 4606fa9e4066Sahrens char *msgid; 4607fa9e4066Sahrens int reason; 460846657f8dSmmusante const char *health; 460946657f8dSmmusante uint_t c; 461046657f8dSmmusante vdev_stat_t *vs; 4611fa9e4066Sahrens 4612088e9d47Seschrock config = zpool_get_config(zhp, NULL); 4613fa9e4066Sahrens reason = zpool_get_status(zhp, &msgid); 4614fa9e4066Sahrens 4615fa9e4066Sahrens cbp->cb_count++; 4616fa9e4066Sahrens 4617fa9e4066Sahrens /* 4618fa9e4066Sahrens * If we were given 'zpool status -x', only report those pools with 4619fa9e4066Sahrens * problems. 4620fa9e4066Sahrens */ 4621b3a6f804STim Connors if (cbp->cb_explain && 4622b3a6f804STim Connors (reason == ZPOOL_STATUS_OK || 4623b3a6f804STim Connors reason == ZPOOL_STATUS_VERSION_OLDER || 4624b3a6f804STim Connors reason == ZPOOL_STATUS_FEAT_DISABLED)) { 4625e9dbad6fSeschrock if (!cbp->cb_allpools) { 4626e9dbad6fSeschrock (void) printf(gettext("pool '%s' is healthy\n"), 4627e9dbad6fSeschrock zpool_get_name(zhp)); 4628e9dbad6fSeschrock if (cbp->cb_first) 4629e9dbad6fSeschrock cbp->cb_first = B_FALSE; 4630e9dbad6fSeschrock } 4631fa9e4066Sahrens return (0); 4632e9dbad6fSeschrock } 4633fa9e4066Sahrens 4634fa9e4066Sahrens if (cbp->cb_first) 463599653d4eSeschrock cbp->cb_first = B_FALSE; 4636fa9e4066Sahrens else 4637fa9e4066Sahrens (void) printf("\n"); 4638fa9e4066Sahrens 46395cabbc6bSPrashanth Sreenivasa nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 46403f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 464146657f8dSmmusante (uint64_t **)&vs, &c) == 0); 4642990b4856Slling health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 4643fa9e4066Sahrens 4644fa9e4066Sahrens (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 4645fa9e4066Sahrens (void) printf(gettext(" state: %s\n"), health); 4646fa9e4066Sahrens 4647fa9e4066Sahrens switch (reason) { 4648fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_R: 4649fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 4650fa9e4066Sahrens "be opened. Sufficient replicas exist for\n\tthe pool to " 4651fa9e4066Sahrens "continue functioning in a degraded state.\n")); 4652fa9e4066Sahrens (void) printf(gettext("action: Attach the missing device and " 4653fa9e4066Sahrens "online it using 'zpool online'.\n")); 4654fa9e4066Sahrens break; 4655fa9e4066Sahrens 4656fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_NR: 4657fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 4658fa9e4066Sahrens "be opened. There are insufficient\n\treplicas for the " 4659fa9e4066Sahrens "pool to continue functioning.\n")); 4660fa9e4066Sahrens (void) printf(gettext("action: Attach the missing device and " 4661fa9e4066Sahrens "online it using 'zpool online'.\n")); 4662fa9e4066Sahrens break; 4663fa9e4066Sahrens 4664fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_R: 4665fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 4666fa9e4066Sahrens "be used because the label is missing or\n\tinvalid. " 4667fa9e4066Sahrens "Sufficient replicas exist for the pool to continue\n\t" 4668fa9e4066Sahrens "functioning in a degraded state.\n")); 4669fa9e4066Sahrens (void) printf(gettext("action: Replace the device using " 4670fa9e4066Sahrens "'zpool replace'.\n")); 4671fa9e4066Sahrens break; 4672fa9e4066Sahrens 4673fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_NR: 4674fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 4675b1b8ab34Slling "be used because the label is missing \n\tor invalid. " 4676fa9e4066Sahrens "There are insufficient replicas for the pool to " 4677fa9e4066Sahrens "continue\n\tfunctioning.\n")); 4678468c413aSTim Haley zpool_explain_recover(zpool_get_handle(zhp), 4679468c413aSTim Haley zpool_get_name(zhp), reason, config); 4680fa9e4066Sahrens break; 4681fa9e4066Sahrens 4682fa9e4066Sahrens case ZPOOL_STATUS_FAILING_DEV: 4683fa9e4066Sahrens (void) printf(gettext("status: One or more devices has " 4684fa9e4066Sahrens "experienced an unrecoverable error. An\n\tattempt was " 4685fa9e4066Sahrens "made to correct the error. Applications are " 4686fa9e4066Sahrens "unaffected.\n")); 4687fa9e4066Sahrens (void) printf(gettext("action: Determine if the device needs " 4688fa9e4066Sahrens "to be replaced, and clear the errors\n\tusing " 4689ea8dc4b6Seschrock "'zpool clear' or replace the device with 'zpool " 4690fa9e4066Sahrens "replace'.\n")); 4691fa9e4066Sahrens break; 4692fa9e4066Sahrens 4693fa9e4066Sahrens case ZPOOL_STATUS_OFFLINE_DEV: 4694fa9e4066Sahrens (void) printf(gettext("status: One or more devices has " 4695d7d4af51Smmusante "been taken offline by the administrator.\n\tSufficient " 4696fa9e4066Sahrens "replicas exist for the pool to continue functioning in " 4697fa9e4066Sahrens "a\n\tdegraded state.\n")); 4698fa9e4066Sahrens (void) printf(gettext("action: Online the device using " 4699fa9e4066Sahrens "'zpool online' or replace the device with\n\t'zpool " 4700fa9e4066Sahrens "replace'.\n")); 4701fa9e4066Sahrens break; 4702fa9e4066Sahrens 4703c25309d4SGeorge Wilson case ZPOOL_STATUS_REMOVED_DEV: 4704c25309d4SGeorge Wilson (void) printf(gettext("status: One or more devices has " 4705c25309d4SGeorge Wilson "been removed by the administrator.\n\tSufficient " 4706c25309d4SGeorge Wilson "replicas exist for the pool to continue functioning in " 4707c25309d4SGeorge Wilson "a\n\tdegraded state.\n")); 4708c25309d4SGeorge Wilson (void) printf(gettext("action: Online the device using " 4709c25309d4SGeorge Wilson "'zpool online' or replace the device with\n\t'zpool " 4710c25309d4SGeorge Wilson "replace'.\n")); 4711c25309d4SGeorge Wilson break; 4712c25309d4SGeorge Wilson 4713fa9e4066Sahrens case ZPOOL_STATUS_RESILVERING: 4714fa9e4066Sahrens (void) printf(gettext("status: One or more devices is " 4715fa9e4066Sahrens "currently being resilvered. The pool will\n\tcontinue " 4716fa9e4066Sahrens "to function, possibly in a degraded state.\n")); 4717fa9e4066Sahrens (void) printf(gettext("action: Wait for the resilver to " 4718fa9e4066Sahrens "complete.\n")); 4719fa9e4066Sahrens break; 4720fa9e4066Sahrens 4721ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_DATA: 4722ea8dc4b6Seschrock (void) printf(gettext("status: One or more devices has " 4723ea8dc4b6Seschrock "experienced an error resulting in data\n\tcorruption. " 4724ea8dc4b6Seschrock "Applications may be affected.\n")); 4725ea8dc4b6Seschrock (void) printf(gettext("action: Restore the file in question " 4726ea8dc4b6Seschrock "if possible. Otherwise restore the\n\tentire pool from " 4727ea8dc4b6Seschrock "backup.\n")); 4728ea8dc4b6Seschrock break; 4729ea8dc4b6Seschrock 4730ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_POOL: 4731ea8dc4b6Seschrock (void) printf(gettext("status: The pool metadata is corrupted " 4732ea8dc4b6Seschrock "and the pool cannot be opened.\n")); 4733468c413aSTim Haley zpool_explain_recover(zpool_get_handle(zhp), 4734468c413aSTim Haley zpool_get_name(zhp), reason, config); 4735ea8dc4b6Seschrock break; 4736ea8dc4b6Seschrock 4737eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_OLDER: 473857221772SChristopher Siden (void) printf(gettext("status: The pool is formatted using a " 473957221772SChristopher Siden "legacy on-disk format. The pool can\n\tstill be used, " 474057221772SChristopher Siden "but some features are unavailable.\n")); 4741eaca9bbdSeschrock (void) printf(gettext("action: Upgrade the pool using 'zpool " 4742eaca9bbdSeschrock "upgrade'. Once this is done, the\n\tpool will no longer " 474357221772SChristopher Siden "be accessible on software that does not support feature\n" 474457221772SChristopher Siden "\tflags.\n")); 4745eaca9bbdSeschrock break; 4746eaca9bbdSeschrock 4747eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 4748eaca9bbdSeschrock (void) printf(gettext("status: The pool has been upgraded to a " 4749eaca9bbdSeschrock "newer, incompatible on-disk version.\n\tThe pool cannot " 4750eaca9bbdSeschrock "be accessed on this system.\n")); 4751eaca9bbdSeschrock (void) printf(gettext("action: Access the pool from a system " 4752eaca9bbdSeschrock "running more recent software, or\n\trestore the pool from " 4753eaca9bbdSeschrock "backup.\n")); 4754eaca9bbdSeschrock break; 4755eaca9bbdSeschrock 475657221772SChristopher Siden case ZPOOL_STATUS_FEAT_DISABLED: 475757221772SChristopher Siden (void) printf(gettext("status: Some supported features are not " 475857221772SChristopher Siden "enabled on the pool. The pool can\n\tstill be used, but " 475957221772SChristopher Siden "some features are unavailable.\n")); 476057221772SChristopher Siden (void) printf(gettext("action: Enable all features using " 476157221772SChristopher Siden "'zpool upgrade'. Once this is done,\n\tthe pool may no " 476257221772SChristopher Siden "longer be accessible by software that does not support\n\t" 476357221772SChristopher Siden "the features. See zpool-features(5) for details.\n")); 476457221772SChristopher Siden break; 476557221772SChristopher Siden 4766ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ: 4767ad135b5dSChristopher Siden (void) printf(gettext("status: The pool cannot be accessed on " 4768ad135b5dSChristopher Siden "this system because it uses the\n\tfollowing feature(s) " 4769ad135b5dSChristopher Siden "not supported on this system:\n")); 4770ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 4771ad135b5dSChristopher Siden (void) printf("\n"); 4772ad135b5dSChristopher Siden (void) printf(gettext("action: Access the pool from a system " 4773ad135b5dSChristopher Siden "that supports the required feature(s),\n\tor restore the " 4774ad135b5dSChristopher Siden "pool from backup.\n")); 4775ad135b5dSChristopher Siden break; 4776ad135b5dSChristopher Siden 4777ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 4778ad135b5dSChristopher Siden (void) printf(gettext("status: The pool can only be accessed " 4779ad135b5dSChristopher Siden "in read-only mode on this system. It\n\tcannot be " 4780ad135b5dSChristopher Siden "accessed in read-write mode because it uses the " 4781ad135b5dSChristopher Siden "following\n\tfeature(s) not supported on this system:\n")); 4782ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 4783ad135b5dSChristopher Siden (void) printf("\n"); 4784ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be accessed in " 4785ad135b5dSChristopher Siden "read-write mode. Import the pool with\n" 4786ad135b5dSChristopher Siden "\t\"-o readonly=on\", access the pool from a system that " 4787ad135b5dSChristopher Siden "supports the\n\trequired feature(s), or restore the " 4788ad135b5dSChristopher Siden "pool from backup.\n")); 4789ad135b5dSChristopher Siden break; 4790ad135b5dSChristopher Siden 47913d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_R: 47923d7072f8Seschrock (void) printf(gettext("status: One or more devices are " 47933d7072f8Seschrock "faulted in response to persistent errors.\n\tSufficient " 47943d7072f8Seschrock "replicas exist for the pool to continue functioning " 47953d7072f8Seschrock "in a\n\tdegraded state.\n")); 47963d7072f8Seschrock (void) printf(gettext("action: Replace the faulted device, " 47973d7072f8Seschrock "or use 'zpool clear' to mark the device\n\trepaired.\n")); 47983d7072f8Seschrock break; 47993d7072f8Seschrock 48003d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_NR: 48013d7072f8Seschrock (void) printf(gettext("status: One or more devices are " 48023d7072f8Seschrock "faulted in response to persistent errors. There are " 48033d7072f8Seschrock "insufficient replicas for the pool to\n\tcontinue " 48043d7072f8Seschrock "functioning.\n")); 48053d7072f8Seschrock (void) printf(gettext("action: Destroy and re-create the pool " 48063d7072f8Seschrock "from a backup source. Manually marking the device\n" 48073d7072f8Seschrock "\trepaired using 'zpool clear' may allow some data " 48083d7072f8Seschrock "to be recovered.\n")); 48093d7072f8Seschrock break; 48103d7072f8Seschrock 481132b87932Sek case ZPOOL_STATUS_IO_FAILURE_WAIT: 481232b87932Sek case ZPOOL_STATUS_IO_FAILURE_CONTINUE: 481332b87932Sek (void) printf(gettext("status: One or more devices are " 48148a79c1b5Sek "faulted in response to IO failures.\n")); 481532b87932Sek (void) printf(gettext("action: Make sure the affected devices " 481632b87932Sek "are connected, then run 'zpool clear'.\n")); 481732b87932Sek break; 481832b87932Sek 4819b87f3af3Sperrin case ZPOOL_STATUS_BAD_LOG: 4820b87f3af3Sperrin (void) printf(gettext("status: An intent log record " 4821b87f3af3Sperrin "could not be read.\n" 4822b87f3af3Sperrin "\tWaiting for adminstrator intervention to fix the " 4823b87f3af3Sperrin "faulted pool.\n")); 4824b87f3af3Sperrin (void) printf(gettext("action: Either restore the affected " 4825b87f3af3Sperrin "device(s) and run 'zpool online',\n" 4826b87f3af3Sperrin "\tor ignore the intent log records by running " 4827b87f3af3Sperrin "'zpool clear'.\n")); 4828b87f3af3Sperrin break; 4829b87f3af3Sperrin 4830fa9e4066Sahrens default: 4831fa9e4066Sahrens /* 4832fa9e4066Sahrens * The remaining errors can't actually be generated, yet. 4833fa9e4066Sahrens */ 4834fa9e4066Sahrens assert(reason == ZPOOL_STATUS_OK); 4835fa9e4066Sahrens } 4836fa9e4066Sahrens 4837fa9e4066Sahrens if (msgid != NULL) 4838654b400cSJoshua M. Clulow (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 4839fa9e4066Sahrens msgid); 4840fa9e4066Sahrens 4841fa9e4066Sahrens if (config != NULL) { 4842fa9e4066Sahrens int namewidth; 4843ea8dc4b6Seschrock uint64_t nerr; 4844fa94a07fSbrendan nvlist_t **spares, **l2cache; 4845fa94a07fSbrendan uint_t nspares, nl2cache; 4846*86714001SSerapheim Dimitropoulos pool_checkpoint_stat_t *pcs = NULL; 48473f9d6ad7SLin Ling pool_scan_stat_t *ps = NULL; 48485cabbc6bSPrashanth Sreenivasa pool_removal_stat_t *prs = NULL; 4849fa9e4066Sahrens 4850*86714001SSerapheim Dimitropoulos (void) nvlist_lookup_uint64_array(nvroot, 4851*86714001SSerapheim Dimitropoulos ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 48523f9d6ad7SLin Ling (void) nvlist_lookup_uint64_array(nvroot, 48533f9d6ad7SLin Ling ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c); 48545cabbc6bSPrashanth Sreenivasa (void) nvlist_lookup_uint64_array(nvroot, 48555cabbc6bSPrashanth Sreenivasa ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c); 4856*86714001SSerapheim Dimitropoulos 4857*86714001SSerapheim Dimitropoulos print_scan_status(ps); 4858*86714001SSerapheim Dimitropoulos print_checkpoint_scan_warning(ps, pcs); 48595cabbc6bSPrashanth Sreenivasa print_removal_status(zhp, prs); 4860*86714001SSerapheim Dimitropoulos print_checkpoint_status(pcs); 48615cabbc6bSPrashanth Sreenivasa 4862c67d9675Seschrock namewidth = max_width(zhp, nvroot, 0, 0); 4863fa9e4066Sahrens if (namewidth < 10) 4864fa9e4066Sahrens namewidth = 10; 4865fa9e4066Sahrens 4866fa9e4066Sahrens (void) printf(gettext("config:\n\n")); 4867fa9e4066Sahrens (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth, 4868fa9e4066Sahrens "NAME", "STATE", "READ", "WRITE", "CKSUM"); 4869c67d9675Seschrock print_status_config(zhp, zpool_get_name(zhp), nvroot, 4870aa8cf21aSNeil Perrin namewidth, 0, B_FALSE); 487199653d4eSeschrock 48724dea40f0SNeil Perrin if (num_logs(nvroot) > 0) 4873e6ca193dSGeorge Wilson print_logs(zhp, nvroot, namewidth, B_TRUE); 4874fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 4875fa94a07fSbrendan &l2cache, &nl2cache) == 0) 4876fa94a07fSbrendan print_l2cache(zhp, l2cache, nl2cache, namewidth); 4877fa94a07fSbrendan 487899653d4eSeschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 487999653d4eSeschrock &spares, &nspares) == 0) 488099653d4eSeschrock print_spares(zhp, spares, nspares, namewidth); 4881ea8dc4b6Seschrock 4882ea8dc4b6Seschrock if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 4883ea8dc4b6Seschrock &nerr) == 0) { 488455434c77Sek nvlist_t *nverrlist = NULL; 488555434c77Sek 4886ea8dc4b6Seschrock /* 4887ea8dc4b6Seschrock * If the approximate error count is small, get a 4888ea8dc4b6Seschrock * precise count by fetching the entire log and 4889ea8dc4b6Seschrock * uniquifying the results. 4890ea8dc4b6Seschrock */ 489175519f38Sek if (nerr > 0 && nerr < 100 && !cbp->cb_verbose && 489255434c77Sek zpool_get_errlog(zhp, &nverrlist) == 0) { 489355434c77Sek nvpair_t *elem; 489455434c77Sek 489555434c77Sek elem = NULL; 489655434c77Sek nerr = 0; 489755434c77Sek while ((elem = nvlist_next_nvpair(nverrlist, 489855434c77Sek elem)) != NULL) { 489955434c77Sek nerr++; 490055434c77Sek } 490155434c77Sek } 490255434c77Sek nvlist_free(nverrlist); 4903ea8dc4b6Seschrock 4904ea8dc4b6Seschrock (void) printf("\n"); 490599653d4eSeschrock 4906ea8dc4b6Seschrock if (nerr == 0) 4907ea8dc4b6Seschrock (void) printf(gettext("errors: No known data " 4908ea8dc4b6Seschrock "errors\n")); 4909ea8dc4b6Seschrock else if (!cbp->cb_verbose) 4910e9dbad6fSeschrock (void) printf(gettext("errors: %llu data " 49115ad82045Snd "errors, use '-v' for a list\n"), 49125ad82045Snd (u_longlong_t)nerr); 4913ea8dc4b6Seschrock else 4914ea8dc4b6Seschrock print_error_log(zhp); 4915ea8dc4b6Seschrock } 49169eb19f4dSGeorge Wilson 49179eb19f4dSGeorge Wilson if (cbp->cb_dedup_stats) 49189eb19f4dSGeorge Wilson print_dedup_stats(config); 4919fa9e4066Sahrens } else { 4920fa9e4066Sahrens (void) printf(gettext("config: The configuration cannot be " 4921fa9e4066Sahrens "determined.\n")); 4922fa9e4066Sahrens } 4923fa9e4066Sahrens 4924fa9e4066Sahrens return (0); 4925fa9e4066Sahrens } 4926fa9e4066Sahrens 4927fa9e4066Sahrens /* 49283f9d6ad7SLin Ling * zpool status [-vx] [-T d|u] [pool] ... [interval [count]] 4929fa9e4066Sahrens * 4930fa9e4066Sahrens * -v Display complete error logs 4931fa9e4066Sahrens * -x Display only pools with potential problems 49329eb19f4dSGeorge Wilson * -D Display dedup status (undocumented) 49333f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format 4934fa9e4066Sahrens * 4935fa9e4066Sahrens * Describes the health status of all pools or some subset. 4936fa9e4066Sahrens */ 4937fa9e4066Sahrens int 4938fa9e4066Sahrens zpool_do_status(int argc, char **argv) 4939fa9e4066Sahrens { 4940fa9e4066Sahrens int c; 4941fa9e4066Sahrens int ret; 49423f9d6ad7SLin Ling unsigned long interval = 0, count = 0; 4943fa9e4066Sahrens status_cbdata_t cb = { 0 }; 4944fa9e4066Sahrens 4945fa9e4066Sahrens /* check options */ 49463f9d6ad7SLin Ling while ((c = getopt(argc, argv, "vxDT:")) != -1) { 4947fa9e4066Sahrens switch (c) { 4948fa9e4066Sahrens case 'v': 494999653d4eSeschrock cb.cb_verbose = B_TRUE; 4950fa9e4066Sahrens break; 4951fa9e4066Sahrens case 'x': 495299653d4eSeschrock cb.cb_explain = B_TRUE; 4953fa9e4066Sahrens break; 49549eb19f4dSGeorge Wilson case 'D': 49559eb19f4dSGeorge Wilson cb.cb_dedup_stats = B_TRUE; 49569eb19f4dSGeorge Wilson break; 49573f9d6ad7SLin Ling case 'T': 49583f9d6ad7SLin Ling get_timestamp_arg(*optarg); 49593f9d6ad7SLin Ling break; 4960fa9e4066Sahrens case '?': 4961fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4962fa9e4066Sahrens optopt); 496399653d4eSeschrock usage(B_FALSE); 4964fa9e4066Sahrens } 4965fa9e4066Sahrens } 4966fa9e4066Sahrens 4967fa9e4066Sahrens argc -= optind; 4968fa9e4066Sahrens argv += optind; 4969fa9e4066Sahrens 49703f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count); 4971fa9e4066Sahrens 4972e9dbad6fSeschrock if (argc == 0) 4973e9dbad6fSeschrock cb.cb_allpools = B_TRUE; 4974e9dbad6fSeschrock 49753f9d6ad7SLin Ling cb.cb_first = B_TRUE; 4976fa9e4066Sahrens 49773f9d6ad7SLin Ling for (;;) { 49783f9d6ad7SLin Ling if (timestamp_fmt != NODATE) 49793f9d6ad7SLin Ling print_timestamp(timestamp_fmt); 4980fa9e4066Sahrens 49813f9d6ad7SLin Ling ret = for_each_pool(argc, argv, B_TRUE, NULL, 49823f9d6ad7SLin Ling status_callback, &cb); 49833f9d6ad7SLin Ling 49843f9d6ad7SLin Ling if (argc == 0 && cb.cb_count == 0) 49853f9d6ad7SLin Ling (void) printf(gettext("no pools available\n")); 49863f9d6ad7SLin Ling else if (cb.cb_explain && cb.cb_first && cb.cb_allpools) 49873f9d6ad7SLin Ling (void) printf(gettext("all pools are healthy\n")); 49883f9d6ad7SLin Ling 49893f9d6ad7SLin Ling if (ret != 0) 49903f9d6ad7SLin Ling return (ret); 49913f9d6ad7SLin Ling 49923f9d6ad7SLin Ling if (interval == 0) 49933f9d6ad7SLin Ling break; 49943f9d6ad7SLin Ling 49953f9d6ad7SLin Ling if (count != 0 && --count == 0) 49963f9d6ad7SLin Ling break; 49973f9d6ad7SLin Ling 49983f9d6ad7SLin Ling (void) sleep(interval); 49993f9d6ad7SLin Ling } 50003f9d6ad7SLin Ling 50013f9d6ad7SLin Ling return (0); 5002fa9e4066Sahrens } 5003fa9e4066Sahrens 5004eaca9bbdSeschrock typedef struct upgrade_cbdata { 5005eaca9bbdSeschrock int cb_first; 500606eeb2adSek int cb_argc; 5007990b4856Slling uint64_t cb_version; 500806eeb2adSek char **cb_argv; 5009eaca9bbdSeschrock } upgrade_cbdata_t; 5010eaca9bbdSeschrock 501157221772SChristopher Siden static int 501257221772SChristopher Siden upgrade_version(zpool_handle_t *zhp, uint64_t version) 501357221772SChristopher Siden { 501457221772SChristopher Siden int ret; 501557221772SChristopher Siden nvlist_t *config; 501657221772SChristopher Siden uint64_t oldversion; 501757221772SChristopher Siden 501857221772SChristopher Siden config = zpool_get_config(zhp, NULL); 501957221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 502057221772SChristopher Siden &oldversion) == 0); 502157221772SChristopher Siden 502257221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(oldversion)); 502357221772SChristopher Siden assert(oldversion < version); 502457221772SChristopher Siden 502557221772SChristopher Siden ret = zpool_upgrade(zhp, version); 502657221772SChristopher Siden if (ret != 0) 502757221772SChristopher Siden return (ret); 502857221772SChristopher Siden 502957221772SChristopher Siden if (version >= SPA_VERSION_FEATURES) { 503057221772SChristopher Siden (void) printf(gettext("Successfully upgraded " 503157221772SChristopher Siden "'%s' from version %llu to feature flags.\n"), 503257221772SChristopher Siden zpool_get_name(zhp), oldversion); 503357221772SChristopher Siden } else { 503457221772SChristopher Siden (void) printf(gettext("Successfully upgraded " 503557221772SChristopher Siden "'%s' from version %llu to version %llu.\n"), 503657221772SChristopher Siden zpool_get_name(zhp), oldversion, version); 503757221772SChristopher Siden } 503857221772SChristopher Siden 503957221772SChristopher Siden return (0); 504057221772SChristopher Siden } 504157221772SChristopher Siden 504257221772SChristopher Siden static int 504357221772SChristopher Siden upgrade_enable_all(zpool_handle_t *zhp, int *countp) 504457221772SChristopher Siden { 504557221772SChristopher Siden int i, ret, count; 504657221772SChristopher Siden boolean_t firstff = B_TRUE; 504757221772SChristopher Siden nvlist_t *enabled = zpool_get_features(zhp); 504857221772SChristopher Siden 504957221772SChristopher Siden count = 0; 505057221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 505157221772SChristopher Siden const char *fname = spa_feature_table[i].fi_uname; 505257221772SChristopher Siden const char *fguid = spa_feature_table[i].fi_guid; 505357221772SChristopher Siden if (!nvlist_exists(enabled, fguid)) { 505457221772SChristopher Siden char *propname; 505557221772SChristopher Siden verify(-1 != asprintf(&propname, "feature@%s", fname)); 505657221772SChristopher Siden ret = zpool_set_prop(zhp, propname, 505757221772SChristopher Siden ZFS_FEATURE_ENABLED); 505857221772SChristopher Siden if (ret != 0) { 505957221772SChristopher Siden free(propname); 506057221772SChristopher Siden return (ret); 506157221772SChristopher Siden } 506257221772SChristopher Siden count++; 506357221772SChristopher Siden 506457221772SChristopher Siden if (firstff) { 506557221772SChristopher Siden (void) printf(gettext("Enabled the " 506657221772SChristopher Siden "following features on '%s':\n"), 506757221772SChristopher Siden zpool_get_name(zhp)); 506857221772SChristopher Siden firstff = B_FALSE; 506957221772SChristopher Siden } 507057221772SChristopher Siden (void) printf(gettext(" %s\n"), fname); 507157221772SChristopher Siden free(propname); 507257221772SChristopher Siden } 507357221772SChristopher Siden } 507457221772SChristopher Siden 507557221772SChristopher Siden if (countp != NULL) 507657221772SChristopher Siden *countp = count; 507757221772SChristopher Siden return (0); 507857221772SChristopher Siden } 507957221772SChristopher Siden 5080eaca9bbdSeschrock static int 5081eaca9bbdSeschrock upgrade_cb(zpool_handle_t *zhp, void *arg) 5082eaca9bbdSeschrock { 5083eaca9bbdSeschrock upgrade_cbdata_t *cbp = arg; 5084eaca9bbdSeschrock nvlist_t *config; 5085eaca9bbdSeschrock uint64_t version; 508657221772SChristopher Siden boolean_t printnl = B_FALSE; 508757221772SChristopher Siden int ret; 5088eaca9bbdSeschrock 5089eaca9bbdSeschrock config = zpool_get_config(zhp, NULL); 5090eaca9bbdSeschrock verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 5091eaca9bbdSeschrock &version) == 0); 5092eaca9bbdSeschrock 509357221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(version)); 5094eaca9bbdSeschrock 509557221772SChristopher Siden if (version < cbp->cb_version) { 509657221772SChristopher Siden cbp->cb_first = B_FALSE; 509757221772SChristopher Siden ret = upgrade_version(zhp, cbp->cb_version); 509857221772SChristopher Siden if (ret != 0) 509957221772SChristopher Siden return (ret); 510057221772SChristopher Siden printnl = B_TRUE; 510157221772SChristopher Siden 510257221772SChristopher Siden /* 510357221772SChristopher Siden * If they did "zpool upgrade -a", then we could 510457221772SChristopher Siden * be doing ioctls to different pools. We need 510557221772SChristopher Siden * to log this history once to each pool, and bypass 510657221772SChristopher Siden * the normal history logging that happens in main(). 510757221772SChristopher Siden */ 510857221772SChristopher Siden (void) zpool_log_history(g_zfs, history_str); 510957221772SChristopher Siden log_history = B_FALSE; 511057221772SChristopher Siden } 511157221772SChristopher Siden 511257221772SChristopher Siden if (cbp->cb_version >= SPA_VERSION_FEATURES) { 511357221772SChristopher Siden int count; 511457221772SChristopher Siden ret = upgrade_enable_all(zhp, &count); 511557221772SChristopher Siden if (ret != 0) 511657221772SChristopher Siden return (ret); 511757221772SChristopher Siden 511857221772SChristopher Siden if (count > 0) { 511999653d4eSeschrock cbp->cb_first = B_FALSE; 512057221772SChristopher Siden printnl = B_TRUE; 5121eaca9bbdSeschrock } 512257221772SChristopher Siden } 5123eaca9bbdSeschrock 512457221772SChristopher Siden if (printnl) { 512557221772SChristopher Siden (void) printf(gettext("\n")); 512657221772SChristopher Siden } 512757221772SChristopher Siden 512857221772SChristopher Siden return (0); 512957221772SChristopher Siden } 513057221772SChristopher Siden 513157221772SChristopher Siden static int 513257221772SChristopher Siden upgrade_list_older_cb(zpool_handle_t *zhp, void *arg) 513357221772SChristopher Siden { 513457221772SChristopher Siden upgrade_cbdata_t *cbp = arg; 513557221772SChristopher Siden nvlist_t *config; 513657221772SChristopher Siden uint64_t version; 513757221772SChristopher Siden 513857221772SChristopher Siden config = zpool_get_config(zhp, NULL); 513957221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 514057221772SChristopher Siden &version) == 0); 514157221772SChristopher Siden 514257221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(version)); 514357221772SChristopher Siden 514457221772SChristopher Siden if (version < SPA_VERSION_FEATURES) { 5145eaca9bbdSeschrock if (cbp->cb_first) { 5146eaca9bbdSeschrock (void) printf(gettext("The following pools are " 514757221772SChristopher Siden "formatted with legacy version numbers and can\n" 514857221772SChristopher Siden "be upgraded to use feature flags. After " 514957221772SChristopher Siden "being upgraded, these pools\nwill no " 515057221772SChristopher Siden "longer be accessible by software that does not " 515157221772SChristopher Siden "support feature\nflags.\n\n")); 5152eaca9bbdSeschrock (void) printf(gettext("VER POOL\n")); 5153eaca9bbdSeschrock (void) printf(gettext("--- ------------\n")); 515499653d4eSeschrock cbp->cb_first = B_FALSE; 5155eaca9bbdSeschrock } 5156eaca9bbdSeschrock 51575ad82045Snd (void) printf("%2llu %s\n", (u_longlong_t)version, 5158eaca9bbdSeschrock zpool_get_name(zhp)); 5159eaca9bbdSeschrock } 5160eaca9bbdSeschrock 516157221772SChristopher Siden return (0); 516257221772SChristopher Siden } 516357221772SChristopher Siden 516457221772SChristopher Siden static int 516557221772SChristopher Siden upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg) 516657221772SChristopher Siden { 516757221772SChristopher Siden upgrade_cbdata_t *cbp = arg; 516857221772SChristopher Siden nvlist_t *config; 516957221772SChristopher Siden uint64_t version; 517057221772SChristopher Siden 517157221772SChristopher Siden config = zpool_get_config(zhp, NULL); 517257221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 517357221772SChristopher Siden &version) == 0); 517457221772SChristopher Siden 517557221772SChristopher Siden if (version >= SPA_VERSION_FEATURES) { 517657221772SChristopher Siden int i; 517757221772SChristopher Siden boolean_t poolfirst = B_TRUE; 517857221772SChristopher Siden nvlist_t *enabled = zpool_get_features(zhp); 517957221772SChristopher Siden 518057221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 518157221772SChristopher Siden const char *fguid = spa_feature_table[i].fi_guid; 518257221772SChristopher Siden const char *fname = spa_feature_table[i].fi_uname; 518357221772SChristopher Siden if (!nvlist_exists(enabled, fguid)) { 518457221772SChristopher Siden if (cbp->cb_first) { 518557221772SChristopher Siden (void) printf(gettext("\nSome " 518657221772SChristopher Siden "supported features are not " 518757221772SChristopher Siden "enabled on the following pools. " 518857221772SChristopher Siden "Once a\nfeature is enabled the " 518957221772SChristopher Siden "pool may become incompatible with " 519057221772SChristopher Siden "software\nthat does not support " 519157221772SChristopher Siden "the feature. See " 519257221772SChristopher Siden "zpool-features(5) for " 519357221772SChristopher Siden "details.\n\n")); 519457221772SChristopher Siden (void) printf(gettext("POOL " 519557221772SChristopher Siden "FEATURE\n")); 519657221772SChristopher Siden (void) printf(gettext("------" 519757221772SChristopher Siden "---------\n")); 519857221772SChristopher Siden cbp->cb_first = B_FALSE; 519957221772SChristopher Siden } 520057221772SChristopher Siden 520157221772SChristopher Siden if (poolfirst) { 520257221772SChristopher Siden (void) printf(gettext("%s\n"), 520357221772SChristopher Siden zpool_get_name(zhp)); 520457221772SChristopher Siden poolfirst = B_FALSE; 520557221772SChristopher Siden } 520657221772SChristopher Siden 520757221772SChristopher Siden (void) printf(gettext(" %s\n"), fname); 520857221772SChristopher Siden } 520957221772SChristopher Siden } 521057221772SChristopher Siden } 521157221772SChristopher Siden 521257221772SChristopher Siden return (0); 5213eaca9bbdSeschrock } 5214eaca9bbdSeschrock 5215eaca9bbdSeschrock /* ARGSUSED */ 5216eaca9bbdSeschrock static int 521706eeb2adSek upgrade_one(zpool_handle_t *zhp, void *data) 5218eaca9bbdSeschrock { 521957221772SChristopher Siden boolean_t printnl = B_FALSE; 5220990b4856Slling upgrade_cbdata_t *cbp = data; 5221990b4856Slling uint64_t cur_version; 5222eaca9bbdSeschrock int ret; 5223eaca9bbdSeschrock 52248654d025Sperrin if (strcmp("log", zpool_get_name(zhp)) == 0) { 52258654d025Sperrin (void) printf(gettext("'log' is now a reserved word\n" 52268654d025Sperrin "Pool 'log' must be renamed using export and import" 52278654d025Sperrin " to upgrade.\n")); 52288654d025Sperrin return (1); 52298654d025Sperrin } 5230990b4856Slling 5231990b4856Slling cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 5232e6c728e1Sbrendan if (cur_version > cbp->cb_version) { 5233eaca9bbdSeschrock (void) printf(gettext("Pool '%s' is already formatted " 523457221772SChristopher Siden "using more current version '%llu'.\n\n"), 5235e6c728e1Sbrendan zpool_get_name(zhp), cur_version); 5236e6c728e1Sbrendan return (0); 5237e6c728e1Sbrendan } 523857221772SChristopher Siden 523957221772SChristopher Siden if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) { 5240e6c728e1Sbrendan (void) printf(gettext("Pool '%s' is already formatted " 524157221772SChristopher Siden "using version %llu.\n\n"), zpool_get_name(zhp), 524257221772SChristopher Siden cbp->cb_version); 5243eaca9bbdSeschrock return (0); 5244eaca9bbdSeschrock } 5245eaca9bbdSeschrock 524657221772SChristopher Siden if (cur_version != cbp->cb_version) { 524757221772SChristopher Siden printnl = B_TRUE; 524857221772SChristopher Siden ret = upgrade_version(zhp, cbp->cb_version); 524957221772SChristopher Siden if (ret != 0) 525057221772SChristopher Siden return (ret); 525157221772SChristopher Siden } 525206eeb2adSek 525357221772SChristopher Siden if (cbp->cb_version >= SPA_VERSION_FEATURES) { 525457221772SChristopher Siden int count = 0; 525557221772SChristopher Siden ret = upgrade_enable_all(zhp, &count); 525657221772SChristopher Siden if (ret != 0) 525757221772SChristopher Siden return (ret); 525857221772SChristopher Siden 525957221772SChristopher Siden if (count != 0) { 526057221772SChristopher Siden printnl = B_TRUE; 526157221772SChristopher Siden } else if (cur_version == SPA_VERSION) { 526257221772SChristopher Siden (void) printf(gettext("Pool '%s' already has all " 526357221772SChristopher Siden "supported features enabled.\n"), 526457221772SChristopher Siden zpool_get_name(zhp)); 526557221772SChristopher Siden } 526657221772SChristopher Siden } 526757221772SChristopher Siden 526857221772SChristopher Siden if (printnl) { 526957221772SChristopher Siden (void) printf(gettext("\n")); 527006eeb2adSek } 5271eaca9bbdSeschrock 527257221772SChristopher Siden return (0); 5273eaca9bbdSeschrock } 5274eaca9bbdSeschrock 5275eaca9bbdSeschrock /* 5276eaca9bbdSeschrock * zpool upgrade 5277eaca9bbdSeschrock * zpool upgrade -v 5278990b4856Slling * zpool upgrade [-V version] <-a | pool ...> 5279eaca9bbdSeschrock * 5280eaca9bbdSeschrock * With no arguments, display downrev'd ZFS pool available for upgrade. 5281eaca9bbdSeschrock * Individual pools can be upgraded by specifying the pool, and '-a' will 5282eaca9bbdSeschrock * upgrade all pools. 5283eaca9bbdSeschrock */ 5284eaca9bbdSeschrock int 5285eaca9bbdSeschrock zpool_do_upgrade(int argc, char **argv) 5286eaca9bbdSeschrock { 5287eaca9bbdSeschrock int c; 5288eaca9bbdSeschrock upgrade_cbdata_t cb = { 0 }; 5289eaca9bbdSeschrock int ret = 0; 5290eaca9bbdSeschrock boolean_t showversions = B_FALSE; 529157221772SChristopher Siden boolean_t upgradeall = B_FALSE; 5292990b4856Slling char *end; 5293990b4856Slling 5294eaca9bbdSeschrock 5295eaca9bbdSeschrock /* check options */ 5296478ed9adSEric Taylor while ((c = getopt(argc, argv, ":avV:")) != -1) { 5297eaca9bbdSeschrock switch (c) { 5298eaca9bbdSeschrock case 'a': 529957221772SChristopher Siden upgradeall = B_TRUE; 5300eaca9bbdSeschrock break; 5301eaca9bbdSeschrock case 'v': 5302eaca9bbdSeschrock showversions = B_TRUE; 5303eaca9bbdSeschrock break; 5304990b4856Slling case 'V': 5305990b4856Slling cb.cb_version = strtoll(optarg, &end, 10); 5306ad135b5dSChristopher Siden if (*end != '\0' || 5307ad135b5dSChristopher Siden !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) { 5308990b4856Slling (void) fprintf(stderr, 5309990b4856Slling gettext("invalid version '%s'\n"), optarg); 5310990b4856Slling usage(B_FALSE); 5311990b4856Slling } 5312990b4856Slling break; 5313478ed9adSEric Taylor case ':': 5314478ed9adSEric Taylor (void) fprintf(stderr, gettext("missing argument for " 5315478ed9adSEric Taylor "'%c' option\n"), optopt); 5316478ed9adSEric Taylor usage(B_FALSE); 5317478ed9adSEric Taylor break; 5318eaca9bbdSeschrock case '?': 5319eaca9bbdSeschrock (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5320eaca9bbdSeschrock optopt); 532199653d4eSeschrock usage(B_FALSE); 5322eaca9bbdSeschrock } 5323eaca9bbdSeschrock } 5324eaca9bbdSeschrock 532506eeb2adSek cb.cb_argc = argc; 532606eeb2adSek cb.cb_argv = argv; 5327eaca9bbdSeschrock argc -= optind; 5328eaca9bbdSeschrock argv += optind; 5329eaca9bbdSeschrock 5330351420b3Slling if (cb.cb_version == 0) { 5331351420b3Slling cb.cb_version = SPA_VERSION; 533257221772SChristopher Siden } else if (!upgradeall && argc == 0) { 5333351420b3Slling (void) fprintf(stderr, gettext("-V option is " 5334351420b3Slling "incompatible with other arguments\n")); 5335351420b3Slling usage(B_FALSE); 5336351420b3Slling } 5337351420b3Slling 5338eaca9bbdSeschrock if (showversions) { 533957221772SChristopher Siden if (upgradeall || argc != 0) { 5340eaca9bbdSeschrock (void) fprintf(stderr, gettext("-v option is " 5341eaca9bbdSeschrock "incompatible with other arguments\n")); 534299653d4eSeschrock usage(B_FALSE); 5343eaca9bbdSeschrock } 534457221772SChristopher Siden } else if (upgradeall) { 5345eaca9bbdSeschrock if (argc != 0) { 5346351420b3Slling (void) fprintf(stderr, gettext("-a option should not " 5347351420b3Slling "be used along with a pool name\n")); 534899653d4eSeschrock usage(B_FALSE); 5349eaca9bbdSeschrock } 5350eaca9bbdSeschrock } 5351eaca9bbdSeschrock 5352ad135b5dSChristopher Siden (void) printf(gettext("This system supports ZFS pool feature " 5353ad135b5dSChristopher Siden "flags.\n\n")); 5354eaca9bbdSeschrock if (showversions) { 535557221772SChristopher Siden int i; 535657221772SChristopher Siden 535757221772SChristopher Siden (void) printf(gettext("The following features are " 535857221772SChristopher Siden "supported:\n\n")); 535957221772SChristopher Siden (void) printf(gettext("FEAT DESCRIPTION\n")); 536057221772SChristopher Siden (void) printf("----------------------------------------------" 536157221772SChristopher Siden "---------------\n"); 536257221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 536357221772SChristopher Siden zfeature_info_t *fi = &spa_feature_table[i]; 5364ca0cc391SMatthew Ahrens const char *ro = 5365ca0cc391SMatthew Ahrens (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 536657221772SChristopher Siden " (read-only compatible)" : ""; 536757221772SChristopher Siden 536857221772SChristopher Siden (void) printf("%-37s%s\n", fi->fi_uname, ro); 536957221772SChristopher Siden (void) printf(" %s\n", fi->fi_desc); 537057221772SChristopher Siden } 537157221772SChristopher Siden (void) printf("\n"); 537257221772SChristopher Siden 537357221772SChristopher Siden (void) printf(gettext("The following legacy versions are also " 5374d7d4af51Smmusante "supported:\n\n")); 5375eaca9bbdSeschrock (void) printf(gettext("VER DESCRIPTION\n")); 5376eaca9bbdSeschrock (void) printf("--- -----------------------------------------" 5377eaca9bbdSeschrock "---------------\n"); 537899653d4eSeschrock (void) printf(gettext(" 1 Initial ZFS version\n")); 537944cd46caSbillm (void) printf(gettext(" 2 Ditto blocks " 538044cd46caSbillm "(replicated metadata)\n")); 538199653d4eSeschrock (void) printf(gettext(" 3 Hot spares and double parity " 538299653d4eSeschrock "RAID-Z\n")); 5383d7306b64Sek (void) printf(gettext(" 4 zpool history\n")); 5384c9431fa1Sahl (void) printf(gettext(" 5 Compression using the gzip " 5385c9431fa1Sahl "algorithm\n")); 5386990b4856Slling (void) printf(gettext(" 6 bootfs pool property\n")); 53878654d025Sperrin (void) printf(gettext(" 7 Separate intent log devices\n")); 5388ecd6cf80Smarks (void) printf(gettext(" 8 Delegated administration\n")); 53898eed72d4Sck (void) printf(gettext(" 9 refquota and refreservation " 5390a9799022Sck "properties\n")); 5391fa94a07fSbrendan (void) printf(gettext(" 10 Cache devices\n")); 5392088f3894Sahrens (void) printf(gettext(" 11 Improved scrub performance\n")); 5393bb0ade09Sahrens (void) printf(gettext(" 12 Snapshot properties\n")); 539474e7dc98SMatthew Ahrens (void) printf(gettext(" 13 snapused property\n")); 539514843421SMatthew Ahrens (void) printf(gettext(" 14 passthrough-x aclinherit\n")); 539614843421SMatthew Ahrens (void) printf(gettext(" 15 user/group space accounting\n")); 5397478ed9adSEric Taylor (void) printf(gettext(" 16 stmf property support\n")); 53987aeab329SAdam Leventhal (void) printf(gettext(" 17 Triple-parity RAID-Z\n")); 5399b24ab676SJeff Bonwick (void) printf(gettext(" 18 Snapshot user holds\n")); 540088ecc943SGeorge Wilson (void) printf(gettext(" 19 Log device removal\n")); 5401b24ab676SJeff Bonwick (void) printf(gettext(" 20 Compression using zle " 5402b24ab676SJeff Bonwick "(zero-length encoding)\n")); 5403b24ab676SJeff Bonwick (void) printf(gettext(" 21 Deduplication\n")); 540492241e0bSTom Erickson (void) printf(gettext(" 22 Received properties\n")); 54056e1f5caaSNeil Perrin (void) printf(gettext(" 23 Slim ZIL\n")); 54060a586ceaSMark Shellenbaum (void) printf(gettext(" 24 System attributes\n")); 54073f9d6ad7SLin Ling (void) printf(gettext(" 25 Improved scrub stats\n")); 5408cde58dbcSMatthew Ahrens (void) printf(gettext(" 26 Improved snapshot deletion " 5409cde58dbcSMatthew Ahrens "performance\n")); 54106e0cbcaaSMatthew Ahrens (void) printf(gettext(" 27 Improved snapshot creation " 54116e0cbcaaSMatthew Ahrens "performance\n")); 5412cb04b873SMark J Musante (void) printf(gettext(" 28 Multiple vdev replacements\n")); 5413b24ab676SJeff Bonwick (void) printf(gettext("\nFor more information on a particular " 54149a8685acSstephanie scheffler "version, including supported releases,\n")); 54159a8685acSstephanie scheffler (void) printf(gettext("see the ZFS Administration Guide.\n\n")); 541657221772SChristopher Siden } else if (argc == 0 && upgradeall) { 541757221772SChristopher Siden cb.cb_first = B_TRUE; 541899653d4eSeschrock ret = zpool_iter(g_zfs, upgrade_cb, &cb); 541957221772SChristopher Siden if (ret == 0 && cb.cb_first) { 542057221772SChristopher Siden if (cb.cb_version == SPA_VERSION) { 542157221772SChristopher Siden (void) printf(gettext("All pools are already " 542257221772SChristopher Siden "formatted using feature flags.\n\n")); 542357221772SChristopher Siden (void) printf(gettext("Every feature flags " 542457221772SChristopher Siden "pool already has all supported features " 542557221772SChristopher Siden "enabled.\n")); 542657221772SChristopher Siden } else { 542757221772SChristopher Siden (void) printf(gettext("All pools are already " 542857221772SChristopher Siden "formatted with version %llu or higher.\n"), 542957221772SChristopher Siden cb.cb_version); 5430eaca9bbdSeschrock } 5431eaca9bbdSeschrock } 543257221772SChristopher Siden } else if (argc == 0) { 543357221772SChristopher Siden cb.cb_first = B_TRUE; 543457221772SChristopher Siden ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb); 543557221772SChristopher Siden assert(ret == 0); 5436eaca9bbdSeschrock 543757221772SChristopher Siden if (cb.cb_first) { 543857221772SChristopher Siden (void) printf(gettext("All pools are formatted " 543957221772SChristopher Siden "using feature flags.\n\n")); 544057221772SChristopher Siden } else { 544157221772SChristopher Siden (void) printf(gettext("\nUse 'zpool upgrade -v' " 544257221772SChristopher Siden "for a list of available legacy versions.\n")); 544357221772SChristopher Siden } 544457221772SChristopher Siden 544557221772SChristopher Siden cb.cb_first = B_TRUE; 544657221772SChristopher Siden ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb); 544757221772SChristopher Siden assert(ret == 0); 544857221772SChristopher Siden 544957221772SChristopher Siden if (cb.cb_first) { 545057221772SChristopher Siden (void) printf(gettext("Every feature flags pool has " 545157221772SChristopher Siden "all supported features enabled.\n")); 545257221772SChristopher Siden } else { 545357221772SChristopher Siden (void) printf(gettext("\n")); 5454eaca9bbdSeschrock } 5455eaca9bbdSeschrock } else { 5456b1b8ab34Slling ret = for_each_pool(argc, argv, B_FALSE, NULL, 5457b1b8ab34Slling upgrade_one, &cb); 545806eeb2adSek } 545906eeb2adSek 546006eeb2adSek return (ret); 546106eeb2adSek } 546206eeb2adSek 5463ecd6cf80Smarks typedef struct hist_cbdata { 5464ecd6cf80Smarks boolean_t first; 54654445fffbSMatthew Ahrens boolean_t longfmt; 54664445fffbSMatthew Ahrens boolean_t internal; 5467ecd6cf80Smarks } hist_cbdata_t; 5468ecd6cf80Smarks 546906eeb2adSek /* 547006eeb2adSek * Print out the command history for a specific pool. 547106eeb2adSek */ 547206eeb2adSek static int 547306eeb2adSek get_history_one(zpool_handle_t *zhp, void *data) 547406eeb2adSek { 547506eeb2adSek nvlist_t *nvhis; 547606eeb2adSek nvlist_t **records; 547706eeb2adSek uint_t numrecords; 547806eeb2adSek int ret, i; 5479ecd6cf80Smarks hist_cbdata_t *cb = (hist_cbdata_t *)data; 548006eeb2adSek 5481ecd6cf80Smarks cb->first = B_FALSE; 548206eeb2adSek 548306eeb2adSek (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); 548406eeb2adSek 548506eeb2adSek if ((ret = zpool_get_history(zhp, &nvhis)) != 0) 548606eeb2adSek return (ret); 548706eeb2adSek 548806eeb2adSek verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, 548906eeb2adSek &records, &numrecords) == 0); 549006eeb2adSek for (i = 0; i < numrecords; i++) { 54914445fffbSMatthew Ahrens nvlist_t *rec = records[i]; 54924445fffbSMatthew Ahrens char tbuf[30] = ""; 5493ecd6cf80Smarks 54944445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_TIME)) { 54954445fffbSMatthew Ahrens time_t tsec; 54964445fffbSMatthew Ahrens struct tm t; 54974445fffbSMatthew Ahrens 54984445fffbSMatthew Ahrens tsec = fnvlist_lookup_uint64(records[i], 54994445fffbSMatthew Ahrens ZPOOL_HIST_TIME); 55004445fffbSMatthew Ahrens (void) localtime_r(&tsec, &t); 55014445fffbSMatthew Ahrens (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 55024445fffbSMatthew Ahrens } 5503ecd6cf80Smarks 55044445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_CMD)) { 55054445fffbSMatthew Ahrens (void) printf("%s %s", tbuf, 55064445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_CMD)); 55074445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) { 55084445fffbSMatthew Ahrens int ievent = 55094445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT); 55104445fffbSMatthew Ahrens if (!cb->internal) 55114445fffbSMatthew Ahrens continue; 55124445fffbSMatthew Ahrens if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) { 55134445fffbSMatthew Ahrens (void) printf("%s unrecognized record:\n", 55144445fffbSMatthew Ahrens tbuf); 55154445fffbSMatthew Ahrens dump_nvlist(rec, 4); 55164445fffbSMatthew Ahrens continue; 55174445fffbSMatthew Ahrens } 55184445fffbSMatthew Ahrens (void) printf("%s [internal %s txg:%lld] %s", tbuf, 55194445fffbSMatthew Ahrens zfs_history_event_names[ievent], 55204445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 55214445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR)); 55224445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) { 55234445fffbSMatthew Ahrens if (!cb->internal) 5524ecd6cf80Smarks continue; 55254445fffbSMatthew Ahrens (void) printf("%s [txg:%lld] %s", tbuf, 55264445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 55274445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME)); 55284445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) { 55294445fffbSMatthew Ahrens (void) printf(" %s (%llu)", 55304445fffbSMatthew Ahrens fnvlist_lookup_string(rec, 55314445fffbSMatthew Ahrens ZPOOL_HIST_DSNAME), 55324445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, 55334445fffbSMatthew Ahrens ZPOOL_HIST_DSID)); 55344445fffbSMatthew Ahrens } 55354445fffbSMatthew Ahrens (void) printf(" %s", fnvlist_lookup_string(rec, 55364445fffbSMatthew Ahrens ZPOOL_HIST_INT_STR)); 55374445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) { 55384445fffbSMatthew Ahrens if (!cb->internal) 55394445fffbSMatthew Ahrens continue; 55404445fffbSMatthew Ahrens (void) printf("%s ioctl %s\n", tbuf, 55414445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL)); 55424445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) { 55434445fffbSMatthew Ahrens (void) printf(" input:\n"); 55444445fffbSMatthew Ahrens dump_nvlist(fnvlist_lookup_nvlist(rec, 55454445fffbSMatthew Ahrens ZPOOL_HIST_INPUT_NVL), 8); 55464445fffbSMatthew Ahrens } 55474445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) { 55484445fffbSMatthew Ahrens (void) printf(" output:\n"); 55494445fffbSMatthew Ahrens dump_nvlist(fnvlist_lookup_nvlist(rec, 55504445fffbSMatthew Ahrens ZPOOL_HIST_OUTPUT_NVL), 8); 55514445fffbSMatthew Ahrens } 5552dfc11533SChris Williamson if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) { 5553dfc11533SChris Williamson (void) printf(" errno: %lld\n", 5554dfc11533SChris Williamson fnvlist_lookup_int64(rec, 5555dfc11533SChris Williamson ZPOOL_HIST_ERRNO)); 5556dfc11533SChris Williamson } 55574445fffbSMatthew Ahrens } else { 55584445fffbSMatthew Ahrens if (!cb->internal) 5559ecd6cf80Smarks continue; 55604445fffbSMatthew Ahrens (void) printf("%s unrecognized record:\n", tbuf); 55614445fffbSMatthew Ahrens dump_nvlist(rec, 4); 556206eeb2adSek } 5563ecd6cf80Smarks 5564ecd6cf80Smarks if (!cb->longfmt) { 5565ecd6cf80Smarks (void) printf("\n"); 5566ecd6cf80Smarks continue; 5567ecd6cf80Smarks } 5568ecd6cf80Smarks (void) printf(" ["); 55694445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_WHO)) { 55704445fffbSMatthew Ahrens uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO); 55714445fffbSMatthew Ahrens struct passwd *pwd = getpwuid(who); 55724445fffbSMatthew Ahrens (void) printf("user %d ", (int)who); 55734445fffbSMatthew Ahrens if (pwd != NULL) 55744445fffbSMatthew Ahrens (void) printf("(%s) ", pwd->pw_name); 5575ecd6cf80Smarks } 55764445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_HOST)) { 55774445fffbSMatthew Ahrens (void) printf("on %s", 55784445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_HOST)); 5579ecd6cf80Smarks } 55804445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) { 55814445fffbSMatthew Ahrens (void) printf(":%s", 55824445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE)); 5583ecd6cf80Smarks } 5584ecd6cf80Smarks (void) printf("]"); 5585ecd6cf80Smarks (void) printf("\n"); 558606eeb2adSek } 558706eeb2adSek (void) printf("\n"); 558806eeb2adSek nvlist_free(nvhis); 558906eeb2adSek 559006eeb2adSek return (ret); 559106eeb2adSek } 559206eeb2adSek 559306eeb2adSek /* 559406eeb2adSek * zpool history <pool> 559506eeb2adSek * 559606eeb2adSek * Displays the history of commands that modified pools. 559706eeb2adSek */ 559806eeb2adSek int 559906eeb2adSek zpool_do_history(int argc, char **argv) 560006eeb2adSek { 5601ecd6cf80Smarks hist_cbdata_t cbdata = { 0 }; 560206eeb2adSek int ret; 5603ecd6cf80Smarks int c; 560406eeb2adSek 5605ecd6cf80Smarks cbdata.first = B_TRUE; 5606ecd6cf80Smarks /* check options */ 5607ecd6cf80Smarks while ((c = getopt(argc, argv, "li")) != -1) { 5608ecd6cf80Smarks switch (c) { 5609ecd6cf80Smarks case 'l': 56104445fffbSMatthew Ahrens cbdata.longfmt = B_TRUE; 5611ecd6cf80Smarks break; 5612ecd6cf80Smarks case 'i': 56134445fffbSMatthew Ahrens cbdata.internal = B_TRUE; 5614ecd6cf80Smarks break; 5615ecd6cf80Smarks case '?': 5616ecd6cf80Smarks (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5617ecd6cf80Smarks optopt); 5618ecd6cf80Smarks usage(B_FALSE); 5619ecd6cf80Smarks } 5620ecd6cf80Smarks } 562106eeb2adSek argc -= optind; 562206eeb2adSek argv += optind; 562306eeb2adSek 5624b1b8ab34Slling ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one, 5625ecd6cf80Smarks &cbdata); 562606eeb2adSek 5627ecd6cf80Smarks if (argc == 0 && cbdata.first == B_TRUE) { 562806eeb2adSek (void) printf(gettext("no pools available\n")); 562906eeb2adSek return (0); 5630eaca9bbdSeschrock } 5631eaca9bbdSeschrock 5632eaca9bbdSeschrock return (ret); 5633eaca9bbdSeschrock } 5634eaca9bbdSeschrock 5635b1b8ab34Slling static int 5636b1b8ab34Slling get_callback(zpool_handle_t *zhp, void *data) 5637b1b8ab34Slling { 5638990b4856Slling zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; 5639b1b8ab34Slling char value[MAXNAMELEN]; 5640990b4856Slling zprop_source_t srctype; 5641990b4856Slling zprop_list_t *pl; 5642b1b8ab34Slling 5643b1b8ab34Slling for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 5644b1b8ab34Slling 5645b1b8ab34Slling /* 5646990b4856Slling * Skip the special fake placeholder. This will also skip 5647990b4856Slling * over the name property when 'all' is specified. 5648b1b8ab34Slling */ 5649990b4856Slling if (pl->pl_prop == ZPOOL_PROP_NAME && 5650b1b8ab34Slling pl == cbp->cb_proplist) 5651b1b8ab34Slling continue; 5652b1b8ab34Slling 5653ad135b5dSChristopher Siden if (pl->pl_prop == ZPROP_INVAL && 5654ad135b5dSChristopher Siden (zpool_prop_feature(pl->pl_user_prop) || 5655ad135b5dSChristopher Siden zpool_prop_unsupported(pl->pl_user_prop))) { 5656ad135b5dSChristopher Siden srctype = ZPROP_SRC_LOCAL; 5657b1b8ab34Slling 5658ad135b5dSChristopher Siden if (zpool_prop_get_feature(zhp, pl->pl_user_prop, 5659ad135b5dSChristopher Siden value, sizeof (value)) == 0) { 5660ad135b5dSChristopher Siden zprop_print_one_property(zpool_get_name(zhp), 5661ad135b5dSChristopher Siden cbp, pl->pl_user_prop, value, srctype, 5662ad135b5dSChristopher Siden NULL, NULL); 5663ad135b5dSChristopher Siden } 5664ad135b5dSChristopher Siden } else { 5665ad135b5dSChristopher Siden if (zpool_get_prop(zhp, pl->pl_prop, value, 5666c58b3526SAdam Stevko sizeof (value), &srctype, cbp->cb_literal) != 0) 5667ad135b5dSChristopher Siden continue; 5668ad135b5dSChristopher Siden 5669ad135b5dSChristopher Siden zprop_print_one_property(zpool_get_name(zhp), cbp, 5670ad135b5dSChristopher Siden zpool_prop_to_name(pl->pl_prop), value, srctype, 5671ad135b5dSChristopher Siden NULL, NULL); 5672ad135b5dSChristopher Siden } 5673b1b8ab34Slling } 5674b1b8ab34Slling return (0); 5675b1b8ab34Slling } 5676b1b8ab34Slling 5677c58b3526SAdam Stevko /* 5678c58b3526SAdam Stevko * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ... 5679c58b3526SAdam Stevko * 5680c58b3526SAdam Stevko * -H Scripted mode. Don't display headers, and separate properties 5681c58b3526SAdam Stevko * by a single tab. 5682c58b3526SAdam Stevko * -o List of columns to display. Defaults to 5683c58b3526SAdam Stevko * "name,property,value,source". 5684c58b3526SAdam Stevko * -p Diplay values in parsable (exact) format. 5685c58b3526SAdam Stevko * 5686c58b3526SAdam Stevko * Get properties of pools in the system. Output space statistics 5687c58b3526SAdam Stevko * for each one as well as other attributes. 5688c58b3526SAdam Stevko */ 5689b1b8ab34Slling int 5690b1b8ab34Slling zpool_do_get(int argc, char **argv) 5691b1b8ab34Slling { 5692990b4856Slling zprop_get_cbdata_t cb = { 0 }; 5693990b4856Slling zprop_list_t fake_name = { 0 }; 5694b1b8ab34Slling int ret; 5695c58b3526SAdam Stevko int c, i; 5696c58b3526SAdam Stevko char *value; 5697b1b8ab34Slling 5698b1b8ab34Slling cb.cb_first = B_TRUE; 5699c58b3526SAdam Stevko 5700c58b3526SAdam Stevko /* 5701c58b3526SAdam Stevko * Set up default columns and sources. 5702c58b3526SAdam Stevko */ 5703990b4856Slling cb.cb_sources = ZPROP_SRC_ALL; 5704b1b8ab34Slling cb.cb_columns[0] = GET_COL_NAME; 5705b1b8ab34Slling cb.cb_columns[1] = GET_COL_PROPERTY; 5706b1b8ab34Slling cb.cb_columns[2] = GET_COL_VALUE; 5707b1b8ab34Slling cb.cb_columns[3] = GET_COL_SOURCE; 5708990b4856Slling cb.cb_type = ZFS_TYPE_POOL; 5709b1b8ab34Slling 5710c58b3526SAdam Stevko /* check options */ 5711c58b3526SAdam Stevko while ((c = getopt(argc, argv, ":Hpo:")) != -1) { 5712c58b3526SAdam Stevko switch (c) { 5713c58b3526SAdam Stevko case 'p': 5714c58b3526SAdam Stevko cb.cb_literal = B_TRUE; 5715c58b3526SAdam Stevko break; 5716c58b3526SAdam Stevko case 'H': 5717c58b3526SAdam Stevko cb.cb_scripted = B_TRUE; 5718c58b3526SAdam Stevko break; 5719c58b3526SAdam Stevko case 'o': 5720c58b3526SAdam Stevko bzero(&cb.cb_columns, sizeof (cb.cb_columns)); 5721c58b3526SAdam Stevko i = 0; 5722c58b3526SAdam Stevko while (*optarg != '\0') { 5723c58b3526SAdam Stevko static char *col_subopts[] = 5724c58b3526SAdam Stevko { "name", "property", "value", "source", 5725c58b3526SAdam Stevko "all", NULL }; 5726c58b3526SAdam Stevko 5727c58b3526SAdam Stevko if (i == ZFS_GET_NCOLS) { 5728c58b3526SAdam Stevko (void) fprintf(stderr, gettext("too " 5729c58b3526SAdam Stevko "many fields given to -o " 5730c58b3526SAdam Stevko "option\n")); 5731c58b3526SAdam Stevko usage(B_FALSE); 5732c58b3526SAdam Stevko } 5733c58b3526SAdam Stevko 5734c58b3526SAdam Stevko switch (getsubopt(&optarg, col_subopts, 5735c58b3526SAdam Stevko &value)) { 5736c58b3526SAdam Stevko case 0: 5737c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_NAME; 5738c58b3526SAdam Stevko break; 5739c58b3526SAdam Stevko case 1: 5740c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_PROPERTY; 5741c58b3526SAdam Stevko break; 5742c58b3526SAdam Stevko case 2: 5743c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_VALUE; 5744c58b3526SAdam Stevko break; 5745c58b3526SAdam Stevko case 3: 5746c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_SOURCE; 5747c58b3526SAdam Stevko break; 5748c58b3526SAdam Stevko case 4: 5749c58b3526SAdam Stevko if (i > 0) { 5750c58b3526SAdam Stevko (void) fprintf(stderr, 5751c58b3526SAdam Stevko gettext("\"all\" conflicts " 5752c58b3526SAdam Stevko "with specific fields " 5753c58b3526SAdam Stevko "given to -o option\n")); 5754c58b3526SAdam Stevko usage(B_FALSE); 5755c58b3526SAdam Stevko } 5756c58b3526SAdam Stevko cb.cb_columns[0] = GET_COL_NAME; 5757c58b3526SAdam Stevko cb.cb_columns[1] = GET_COL_PROPERTY; 5758c58b3526SAdam Stevko cb.cb_columns[2] = GET_COL_VALUE; 5759c58b3526SAdam Stevko cb.cb_columns[3] = GET_COL_SOURCE; 5760c58b3526SAdam Stevko i = ZFS_GET_NCOLS; 5761c58b3526SAdam Stevko break; 5762c58b3526SAdam Stevko default: 5763c58b3526SAdam Stevko (void) fprintf(stderr, 5764c58b3526SAdam Stevko gettext("invalid column name " 5765c58b3526SAdam Stevko "'%s'\n"), value); 5766c58b3526SAdam Stevko usage(B_FALSE); 5767c58b3526SAdam Stevko } 5768c58b3526SAdam Stevko } 5769c58b3526SAdam Stevko break; 5770c58b3526SAdam Stevko case '?': 5771c58b3526SAdam Stevko (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5772c58b3526SAdam Stevko optopt); 5773c58b3526SAdam Stevko usage(B_FALSE); 5774c58b3526SAdam Stevko } 5775c58b3526SAdam Stevko } 5776c58b3526SAdam Stevko 5777c58b3526SAdam Stevko argc -= optind; 5778c58b3526SAdam Stevko argv += optind; 5779c58b3526SAdam Stevko 5780c58b3526SAdam Stevko if (argc < 1) { 5781c58b3526SAdam Stevko (void) fprintf(stderr, gettext("missing property " 5782c58b3526SAdam Stevko "argument\n")); 5783c58b3526SAdam Stevko usage(B_FALSE); 5784c58b3526SAdam Stevko } 5785c58b3526SAdam Stevko 5786c58b3526SAdam Stevko if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist, 5787990b4856Slling ZFS_TYPE_POOL) != 0) 5788b1b8ab34Slling usage(B_FALSE); 5789b1b8ab34Slling 5790c58b3526SAdam Stevko argc--; 5791c58b3526SAdam Stevko argv++; 5792c58b3526SAdam Stevko 5793b1b8ab34Slling if (cb.cb_proplist != NULL) { 5794990b4856Slling fake_name.pl_prop = ZPOOL_PROP_NAME; 5795b1b8ab34Slling fake_name.pl_width = strlen(gettext("NAME")); 5796b1b8ab34Slling fake_name.pl_next = cb.cb_proplist; 5797b1b8ab34Slling cb.cb_proplist = &fake_name; 5798b1b8ab34Slling } 5799b1b8ab34Slling 5800c58b3526SAdam Stevko ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, 5801b1b8ab34Slling get_callback, &cb); 5802b1b8ab34Slling 5803b1b8ab34Slling if (cb.cb_proplist == &fake_name) 5804990b4856Slling zprop_free_list(fake_name.pl_next); 5805b1b8ab34Slling else 5806990b4856Slling zprop_free_list(cb.cb_proplist); 5807b1b8ab34Slling 5808b1b8ab34Slling return (ret); 5809b1b8ab34Slling } 5810b1b8ab34Slling 5811b1b8ab34Slling typedef struct set_cbdata { 5812b1b8ab34Slling char *cb_propname; 5813b1b8ab34Slling char *cb_value; 5814b1b8ab34Slling boolean_t cb_any_successful; 5815b1b8ab34Slling } set_cbdata_t; 5816b1b8ab34Slling 5817b1b8ab34Slling int 5818b1b8ab34Slling set_callback(zpool_handle_t *zhp, void *data) 5819b1b8ab34Slling { 5820b1b8ab34Slling int error; 5821b1b8ab34Slling set_cbdata_t *cb = (set_cbdata_t *)data; 5822b1b8ab34Slling 5823b1b8ab34Slling error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value); 5824b1b8ab34Slling 5825b1b8ab34Slling if (!error) 5826b1b8ab34Slling cb->cb_any_successful = B_TRUE; 5827b1b8ab34Slling 5828b1b8ab34Slling return (error); 5829b1b8ab34Slling } 5830b1b8ab34Slling 5831b1b8ab34Slling int 5832b1b8ab34Slling zpool_do_set(int argc, char **argv) 5833b1b8ab34Slling { 5834b1b8ab34Slling set_cbdata_t cb = { 0 }; 5835b1b8ab34Slling int error; 5836b1b8ab34Slling 5837b1b8ab34Slling if (argc > 1 && argv[1][0] == '-') { 5838b1b8ab34Slling (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5839b1b8ab34Slling argv[1][1]); 5840b1b8ab34Slling usage(B_FALSE); 5841b1b8ab34Slling } 5842b1b8ab34Slling 5843b1b8ab34Slling if (argc < 2) { 5844b1b8ab34Slling (void) fprintf(stderr, gettext("missing property=value " 5845b1b8ab34Slling "argument\n")); 5846b1b8ab34Slling usage(B_FALSE); 5847b1b8ab34Slling } 5848b1b8ab34Slling 5849b1b8ab34Slling if (argc < 3) { 5850b1b8ab34Slling (void) fprintf(stderr, gettext("missing pool name\n")); 5851b1b8ab34Slling usage(B_FALSE); 5852b1b8ab34Slling } 5853b1b8ab34Slling 5854b1b8ab34Slling if (argc > 3) { 5855b1b8ab34Slling (void) fprintf(stderr, gettext("too many pool names\n")); 5856b1b8ab34Slling usage(B_FALSE); 5857b1b8ab34Slling } 5858b1b8ab34Slling 5859b1b8ab34Slling cb.cb_propname = argv[1]; 5860b1b8ab34Slling cb.cb_value = strchr(cb.cb_propname, '='); 5861b1b8ab34Slling if (cb.cb_value == NULL) { 5862b1b8ab34Slling (void) fprintf(stderr, gettext("missing value in " 5863b1b8ab34Slling "property=value argument\n")); 5864b1b8ab34Slling usage(B_FALSE); 5865b1b8ab34Slling } 5866b1b8ab34Slling 5867b1b8ab34Slling *(cb.cb_value) = '\0'; 5868b1b8ab34Slling cb.cb_value++; 5869b1b8ab34Slling 5870b1b8ab34Slling error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, 5871b1b8ab34Slling set_callback, &cb); 5872b1b8ab34Slling 5873b1b8ab34Slling return (error); 5874b1b8ab34Slling } 5875b1b8ab34Slling 5876b1b8ab34Slling static int 5877b1b8ab34Slling find_command_idx(char *command, int *idx) 5878b1b8ab34Slling { 5879b1b8ab34Slling int i; 5880b1b8ab34Slling 5881b1b8ab34Slling for (i = 0; i < NCOMMAND; i++) { 5882b1b8ab34Slling if (command_table[i].name == NULL) 5883b1b8ab34Slling continue; 5884b1b8ab34Slling 5885b1b8ab34Slling if (strcmp(command, command_table[i].name) == 0) { 5886b1b8ab34Slling *idx = i; 5887b1b8ab34Slling return (0); 5888b1b8ab34Slling } 5889b1b8ab34Slling } 5890b1b8ab34Slling return (1); 5891b1b8ab34Slling } 5892b1b8ab34Slling 5893fa9e4066Sahrens int 5894fa9e4066Sahrens main(int argc, char **argv) 5895fa9e4066Sahrens { 5896b327cd3fSIgor Kozhukhov int ret = 0; 5897fa9e4066Sahrens int i; 5898fa9e4066Sahrens char *cmdname; 5899fa9e4066Sahrens 5900fa9e4066Sahrens (void) setlocale(LC_ALL, ""); 5901fa9e4066Sahrens (void) textdomain(TEXT_DOMAIN); 5902fa9e4066Sahrens 590399653d4eSeschrock if ((g_zfs = libzfs_init()) == NULL) { 590499653d4eSeschrock (void) fprintf(stderr, gettext("internal error: failed to " 5905203a47d8Snd "initialize ZFS library\n")); 590699653d4eSeschrock return (1); 590799653d4eSeschrock } 590899653d4eSeschrock 590999653d4eSeschrock libzfs_print_on_error(g_zfs, B_TRUE); 591099653d4eSeschrock 5911fa9e4066Sahrens opterr = 0; 5912fa9e4066Sahrens 5913fa9e4066Sahrens /* 5914fa9e4066Sahrens * Make sure the user has specified some command. 5915fa9e4066Sahrens */ 5916fa9e4066Sahrens if (argc < 2) { 5917fa9e4066Sahrens (void) fprintf(stderr, gettext("missing command\n")); 591899653d4eSeschrock usage(B_FALSE); 5919fa9e4066Sahrens } 5920fa9e4066Sahrens 5921fa9e4066Sahrens cmdname = argv[1]; 5922fa9e4066Sahrens 5923fa9e4066Sahrens /* 5924fa9e4066Sahrens * Special case '-?' 5925fa9e4066Sahrens */ 5926fa9e4066Sahrens if (strcmp(cmdname, "-?") == 0) 592799653d4eSeschrock usage(B_TRUE); 5928fa9e4066Sahrens 59294445fffbSMatthew Ahrens zfs_save_arguments(argc, argv, history_str, sizeof (history_str)); 59302a6b87f0Sek 5931fa9e4066Sahrens /* 5932fa9e4066Sahrens * Run the appropriate command. 5933fa9e4066Sahrens */ 5934b1b8ab34Slling if (find_command_idx(cmdname, &i) == 0) { 5935b1b8ab34Slling current_command = &command_table[i]; 5936b1b8ab34Slling ret = command_table[i].func(argc - 1, argv + 1); 593791ebeef5Sahrens } else if (strchr(cmdname, '=')) { 593891ebeef5Sahrens verify(find_command_idx("set", &i) == 0); 593991ebeef5Sahrens current_command = &command_table[i]; 594091ebeef5Sahrens ret = command_table[i].func(argc, argv); 594191ebeef5Sahrens } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 594291ebeef5Sahrens /* 594391ebeef5Sahrens * 'freeze' is a vile debugging abomination, so we treat 594491ebeef5Sahrens * it as such. 594591ebeef5Sahrens */ 5946ea8dc4b6Seschrock char buf[16384]; 5947ea8dc4b6Seschrock int fd = open(ZFS_DEV, O_RDWR); 5948fa9e4066Sahrens (void) strcpy((void *)buf, argv[2]); 5949fa9e4066Sahrens return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf)); 595091ebeef5Sahrens } else { 5951fa9e4066Sahrens (void) fprintf(stderr, gettext("unrecognized " 5952fa9e4066Sahrens "command '%s'\n"), cmdname); 595399653d4eSeschrock usage(B_FALSE); 5954fa9e4066Sahrens } 5955fa9e4066Sahrens 59564445fffbSMatthew Ahrens if (ret == 0 && log_history) 59574445fffbSMatthew Ahrens (void) zpool_log_history(g_zfs, history_str); 59584445fffbSMatthew Ahrens 595999653d4eSeschrock libzfs_fini(g_zfs); 596099653d4eSeschrock 5961fa9e4066Sahrens /* 5962fa9e4066Sahrens * The 'ZFS_ABORT' environment variable causes us to dump core on exit 5963fa9e4066Sahrens * for the purposes of running ::findleaks. 5964fa9e4066Sahrens */ 5965fa9e4066Sahrens if (getenv("ZFS_ABORT") != NULL) { 5966fa9e4066Sahrens (void) printf("dumping core by request\n"); 5967fa9e4066Sahrens abort(); 5968fa9e4066Sahrens } 5969fa9e4066Sahrens 5970fa9e4066Sahrens return (ret); 5971fa9e4066Sahrens } 5972