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. 30663207adSDon Brady * Copyright (c) 2017, Intel Corporation. 31084fd14fSBrian Behlendorf * Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com> 3295fa23b1SJerry Jelinek * Copyright 2019 Joyent, Inc. 335711d393Sloli * Copyright (c) 2012 by Cyril Plisko. All rights reserved. 34*c4e4d410SAndy Fiddaman * Copyright 2019 OmniOS Community Edition (OmniOSce) Association. 35fa9e4066Sahrens */ 36fa9e4066Sahrens 37fa9e4066Sahrens #include <assert.h> 38fa9e4066Sahrens #include <ctype.h> 39fa9e4066Sahrens #include <dirent.h> 40fa9e4066Sahrens #include <errno.h> 41fa9e4066Sahrens #include <fcntl.h> 4286714001SSerapheim Dimitropoulos #include <getopt.h> 43fa9e4066Sahrens #include <libgen.h> 44fa9e4066Sahrens #include <libintl.h> 45fa9e4066Sahrens #include <libuutil.h> 46fa9e4066Sahrens #include <locale.h> 47fa9e4066Sahrens #include <stdio.h> 48fa9e4066Sahrens #include <stdlib.h> 49fa9e4066Sahrens #include <string.h> 50fa9e4066Sahrens #include <strings.h> 51fa9e4066Sahrens #include <unistd.h> 52fa9e4066Sahrens #include <priv.h> 53ecd6cf80Smarks #include <pwd.h> 54ecd6cf80Smarks #include <zone.h> 554263d13fSGeorge Wilson #include <zfs_prop.h> 56b1b8ab34Slling #include <sys/fs/zfs.h> 57fa9e4066Sahrens #include <sys/stat.h> 58e0f1c0afSOlaf Faaland #include <sys/debug.h> 59fa9e4066Sahrens 60fa9e4066Sahrens #include <libzfs.h> 61fa9e4066Sahrens 62fa9e4066Sahrens #include "zpool_util.h" 63b7b97454Sperrin #include "zfs_comutil.h" 64ad135b5dSChristopher Siden #include "zfeature_common.h" 65fa9e4066Sahrens 6626fd7700SKrishnendu Sadhukhan - Sun Microsystems #include "statcommon.h" 6726fd7700SKrishnendu Sadhukhan - Sun Microsystems 68fa9e4066Sahrens static int zpool_do_create(int, char **); 69fa9e4066Sahrens static int zpool_do_destroy(int, char **); 70fa9e4066Sahrens 71fa9e4066Sahrens static int zpool_do_add(int, char **); 7299653d4eSeschrock static int zpool_do_remove(int, char **); 736401734dSWill Andrews static int zpool_do_labelclear(int, char **); 74fa9e4066Sahrens 7586714001SSerapheim Dimitropoulos static int zpool_do_checkpoint(int, char **); 7686714001SSerapheim Dimitropoulos 77fa9e4066Sahrens static int zpool_do_list(int, char **); 78fa9e4066Sahrens static int zpool_do_iostat(int, char **); 79fa9e4066Sahrens static int zpool_do_status(int, char **); 80fa9e4066Sahrens 81fa9e4066Sahrens static int zpool_do_online(int, char **); 82fa9e4066Sahrens static int zpool_do_offline(int, char **); 83ea8dc4b6Seschrock static int zpool_do_clear(int, char **); 844263d13fSGeorge Wilson static int zpool_do_reopen(int, char **); 85fa9e4066Sahrens 86e9103aaeSGarrett D'Amore static int zpool_do_reguid(int, char **); 87e9103aaeSGarrett D'Amore 88fa9e4066Sahrens static int zpool_do_attach(int, char **); 89fa9e4066Sahrens static int zpool_do_detach(int, char **); 90fa9e4066Sahrens static int zpool_do_replace(int, char **); 911195e687SMark J Musante static int zpool_do_split(int, char **); 92fa9e4066Sahrens 93094e47e9SGeorge Wilson static int zpool_do_initialize(int, char **); 94fa9e4066Sahrens static int zpool_do_scrub(int, char **); 95e4c795beSTom Caputi static int zpool_do_resilver(int, char **); 96084fd14fSBrian Behlendorf static int zpool_do_trim(int, char **); 97fa9e4066Sahrens 98fa9e4066Sahrens static int zpool_do_import(int, char **); 99fa9e4066Sahrens static int zpool_do_export(int, char **); 100fa9e4066Sahrens 101eaca9bbdSeschrock static int zpool_do_upgrade(int, char **); 102eaca9bbdSeschrock 10306eeb2adSek static int zpool_do_history(int, char **); 10406eeb2adSek 105b1b8ab34Slling static int zpool_do_get(int, char **); 106b1b8ab34Slling static int zpool_do_set(int, char **); 107b1b8ab34Slling 1089c2acf00SAlek Pinchuk static int zpool_do_sync(int, char **); 1099c2acf00SAlek Pinchuk 110fa9e4066Sahrens /* 111fa9e4066Sahrens * These libumem hooks provide a reasonable set of defaults for the allocator's 112fa9e4066Sahrens * debugging facilities. 113fa9e4066Sahrens */ 11429ab75c9Srm 11529ab75c9Srm #ifdef DEBUG 116fa9e4066Sahrens const char * 11799653d4eSeschrock _umem_debug_init(void) 118fa9e4066Sahrens { 119fa9e4066Sahrens return ("default,verbose"); /* $UMEM_DEBUG setting */ 120fa9e4066Sahrens } 121fa9e4066Sahrens 122fa9e4066Sahrens const char * 123fa9e4066Sahrens _umem_logging_init(void) 124fa9e4066Sahrens { 125fa9e4066Sahrens return ("fail,contents"); /* $UMEM_LOGGING setting */ 126fa9e4066Sahrens } 12729ab75c9Srm #endif 128fa9e4066Sahrens 12965cd9f28Seschrock typedef enum { 13065cd9f28Seschrock HELP_ADD, 13165cd9f28Seschrock HELP_ATTACH, 132ea8dc4b6Seschrock HELP_CLEAR, 13365cd9f28Seschrock HELP_CREATE, 13486714001SSerapheim Dimitropoulos HELP_CHECKPOINT, 13565cd9f28Seschrock HELP_DESTROY, 13665cd9f28Seschrock HELP_DETACH, 13765cd9f28Seschrock HELP_EXPORT, 13806eeb2adSek HELP_HISTORY, 13965cd9f28Seschrock HELP_IMPORT, 14065cd9f28Seschrock HELP_IOSTAT, 1416401734dSWill Andrews HELP_LABELCLEAR, 14265cd9f28Seschrock HELP_LIST, 14365cd9f28Seschrock HELP_OFFLINE, 14465cd9f28Seschrock HELP_ONLINE, 14565cd9f28Seschrock HELP_REPLACE, 14699653d4eSeschrock HELP_REMOVE, 147094e47e9SGeorge Wilson HELP_INITIALIZE, 14865cd9f28Seschrock HELP_SCRUB, 149e4c795beSTom Caputi HELP_RESILVER, 150084fd14fSBrian Behlendorf HELP_TRIM, 151eaca9bbdSeschrock HELP_STATUS, 152b1b8ab34Slling HELP_UPGRADE, 153b1b8ab34Slling HELP_GET, 1541195e687SMark J Musante HELP_SET, 155e9103aaeSGarrett D'Amore HELP_SPLIT, 1569c2acf00SAlek Pinchuk HELP_SYNC, 1574263d13fSGeorge Wilson HELP_REGUID, 1584263d13fSGeorge Wilson HELP_REOPEN 15965cd9f28Seschrock } zpool_help_t; 16065cd9f28Seschrock 16165cd9f28Seschrock 162fa9e4066Sahrens typedef struct zpool_command { 163fa9e4066Sahrens const char *name; 164fa9e4066Sahrens int (*func)(int, char **); 16565cd9f28Seschrock zpool_help_t usage; 166fa9e4066Sahrens } zpool_command_t; 167fa9e4066Sahrens 168fa9e4066Sahrens /* 169fa9e4066Sahrens * Master command table. Each ZFS command has a name, associated function, and 170ea8dc4b6Seschrock * usage message. The usage messages need to be internationalized, so we have 171ea8dc4b6Seschrock * to have a function to return the usage message based on a command index. 17265cd9f28Seschrock * 17365cd9f28Seschrock * These commands are organized according to how they are displayed in the usage 17465cd9f28Seschrock * message. An empty command (one with a NULL name) indicates an empty line in 17565cd9f28Seschrock * the generic usage message. 176fa9e4066Sahrens */ 177fa9e4066Sahrens static zpool_command_t command_table[] = { 17865cd9f28Seschrock { "create", zpool_do_create, HELP_CREATE }, 17965cd9f28Seschrock { "destroy", zpool_do_destroy, HELP_DESTROY }, 180fa9e4066Sahrens { NULL }, 18165cd9f28Seschrock { "add", zpool_do_add, HELP_ADD }, 18299653d4eSeschrock { "remove", zpool_do_remove, HELP_REMOVE }, 183fa9e4066Sahrens { NULL }, 1846401734dSWill Andrews { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR }, 1856401734dSWill Andrews { NULL }, 18686714001SSerapheim Dimitropoulos { "checkpoint", zpool_do_checkpoint, HELP_CHECKPOINT }, 18786714001SSerapheim Dimitropoulos { NULL }, 18865cd9f28Seschrock { "list", zpool_do_list, HELP_LIST }, 18965cd9f28Seschrock { "iostat", zpool_do_iostat, HELP_IOSTAT }, 19065cd9f28Seschrock { "status", zpool_do_status, HELP_STATUS }, 191fa9e4066Sahrens { NULL }, 19265cd9f28Seschrock { "online", zpool_do_online, HELP_ONLINE }, 19365cd9f28Seschrock { "offline", zpool_do_offline, HELP_OFFLINE }, 194ea8dc4b6Seschrock { "clear", zpool_do_clear, HELP_CLEAR }, 1954263d13fSGeorge Wilson { "reopen", zpool_do_reopen, HELP_REOPEN }, 196fa9e4066Sahrens { NULL }, 19765cd9f28Seschrock { "attach", zpool_do_attach, HELP_ATTACH }, 19865cd9f28Seschrock { "detach", zpool_do_detach, HELP_DETACH }, 19965cd9f28Seschrock { "replace", zpool_do_replace, HELP_REPLACE }, 2001195e687SMark J Musante { "split", zpool_do_split, HELP_SPLIT }, 201fa9e4066Sahrens { NULL }, 202094e47e9SGeorge Wilson { "initialize", zpool_do_initialize, HELP_INITIALIZE }, 203e4c795beSTom Caputi { "resilver", zpool_do_resilver, HELP_RESILVER }, 20465cd9f28Seschrock { "scrub", zpool_do_scrub, HELP_SCRUB }, 205084fd14fSBrian Behlendorf { "trim", zpool_do_trim, HELP_TRIM }, 206fa9e4066Sahrens { NULL }, 20765cd9f28Seschrock { "import", zpool_do_import, HELP_IMPORT }, 20865cd9f28Seschrock { "export", zpool_do_export, HELP_EXPORT }, 20906eeb2adSek { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, 210e9103aaeSGarrett D'Amore { "reguid", zpool_do_reguid, HELP_REGUID }, 21106eeb2adSek { NULL }, 212b1b8ab34Slling { "history", zpool_do_history, HELP_HISTORY }, 213b1b8ab34Slling { "get", zpool_do_get, HELP_GET }, 214b1b8ab34Slling { "set", zpool_do_set, HELP_SET }, 2159c2acf00SAlek Pinchuk { "sync", zpool_do_sync, HELP_SYNC }, 216fa9e4066Sahrens }; 217fa9e4066Sahrens 218fa9e4066Sahrens #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 219fa9e4066Sahrens 220663207adSDon Brady #define VDEV_ALLOC_CLASS_LOGS "logs" 221663207adSDon Brady 2224445fffbSMatthew Ahrens static zpool_command_t *current_command; 2232a6b87f0Sek static char history_str[HIS_MAX_RECORD_LEN]; 2244445fffbSMatthew Ahrens static boolean_t log_history = B_TRUE; 22526fd7700SKrishnendu Sadhukhan - Sun Microsystems static uint_t timestamp_fmt = NODATE; 22626fd7700SKrishnendu Sadhukhan - Sun Microsystems 22765cd9f28Seschrock static const char * 2289a686fbcSPaul Dagnelie get_usage(zpool_help_t idx) 2299a686fbcSPaul Dagnelie { 23065cd9f28Seschrock switch (idx) { 23165cd9f28Seschrock case HELP_ADD: 2325711d393Sloli return (gettext("\tadd [-fgLnP] [-o property=value] " 2335711d393Sloli "<pool> <vdev> ...\n")); 23465cd9f28Seschrock case HELP_ATTACH: 2355711d393Sloli return (gettext("\tattach [-f] [-o property=value] " 2365711d393Sloli "<pool> <device> <new-device>\n")); 237ea8dc4b6Seschrock case HELP_CLEAR: 238468c413aSTim Haley return (gettext("\tclear [-nF] <pool> [device]\n")); 23965cd9f28Seschrock case HELP_CREATE: 2407855d95bSToomas Soome return (gettext("\tcreate [-fnd] [-B] " 2417855d95bSToomas Soome "[-o property=value] ... \n" 24204e56356SAndriy Gapon "\t [-O file-system-property=value] ...\n" 24304e56356SAndriy Gapon "\t [-m mountpoint] [-R root] [-t tempname] " 24404e56356SAndriy Gapon "<pool> <vdev> ...\n")); 24586714001SSerapheim Dimitropoulos case HELP_CHECKPOINT: 24686714001SSerapheim Dimitropoulos return (gettext("\tcheckpoint [--discard] <pool> ...\n")); 24765cd9f28Seschrock case HELP_DESTROY: 24865cd9f28Seschrock return (gettext("\tdestroy [-f] <pool>\n")); 24965cd9f28Seschrock case HELP_DETACH: 25065cd9f28Seschrock return (gettext("\tdetach <pool> <device>\n")); 25165cd9f28Seschrock case HELP_EXPORT: 25265cd9f28Seschrock return (gettext("\texport [-f] <pool> ...\n")); 25306eeb2adSek case HELP_HISTORY: 254ecd6cf80Smarks return (gettext("\thistory [-il] [<pool>] ...\n")); 25565cd9f28Seschrock case HELP_IMPORT: 2564c58d714Sdarrenm return (gettext("\timport [-d dir] [-D]\n" 257eb633035STom Caputi "\timport [-d dir | -c cachefile] [-F [-n]] [-l] " 258eb633035STom Caputi "<pool | id>\n" 2592f8aaab3Seschrock "\timport [-o mntopts] [-o property=value] ... \n" 260eb633035STom Caputi "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] " 261f9af39baSGeorge Wilson "[-R root] [-F [-n]] -a\n" 2622f8aaab3Seschrock "\timport [-o mntopts] [-o property=value] ... \n" 263eb633035STom Caputi "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] " 26404e56356SAndriy Gapon "[-R root] [-F [-n]] [-t]\n" 26586714001SSerapheim Dimitropoulos "\t [--rewind-to-checkpoint] <pool | id> [newpool]\n")); 26665cd9f28Seschrock case HELP_IOSTAT: 267663207adSDon Brady return (gettext("\tiostat [-gLPv] [-T d|u] [pool] ... " 268663207adSDon Brady "[interval [count]]\n")); 2696401734dSWill Andrews case HELP_LABELCLEAR: 2706401734dSWill Andrews return (gettext("\tlabelclear [-f] <vdev>\n")); 27165cd9f28Seschrock case HELP_LIST: 272663207adSDon Brady return (gettext("\tlist [-gHLpPv] [-o property[,...]] " 2733f9d6ad7SLin Ling "[-T d|u] [pool] ... [interval [count]]\n")); 27465cd9f28Seschrock case HELP_OFFLINE: 275441d80aaSlling return (gettext("\toffline [-t] <pool> <device> ...\n")); 27665cd9f28Seschrock case HELP_ONLINE: 277441d80aaSlling return (gettext("\tonline <pool> <device> ...\n")); 27865cd9f28Seschrock case HELP_REPLACE: 27965cd9f28Seschrock return (gettext("\treplace [-f] <pool> <device> " 280e45ce728Sahrens "[new-device]\n")); 28199653d4eSeschrock case HELP_REMOVE: 2825cabbc6bSPrashanth Sreenivasa return (gettext("\tremove [-nps] <pool> <device> ...\n")); 2834263d13fSGeorge Wilson case HELP_REOPEN: 28431d7e8faSGeorge Wilson return (gettext("\treopen <pool>\n")); 285094e47e9SGeorge Wilson case HELP_INITIALIZE: 286084fd14fSBrian Behlendorf return (gettext("\tinitialize [-c | -s] <pool> " 287084fd14fSBrian Behlendorf "[<device> ...]\n")); 28865cd9f28Seschrock case HELP_SCRUB: 2891702cce7SAlek Pinchuk return (gettext("\tscrub [-s | -p] <pool> ...\n")); 290e4c795beSTom Caputi case HELP_RESILVER: 291e4c795beSTom Caputi return (gettext("\tresilver <pool> ...\n")); 292084fd14fSBrian Behlendorf case HELP_TRIM: 293084fd14fSBrian Behlendorf return (gettext("\ttrim [-d] [-r <rate>] [-c | -s] <pool> " 294084fd14fSBrian Behlendorf "[<device> ...]\n")); 29565cd9f28Seschrock case HELP_STATUS: 296084fd14fSBrian Behlendorf return (gettext("\tstatus [-igLPvxD] [-T d|u] [pool] ... " 297663207adSDon Brady "[interval [count]]\n")); 298eaca9bbdSeschrock case HELP_UPGRADE: 299eaca9bbdSeschrock return (gettext("\tupgrade\n" 300eaca9bbdSeschrock "\tupgrade -v\n" 301990b4856Slling "\tupgrade [-V version] <-a | pool ...>\n")); 302b1b8ab34Slling case HELP_GET: 303c58b3526SAdam Stevko return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] " 304c58b3526SAdam Stevko "<\"all\" | property[,...]> <pool> ...\n")); 305b1b8ab34Slling case HELP_SET: 306b1b8ab34Slling return (gettext("\tset <property=value> <pool> \n")); 3071195e687SMark J Musante case HELP_SPLIT: 308eb633035STom Caputi return (gettext("\tsplit [-gLlnP] [-R altroot] [-o mntopts]\n" 3091195e687SMark J Musante "\t [-o property=value] <pool> <newpool> " 3101195e687SMark J Musante "[<device> ...]\n")); 311e9103aaeSGarrett D'Amore case HELP_REGUID: 312e9103aaeSGarrett D'Amore return (gettext("\treguid <pool>\n")); 3139c2acf00SAlek Pinchuk case HELP_SYNC: 3149c2acf00SAlek Pinchuk return (gettext("\tsync [pool] ...\n")); 31565cd9f28Seschrock } 31665cd9f28Seschrock 31765cd9f28Seschrock abort(); 31865cd9f28Seschrock /* NOTREACHED */ 31965cd9f28Seschrock } 32065cd9f28Seschrock 321084fd14fSBrian Behlendorf static void 322084fd14fSBrian Behlendorf zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res) 323084fd14fSBrian Behlendorf { 324084fd14fSBrian Behlendorf uint_t children = 0; 325084fd14fSBrian Behlendorf nvlist_t **child; 326084fd14fSBrian Behlendorf uint_t i; 327084fd14fSBrian Behlendorf 328084fd14fSBrian Behlendorf (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 329084fd14fSBrian Behlendorf &child, &children); 330084fd14fSBrian Behlendorf 331084fd14fSBrian Behlendorf if (children == 0) { 332084fd14fSBrian Behlendorf char *path = zpool_vdev_name(g_zfs, zhp, nvroot, 0); 333084fd14fSBrian Behlendorf 334084fd14fSBrian Behlendorf if (strcmp(path, VDEV_TYPE_INDIRECT) != 0) 335084fd14fSBrian Behlendorf fnvlist_add_boolean(res, path); 336084fd14fSBrian Behlendorf 337084fd14fSBrian Behlendorf free(path); 338084fd14fSBrian Behlendorf return; 339084fd14fSBrian Behlendorf } 340084fd14fSBrian Behlendorf 341084fd14fSBrian Behlendorf for (i = 0; i < children; i++) { 342084fd14fSBrian Behlendorf zpool_collect_leaves(zhp, child[i], res); 343084fd14fSBrian Behlendorf } 344084fd14fSBrian Behlendorf } 345fa9e4066Sahrens 346b1b8ab34Slling /* 347b1b8ab34Slling * Callback routine that will print out a pool property value. 348b1b8ab34Slling */ 349990b4856Slling static int 350990b4856Slling print_prop_cb(int prop, void *cb) 351b1b8ab34Slling { 352b1b8ab34Slling FILE *fp = cb; 353b1b8ab34Slling 354663207adSDon Brady (void) fprintf(fp, "\t%-19s ", zpool_prop_to_name(prop)); 355b1b8ab34Slling 356990b4856Slling if (zpool_prop_readonly(prop)) 357990b4856Slling (void) fprintf(fp, " NO "); 358990b4856Slling else 359b24ab676SJeff Bonwick (void) fprintf(fp, " YES "); 360990b4856Slling 361b1b8ab34Slling if (zpool_prop_values(prop) == NULL) 362b1b8ab34Slling (void) fprintf(fp, "-\n"); 363b1b8ab34Slling else 364b1b8ab34Slling (void) fprintf(fp, "%s\n", zpool_prop_values(prop)); 365b1b8ab34Slling 366990b4856Slling return (ZPROP_CONT); 367b1b8ab34Slling } 368b1b8ab34Slling 369fa9e4066Sahrens /* 370fa9e4066Sahrens * Display usage message. If we're inside a command, display only the usage for 371fa9e4066Sahrens * that command. Otherwise, iterate over the entire command table and display 372fa9e4066Sahrens * a complete usage message. 373fa9e4066Sahrens */ 374fa9e4066Sahrens void 37599653d4eSeschrock usage(boolean_t requested) 376fa9e4066Sahrens { 377fa9e4066Sahrens FILE *fp = requested ? stdout : stderr; 378fa9e4066Sahrens 379fa9e4066Sahrens if (current_command == NULL) { 380fa9e4066Sahrens int i; 381fa9e4066Sahrens 382fa9e4066Sahrens (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 383fa9e4066Sahrens (void) fprintf(fp, 384fa9e4066Sahrens gettext("where 'command' is one of the following:\n\n")); 385fa9e4066Sahrens 386fa9e4066Sahrens for (i = 0; i < NCOMMAND; i++) { 387fa9e4066Sahrens if (command_table[i].name == NULL) 388fa9e4066Sahrens (void) fprintf(fp, "\n"); 389fa9e4066Sahrens else 390fa9e4066Sahrens (void) fprintf(fp, "%s", 39165cd9f28Seschrock get_usage(command_table[i].usage)); 392fa9e4066Sahrens } 393fa9e4066Sahrens } else { 394fa9e4066Sahrens (void) fprintf(fp, gettext("usage:\n")); 39565cd9f28Seschrock (void) fprintf(fp, "%s", get_usage(current_command->usage)); 396fa9e4066Sahrens } 397fa9e4066Sahrens 398b1b8ab34Slling if (current_command != NULL && 399b1b8ab34Slling ((strcmp(current_command->name, "set") == 0) || 400990b4856Slling (strcmp(current_command->name, "get") == 0) || 401990b4856Slling (strcmp(current_command->name, "list") == 0))) { 402b1b8ab34Slling 403b1b8ab34Slling (void) fprintf(fp, 404b1b8ab34Slling gettext("\nthe following properties are supported:\n")); 405b1b8ab34Slling 406663207adSDon Brady (void) fprintf(fp, "\n\t%-19s %s %s\n\n", 407990b4856Slling "PROPERTY", "EDIT", "VALUES"); 408b1b8ab34Slling 409b1b8ab34Slling /* Iterate over all properties */ 410990b4856Slling (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, 411990b4856Slling ZFS_TYPE_POOL); 412ad135b5dSChristopher Siden 413663207adSDon Brady (void) fprintf(fp, "\t%-19s ", "feature@..."); 414ad135b5dSChristopher Siden (void) fprintf(fp, "YES disabled | enabled | active\n"); 415ad135b5dSChristopher Siden 416ad135b5dSChristopher Siden (void) fprintf(fp, gettext("\nThe feature@ properties must be " 417ad135b5dSChristopher Siden "appended with a feature name.\nSee zpool-features(5).\n")); 418b1b8ab34Slling } 419b1b8ab34Slling 420e9dbad6fSeschrock /* 421e9dbad6fSeschrock * See comments at end of main(). 422e9dbad6fSeschrock */ 423e9dbad6fSeschrock if (getenv("ZFS_ABORT") != NULL) { 424e9dbad6fSeschrock (void) printf("dumping core by request\n"); 425e9dbad6fSeschrock abort(); 426e9dbad6fSeschrock } 427e9dbad6fSeschrock 428fa9e4066Sahrens exit(requested ? 0 : 2); 429fa9e4066Sahrens } 430fa9e4066Sahrens 431663207adSDon Brady /* 432663207adSDon Brady * print a pool vdev config for dry runs 433663207adSDon Brady */ 434663207adSDon Brady static void 4358654d025Sperrin print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, 436663207adSDon Brady const char *match, int name_flags) 437fa9e4066Sahrens { 438fa9e4066Sahrens nvlist_t **child; 439fa9e4066Sahrens uint_t c, children; 440afefbcddSeschrock char *vname; 441663207adSDon Brady boolean_t printed = B_FALSE; 442fa9e4066Sahrens 443fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 444663207adSDon Brady &child, &children) != 0) { 445663207adSDon Brady if (name != NULL) 446663207adSDon Brady (void) printf("\t%*s%s\n", indent, "", name); 447fa9e4066Sahrens return; 448663207adSDon Brady } 449fa9e4066Sahrens 450afefbcddSeschrock for (c = 0; c < children; c++) { 4518654d025Sperrin uint64_t is_log = B_FALSE; 452663207adSDon Brady char *class = ""; 4538654d025Sperrin 4548654d025Sperrin (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 4558654d025Sperrin &is_log); 456663207adSDon Brady if (is_log) 457663207adSDon Brady class = VDEV_ALLOC_BIAS_LOG; 458663207adSDon Brady (void) nvlist_lookup_string(child[c], 459663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &class); 460663207adSDon Brady if (strcmp(match, class) != 0) 4618654d025Sperrin continue; 4628654d025Sperrin 463663207adSDon Brady if (!printed && name != NULL) { 464663207adSDon Brady (void) printf("\t%*s%s\n", indent, "", name); 465663207adSDon Brady printed = B_TRUE; 466663207adSDon Brady } 467663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags); 468663207adSDon Brady print_vdev_tree(zhp, vname, child[c], indent + 2, "", 469663207adSDon Brady name_flags); 470afefbcddSeschrock free(vname); 471afefbcddSeschrock } 472fa9e4066Sahrens } 473fa9e4066Sahrens 47457221772SChristopher Siden static boolean_t 47557221772SChristopher Siden prop_list_contains_feature(nvlist_t *proplist) 47657221772SChristopher Siden { 47757221772SChristopher Siden nvpair_t *nvp; 47857221772SChristopher Siden for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp; 47957221772SChristopher Siden nvp = nvlist_next_nvpair(proplist, nvp)) { 48057221772SChristopher Siden if (zpool_prop_feature(nvpair_name(nvp))) 48157221772SChristopher Siden return (B_TRUE); 48257221772SChristopher Siden } 48357221772SChristopher Siden return (B_FALSE); 48457221772SChristopher Siden } 48557221772SChristopher Siden 486990b4856Slling /* 487990b4856Slling * Add a property pair (name, string-value) into a property nvlist. 488990b4856Slling */ 489990b4856Slling static int 4900a48a24eStimh add_prop_list(const char *propname, char *propval, nvlist_t **props, 4910a48a24eStimh boolean_t poolprop) 492990b4856Slling { 493d2aa06e8SAndrew Stormont zpool_prop_t prop = ZPOOL_PROP_INVAL; 4940a48a24eStimh zfs_prop_t fprop; 495990b4856Slling nvlist_t *proplist; 4960a48a24eStimh const char *normnm; 4970a48a24eStimh char *strval; 498990b4856Slling 499990b4856Slling if (*props == NULL && 500990b4856Slling nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) { 501990b4856Slling (void) fprintf(stderr, 502990b4856Slling gettext("internal error: out of memory\n")); 503990b4856Slling return (1); 504990b4856Slling } 505990b4856Slling 506990b4856Slling proplist = *props; 507990b4856Slling 5080a48a24eStimh if (poolprop) { 50957221772SChristopher Siden const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION); 51057221772SChristopher Siden 511d2aa06e8SAndrew Stormont if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL && 512ad135b5dSChristopher Siden !zpool_prop_feature(propname)) { 5130a48a24eStimh (void) fprintf(stderr, gettext("property '%s' is " 5140a48a24eStimh "not a valid pool property\n"), propname); 5150a48a24eStimh return (2); 5160a48a24eStimh } 51757221772SChristopher Siden 51857221772SChristopher Siden /* 51957221772SChristopher Siden * feature@ properties and version should not be specified 52057221772SChristopher Siden * at the same time. 52157221772SChristopher Siden */ 5224ae5f5f0SAlan Somers if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) && 52357221772SChristopher Siden nvlist_exists(proplist, vname)) || 52457221772SChristopher Siden (prop == ZPOOL_PROP_VERSION && 52557221772SChristopher Siden prop_list_contains_feature(proplist))) { 52657221772SChristopher Siden (void) fprintf(stderr, gettext("'feature@' and " 52757221772SChristopher Siden "'version' properties cannot be specified " 52857221772SChristopher Siden "together\n")); 52957221772SChristopher Siden return (2); 53057221772SChristopher Siden } 53157221772SChristopher Siden 53257221772SChristopher Siden 533ad135b5dSChristopher Siden if (zpool_prop_feature(propname)) 534ad135b5dSChristopher Siden normnm = propname; 535ad135b5dSChristopher Siden else 536ad135b5dSChristopher Siden normnm = zpool_prop_to_name(prop); 5370a48a24eStimh } else { 53814843421SMatthew Ahrens if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) { 53914843421SMatthew Ahrens normnm = zfs_prop_to_name(fprop); 54014843421SMatthew Ahrens } else { 54114843421SMatthew Ahrens normnm = propname; 5420a48a24eStimh } 543990b4856Slling } 544990b4856Slling 5450a48a24eStimh if (nvlist_lookup_string(proplist, normnm, &strval) == 0 && 5460a48a24eStimh prop != ZPOOL_PROP_CACHEFILE) { 547990b4856Slling (void) fprintf(stderr, gettext("property '%s' " 548990b4856Slling "specified multiple times\n"), propname); 549990b4856Slling return (2); 550990b4856Slling } 551990b4856Slling 5520a48a24eStimh if (nvlist_add_string(proplist, normnm, propval) != 0) { 553990b4856Slling (void) fprintf(stderr, gettext("internal " 554990b4856Slling "error: out of memory\n")); 555990b4856Slling return (1); 556990b4856Slling } 557990b4856Slling 558990b4856Slling return (0); 559990b4856Slling } 560990b4856Slling 56104e56356SAndriy Gapon /* 56204e56356SAndriy Gapon * Set a default property pair (name, string-value) in a property nvlist 56304e56356SAndriy Gapon */ 56404e56356SAndriy Gapon static int 56504e56356SAndriy Gapon add_prop_list_default(const char *propname, char *propval, nvlist_t **props, 56604e56356SAndriy Gapon boolean_t poolprop) 56704e56356SAndriy Gapon { 56804e56356SAndriy Gapon char *pval; 56904e56356SAndriy Gapon 57004e56356SAndriy Gapon if (nvlist_lookup_string(*props, propname, &pval) == 0) 57104e56356SAndriy Gapon return (0); 57204e56356SAndriy Gapon 57304e56356SAndriy Gapon return (add_prop_list(propname, propval, props, poolprop)); 57404e56356SAndriy Gapon } 57504e56356SAndriy Gapon 576fa9e4066Sahrens /* 577663207adSDon Brady * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ... 578fa9e4066Sahrens * 579fa9e4066Sahrens * -f Force addition of devices, even if they appear in use 580663207adSDon Brady * -g Display guid for individual vdev name. 581663207adSDon Brady * -L Follow links when resolving vdev path name. 582fa9e4066Sahrens * -n Do not add the devices, but display the resulting layout if 583fa9e4066Sahrens * they were to be added. 584663207adSDon Brady * -P Display full path for vdev name. 5855711d393Sloli * -o Set property=value. 586fa9e4066Sahrens * 587fa9e4066Sahrens * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 588fa9e4066Sahrens * handled by get_vdev_spec(), which constructs the nvlist needed to pass to 589fa9e4066Sahrens * libzfs. 590fa9e4066Sahrens */ 591fa9e4066Sahrens int 592fa9e4066Sahrens zpool_do_add(int argc, char **argv) 593fa9e4066Sahrens { 59499653d4eSeschrock boolean_t force = B_FALSE; 59599653d4eSeschrock boolean_t dryrun = B_FALSE; 596663207adSDon Brady int name_flags = 0; 597fa9e4066Sahrens int c; 598fa9e4066Sahrens nvlist_t *nvroot; 599fa9e4066Sahrens char *poolname; 6007855d95bSToomas Soome zpool_boot_label_t boot_type; 6017855d95bSToomas Soome uint64_t boot_size; 602fa9e4066Sahrens int ret; 603fa9e4066Sahrens zpool_handle_t *zhp; 604fa9e4066Sahrens nvlist_t *config; 6055711d393Sloli nvlist_t *props = NULL; 6065711d393Sloli char *propval; 607fa9e4066Sahrens 608fa9e4066Sahrens /* check options */ 6095711d393Sloli while ((c = getopt(argc, argv, "fgLnPo:")) != -1) { 610fa9e4066Sahrens switch (c) { 611fa9e4066Sahrens case 'f': 61299653d4eSeschrock force = B_TRUE; 613fa9e4066Sahrens break; 614663207adSDon Brady case 'g': 615663207adSDon Brady name_flags |= VDEV_NAME_GUID; 616663207adSDon Brady break; 617663207adSDon Brady case 'L': 618663207adSDon Brady name_flags |= VDEV_NAME_FOLLOW_LINKS; 619663207adSDon Brady break; 620fa9e4066Sahrens case 'n': 62199653d4eSeschrock dryrun = B_TRUE; 622fa9e4066Sahrens break; 623663207adSDon Brady case 'P': 624663207adSDon Brady name_flags |= VDEV_NAME_PATH; 625663207adSDon Brady break; 6265711d393Sloli case 'o': 6275711d393Sloli if ((propval = strchr(optarg, '=')) == NULL) { 6285711d393Sloli (void) fprintf(stderr, gettext("missing " 6295711d393Sloli "'=' for -o option\n")); 6305711d393Sloli usage(B_FALSE); 6315711d393Sloli } 6325711d393Sloli *propval = '\0'; 6335711d393Sloli propval++; 6345711d393Sloli 6355711d393Sloli if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) || 6365711d393Sloli (add_prop_list(optarg, propval, &props, B_TRUE))) 6375711d393Sloli usage(B_FALSE); 6385711d393Sloli break; 639fa9e4066Sahrens case '?': 640fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 641fa9e4066Sahrens optopt); 64299653d4eSeschrock usage(B_FALSE); 643fa9e4066Sahrens } 644fa9e4066Sahrens } 645fa9e4066Sahrens 646fa9e4066Sahrens argc -= optind; 647fa9e4066Sahrens argv += optind; 648fa9e4066Sahrens 649fa9e4066Sahrens /* get pool name and check number of arguments */ 650fa9e4066Sahrens if (argc < 1) { 651fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 65299653d4eSeschrock usage(B_FALSE); 653fa9e4066Sahrens } 654fa9e4066Sahrens if (argc < 2) { 655fa9e4066Sahrens (void) fprintf(stderr, gettext("missing vdev specification\n")); 65699653d4eSeschrock usage(B_FALSE); 657fa9e4066Sahrens } 658fa9e4066Sahrens 659fa9e4066Sahrens poolname = argv[0]; 660fa9e4066Sahrens 661fa9e4066Sahrens argc--; 662fa9e4066Sahrens argv++; 663fa9e4066Sahrens 66499653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 665fa9e4066Sahrens return (1); 666fa9e4066Sahrens 667088e9d47Seschrock if ((config = zpool_get_config(zhp, NULL)) == NULL) { 668fa9e4066Sahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 669fa9e4066Sahrens poolname); 670fa9e4066Sahrens zpool_close(zhp); 671fa9e4066Sahrens return (1); 672fa9e4066Sahrens } 673fa9e4066Sahrens 6747855d95bSToomas Soome if (zpool_is_bootable(zhp)) 6757855d95bSToomas Soome boot_type = ZPOOL_COPY_BOOT_LABEL; 6767855d95bSToomas Soome else 6777855d95bSToomas Soome boot_type = ZPOOL_NO_BOOT_LABEL; 6787855d95bSToomas Soome 6795711d393Sloli /* unless manually specified use "ashift" pool property (if set) */ 6805711d393Sloli if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) { 6815711d393Sloli int intval; 6825711d393Sloli zprop_source_t src; 6835711d393Sloli char strval[ZPOOL_MAXPROPLEN]; 6845711d393Sloli 6855711d393Sloli intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src); 6865711d393Sloli if (src != ZPROP_SRC_DEFAULT) { 6875711d393Sloli (void) sprintf(strval, "%" PRId32, intval); 6885711d393Sloli verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval, 6895711d393Sloli &props, B_TRUE) == 0); 6905711d393Sloli } 6915711d393Sloli } 6925711d393Sloli 693fa9e4066Sahrens /* pass off to get_vdev_spec for processing */ 6947855d95bSToomas Soome boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 6955711d393Sloli nvroot = make_root_vdev(zhp, props, force, !force, B_FALSE, dryrun, 6967855d95bSToomas Soome boot_type, boot_size, argc, argv); 697fa9e4066Sahrens if (nvroot == NULL) { 698fa9e4066Sahrens zpool_close(zhp); 699fa9e4066Sahrens return (1); 700fa9e4066Sahrens } 701fa9e4066Sahrens 702fa9e4066Sahrens if (dryrun) { 703fa9e4066Sahrens nvlist_t *poolnvroot; 704fa9e4066Sahrens 705fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 706fa9e4066Sahrens &poolnvroot) == 0); 707fa9e4066Sahrens 708fa9e4066Sahrens (void) printf(gettext("would update '%s' to the following " 709fa9e4066Sahrens "configuration:\n"), zpool_get_name(zhp)); 710fa9e4066Sahrens 7118654d025Sperrin /* print original main pool and new tree */ 712663207adSDon Brady print_vdev_tree(zhp, poolname, poolnvroot, 0, "", 713663207adSDon Brady name_flags | VDEV_NAME_TYPE_ID); 714663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, "", name_flags); 715663207adSDon Brady 716663207adSDon Brady /* print other classes: 'dedup', 'special', and 'log' */ 717663207adSDon Brady print_vdev_tree(zhp, "dedup", poolnvroot, 0, 718663207adSDon Brady VDEV_ALLOC_BIAS_DEDUP, name_flags); 719663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_DEDUP, 720663207adSDon Brady name_flags); 721663207adSDon Brady 722663207adSDon Brady print_vdev_tree(zhp, "special", poolnvroot, 0, 723663207adSDon Brady VDEV_ALLOC_BIAS_SPECIAL, name_flags); 724663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_SPECIAL, 725663207adSDon Brady name_flags); 726663207adSDon Brady 727663207adSDon Brady print_vdev_tree(zhp, "logs", poolnvroot, 0, VDEV_ALLOC_BIAS_LOG, 728663207adSDon Brady name_flags); 729663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_LOG, 730663207adSDon Brady name_flags); 731fa9e4066Sahrens 732fa9e4066Sahrens ret = 0; 733fa9e4066Sahrens } else { 734fa9e4066Sahrens ret = (zpool_add(zhp, nvroot) != 0); 735fa9e4066Sahrens } 736fa9e4066Sahrens 7375711d393Sloli nvlist_free(props); 73899653d4eSeschrock nvlist_free(nvroot); 73999653d4eSeschrock zpool_close(zhp); 74099653d4eSeschrock 74199653d4eSeschrock return (ret); 74299653d4eSeschrock } 74399653d4eSeschrock 74499653d4eSeschrock /* 7453f9d6ad7SLin Ling * zpool remove <pool> <vdev> ... 74699653d4eSeschrock * 7475cabbc6bSPrashanth Sreenivasa * Removes the given vdev from the pool. 74899653d4eSeschrock */ 74999653d4eSeschrock int 75099653d4eSeschrock zpool_do_remove(int argc, char **argv) 75199653d4eSeschrock { 75299653d4eSeschrock char *poolname; 753fa94a07fSbrendan int i, ret = 0; 75499653d4eSeschrock zpool_handle_t *zhp; 7555cabbc6bSPrashanth Sreenivasa boolean_t stop = B_FALSE; 7565cabbc6bSPrashanth Sreenivasa boolean_t noop = B_FALSE; 7575cabbc6bSPrashanth Sreenivasa boolean_t parsable = B_FALSE; 7585cabbc6bSPrashanth Sreenivasa char c; 75999653d4eSeschrock 7605cabbc6bSPrashanth Sreenivasa /* check options */ 7615cabbc6bSPrashanth Sreenivasa while ((c = getopt(argc, argv, "nps")) != -1) { 7625cabbc6bSPrashanth Sreenivasa switch (c) { 7635cabbc6bSPrashanth Sreenivasa case 'n': 7645cabbc6bSPrashanth Sreenivasa noop = B_TRUE; 7655cabbc6bSPrashanth Sreenivasa break; 7665cabbc6bSPrashanth Sreenivasa case 'p': 7675cabbc6bSPrashanth Sreenivasa parsable = B_TRUE; 7685cabbc6bSPrashanth Sreenivasa break; 7695cabbc6bSPrashanth Sreenivasa case 's': 7705cabbc6bSPrashanth Sreenivasa stop = B_TRUE; 7715cabbc6bSPrashanth Sreenivasa break; 7725cabbc6bSPrashanth Sreenivasa case '?': 7735cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("invalid option '%c'\n"), 7745cabbc6bSPrashanth Sreenivasa optopt); 7755cabbc6bSPrashanth Sreenivasa usage(B_FALSE); 7765cabbc6bSPrashanth Sreenivasa } 7775cabbc6bSPrashanth Sreenivasa } 7785cabbc6bSPrashanth Sreenivasa 7795cabbc6bSPrashanth Sreenivasa argc -= optind; 7805cabbc6bSPrashanth Sreenivasa argv += optind; 78199653d4eSeschrock 78299653d4eSeschrock /* get pool name and check number of arguments */ 78399653d4eSeschrock if (argc < 1) { 78499653d4eSeschrock (void) fprintf(stderr, gettext("missing pool name argument\n")); 78599653d4eSeschrock usage(B_FALSE); 78699653d4eSeschrock } 78799653d4eSeschrock 78899653d4eSeschrock poolname = argv[0]; 78999653d4eSeschrock 79099653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 79199653d4eSeschrock return (1); 79299653d4eSeschrock 7935cabbc6bSPrashanth Sreenivasa if (stop && noop) { 7945cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("stop request ignored\n")); 7955cabbc6bSPrashanth Sreenivasa return (0); 7965cabbc6bSPrashanth Sreenivasa } 7975cabbc6bSPrashanth Sreenivasa 7985cabbc6bSPrashanth Sreenivasa if (stop) { 7995cabbc6bSPrashanth Sreenivasa if (argc > 1) { 8005cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("too many arguments\n")); 8015cabbc6bSPrashanth Sreenivasa usage(B_FALSE); 8025cabbc6bSPrashanth Sreenivasa } 8035cabbc6bSPrashanth Sreenivasa if (zpool_vdev_remove_cancel(zhp) != 0) 804fa94a07fSbrendan ret = 1; 8055cabbc6bSPrashanth Sreenivasa } else { 8065cabbc6bSPrashanth Sreenivasa if (argc < 2) { 8075cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("missing device\n")); 8085cabbc6bSPrashanth Sreenivasa usage(B_FALSE); 8095cabbc6bSPrashanth Sreenivasa } 8105cabbc6bSPrashanth Sreenivasa 8115cabbc6bSPrashanth Sreenivasa for (i = 1; i < argc; i++) { 8125cabbc6bSPrashanth Sreenivasa if (noop) { 8135cabbc6bSPrashanth Sreenivasa uint64_t size; 8145cabbc6bSPrashanth Sreenivasa 8155cabbc6bSPrashanth Sreenivasa if (zpool_vdev_indirect_size(zhp, argv[i], 8165cabbc6bSPrashanth Sreenivasa &size) != 0) { 8175cabbc6bSPrashanth Sreenivasa ret = 1; 8185cabbc6bSPrashanth Sreenivasa break; 8195cabbc6bSPrashanth Sreenivasa } 8205cabbc6bSPrashanth Sreenivasa if (parsable) { 8215cabbc6bSPrashanth Sreenivasa (void) printf("%s %llu\n", 8225cabbc6bSPrashanth Sreenivasa argv[i], size); 8235cabbc6bSPrashanth Sreenivasa } else { 8245cabbc6bSPrashanth Sreenivasa char valstr[32]; 8255cabbc6bSPrashanth Sreenivasa zfs_nicenum(size, valstr, 8265cabbc6bSPrashanth Sreenivasa sizeof (valstr)); 8275cabbc6bSPrashanth Sreenivasa (void) printf("Memory that will be " 8285cabbc6bSPrashanth Sreenivasa "used after removing %s: %s\n", 8295cabbc6bSPrashanth Sreenivasa argv[i], valstr); 8305cabbc6bSPrashanth Sreenivasa } 8315cabbc6bSPrashanth Sreenivasa } else { 8325cabbc6bSPrashanth Sreenivasa if (zpool_vdev_remove(zhp, argv[i]) != 0) 8335cabbc6bSPrashanth Sreenivasa ret = 1; 8345cabbc6bSPrashanth Sreenivasa } 8355cabbc6bSPrashanth Sreenivasa } 836fa94a07fSbrendan } 83799653d4eSeschrock 838fa9e4066Sahrens return (ret); 839fa9e4066Sahrens } 840fa9e4066Sahrens 8416401734dSWill Andrews /* 8426401734dSWill Andrews * zpool labelclear [-f] <vdev> 8436401734dSWill Andrews * 8446401734dSWill Andrews * -f Force clearing the label for the vdevs which are members of 8456401734dSWill Andrews * the exported or foreign pools. 8466401734dSWill Andrews * 8476401734dSWill Andrews * Verifies that the vdev is not active and zeros out the label information 8486401734dSWill Andrews * on the device. 8496401734dSWill Andrews */ 8506401734dSWill Andrews int 8516401734dSWill Andrews zpool_do_labelclear(int argc, char **argv) 8526401734dSWill Andrews { 8536401734dSWill Andrews char vdev[MAXPATHLEN]; 8546401734dSWill Andrews char *name = NULL; 8556401734dSWill Andrews struct stat st; 8566401734dSWill Andrews int c, fd, ret = 0; 8576401734dSWill Andrews nvlist_t *config; 8586401734dSWill Andrews pool_state_t state; 8596401734dSWill Andrews boolean_t inuse = B_FALSE; 8606401734dSWill Andrews boolean_t force = B_FALSE; 8616401734dSWill Andrews 8626401734dSWill Andrews /* check options */ 8636401734dSWill Andrews while ((c = getopt(argc, argv, "f")) != -1) { 8646401734dSWill Andrews switch (c) { 8656401734dSWill Andrews case 'f': 8666401734dSWill Andrews force = B_TRUE; 8676401734dSWill Andrews break; 8686401734dSWill Andrews default: 8696401734dSWill Andrews (void) fprintf(stderr, gettext("invalid option '%c'\n"), 8706401734dSWill Andrews optopt); 8716401734dSWill Andrews usage(B_FALSE); 8726401734dSWill Andrews } 8736401734dSWill Andrews } 8746401734dSWill Andrews 8756401734dSWill Andrews argc -= optind; 8766401734dSWill Andrews argv += optind; 8776401734dSWill Andrews 8786401734dSWill Andrews /* get vdev name */ 8796401734dSWill Andrews if (argc < 1) { 8806401734dSWill Andrews (void) fprintf(stderr, gettext("missing vdev name\n")); 8816401734dSWill Andrews usage(B_FALSE); 8826401734dSWill Andrews } 8836401734dSWill Andrews if (argc > 1) { 8846401734dSWill Andrews (void) fprintf(stderr, gettext("too many arguments\n")); 8856401734dSWill Andrews usage(B_FALSE); 8866401734dSWill Andrews } 8876401734dSWill Andrews 8886401734dSWill Andrews /* 8896401734dSWill Andrews * Check if we were given absolute path and use it as is. 8906401734dSWill Andrews * Otherwise if the provided vdev name doesn't point to a file, 8916401734dSWill Andrews * try prepending dsk path and appending s0. 8926401734dSWill Andrews */ 8936401734dSWill Andrews (void) strlcpy(vdev, argv[0], sizeof (vdev)); 8946401734dSWill Andrews if (vdev[0] != '/' && stat(vdev, &st) != 0) { 8956401734dSWill Andrews char *s; 8966401734dSWill Andrews 8976401734dSWill Andrews (void) snprintf(vdev, sizeof (vdev), "%s/%s", 8986401734dSWill Andrews ZFS_DISK_ROOT, argv[0]); 8996401734dSWill Andrews if ((s = strrchr(argv[0], 's')) == NULL || 9006401734dSWill Andrews !isdigit(*(s + 1))) 9016401734dSWill Andrews (void) strlcat(vdev, "s0", sizeof (vdev)); 9026401734dSWill Andrews if (stat(vdev, &st) != 0) { 9036401734dSWill Andrews (void) fprintf(stderr, gettext( 9046401734dSWill Andrews "failed to find device %s, try specifying absolute " 9056401734dSWill Andrews "path instead\n"), argv[0]); 9066401734dSWill Andrews return (1); 9076401734dSWill Andrews } 9086401734dSWill Andrews } 9096401734dSWill Andrews 9106401734dSWill Andrews if ((fd = open(vdev, O_RDWR)) < 0) { 9116401734dSWill Andrews (void) fprintf(stderr, gettext("failed to open %s: %s\n"), 9126401734dSWill Andrews vdev, strerror(errno)); 9136401734dSWill Andrews return (1); 9146401734dSWill Andrews } 9156401734dSWill Andrews 916c861bfbdSAlan Somers if (zpool_read_label(fd, &config) != 0) { 9176401734dSWill Andrews (void) fprintf(stderr, 9186401734dSWill Andrews gettext("failed to read label from %s\n"), vdev); 9196401734dSWill Andrews return (1); 9206401734dSWill Andrews } 9216401734dSWill Andrews nvlist_free(config); 9226401734dSWill Andrews 9236401734dSWill Andrews ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse); 9246401734dSWill Andrews if (ret != 0) { 9256401734dSWill Andrews (void) fprintf(stderr, 9266401734dSWill Andrews gettext("failed to check state for %s\n"), vdev); 9276401734dSWill Andrews return (1); 9286401734dSWill Andrews } 9296401734dSWill Andrews 9306401734dSWill Andrews if (!inuse) 9316401734dSWill Andrews goto wipe_label; 9326401734dSWill Andrews 9336401734dSWill Andrews switch (state) { 9346401734dSWill Andrews default: 9356401734dSWill Andrews case POOL_STATE_ACTIVE: 9366401734dSWill Andrews case POOL_STATE_SPARE: 9376401734dSWill Andrews case POOL_STATE_L2CACHE: 9386401734dSWill Andrews (void) fprintf(stderr, gettext( 9396401734dSWill Andrews "%s is a member (%s) of pool \"%s\"\n"), 9406401734dSWill Andrews vdev, zpool_pool_state_to_name(state), name); 9416401734dSWill Andrews ret = 1; 9426401734dSWill Andrews goto errout; 9436401734dSWill Andrews 9446401734dSWill Andrews case POOL_STATE_EXPORTED: 9456401734dSWill Andrews if (force) 9466401734dSWill Andrews break; 9476401734dSWill Andrews (void) fprintf(stderr, gettext( 9486401734dSWill Andrews "use '-f' to override the following error:\n" 9496401734dSWill Andrews "%s is a member of exported pool \"%s\"\n"), 9506401734dSWill Andrews vdev, name); 9516401734dSWill Andrews ret = 1; 9526401734dSWill Andrews goto errout; 9536401734dSWill Andrews 9546401734dSWill Andrews case POOL_STATE_POTENTIALLY_ACTIVE: 9556401734dSWill Andrews if (force) 9566401734dSWill Andrews break; 9576401734dSWill Andrews (void) fprintf(stderr, gettext( 9586401734dSWill Andrews "use '-f' to override the following error:\n" 9596401734dSWill Andrews "%s is a member of potentially active pool \"%s\"\n"), 9606401734dSWill Andrews vdev, name); 9616401734dSWill Andrews ret = 1; 9626401734dSWill Andrews goto errout; 9636401734dSWill Andrews 9646401734dSWill Andrews case POOL_STATE_DESTROYED: 9656401734dSWill Andrews /* inuse should never be set for a destroyed pool */ 9666401734dSWill Andrews assert(0); 9676401734dSWill Andrews break; 9686401734dSWill Andrews } 9696401734dSWill Andrews 9706401734dSWill Andrews wipe_label: 9716401734dSWill Andrews ret = zpool_clear_label(fd); 9726401734dSWill Andrews if (ret != 0) { 9736401734dSWill Andrews (void) fprintf(stderr, 9746401734dSWill Andrews gettext("failed to clear label for %s\n"), vdev); 9756401734dSWill Andrews } 9766401734dSWill Andrews 9776401734dSWill Andrews errout: 9786401734dSWill Andrews free(name); 9796401734dSWill Andrews (void) close(fd); 9806401734dSWill Andrews 9816401734dSWill Andrews return (ret); 9826401734dSWill Andrews } 9836401734dSWill Andrews 984fa9e4066Sahrens /* 9857855d95bSToomas Soome * zpool create [-fnd] [-B] [-o property=value] ... 9860a48a24eStimh * [-O file-system-property=value] ... 98704e56356SAndriy Gapon * [-R root] [-m mountpoint] [-t tempname] <pool> <dev> ... 988fa9e4066Sahrens * 9897855d95bSToomas Soome * -B Create boot partition. 990fa9e4066Sahrens * -f Force creation, even if devices appear in use 991fa9e4066Sahrens * -n Do not create the pool, but display the resulting layout if it 992fa9e4066Sahrens * were to be created. 99304e56356SAndriy Gapon * -R Create a pool under an alternate root 99404e56356SAndriy Gapon * -m Set default mountpoint for the root dataset. By default it's 995ad135b5dSChristopher Siden * '/<pool>' 99604e56356SAndriy Gapon * -t Use the temporary name until the pool is exported. 997990b4856Slling * -o Set property=value. 998ad135b5dSChristopher Siden * -d Don't automatically enable all supported pool features 999ad135b5dSChristopher Siden * (individual features can be enabled with -o). 10000a48a24eStimh * -O Set fsproperty=value in the pool's root file system 1001fa9e4066Sahrens * 1002b1b8ab34Slling * Creates the named pool according to the given vdev specification. The 1003fa9e4066Sahrens * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once 1004fa9e4066Sahrens * we get the nvlist back from get_vdev_spec(), we either print out the contents 1005fa9e4066Sahrens * (if '-n' was specified), or pass it to libzfs to do the creation. 1006fa9e4066Sahrens */ 10077855d95bSToomas Soome 10087855d95bSToomas Soome #define SYSTEM256 (256 * 1024 * 1024) 1009fa9e4066Sahrens int 1010fa9e4066Sahrens zpool_do_create(int argc, char **argv) 1011fa9e4066Sahrens { 101299653d4eSeschrock boolean_t force = B_FALSE; 101399653d4eSeschrock boolean_t dryrun = B_FALSE; 1014ad135b5dSChristopher Siden boolean_t enable_all_pool_feat = B_TRUE; 10157855d95bSToomas Soome zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL; 10167855d95bSToomas Soome uint64_t boot_size = 0; 1017fa9e4066Sahrens int c; 1018990b4856Slling nvlist_t *nvroot = NULL; 1019fa9e4066Sahrens char *poolname; 102004e56356SAndriy Gapon char *tname = NULL; 1021990b4856Slling int ret = 1; 1022fa9e4066Sahrens char *altroot = NULL; 1023fa9e4066Sahrens char *mountpoint = NULL; 10240a48a24eStimh nvlist_t *fsprops = NULL; 1025990b4856Slling nvlist_t *props = NULL; 10262f8aaab3Seschrock char *propval; 1027fa9e4066Sahrens 1028fa9e4066Sahrens /* check options */ 102904e56356SAndriy Gapon while ((c = getopt(argc, argv, ":fndBR:m:o:O:t:")) != -1) { 1030fa9e4066Sahrens switch (c) { 1031fa9e4066Sahrens case 'f': 103299653d4eSeschrock force = B_TRUE; 1033fa9e4066Sahrens break; 1034fa9e4066Sahrens case 'n': 103599653d4eSeschrock dryrun = B_TRUE; 1036fa9e4066Sahrens break; 1037ad135b5dSChristopher Siden case 'd': 1038ad135b5dSChristopher Siden enable_all_pool_feat = B_FALSE; 1039ad135b5dSChristopher Siden break; 10407855d95bSToomas Soome case 'B': 10417855d95bSToomas Soome /* 10427855d95bSToomas Soome * We should create the system partition. 10437855d95bSToomas Soome * Also make sure the size is set. 10447855d95bSToomas Soome */ 10457855d95bSToomas Soome boot_type = ZPOOL_CREATE_BOOT_LABEL; 10467855d95bSToomas Soome if (boot_size == 0) 10477855d95bSToomas Soome boot_size = SYSTEM256; 10487855d95bSToomas Soome break; 1049fa9e4066Sahrens case 'R': 1050fa9e4066Sahrens altroot = optarg; 1051990b4856Slling if (add_prop_list(zpool_prop_to_name( 10520a48a24eStimh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 1053990b4856Slling goto errout; 105404e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name( 10550a48a24eStimh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 1056990b4856Slling goto errout; 1057fa9e4066Sahrens break; 1058fa9e4066Sahrens case 'm': 10598b713775SWill Andrews /* Equivalent to -O mountpoint=optarg */ 1060fa9e4066Sahrens mountpoint = optarg; 1061fa9e4066Sahrens break; 1062990b4856Slling case 'o': 1063990b4856Slling if ((propval = strchr(optarg, '=')) == NULL) { 1064990b4856Slling (void) fprintf(stderr, gettext("missing " 1065990b4856Slling "'=' for -o option\n")); 1066990b4856Slling goto errout; 1067990b4856Slling } 1068990b4856Slling *propval = '\0'; 1069990b4856Slling propval++; 1070990b4856Slling 10710a48a24eStimh if (add_prop_list(optarg, propval, &props, B_TRUE)) 10720a48a24eStimh goto errout; 1073ad135b5dSChristopher Siden 10747855d95bSToomas Soome /* 10757855d95bSToomas Soome * Get bootsize value for make_root_vdev(). 10767855d95bSToomas Soome */ 10777855d95bSToomas Soome if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) { 10787855d95bSToomas Soome if (zfs_nicestrtonum(g_zfs, propval, 10797855d95bSToomas Soome &boot_size) < 0 || boot_size == 0) { 10807855d95bSToomas Soome (void) fprintf(stderr, 10817855d95bSToomas Soome gettext("bad boot partition size " 10827855d95bSToomas Soome "'%s': %s\n"), propval, 10837855d95bSToomas Soome libzfs_error_description(g_zfs)); 10847855d95bSToomas Soome goto errout; 10857855d95bSToomas Soome } 10867855d95bSToomas Soome } 10877855d95bSToomas Soome 1088ad135b5dSChristopher Siden /* 1089ad135b5dSChristopher Siden * If the user is creating a pool that doesn't support 1090ad135b5dSChristopher Siden * feature flags, don't enable any features. 1091ad135b5dSChristopher Siden */ 1092ad135b5dSChristopher Siden if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) { 1093ad135b5dSChristopher Siden char *end; 1094ad135b5dSChristopher Siden u_longlong_t ver; 1095ad135b5dSChristopher Siden 1096ad135b5dSChristopher Siden ver = strtoull(propval, &end, 10); 1097ad135b5dSChristopher Siden if (*end == '\0' && 1098ad135b5dSChristopher Siden ver < SPA_VERSION_FEATURES) { 1099ad135b5dSChristopher Siden enable_all_pool_feat = B_FALSE; 1100ad135b5dSChristopher Siden } 1101ad135b5dSChristopher Siden } 1102c423721fSXin Li if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT) 1103c423721fSXin Li altroot = propval; 11040a48a24eStimh break; 11050a48a24eStimh case 'O': 11060a48a24eStimh if ((propval = strchr(optarg, '=')) == NULL) { 11070a48a24eStimh (void) fprintf(stderr, gettext("missing " 11080a48a24eStimh "'=' for -O option\n")); 11090a48a24eStimh goto errout; 11100a48a24eStimh } 11110a48a24eStimh *propval = '\0'; 11120a48a24eStimh propval++; 11130a48a24eStimh 11148b713775SWill Andrews /* 11158b713775SWill Andrews * Mountpoints are checked and then added later. 11168b713775SWill Andrews * Uniquely among properties, they can be specified 11178b713775SWill Andrews * more than once, to avoid conflict with -m. 11188b713775SWill Andrews */ 11198b713775SWill Andrews if (0 == strcmp(optarg, 11208b713775SWill Andrews zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) { 11218b713775SWill Andrews mountpoint = propval; 11228b713775SWill Andrews } else if (add_prop_list(optarg, propval, &fsprops, 11238b713775SWill Andrews B_FALSE)) { 1124990b4856Slling goto errout; 11258b713775SWill Andrews } 1126990b4856Slling break; 112704e56356SAndriy Gapon case 't': 112804e56356SAndriy Gapon /* 112904e56356SAndriy Gapon * Sanity check temporary pool name. 113004e56356SAndriy Gapon */ 113104e56356SAndriy Gapon if (strchr(optarg, '/') != NULL) { 113204e56356SAndriy Gapon (void) fprintf(stderr, gettext("cannot create " 113304e56356SAndriy Gapon "'%s': invalid character '/' in temporary " 113404e56356SAndriy Gapon "name\n"), optarg); 113504e56356SAndriy Gapon (void) fprintf(stderr, gettext("use 'zfs " 113604e56356SAndriy Gapon "create' to create a dataset\n")); 113704e56356SAndriy Gapon goto errout; 113804e56356SAndriy Gapon } 113904e56356SAndriy Gapon 114004e56356SAndriy Gapon if (add_prop_list(zpool_prop_to_name( 114104e56356SAndriy Gapon ZPOOL_PROP_TNAME), optarg, &props, B_TRUE)) 114204e56356SAndriy Gapon goto errout; 114304e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name( 114404e56356SAndriy Gapon ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 114504e56356SAndriy Gapon goto errout; 114604e56356SAndriy Gapon tname = optarg; 114704e56356SAndriy Gapon break; 1148fa9e4066Sahrens case ':': 1149fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 1150fa9e4066Sahrens "'%c' option\n"), optopt); 1151990b4856Slling goto badusage; 1152fa9e4066Sahrens case '?': 1153fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1154fa9e4066Sahrens optopt); 1155990b4856Slling goto badusage; 1156fa9e4066Sahrens } 1157fa9e4066Sahrens } 1158fa9e4066Sahrens 1159fa9e4066Sahrens argc -= optind; 1160fa9e4066Sahrens argv += optind; 1161fa9e4066Sahrens 1162fa9e4066Sahrens /* get pool name and check number of arguments */ 1163fa9e4066Sahrens if (argc < 1) { 1164fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 1165990b4856Slling goto badusage; 1166fa9e4066Sahrens } 1167fa9e4066Sahrens if (argc < 2) { 1168fa9e4066Sahrens (void) fprintf(stderr, gettext("missing vdev specification\n")); 1169990b4856Slling goto badusage; 1170fa9e4066Sahrens } 1171fa9e4066Sahrens 1172fa9e4066Sahrens poolname = argv[0]; 1173fa9e4066Sahrens 1174fa9e4066Sahrens /* 1175fa9e4066Sahrens * As a special case, check for use of '/' in the name, and direct the 1176fa9e4066Sahrens * user to use 'zfs create' instead. 1177fa9e4066Sahrens */ 1178fa9e4066Sahrens if (strchr(poolname, '/') != NULL) { 1179fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot create '%s': invalid " 1180fa9e4066Sahrens "character '/' in pool name\n"), poolname); 1181fa9e4066Sahrens (void) fprintf(stderr, gettext("use 'zfs create' to " 1182fa9e4066Sahrens "create a dataset\n")); 1183990b4856Slling goto errout; 1184fa9e4066Sahrens } 1185fa9e4066Sahrens 11867855d95bSToomas Soome /* 11877855d95bSToomas Soome * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used, 11887855d95bSToomas Soome * and not set otherwise. 11897855d95bSToomas Soome */ 11907855d95bSToomas Soome if (boot_type == ZPOOL_CREATE_BOOT_LABEL) { 11917855d95bSToomas Soome const char *propname; 11927855d95bSToomas Soome char *strptr, *buf = NULL; 11937855d95bSToomas Soome int rv; 11947855d95bSToomas Soome 11957855d95bSToomas Soome propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 11967855d95bSToomas Soome if (nvlist_lookup_string(props, propname, &strptr) != 0) { 11977855d95bSToomas Soome (void) asprintf(&buf, "%" PRIu64, boot_size); 11987855d95bSToomas Soome if (buf == NULL) { 11997855d95bSToomas Soome (void) fprintf(stderr, 12007855d95bSToomas Soome gettext("internal error: out of memory\n")); 12017855d95bSToomas Soome goto errout; 12027855d95bSToomas Soome } 12037855d95bSToomas Soome rv = add_prop_list(propname, buf, &props, B_TRUE); 12047855d95bSToomas Soome free(buf); 12057855d95bSToomas Soome if (rv != 0) 12067855d95bSToomas Soome goto errout; 12077855d95bSToomas Soome } 12087855d95bSToomas Soome } else { 12097855d95bSToomas Soome const char *propname; 12107855d95bSToomas Soome char *strptr; 12117855d95bSToomas Soome 12127855d95bSToomas Soome propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 12137855d95bSToomas Soome if (nvlist_lookup_string(props, propname, &strptr) == 0) { 12147855d95bSToomas Soome (void) fprintf(stderr, gettext("error: setting boot " 12157855d95bSToomas Soome "partition size requires option '-B'\n")); 12167855d95bSToomas Soome goto errout; 12177855d95bSToomas Soome } 12187855d95bSToomas Soome } 12197855d95bSToomas Soome 1220fa9e4066Sahrens /* pass off to get_vdev_spec for bulk processing */ 12215711d393Sloli nvroot = make_root_vdev(NULL, props, force, !force, B_FALSE, dryrun, 12227855d95bSToomas Soome boot_type, boot_size, argc - 1, argv + 1); 1223fa9e4066Sahrens if (nvroot == NULL) 12240a48a24eStimh goto errout; 1225fa9e4066Sahrens 122699653d4eSeschrock /* make_root_vdev() allows 0 toplevel children if there are spares */ 1227b7b97454Sperrin if (!zfs_allocatable_devs(nvroot)) { 122899653d4eSeschrock (void) fprintf(stderr, gettext("invalid vdev " 122999653d4eSeschrock "specification: at least one toplevel vdev must be " 123099653d4eSeschrock "specified\n")); 1231990b4856Slling goto errout; 123299653d4eSeschrock } 123399653d4eSeschrock 1234fa9e4066Sahrens if (altroot != NULL && altroot[0] != '/') { 1235fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid alternate root '%s': " 1236e9dbad6fSeschrock "must be an absolute path\n"), altroot); 1237990b4856Slling goto errout; 1238fa9e4066Sahrens } 1239fa9e4066Sahrens 1240fa9e4066Sahrens /* 1241fa9e4066Sahrens * Check the validity of the mountpoint and direct the user to use the 1242fa9e4066Sahrens * '-m' mountpoint option if it looks like its in use. 1243fa9e4066Sahrens */ 1244fa9e4066Sahrens if (mountpoint == NULL || 1245fa9e4066Sahrens (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 1246fa9e4066Sahrens strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) { 1247fa9e4066Sahrens char buf[MAXPATHLEN]; 124811022c7cStimh DIR *dirp; 1249fa9e4066Sahrens 1250fa9e4066Sahrens if (mountpoint && mountpoint[0] != '/') { 1251fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid mountpoint " 1252fa9e4066Sahrens "'%s': must be an absolute path, 'legacy', or " 1253fa9e4066Sahrens "'none'\n"), mountpoint); 1254990b4856Slling goto errout; 1255fa9e4066Sahrens } 1256fa9e4066Sahrens 1257fa9e4066Sahrens if (mountpoint == NULL) { 1258fa9e4066Sahrens if (altroot != NULL) 1259fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s/%s", 1260fa9e4066Sahrens altroot, poolname); 1261fa9e4066Sahrens else 1262fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "/%s", 1263fa9e4066Sahrens poolname); 1264fa9e4066Sahrens } else { 1265fa9e4066Sahrens if (altroot != NULL) 1266fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s%s", 1267fa9e4066Sahrens altroot, mountpoint); 1268fa9e4066Sahrens else 1269fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s", 1270fa9e4066Sahrens mountpoint); 1271fa9e4066Sahrens } 1272fa9e4066Sahrens 127311022c7cStimh if ((dirp = opendir(buf)) == NULL && errno != ENOENT) { 127411022c7cStimh (void) fprintf(stderr, gettext("mountpoint '%s' : " 127511022c7cStimh "%s\n"), buf, strerror(errno)); 1276fa9e4066Sahrens (void) fprintf(stderr, gettext("use '-m' " 1277fa9e4066Sahrens "option to provide a different default\n")); 1278990b4856Slling goto errout; 127911022c7cStimh } else if (dirp) { 128011022c7cStimh int count = 0; 128111022c7cStimh 128211022c7cStimh while (count < 3 && readdir(dirp) != NULL) 128311022c7cStimh count++; 128411022c7cStimh (void) closedir(dirp); 128511022c7cStimh 128611022c7cStimh if (count > 2) { 128711022c7cStimh (void) fprintf(stderr, gettext("mountpoint " 128811022c7cStimh "'%s' exists and is not empty\n"), buf); 128911022c7cStimh (void) fprintf(stderr, gettext("use '-m' " 129011022c7cStimh "option to provide a " 129111022c7cStimh "different default\n")); 129211022c7cStimh goto errout; 129311022c7cStimh } 1294fa9e4066Sahrens } 1295fa9e4066Sahrens } 1296fa9e4066Sahrens 12978b713775SWill Andrews /* 12988b713775SWill Andrews * Now that the mountpoint's validity has been checked, ensure that 12998b713775SWill Andrews * the property is set appropriately prior to creating the pool. 13008b713775SWill Andrews */ 13018b713775SWill Andrews if (mountpoint != NULL) { 13028b713775SWill Andrews ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 13038b713775SWill Andrews mountpoint, &fsprops, B_FALSE); 13048b713775SWill Andrews if (ret != 0) 13058b713775SWill Andrews goto errout; 13068b713775SWill Andrews } 13078b713775SWill Andrews 13088b713775SWill Andrews ret = 1; 1309fa9e4066Sahrens if (dryrun) { 1310fa9e4066Sahrens /* 1311fa9e4066Sahrens * For a dry run invocation, print out a basic message and run 1312fa9e4066Sahrens * through all the vdevs in the list and print out in an 1313fa9e4066Sahrens * appropriate hierarchy. 1314fa9e4066Sahrens */ 1315fa9e4066Sahrens (void) printf(gettext("would create '%s' with the " 1316fa9e4066Sahrens "following layout:\n\n"), poolname); 1317fa9e4066Sahrens 1318663207adSDon Brady print_vdev_tree(NULL, poolname, nvroot, 0, "", 0); 1319663207adSDon Brady print_vdev_tree(NULL, "dedup", nvroot, 0, 1320663207adSDon Brady VDEV_ALLOC_BIAS_DEDUP, 0); 1321663207adSDon Brady print_vdev_tree(NULL, "special", nvroot, 0, 1322663207adSDon Brady VDEV_ALLOC_BIAS_SPECIAL, 0); 1323663207adSDon Brady print_vdev_tree(NULL, "logs", nvroot, 0, 1324663207adSDon Brady VDEV_ALLOC_BIAS_LOG, 0); 1325fa9e4066Sahrens 1326fa9e4066Sahrens ret = 0; 1327fa9e4066Sahrens } else { 1328fa9e4066Sahrens /* 1329fa9e4066Sahrens * Hand off to libzfs. 1330fa9e4066Sahrens */ 1331ad135b5dSChristopher Siden if (enable_all_pool_feat) { 13322acef22dSMatthew Ahrens spa_feature_t i; 1333ad135b5dSChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 1334ad135b5dSChristopher Siden char propname[MAXPATHLEN]; 1335ad135b5dSChristopher Siden zfeature_info_t *feat = &spa_feature_table[i]; 1336ad135b5dSChristopher Siden 1337ad135b5dSChristopher Siden (void) snprintf(propname, sizeof (propname), 1338ad135b5dSChristopher Siden "feature@%s", feat->fi_uname); 1339ad135b5dSChristopher Siden 1340ad135b5dSChristopher Siden /* 1341ad135b5dSChristopher Siden * Skip feature if user specified it manually 1342ad135b5dSChristopher Siden * on the command line. 1343ad135b5dSChristopher Siden */ 1344ad135b5dSChristopher Siden if (nvlist_exists(props, propname)) 1345ad135b5dSChristopher Siden continue; 1346ad135b5dSChristopher Siden 13478b713775SWill Andrews ret = add_prop_list(propname, 13488b713775SWill Andrews ZFS_FEATURE_ENABLED, &props, B_TRUE); 13498b713775SWill Andrews if (ret != 0) 1350ad135b5dSChristopher Siden goto errout; 1351ad135b5dSChristopher Siden } 1352ad135b5dSChristopher Siden } 13538b713775SWill Andrews 13548b713775SWill Andrews ret = 1; 13550a48a24eStimh if (zpool_create(g_zfs, poolname, 13560a48a24eStimh nvroot, props, fsprops) == 0) { 135704e56356SAndriy Gapon zfs_handle_t *pool = zfs_open(g_zfs, 135804e56356SAndriy Gapon tname ? tname : poolname, ZFS_TYPE_FILESYSTEM); 1359fa9e4066Sahrens if (pool != NULL) { 1360fa9e4066Sahrens if (zfs_mount(pool, NULL, 0) == 0) 1361da6c28aaSamw ret = zfs_shareall(pool); 1362fa9e4066Sahrens zfs_close(pool); 1363fa9e4066Sahrens } 136499653d4eSeschrock } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { 136599653d4eSeschrock (void) fprintf(stderr, gettext("pool name may have " 136699653d4eSeschrock "been omitted\n")); 1367fa9e4066Sahrens } 1368fa9e4066Sahrens } 1369fa9e4066Sahrens 1370990b4856Slling errout: 13712f8aaab3Seschrock nvlist_free(nvroot); 13720a48a24eStimh nvlist_free(fsprops); 13732f8aaab3Seschrock nvlist_free(props); 1374fa9e4066Sahrens return (ret); 1375990b4856Slling badusage: 13760a48a24eStimh nvlist_free(fsprops); 1377990b4856Slling nvlist_free(props); 1378990b4856Slling usage(B_FALSE); 1379990b4856Slling return (2); 1380fa9e4066Sahrens } 1381fa9e4066Sahrens 1382fa9e4066Sahrens /* 1383fa9e4066Sahrens * zpool destroy <pool> 1384fa9e4066Sahrens * 138504e56356SAndriy Gapon * -f Forcefully unmount any datasets 1386fa9e4066Sahrens * 1387fa9e4066Sahrens * Destroy the given pool. Automatically unmounts any datasets in the pool. 1388fa9e4066Sahrens */ 1389fa9e4066Sahrens int 1390fa9e4066Sahrens zpool_do_destroy(int argc, char **argv) 1391fa9e4066Sahrens { 139299653d4eSeschrock boolean_t force = B_FALSE; 1393fa9e4066Sahrens int c; 1394fa9e4066Sahrens char *pool; 1395fa9e4066Sahrens zpool_handle_t *zhp; 1396fa9e4066Sahrens int ret; 1397fa9e4066Sahrens 1398fa9e4066Sahrens /* check options */ 1399fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) { 1400fa9e4066Sahrens switch (c) { 1401fa9e4066Sahrens case 'f': 140299653d4eSeschrock force = B_TRUE; 1403fa9e4066Sahrens break; 1404fa9e4066Sahrens case '?': 1405fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1406fa9e4066Sahrens optopt); 140799653d4eSeschrock usage(B_FALSE); 1408fa9e4066Sahrens } 1409fa9e4066Sahrens } 1410fa9e4066Sahrens 1411fa9e4066Sahrens argc -= optind; 1412fa9e4066Sahrens argv += optind; 1413fa9e4066Sahrens 1414fa9e4066Sahrens /* check arguments */ 1415fa9e4066Sahrens if (argc < 1) { 1416fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool argument\n")); 141799653d4eSeschrock usage(B_FALSE); 1418fa9e4066Sahrens } 1419fa9e4066Sahrens if (argc > 1) { 1420fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 142199653d4eSeschrock usage(B_FALSE); 1422fa9e4066Sahrens } 1423fa9e4066Sahrens 1424fa9e4066Sahrens pool = argv[0]; 1425fa9e4066Sahrens 142699653d4eSeschrock if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 1427fa9e4066Sahrens /* 1428fa9e4066Sahrens * As a special case, check for use of '/' in the name, and 1429fa9e4066Sahrens * direct the user to use 'zfs destroy' instead. 1430fa9e4066Sahrens */ 1431fa9e4066Sahrens if (strchr(pool, '/') != NULL) 1432fa9e4066Sahrens (void) fprintf(stderr, gettext("use 'zfs destroy' to " 1433fa9e4066Sahrens "destroy a dataset\n")); 1434fa9e4066Sahrens return (1); 1435fa9e4066Sahrens } 1436fa9e4066Sahrens 1437f3861e1aSahl if (zpool_disable_datasets(zhp, force) != 0) { 1438fa9e4066Sahrens (void) fprintf(stderr, gettext("could not destroy '%s': " 1439fa9e4066Sahrens "could not unmount datasets\n"), zpool_get_name(zhp)); 1440fa9e4066Sahrens return (1); 1441fa9e4066Sahrens } 1442fa9e4066Sahrens 14434445fffbSMatthew Ahrens /* The history must be logged as part of the export */ 14444445fffbSMatthew Ahrens log_history = B_FALSE; 14454445fffbSMatthew Ahrens 14464445fffbSMatthew Ahrens ret = (zpool_destroy(zhp, history_str) != 0); 1447fa9e4066Sahrens 1448fa9e4066Sahrens zpool_close(zhp); 1449fa9e4066Sahrens 1450fa9e4066Sahrens return (ret); 1451fa9e4066Sahrens } 1452fa9e4066Sahrens 1453fa9e4066Sahrens /* 1454fa9e4066Sahrens * zpool export [-f] <pool> ... 1455fa9e4066Sahrens * 1456fa9e4066Sahrens * -f Forcefully unmount datasets 1457fa9e4066Sahrens * 1458b1b8ab34Slling * Export the given pools. By default, the command will attempt to cleanly 1459fa9e4066Sahrens * unmount any active datasets within the pool. If the '-f' flag is specified, 1460fa9e4066Sahrens * then the datasets will be forcefully unmounted. 1461fa9e4066Sahrens */ 1462fa9e4066Sahrens int 1463fa9e4066Sahrens zpool_do_export(int argc, char **argv) 1464fa9e4066Sahrens { 146599653d4eSeschrock boolean_t force = B_FALSE; 1466394ab0cbSGeorge Wilson boolean_t hardforce = B_FALSE; 1467fa9e4066Sahrens int c; 1468fa9e4066Sahrens zpool_handle_t *zhp; 1469fa9e4066Sahrens int ret; 1470fa9e4066Sahrens int i; 1471fa9e4066Sahrens 1472fa9e4066Sahrens /* check options */ 1473394ab0cbSGeorge Wilson while ((c = getopt(argc, argv, "fF")) != -1) { 1474fa9e4066Sahrens switch (c) { 1475fa9e4066Sahrens case 'f': 147699653d4eSeschrock force = B_TRUE; 1477fa9e4066Sahrens break; 1478394ab0cbSGeorge Wilson case 'F': 1479394ab0cbSGeorge Wilson hardforce = B_TRUE; 1480394ab0cbSGeorge Wilson break; 1481fa9e4066Sahrens case '?': 1482fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1483fa9e4066Sahrens optopt); 148499653d4eSeschrock usage(B_FALSE); 1485fa9e4066Sahrens } 1486fa9e4066Sahrens } 1487fa9e4066Sahrens 1488fa9e4066Sahrens argc -= optind; 1489fa9e4066Sahrens argv += optind; 1490fa9e4066Sahrens 1491fa9e4066Sahrens /* check arguments */ 1492fa9e4066Sahrens if (argc < 1) { 1493fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool argument\n")); 149499653d4eSeschrock usage(B_FALSE); 1495fa9e4066Sahrens } 1496fa9e4066Sahrens 1497fa9e4066Sahrens ret = 0; 1498fa9e4066Sahrens for (i = 0; i < argc; i++) { 149999653d4eSeschrock if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) { 1500fa9e4066Sahrens ret = 1; 1501fa9e4066Sahrens continue; 1502fa9e4066Sahrens } 1503fa9e4066Sahrens 1504f3861e1aSahl if (zpool_disable_datasets(zhp, force) != 0) { 1505fa9e4066Sahrens ret = 1; 1506fa9e4066Sahrens zpool_close(zhp); 1507fa9e4066Sahrens continue; 1508fa9e4066Sahrens } 1509fa9e4066Sahrens 15104445fffbSMatthew Ahrens /* The history must be logged as part of the export */ 15114445fffbSMatthew Ahrens log_history = B_FALSE; 15124445fffbSMatthew Ahrens 1513394ab0cbSGeorge Wilson if (hardforce) { 15144445fffbSMatthew Ahrens if (zpool_export_force(zhp, history_str) != 0) 1515394ab0cbSGeorge Wilson ret = 1; 15164445fffbSMatthew Ahrens } else if (zpool_export(zhp, force, history_str) != 0) { 1517fa9e4066Sahrens ret = 1; 1518394ab0cbSGeorge Wilson } 1519fa9e4066Sahrens 1520fa9e4066Sahrens zpool_close(zhp); 1521fa9e4066Sahrens } 1522fa9e4066Sahrens 1523fa9e4066Sahrens return (ret); 1524fa9e4066Sahrens } 1525fa9e4066Sahrens 1526fa9e4066Sahrens /* 1527fa9e4066Sahrens * Given a vdev configuration, determine the maximum width needed for the device 1528fa9e4066Sahrens * name column. 1529fa9e4066Sahrens */ 1530fa9e4066Sahrens static int 1531663207adSDon Brady max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max, 1532663207adSDon Brady int name_flags) 1533fa9e4066Sahrens { 1534663207adSDon Brady char *name; 1535fa9e4066Sahrens nvlist_t **child; 1536fa9e4066Sahrens uint_t c, children; 1537fa9e4066Sahrens int ret; 1538fa9e4066Sahrens 1539663207adSDon Brady name = zpool_vdev_name(g_zfs, zhp, nv, name_flags | VDEV_NAME_TYPE_ID); 1540fa9e4066Sahrens if (strlen(name) + depth > max) 1541fa9e4066Sahrens max = strlen(name) + depth; 1542fa9e4066Sahrens 1543afefbcddSeschrock free(name); 1544afefbcddSeschrock 154599653d4eSeschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 154699653d4eSeschrock &child, &children) == 0) { 154799653d4eSeschrock for (c = 0; c < children; c++) 154899653d4eSeschrock if ((ret = max_width(zhp, child[c], depth + 2, 1549663207adSDon Brady max, name_flags)) > max) 155099653d4eSeschrock max = ret; 155199653d4eSeschrock } 155299653d4eSeschrock 1553fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1554fa94a07fSbrendan &child, &children) == 0) { 1555fa94a07fSbrendan for (c = 0; c < children; c++) 1556fa94a07fSbrendan if ((ret = max_width(zhp, child[c], depth + 2, 1557663207adSDon Brady max, name_flags)) > max) 1558fa94a07fSbrendan max = ret; 1559fa94a07fSbrendan } 1560fa94a07fSbrendan 1561fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 156299653d4eSeschrock &child, &children) == 0) { 156399653d4eSeschrock for (c = 0; c < children; c++) 156499653d4eSeschrock if ((ret = max_width(zhp, child[c], depth + 2, 1565663207adSDon Brady max, name_flags)) > max) 156699653d4eSeschrock max = ret; 156799653d4eSeschrock } 1568fa9e4066Sahrens 1569fa9e4066Sahrens return (max); 1570fa9e4066Sahrens } 1571fa9e4066Sahrens 1572e6ca193dSGeorge Wilson typedef struct spare_cbdata { 1573e6ca193dSGeorge Wilson uint64_t cb_guid; 1574e6ca193dSGeorge Wilson zpool_handle_t *cb_zhp; 1575e6ca193dSGeorge Wilson } spare_cbdata_t; 1576e6ca193dSGeorge Wilson 1577e6ca193dSGeorge Wilson static boolean_t 1578e6ca193dSGeorge Wilson find_vdev(nvlist_t *nv, uint64_t search) 1579e6ca193dSGeorge Wilson { 1580e6ca193dSGeorge Wilson uint64_t guid; 1581e6ca193dSGeorge Wilson nvlist_t **child; 1582e6ca193dSGeorge Wilson uint_t c, children; 1583e6ca193dSGeorge Wilson 1584e6ca193dSGeorge Wilson if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 1585e6ca193dSGeorge Wilson search == guid) 1586e6ca193dSGeorge Wilson return (B_TRUE); 1587e6ca193dSGeorge Wilson 1588e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1589e6ca193dSGeorge Wilson &child, &children) == 0) { 1590e6ca193dSGeorge Wilson for (c = 0; c < children; c++) 1591e6ca193dSGeorge Wilson if (find_vdev(child[c], search)) 1592e6ca193dSGeorge Wilson return (B_TRUE); 1593e6ca193dSGeorge Wilson } 1594e6ca193dSGeorge Wilson 1595e6ca193dSGeorge Wilson return (B_FALSE); 1596e6ca193dSGeorge Wilson } 1597e6ca193dSGeorge Wilson 1598e6ca193dSGeorge Wilson static int 1599e6ca193dSGeorge Wilson find_spare(zpool_handle_t *zhp, void *data) 1600e6ca193dSGeorge Wilson { 1601e6ca193dSGeorge Wilson spare_cbdata_t *cbp = data; 1602e6ca193dSGeorge Wilson nvlist_t *config, *nvroot; 1603e6ca193dSGeorge Wilson 1604e6ca193dSGeorge Wilson config = zpool_get_config(zhp, NULL); 1605e6ca193dSGeorge Wilson verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1606e6ca193dSGeorge Wilson &nvroot) == 0); 1607e6ca193dSGeorge Wilson 1608e6ca193dSGeorge Wilson if (find_vdev(nvroot, cbp->cb_guid)) { 1609e6ca193dSGeorge Wilson cbp->cb_zhp = zhp; 1610e6ca193dSGeorge Wilson return (1); 1611e6ca193dSGeorge Wilson } 1612e6ca193dSGeorge Wilson 1613e6ca193dSGeorge Wilson zpool_close(zhp); 1614e6ca193dSGeorge Wilson return (0); 1615e6ca193dSGeorge Wilson } 1616e6ca193dSGeorge Wilson 1617663207adSDon Brady typedef struct status_cbdata { 1618663207adSDon Brady int cb_count; 1619663207adSDon Brady int cb_name_flags; 1620663207adSDon Brady int cb_namewidth; 1621663207adSDon Brady boolean_t cb_allpools; 1622663207adSDon Brady boolean_t cb_verbose; 1623663207adSDon Brady boolean_t cb_explain; 1624663207adSDon Brady boolean_t cb_first; 1625663207adSDon Brady boolean_t cb_dedup_stats; 1626663207adSDon Brady boolean_t cb_print_status; 1627084fd14fSBrian Behlendorf boolean_t cb_print_vdev_init; 1628084fd14fSBrian Behlendorf boolean_t cb_print_vdev_trim; 1629663207adSDon Brady } status_cbdata_t; 1630663207adSDon Brady 1631084fd14fSBrian Behlendorf /* 1632084fd14fSBrian Behlendorf * Print vdev initialization status for leaves 1633084fd14fSBrian Behlendorf */ 1634084fd14fSBrian Behlendorf static void 1635084fd14fSBrian Behlendorf print_status_initialize(vdev_stat_t *vs, boolean_t verbose) 1636084fd14fSBrian Behlendorf { 1637084fd14fSBrian Behlendorf if (verbose) { 1638084fd14fSBrian Behlendorf if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE || 1639084fd14fSBrian Behlendorf vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED || 1640084fd14fSBrian Behlendorf vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) && 1641084fd14fSBrian Behlendorf !vs->vs_scan_removing) { 1642084fd14fSBrian Behlendorf char zbuf[1024]; 1643084fd14fSBrian Behlendorf char tbuf[256]; 1644084fd14fSBrian Behlendorf struct tm zaction_ts; 1645084fd14fSBrian Behlendorf 1646084fd14fSBrian Behlendorf time_t t = vs->vs_initialize_action_time; 1647084fd14fSBrian Behlendorf int initialize_pct = 100; 1648084fd14fSBrian Behlendorf if (vs->vs_initialize_state != 1649084fd14fSBrian Behlendorf VDEV_INITIALIZE_COMPLETE) { 1650084fd14fSBrian Behlendorf initialize_pct = (vs->vs_initialize_bytes_done * 1651084fd14fSBrian Behlendorf 100 / (vs->vs_initialize_bytes_est + 1)); 1652084fd14fSBrian Behlendorf } 1653084fd14fSBrian Behlendorf 1654084fd14fSBrian Behlendorf (void) localtime_r(&t, &zaction_ts); 1655084fd14fSBrian Behlendorf (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts); 1656084fd14fSBrian Behlendorf 1657084fd14fSBrian Behlendorf switch (vs->vs_initialize_state) { 1658084fd14fSBrian Behlendorf case VDEV_INITIALIZE_SUSPENDED: 1659084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 1660084fd14fSBrian Behlendorf gettext("suspended, started at"), tbuf); 1661084fd14fSBrian Behlendorf break; 1662084fd14fSBrian Behlendorf case VDEV_INITIALIZE_ACTIVE: 1663084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 1664084fd14fSBrian Behlendorf gettext("started at"), tbuf); 1665084fd14fSBrian Behlendorf break; 1666084fd14fSBrian Behlendorf case VDEV_INITIALIZE_COMPLETE: 1667084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 1668084fd14fSBrian Behlendorf gettext("completed at"), tbuf); 1669084fd14fSBrian Behlendorf break; 1670084fd14fSBrian Behlendorf } 1671084fd14fSBrian Behlendorf 1672084fd14fSBrian Behlendorf (void) printf(gettext(" (%d%% initialized%s)"), 1673084fd14fSBrian Behlendorf initialize_pct, zbuf); 1674084fd14fSBrian Behlendorf } else { 1675084fd14fSBrian Behlendorf (void) printf(gettext(" (uninitialized)")); 1676084fd14fSBrian Behlendorf } 1677084fd14fSBrian Behlendorf } else if (vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE) { 1678084fd14fSBrian Behlendorf (void) printf(gettext(" (initializing)")); 1679084fd14fSBrian Behlendorf } 1680084fd14fSBrian Behlendorf } 1681084fd14fSBrian Behlendorf 1682084fd14fSBrian Behlendorf /* 1683084fd14fSBrian Behlendorf * Print vdev TRIM status for leaves 1684084fd14fSBrian Behlendorf */ 1685084fd14fSBrian Behlendorf static void 1686084fd14fSBrian Behlendorf print_status_trim(vdev_stat_t *vs, boolean_t verbose) 1687084fd14fSBrian Behlendorf { 1688084fd14fSBrian Behlendorf if (verbose) { 1689084fd14fSBrian Behlendorf if ((vs->vs_trim_state == VDEV_TRIM_ACTIVE || 1690084fd14fSBrian Behlendorf vs->vs_trim_state == VDEV_TRIM_SUSPENDED || 1691084fd14fSBrian Behlendorf vs->vs_trim_state == VDEV_TRIM_COMPLETE) && 1692084fd14fSBrian Behlendorf !vs->vs_scan_removing) { 1693084fd14fSBrian Behlendorf char zbuf[1024]; 1694084fd14fSBrian Behlendorf char tbuf[256]; 1695084fd14fSBrian Behlendorf struct tm zaction_ts; 1696084fd14fSBrian Behlendorf 1697084fd14fSBrian Behlendorf time_t t = vs->vs_trim_action_time; 1698084fd14fSBrian Behlendorf int trim_pct = 100; 1699084fd14fSBrian Behlendorf if (vs->vs_trim_state != VDEV_TRIM_COMPLETE) { 1700084fd14fSBrian Behlendorf trim_pct = (vs->vs_trim_bytes_done * 1701084fd14fSBrian Behlendorf 100 / (vs->vs_trim_bytes_est + 1)); 1702084fd14fSBrian Behlendorf } 1703084fd14fSBrian Behlendorf 1704084fd14fSBrian Behlendorf (void) localtime_r(&t, &zaction_ts); 1705084fd14fSBrian Behlendorf (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts); 1706084fd14fSBrian Behlendorf 1707084fd14fSBrian Behlendorf switch (vs->vs_trim_state) { 1708084fd14fSBrian Behlendorf case VDEV_TRIM_SUSPENDED: 1709084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 1710084fd14fSBrian Behlendorf gettext("suspended, started at"), tbuf); 1711084fd14fSBrian Behlendorf break; 1712084fd14fSBrian Behlendorf case VDEV_TRIM_ACTIVE: 1713084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 1714084fd14fSBrian Behlendorf gettext("started at"), tbuf); 1715084fd14fSBrian Behlendorf break; 1716084fd14fSBrian Behlendorf case VDEV_TRIM_COMPLETE: 1717084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 1718084fd14fSBrian Behlendorf gettext("completed at"), tbuf); 1719084fd14fSBrian Behlendorf break; 1720084fd14fSBrian Behlendorf } 1721084fd14fSBrian Behlendorf 1722084fd14fSBrian Behlendorf (void) printf(gettext(" (%d%% trimmed%s)"), 1723084fd14fSBrian Behlendorf trim_pct, zbuf); 1724084fd14fSBrian Behlendorf } else if (vs->vs_trim_notsup) { 1725084fd14fSBrian Behlendorf (void) printf(gettext(" (trim unsupported)")); 1726084fd14fSBrian Behlendorf } else { 1727084fd14fSBrian Behlendorf (void) printf(gettext(" (untrimmed)")); 1728084fd14fSBrian Behlendorf } 1729084fd14fSBrian Behlendorf } else if (vs->vs_trim_state == VDEV_TRIM_ACTIVE) { 1730084fd14fSBrian Behlendorf (void) printf(gettext(" (trimming)")); 1731084fd14fSBrian Behlendorf } 1732084fd14fSBrian Behlendorf } 1733084fd14fSBrian Behlendorf 1734e6ca193dSGeorge Wilson /* 1735e6ca193dSGeorge Wilson * Print out configuration state as requested by status_callback. 1736e6ca193dSGeorge Wilson */ 1737663207adSDon Brady static void 1738663207adSDon Brady print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name, 1739663207adSDon Brady nvlist_t *nv, int depth, boolean_t isspare) 1740e6ca193dSGeorge Wilson { 174164dee23eSTony Hutter nvlist_t **child, *root; 1742e6ca193dSGeorge Wilson uint_t c, children; 17433f9d6ad7SLin Ling pool_scan_stat_t *ps = NULL; 1744e6ca193dSGeorge Wilson vdev_stat_t *vs; 17453f9d6ad7SLin Ling char rbuf[6], wbuf[6], cbuf[6]; 1746e6ca193dSGeorge Wilson char *vname; 1747e6ca193dSGeorge Wilson uint64_t notpresent; 1748663207adSDon Brady spare_cbdata_t spare_cb; 17496401734dSWill Andrews const char *state; 17505cabbc6bSPrashanth Sreenivasa char *type; 1751e6ca193dSGeorge Wilson 1752e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1753e6ca193dSGeorge Wilson &child, &children) != 0) 1754e6ca193dSGeorge Wilson children = 0; 1755e6ca193dSGeorge Wilson 17563f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 17573f9d6ad7SLin Ling (uint64_t **)&vs, &c) == 0); 17583f9d6ad7SLin Ling 17595cabbc6bSPrashanth Sreenivasa verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 17605cabbc6bSPrashanth Sreenivasa 17615cabbc6bSPrashanth Sreenivasa if (strcmp(type, VDEV_TYPE_INDIRECT) == 0) 17625cabbc6bSPrashanth Sreenivasa return; 17635cabbc6bSPrashanth Sreenivasa 1764e6ca193dSGeorge Wilson state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1765e6ca193dSGeorge Wilson if (isspare) { 1766e6ca193dSGeorge Wilson /* 1767e6ca193dSGeorge Wilson * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 1768e6ca193dSGeorge Wilson * online drives. 1769e6ca193dSGeorge Wilson */ 1770e6ca193dSGeorge Wilson if (vs->vs_aux == VDEV_AUX_SPARED) 1771e6ca193dSGeorge Wilson state = "INUSE"; 1772e6ca193dSGeorge Wilson else if (vs->vs_state == VDEV_STATE_HEALTHY) 1773e6ca193dSGeorge Wilson state = "AVAIL"; 1774e6ca193dSGeorge Wilson } 1775e6ca193dSGeorge Wilson 1776663207adSDon Brady (void) printf("\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth, 1777e6ca193dSGeorge Wilson name, state); 1778e6ca193dSGeorge Wilson 1779e6ca193dSGeorge Wilson if (!isspare) { 1780e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 1781e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 1782e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 1783e6ca193dSGeorge Wilson (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 1784e6ca193dSGeorge Wilson } 1785e6ca193dSGeorge Wilson 1786e6ca193dSGeorge Wilson if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1787e6ca193dSGeorge Wilson ¬present) == 0) { 1788e6ca193dSGeorge Wilson char *path; 1789e6ca193dSGeorge Wilson verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 1790e6ca193dSGeorge Wilson (void) printf(" was %s", path); 1791e6ca193dSGeorge Wilson } else if (vs->vs_aux != 0) { 1792e6ca193dSGeorge Wilson (void) printf(" "); 1793e6ca193dSGeorge Wilson 1794e6ca193dSGeorge Wilson switch (vs->vs_aux) { 1795e6ca193dSGeorge Wilson case VDEV_AUX_OPEN_FAILED: 1796e6ca193dSGeorge Wilson (void) printf(gettext("cannot open")); 1797e6ca193dSGeorge Wilson break; 1798e6ca193dSGeorge Wilson 1799e6ca193dSGeorge Wilson case VDEV_AUX_BAD_GUID_SUM: 1800e6ca193dSGeorge Wilson (void) printf(gettext("missing device")); 1801e6ca193dSGeorge Wilson break; 1802e6ca193dSGeorge Wilson 1803e6ca193dSGeorge Wilson case VDEV_AUX_NO_REPLICAS: 1804e6ca193dSGeorge Wilson (void) printf(gettext("insufficient replicas")); 1805e6ca193dSGeorge Wilson break; 1806e6ca193dSGeorge Wilson 1807e6ca193dSGeorge Wilson case VDEV_AUX_VERSION_NEWER: 1808e6ca193dSGeorge Wilson (void) printf(gettext("newer version")); 1809e6ca193dSGeorge Wilson break; 1810e6ca193dSGeorge Wilson 1811ad135b5dSChristopher Siden case VDEV_AUX_UNSUP_FEAT: 1812ad135b5dSChristopher Siden (void) printf(gettext("unsupported feature(s)")); 1813ad135b5dSChristopher Siden break; 1814ad135b5dSChristopher Siden 1815e6ca193dSGeorge Wilson case VDEV_AUX_SPARED: 1816e6ca193dSGeorge Wilson verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 1817663207adSDon Brady &spare_cb.cb_guid) == 0); 1818663207adSDon Brady if (zpool_iter(g_zfs, find_spare, &spare_cb) == 1) { 1819663207adSDon Brady if (strcmp(zpool_get_name(spare_cb.cb_zhp), 1820e6ca193dSGeorge Wilson zpool_get_name(zhp)) == 0) 1821e6ca193dSGeorge Wilson (void) printf(gettext("currently in " 1822e6ca193dSGeorge Wilson "use")); 1823e6ca193dSGeorge Wilson else 1824e6ca193dSGeorge Wilson (void) printf(gettext("in use by " 1825e6ca193dSGeorge Wilson "pool '%s'"), 1826663207adSDon Brady zpool_get_name(spare_cb.cb_zhp)); 1827663207adSDon Brady zpool_close(spare_cb.cb_zhp); 1828e6ca193dSGeorge Wilson } else { 1829e6ca193dSGeorge Wilson (void) printf(gettext("currently in use")); 1830e6ca193dSGeorge Wilson } 1831e6ca193dSGeorge Wilson break; 1832e6ca193dSGeorge Wilson 1833e6ca193dSGeorge Wilson case VDEV_AUX_ERR_EXCEEDED: 1834e6ca193dSGeorge Wilson (void) printf(gettext("too many errors")); 1835e6ca193dSGeorge Wilson break; 1836e6ca193dSGeorge Wilson 1837e6ca193dSGeorge Wilson case VDEV_AUX_IO_FAILURE: 1838e6ca193dSGeorge Wilson (void) printf(gettext("experienced I/O failures")); 1839e6ca193dSGeorge Wilson break; 1840e6ca193dSGeorge Wilson 1841e6ca193dSGeorge Wilson case VDEV_AUX_BAD_LOG: 1842e6ca193dSGeorge Wilson (void) printf(gettext("bad intent log")); 1843e6ca193dSGeorge Wilson break; 1844e6ca193dSGeorge Wilson 1845069f55e2SEric Schrock case VDEV_AUX_EXTERNAL: 1846069f55e2SEric Schrock (void) printf(gettext("external device fault")); 1847069f55e2SEric Schrock break; 1848069f55e2SEric Schrock 18491195e687SMark J Musante case VDEV_AUX_SPLIT_POOL: 18501195e687SMark J Musante (void) printf(gettext("split into new pool")); 18511195e687SMark J Musante break; 18521195e687SMark J Musante 1853e0f1c0afSOlaf Faaland case VDEV_AUX_ACTIVE: 1854e0f1c0afSOlaf Faaland (void) printf(gettext("currently in use")); 1855e0f1c0afSOlaf Faaland break; 1856e0f1c0afSOlaf Faaland 18576f793812SPavel Zakharov case VDEV_AUX_CHILDREN_OFFLINE: 18586f793812SPavel Zakharov (void) printf(gettext("all children offline")); 18596f793812SPavel Zakharov break; 18606f793812SPavel Zakharov 1861e6ca193dSGeorge Wilson default: 1862e6ca193dSGeorge Wilson (void) printf(gettext("corrupted data")); 1863e6ca193dSGeorge Wilson break; 1864e6ca193dSGeorge Wilson } 18653f9d6ad7SLin Ling } 18663f9d6ad7SLin Ling 186764dee23eSTony Hutter /* The root vdev has the scrub/resilver stats */ 186864dee23eSTony Hutter root = fnvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 186964dee23eSTony Hutter ZPOOL_CONFIG_VDEV_TREE); 187064dee23eSTony Hutter (void) nvlist_lookup_uint64_array(root, ZPOOL_CONFIG_SCAN_STATS, 18713f9d6ad7SLin Ling (uint64_t **)&ps, &c); 18723f9d6ad7SLin Ling 1873e4c795beSTom Caputi if (ps != NULL && ps->pss_state == DSS_SCANNING && children == 0) { 1874e4c795beSTom Caputi if (vs->vs_scan_processed != 0) { 1875e4c795beSTom Caputi (void) printf(gettext(" (%s)"), 1876e4c795beSTom Caputi (ps->pss_func == POOL_SCAN_RESILVER) ? 1877e4c795beSTom Caputi "resilvering" : "repairing"); 1878e4c795beSTom Caputi } else if (vs->vs_resilver_deferred) { 1879e4c795beSTom Caputi (void) printf(gettext(" (awaiting resilver)")); 1880e4c795beSTom Caputi } 1881e6ca193dSGeorge Wilson } 1882e6ca193dSGeorge Wilson 1883084fd14fSBrian Behlendorf /* Display vdev initialization and trim status for leaves */ 1884084fd14fSBrian Behlendorf if (children == 0) { 1885084fd14fSBrian Behlendorf print_status_initialize(vs, cb->cb_print_vdev_init); 1886084fd14fSBrian Behlendorf print_status_trim(vs, cb->cb_print_vdev_trim); 1887094e47e9SGeorge Wilson } 1888094e47e9SGeorge Wilson 1889e6ca193dSGeorge Wilson (void) printf("\n"); 1890e6ca193dSGeorge Wilson 1891e6ca193dSGeorge Wilson for (c = 0; c < children; c++) { 189288ecc943SGeorge Wilson uint64_t islog = B_FALSE, ishole = B_FALSE; 1893e6ca193dSGeorge Wilson 189488ecc943SGeorge Wilson /* Don't print logs or holes here */ 1895e6ca193dSGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 189688ecc943SGeorge Wilson &islog); 189788ecc943SGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, 189888ecc943SGeorge Wilson &ishole); 189988ecc943SGeorge Wilson if (islog || ishole) 1900e6ca193dSGeorge Wilson continue; 1901663207adSDon Brady /* Only print normal classes here */ 1902663207adSDon Brady if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 1903663207adSDon Brady continue; 1904663207adSDon Brady 1905663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 1906663207adSDon Brady cb->cb_name_flags | VDEV_NAME_TYPE_ID); 190764dee23eSTony Hutter 1908663207adSDon Brady print_status_config(zhp, cb, vname, child[c], depth + 2, 1909663207adSDon Brady isspare); 1910e6ca193dSGeorge Wilson free(vname); 1911e6ca193dSGeorge Wilson } 1912e6ca193dSGeorge Wilson } 1913e6ca193dSGeorge Wilson 1914fa9e4066Sahrens /* 1915fa9e4066Sahrens * Print the configuration of an exported pool. Iterate over all vdevs in the 1916fa9e4066Sahrens * pool, printing out the name and status for each one. 1917fa9e4066Sahrens */ 1918663207adSDon Brady static void 1919663207adSDon Brady print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv, 1920663207adSDon Brady int depth) 1921fa9e4066Sahrens { 1922fa9e4066Sahrens nvlist_t **child; 1923fa9e4066Sahrens uint_t c, children; 1924fa9e4066Sahrens vdev_stat_t *vs; 1925afefbcddSeschrock char *type, *vname; 1926fa9e4066Sahrens 1927fa9e4066Sahrens verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 192888ecc943SGeorge Wilson if (strcmp(type, VDEV_TYPE_MISSING) == 0 || 192988ecc943SGeorge Wilson strcmp(type, VDEV_TYPE_HOLE) == 0) 1930fa9e4066Sahrens return; 1931fa9e4066Sahrens 19323f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 1933fa9e4066Sahrens (uint64_t **)&vs, &c) == 0); 1934fa9e4066Sahrens 1935663207adSDon Brady (void) printf("\t%*s%-*s", depth, "", cb->cb_namewidth - depth, name); 1936990b4856Slling (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); 1937fa9e4066Sahrens 1938fa9e4066Sahrens if (vs->vs_aux != 0) { 19393d7072f8Seschrock (void) printf(" "); 1940fa9e4066Sahrens 1941fa9e4066Sahrens switch (vs->vs_aux) { 1942fa9e4066Sahrens case VDEV_AUX_OPEN_FAILED: 1943fa9e4066Sahrens (void) printf(gettext("cannot open")); 1944fa9e4066Sahrens break; 1945fa9e4066Sahrens 1946fa9e4066Sahrens case VDEV_AUX_BAD_GUID_SUM: 1947fa9e4066Sahrens (void) printf(gettext("missing device")); 1948fa9e4066Sahrens break; 1949fa9e4066Sahrens 1950fa9e4066Sahrens case VDEV_AUX_NO_REPLICAS: 1951fa9e4066Sahrens (void) printf(gettext("insufficient replicas")); 1952fa9e4066Sahrens break; 1953fa9e4066Sahrens 1954eaca9bbdSeschrock case VDEV_AUX_VERSION_NEWER: 1955eaca9bbdSeschrock (void) printf(gettext("newer version")); 1956eaca9bbdSeschrock break; 1957eaca9bbdSeschrock 1958ad135b5dSChristopher Siden case VDEV_AUX_UNSUP_FEAT: 1959ad135b5dSChristopher Siden (void) printf(gettext("unsupported feature(s)")); 1960ad135b5dSChristopher Siden break; 1961ad135b5dSChristopher Siden 19623d7072f8Seschrock case VDEV_AUX_ERR_EXCEEDED: 19633d7072f8Seschrock (void) printf(gettext("too many errors")); 19643d7072f8Seschrock break; 19653d7072f8Seschrock 1966e0f1c0afSOlaf Faaland case VDEV_AUX_ACTIVE: 1967e0f1c0afSOlaf Faaland (void) printf(gettext("currently in use")); 1968e0f1c0afSOlaf Faaland break; 1969e0f1c0afSOlaf Faaland 19706f793812SPavel Zakharov case VDEV_AUX_CHILDREN_OFFLINE: 19716f793812SPavel Zakharov (void) printf(gettext("all children offline")); 19726f793812SPavel Zakharov break; 19736f793812SPavel Zakharov 1974fa9e4066Sahrens default: 1975fa9e4066Sahrens (void) printf(gettext("corrupted data")); 1976fa9e4066Sahrens break; 1977fa9e4066Sahrens } 1978fa9e4066Sahrens } 1979fa9e4066Sahrens (void) printf("\n"); 1980fa9e4066Sahrens 1981fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1982fa9e4066Sahrens &child, &children) != 0) 1983fa9e4066Sahrens return; 1984fa9e4066Sahrens 1985afefbcddSeschrock for (c = 0; c < children; c++) { 19868654d025Sperrin uint64_t is_log = B_FALSE; 19878654d025Sperrin 19888654d025Sperrin (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 19898654d025Sperrin &is_log); 1990e6ca193dSGeorge Wilson if (is_log) 19918654d025Sperrin continue; 1992663207adSDon Brady if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 1993663207adSDon Brady continue; 19948654d025Sperrin 1995663207adSDon Brady vname = zpool_vdev_name(g_zfs, NULL, child[c], 1996663207adSDon Brady cb->cb_name_flags | VDEV_NAME_TYPE_ID); 1997663207adSDon Brady print_import_config(cb, vname, child[c], depth + 2); 1998afefbcddSeschrock free(vname); 1999afefbcddSeschrock } 200099653d4eSeschrock 2001fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 2002fa94a07fSbrendan &child, &children) == 0) { 2003fa94a07fSbrendan (void) printf(gettext("\tcache\n")); 2004fa94a07fSbrendan for (c = 0; c < children; c++) { 2005663207adSDon Brady vname = zpool_vdev_name(g_zfs, NULL, child[c], 2006663207adSDon Brady cb->cb_name_flags); 2007fa94a07fSbrendan (void) printf("\t %s\n", vname); 2008fa94a07fSbrendan free(vname); 2009fa94a07fSbrendan } 2010fa94a07fSbrendan } 201199653d4eSeschrock 2012fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 2013fa94a07fSbrendan &child, &children) == 0) { 2014fa94a07fSbrendan (void) printf(gettext("\tspares\n")); 2015fa94a07fSbrendan for (c = 0; c < children; c++) { 2016663207adSDon Brady vname = zpool_vdev_name(g_zfs, NULL, child[c], 2017663207adSDon Brady cb->cb_name_flags); 2018fa94a07fSbrendan (void) printf("\t %s\n", vname); 2019fa94a07fSbrendan free(vname); 2020fa94a07fSbrendan } 202199653d4eSeschrock } 2022fa9e4066Sahrens } 2023fa9e4066Sahrens 2024e6ca193dSGeorge Wilson /* 2025663207adSDon Brady * Print specialized class vdevs. 2026663207adSDon Brady * 2027663207adSDon Brady * These are recorded as top level vdevs in the main pool child array 2028663207adSDon Brady * but with "is_log" set to 1 or an "alloc_bias" string. We use either 2029663207adSDon Brady * print_status_config() or print_import_config() to print the top level 2030663207adSDon Brady * class vdevs then any of their children (eg mirrored slogs) are printed 2031663207adSDon Brady * recursively - which works because only the top level vdev is marked. 2032e6ca193dSGeorge Wilson */ 2033e6ca193dSGeorge Wilson static void 2034663207adSDon Brady print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv, 2035663207adSDon Brady const char *class) 2036e6ca193dSGeorge Wilson { 2037e6ca193dSGeorge Wilson uint_t c, children; 2038e6ca193dSGeorge Wilson nvlist_t **child; 2039663207adSDon Brady boolean_t printed = B_FALSE; 2040663207adSDon Brady 2041663207adSDon Brady assert(zhp != NULL || !cb->cb_verbose); 2042e6ca193dSGeorge Wilson 2043e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, 2044e6ca193dSGeorge Wilson &children) != 0) 2045e6ca193dSGeorge Wilson return; 2046e6ca193dSGeorge Wilson 2047e6ca193dSGeorge Wilson for (c = 0; c < children; c++) { 2048e6ca193dSGeorge Wilson uint64_t is_log = B_FALSE; 2049663207adSDon Brady char *bias = NULL; 2050663207adSDon Brady char *type = NULL; 2051e6ca193dSGeorge Wilson 2052e6ca193dSGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 2053e6ca193dSGeorge Wilson &is_log); 2054663207adSDon Brady 2055663207adSDon Brady if (is_log) { 2056663207adSDon Brady bias = VDEV_ALLOC_CLASS_LOGS; 2057663207adSDon Brady } else { 2058663207adSDon Brady (void) nvlist_lookup_string(child[c], 2059663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &bias); 2060663207adSDon Brady (void) nvlist_lookup_string(child[c], 2061663207adSDon Brady ZPOOL_CONFIG_TYPE, &type); 2062663207adSDon Brady } 2063663207adSDon Brady 2064663207adSDon Brady if (bias == NULL || strcmp(bias, class) != 0) 2065e6ca193dSGeorge Wilson continue; 2066663207adSDon Brady if (!is_log && strcmp(type, VDEV_TYPE_INDIRECT) == 0) 2067663207adSDon Brady continue; 2068663207adSDon Brady 2069663207adSDon Brady if (!printed) { 2070663207adSDon Brady (void) printf("\t%s\t\n", gettext(class)); 2071663207adSDon Brady printed = B_TRUE; 2072663207adSDon Brady } 2073663207adSDon Brady 2074663207adSDon Brady char *name = zpool_vdev_name(g_zfs, zhp, child[c], 2075663207adSDon Brady cb->cb_name_flags | VDEV_NAME_TYPE_ID); 2076663207adSDon Brady if (cb->cb_print_status) 2077663207adSDon Brady print_status_config(zhp, cb, name, child[c], 2, 2078663207adSDon Brady B_FALSE); 2079e6ca193dSGeorge Wilson else 2080663207adSDon Brady print_import_config(cb, name, child[c], 2); 2081e6ca193dSGeorge Wilson free(name); 2082e6ca193dSGeorge Wilson } 2083e6ca193dSGeorge Wilson } 2084468c413aSTim Haley 2085fa9e4066Sahrens /* 2086fa9e4066Sahrens * Display the status for the given pool. 2087fa9e4066Sahrens */ 2088fa9e4066Sahrens static void 2089fa9e4066Sahrens show_import(nvlist_t *config) 2090fa9e4066Sahrens { 2091fa9e4066Sahrens uint64_t pool_state; 2092fa9e4066Sahrens vdev_stat_t *vs; 2093fa9e4066Sahrens char *name; 2094fa9e4066Sahrens uint64_t guid; 2095e0f1c0afSOlaf Faaland uint64_t hostid = 0; 2096fa9e4066Sahrens char *msgid; 2097e0f1c0afSOlaf Faaland char *hostname = "unknown"; 2098e0f1c0afSOlaf Faaland nvlist_t *nvroot, *nvinfo; 2099fa9e4066Sahrens int reason; 2100eb633035STom Caputi zpool_errata_t errata; 210146657f8dSmmusante const char *health; 2102fa9e4066Sahrens uint_t vsc; 21038704186eSDan McDonald char *comment; 2104663207adSDon Brady status_cbdata_t cb = { 0 }; 2105fa9e4066Sahrens 2106fa9e4066Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 2107fa9e4066Sahrens &name) == 0); 2108fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 2109fa9e4066Sahrens &guid) == 0); 2110fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 2111fa9e4066Sahrens &pool_state) == 0); 2112fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2113fa9e4066Sahrens &nvroot) == 0); 2114fa9e4066Sahrens 21153f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 2116fa9e4066Sahrens (uint64_t **)&vs, &vsc) == 0); 2117990b4856Slling health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 2118fa9e4066Sahrens 2119eb633035STom Caputi reason = zpool_import_status(config, &msgid, &errata); 2120fa9e4066Sahrens 21218704186eSDan McDonald (void) printf(gettext(" pool: %s\n"), name); 21228704186eSDan McDonald (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); 21238704186eSDan McDonald (void) printf(gettext(" state: %s"), health); 21244c58d714Sdarrenm if (pool_state == POOL_STATE_DESTROYED) 2125b1b8ab34Slling (void) printf(gettext(" (DESTROYED)")); 21264c58d714Sdarrenm (void) printf("\n"); 2127fa9e4066Sahrens 2128fa9e4066Sahrens switch (reason) { 2129fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_R: 2130fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_NR: 2131fa9e4066Sahrens case ZPOOL_STATUS_BAD_GUID_SUM: 21328704186eSDan McDonald (void) printf(gettext(" status: One or more devices are " 21338704186eSDan McDonald "missing from the system.\n")); 2134fa9e4066Sahrens break; 2135fa9e4066Sahrens 2136fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_R: 2137fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_NR: 21388704186eSDan McDonald (void) printf(gettext(" status: One or more devices contains " 2139fa9e4066Sahrens "corrupted data.\n")); 2140fa9e4066Sahrens break; 2141fa9e4066Sahrens 2142fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_DATA: 21438704186eSDan McDonald (void) printf( 21448704186eSDan McDonald gettext(" status: The pool data is corrupted.\n")); 2145fa9e4066Sahrens break; 2146fa9e4066Sahrens 2147441d80aaSlling case ZPOOL_STATUS_OFFLINE_DEV: 21488704186eSDan McDonald (void) printf(gettext(" status: One or more devices " 2149441d80aaSlling "are offlined.\n")); 2150441d80aaSlling break; 2151441d80aaSlling 2152ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_POOL: 21538704186eSDan McDonald (void) printf(gettext(" status: The pool metadata is " 2154ea8dc4b6Seschrock "corrupted.\n")); 2155ea8dc4b6Seschrock break; 2156ea8dc4b6Seschrock 2157eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_OLDER: 215857221772SChristopher Siden (void) printf(gettext(" status: The pool is formatted using a " 215957221772SChristopher Siden "legacy on-disk version.\n")); 2160eaca9bbdSeschrock break; 2161eaca9bbdSeschrock 2162eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 21638704186eSDan McDonald (void) printf(gettext(" status: The pool is formatted using an " 2164eaca9bbdSeschrock "incompatible version.\n")); 2165eaca9bbdSeschrock break; 2166b87f3af3Sperrin 216757221772SChristopher Siden case ZPOOL_STATUS_FEAT_DISABLED: 216857221772SChristopher Siden (void) printf(gettext(" status: Some supported features are " 216957221772SChristopher Siden "not enabled on the pool.\n")); 217057221772SChristopher Siden break; 217157221772SChristopher Siden 2172ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ: 2173ad135b5dSChristopher Siden (void) printf(gettext("status: The pool uses the following " 2174edc8ef7dSToomas Soome "feature(s) not supported on this system:\n")); 2175ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 2176ad135b5dSChristopher Siden break; 2177ad135b5dSChristopher Siden 2178ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 2179ad135b5dSChristopher Siden (void) printf(gettext("status: The pool can only be accessed " 2180ad135b5dSChristopher Siden "in read-only mode on this system. It\n\tcannot be " 2181ad135b5dSChristopher Siden "accessed in read-write mode because it uses the " 2182ad135b5dSChristopher Siden "following\n\tfeature(s) not supported on this system:\n")); 2183ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 2184ad135b5dSChristopher Siden break; 2185ad135b5dSChristopher Siden 2186e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_ACTIVE: 2187e0f1c0afSOlaf Faaland (void) printf(gettext(" status: The pool is currently " 2188e0f1c0afSOlaf Faaland "imported by another system.\n")); 2189e0f1c0afSOlaf Faaland break; 2190e0f1c0afSOlaf Faaland 2191e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_REQUIRED: 2192e0f1c0afSOlaf Faaland (void) printf(gettext(" status: The pool has the " 2193e0f1c0afSOlaf Faaland "multihost property on. It cannot\n\tbe safely imported " 2194e0f1c0afSOlaf Faaland "when the system hostid is not set.\n")); 2195e0f1c0afSOlaf Faaland break; 2196e0f1c0afSOlaf Faaland 219795173954Sek case ZPOOL_STATUS_HOSTID_MISMATCH: 21988704186eSDan McDonald (void) printf(gettext(" status: The pool was last accessed by " 219995173954Sek "another system.\n")); 220095173954Sek break; 2201b87f3af3Sperrin 22023d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_R: 22033d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_NR: 22048704186eSDan McDonald (void) printf(gettext(" status: One or more devices are " 22053d7072f8Seschrock "faulted.\n")); 22063d7072f8Seschrock break; 22073d7072f8Seschrock 2208b87f3af3Sperrin case ZPOOL_STATUS_BAD_LOG: 22098704186eSDan McDonald (void) printf(gettext(" status: An intent log record cannot be " 2210b87f3af3Sperrin "read.\n")); 2211b87f3af3Sperrin break; 2212b87f3af3Sperrin 22133f9d6ad7SLin Ling case ZPOOL_STATUS_RESILVERING: 22148704186eSDan McDonald (void) printf(gettext(" status: One or more devices were being " 22153f9d6ad7SLin Ling "resilvered.\n")); 22163f9d6ad7SLin Ling break; 22173f9d6ad7SLin Ling 2218eb633035STom Caputi case ZPOOL_STATUS_ERRATA: 2219eb633035STom Caputi (void) printf(gettext(" status: Errata #%d detected.\n"), 2220eb633035STom Caputi errata); 2221eb633035STom Caputi break; 2222eb633035STom Caputi 2223fa9e4066Sahrens default: 2224fa9e4066Sahrens /* 2225fa9e4066Sahrens * No other status can be seen when importing pools. 2226fa9e4066Sahrens */ 2227fa9e4066Sahrens assert(reason == ZPOOL_STATUS_OK); 2228fa9e4066Sahrens } 2229fa9e4066Sahrens 2230fa9e4066Sahrens /* 2231fa9e4066Sahrens * Print out an action according to the overall state of the pool. 2232fa9e4066Sahrens */ 223346657f8dSmmusante if (vs->vs_state == VDEV_STATE_HEALTHY) { 223457221772SChristopher Siden if (reason == ZPOOL_STATUS_VERSION_OLDER || 223557221772SChristopher Siden reason == ZPOOL_STATUS_FEAT_DISABLED) { 22368704186eSDan McDonald (void) printf(gettext(" action: The pool can be " 2237eaca9bbdSeschrock "imported using its name or numeric identifier, " 2238eaca9bbdSeschrock "though\n\tsome features will not be available " 2239eaca9bbdSeschrock "without an explicit 'zpool upgrade'.\n")); 224057221772SChristopher Siden } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) { 22418704186eSDan McDonald (void) printf(gettext(" action: The pool can be " 224295173954Sek "imported using its name or numeric " 224395173954Sek "identifier and\n\tthe '-f' flag.\n")); 2244eb633035STom Caputi } else if (reason == ZPOOL_STATUS_ERRATA) { 2245eb633035STom Caputi switch (errata) { 2246eb633035STom Caputi case ZPOOL_ERRATA_NONE: 2247eb633035STom Caputi break; 2248eb633035STom Caputi 2249eb633035STom Caputi case ZPOOL_ERRATA_ZOL_2094_SCRUB: 2250eb633035STom Caputi (void) printf(gettext(" action: The pool can " 2251eb633035STom Caputi "be imported using its name or numeric " 2252eb633035STom Caputi "identifier,\n\thowever there is a compat" 2253eb633035STom Caputi "ibility issue which should be corrected" 2254eb633035STom Caputi "\n\tby running 'zpool scrub'\n")); 2255eb633035STom Caputi break; 2256eb633035STom Caputi 2257eb633035STom Caputi case ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY: 2258eb633035STom Caputi (void) printf(gettext(" action: The pool can" 2259eb633035STom Caputi "not be imported with this version of ZFS " 2260eb633035STom Caputi "due to\n\tan active asynchronous destroy. " 2261eb633035STom Caputi "Revert to an earlier version\n\tand " 2262eb633035STom Caputi "allow the destroy to complete before " 2263eb633035STom Caputi "updating.\n")); 2264eb633035STom Caputi break; 2265eb633035STom Caputi 2266eb633035STom Caputi case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION: 2267eb633035STom Caputi (void) printf(gettext(" action: Existing " 2268eb633035STom Caputi "encrypted datasets contain an on-disk " 2269eb633035STom Caputi "incompatibility, which\n\tneeds to be " 2270eb633035STom Caputi "corrected. Backup these datasets to new " 2271eb633035STom Caputi "encrypted datasets\n\tand destroy the " 2272eb633035STom Caputi "old ones.\n")); 2273eb633035STom Caputi break; 2274eb633035STom Caputi case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION: 2275eb633035STom Caputi (void) printf(gettext(" action: Any existing " 2276eb633035STom Caputi "encrypted datasets contain an on-disk " 2277eb633035STom Caputi "incompatibility which\n\tmay cause " 2278eb633035STom Caputi "on-disk corruption with 'zfs recv' and " 2279eb633035STom Caputi "which needs to be\n\tcorrected. Enable " 2280eb633035STom Caputi "the bookmark_v2 feature and backup " 2281eb633035STom Caputi "these datasets to new encrypted " 2282eb633035STom Caputi "datasets and\n\tdestroy the old ones. " 2283eb633035STom Caputi "If this pool does not contain any " 2284eb633035STom Caputi "encrypted datasets, simply enable\n\t" 2285eb633035STom Caputi "the bookmark_v2 feature.\n")); 2286eb633035STom Caputi break; 2287eb633035STom Caputi default: 2288eb633035STom Caputi /* 2289eb633035STom Caputi * All errata must contain an action message. 2290eb633035STom Caputi */ 2291eb633035STom Caputi assert(0); 2292eb633035STom Caputi } 229357221772SChristopher Siden } else { 22948704186eSDan McDonald (void) printf(gettext(" action: The pool can be " 2295eaca9bbdSeschrock "imported using its name or numeric " 2296eaca9bbdSeschrock "identifier.\n")); 229757221772SChristopher Siden } 229846657f8dSmmusante } else if (vs->vs_state == VDEV_STATE_DEGRADED) { 22998704186eSDan McDonald (void) printf(gettext(" action: The pool can be imported " 2300fa9e4066Sahrens "despite missing or damaged devices. The\n\tfault " 2301eaca9bbdSeschrock "tolerance of the pool may be compromised if imported.\n")); 2302fa9e4066Sahrens } else { 2303eaca9bbdSeschrock switch (reason) { 2304eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 23058704186eSDan McDonald (void) printf(gettext(" action: The pool cannot be " 2306eaca9bbdSeschrock "imported. Access the pool on a system running " 2307eaca9bbdSeschrock "newer\n\tsoftware, or recreate the pool from " 2308eaca9bbdSeschrock "backup.\n")); 2309eaca9bbdSeschrock break; 2310ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ: 2311ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be " 2312ad135b5dSChristopher Siden "imported. Access the pool on a system that " 2313ad135b5dSChristopher Siden "supports\n\tthe required feature(s), or recreate " 2314ad135b5dSChristopher Siden "the pool from backup.\n")); 2315ad135b5dSChristopher Siden break; 2316ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 2317ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be " 2318ad135b5dSChristopher Siden "imported in read-write mode. Import the pool " 2319ad135b5dSChristopher Siden "with\n" 2320ad135b5dSChristopher Siden "\t\"-o readonly=on\", access the pool on a system " 2321ad135b5dSChristopher Siden "that supports the\n\trequired feature(s), or " 2322ad135b5dSChristopher Siden "recreate the pool from backup.\n")); 2323ad135b5dSChristopher Siden break; 2324eaca9bbdSeschrock case ZPOOL_STATUS_MISSING_DEV_R: 2325eaca9bbdSeschrock case ZPOOL_STATUS_MISSING_DEV_NR: 2326eaca9bbdSeschrock case ZPOOL_STATUS_BAD_GUID_SUM: 23278704186eSDan McDonald (void) printf(gettext(" action: The pool cannot be " 2328fa9e4066Sahrens "imported. Attach the missing\n\tdevices and try " 2329fa9e4066Sahrens "again.\n")); 2330eaca9bbdSeschrock break; 2331e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_ACTIVE: 2332e0f1c0afSOlaf Faaland VERIFY0(nvlist_lookup_nvlist(config, 2333e0f1c0afSOlaf Faaland ZPOOL_CONFIG_LOAD_INFO, &nvinfo)); 2334e0f1c0afSOlaf Faaland 2335e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME)) 2336e0f1c0afSOlaf Faaland hostname = fnvlist_lookup_string(nvinfo, 2337e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTNAME); 2338e0f1c0afSOlaf Faaland 2339e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID)) 2340e0f1c0afSOlaf Faaland hostid = fnvlist_lookup_uint64(nvinfo, 2341e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTID); 2342e0f1c0afSOlaf Faaland 2343e0f1c0afSOlaf Faaland (void) printf(gettext(" action: The pool must be " 2344e0f1c0afSOlaf Faaland "exported from %s (hostid=%lx)\n\tbefore it " 2345e0f1c0afSOlaf Faaland "can be safely imported.\n"), hostname, 2346e0f1c0afSOlaf Faaland (unsigned long) hostid); 2347e0f1c0afSOlaf Faaland break; 2348e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_REQUIRED: 2349e0f1c0afSOlaf Faaland (void) printf(gettext(" action: Check the SMF " 2350e0f1c0afSOlaf Faaland "svc:/system/hostid service.\n")); 2351e0f1c0afSOlaf Faaland break; 2352eaca9bbdSeschrock default: 23538704186eSDan McDonald (void) printf(gettext(" action: The pool cannot be " 2354fa9e4066Sahrens "imported due to damaged devices or data.\n")); 2355eaca9bbdSeschrock } 2356eaca9bbdSeschrock } 2357eaca9bbdSeschrock 23588704186eSDan McDonald /* Print the comment attached to the pool. */ 23598704186eSDan McDonald if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0) 23608704186eSDan McDonald (void) printf(gettext("comment: %s\n"), comment); 23618704186eSDan McDonald 236246657f8dSmmusante /* 236346657f8dSmmusante * If the state is "closed" or "can't open", and the aux state 236446657f8dSmmusante * is "corrupt data": 236546657f8dSmmusante */ 236646657f8dSmmusante if (((vs->vs_state == VDEV_STATE_CLOSED) || 236746657f8dSmmusante (vs->vs_state == VDEV_STATE_CANT_OPEN)) && 236846657f8dSmmusante (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) { 2369eaca9bbdSeschrock if (pool_state == POOL_STATE_DESTROYED) 2370eaca9bbdSeschrock (void) printf(gettext("\tThe pool was destroyed, " 2371eaca9bbdSeschrock "but can be imported using the '-Df' flags.\n")); 2372eaca9bbdSeschrock else if (pool_state != POOL_STATE_EXPORTED) 2373eaca9bbdSeschrock (void) printf(gettext("\tThe pool may be active on " 237418ce54dfSek "another system, but can be imported using\n\t" 2375eaca9bbdSeschrock "the '-f' flag.\n")); 2376fa9e4066Sahrens } 2377fa9e4066Sahrens 2378fa9e4066Sahrens if (msgid != NULL) 2379654b400cSJoshua M. Clulow (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 2380fa9e4066Sahrens msgid); 2381fa9e4066Sahrens 23828704186eSDan McDonald (void) printf(gettext(" config:\n\n")); 2383fa9e4066Sahrens 2384663207adSDon Brady cb.cb_namewidth = max_width(NULL, nvroot, 0, 0, 0); 2385663207adSDon Brady if (cb.cb_namewidth < 10) 2386663207adSDon Brady cb.cb_namewidth = 10; 23878654d025Sperrin 2388663207adSDon Brady print_import_config(&cb, name, nvroot, 0); 2389663207adSDon Brady 2390663207adSDon Brady print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_DEDUP); 2391663207adSDon Brady print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_SPECIAL); 2392663207adSDon Brady print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_CLASS_LOGS); 2393fa9e4066Sahrens 2394fa9e4066Sahrens if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 239546657f8dSmmusante (void) printf(gettext("\n\tAdditional devices are known to " 2396fa9e4066Sahrens "be part of this pool, though their\n\texact " 239746657f8dSmmusante "configuration cannot be determined.\n")); 2398fa9e4066Sahrens } 2399fa9e4066Sahrens } 2400fa9e4066Sahrens 2401e0f1c0afSOlaf Faaland static boolean_t 2402e0f1c0afSOlaf Faaland zfs_force_import_required(nvlist_t *config) 2403e0f1c0afSOlaf Faaland { 2404e0f1c0afSOlaf Faaland uint64_t state; 2405e0f1c0afSOlaf Faaland uint64_t hostid = 0; 2406e0f1c0afSOlaf Faaland nvlist_t *nvinfo; 2407e0f1c0afSOlaf Faaland 2408e0f1c0afSOlaf Faaland state = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE); 2409e0f1c0afSOlaf Faaland (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid); 2410e0f1c0afSOlaf Faaland 2411e0f1c0afSOlaf Faaland if (state != POOL_STATE_EXPORTED && hostid != get_system_hostid()) 2412e0f1c0afSOlaf Faaland return (B_TRUE); 2413e0f1c0afSOlaf Faaland 2414e0f1c0afSOlaf Faaland nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO); 2415e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) { 2416e0f1c0afSOlaf Faaland mmp_state_t mmp_state = fnvlist_lookup_uint64(nvinfo, 2417e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_STATE); 2418e0f1c0afSOlaf Faaland 2419e0f1c0afSOlaf Faaland if (mmp_state != MMP_STATE_INACTIVE) 2420e0f1c0afSOlaf Faaland return (B_TRUE); 2421e0f1c0afSOlaf Faaland } 2422e0f1c0afSOlaf Faaland 2423e0f1c0afSOlaf Faaland return (B_FALSE); 2424e0f1c0afSOlaf Faaland } 2425e0f1c0afSOlaf Faaland 2426fa9e4066Sahrens /* 2427fa9e4066Sahrens * Perform the import for the given configuration. This passes the heavy 2428990b4856Slling * lifting off to zpool_import_props(), and then mounts the datasets contained 2429990b4856Slling * within the pool. 2430fa9e4066Sahrens */ 2431fa9e4066Sahrens static int 2432fa9e4066Sahrens do_import(nvlist_t *config, const char *newname, const char *mntopts, 24334b964adaSGeorge Wilson nvlist_t *props, int flags) 2434fa9e4066Sahrens { 2435eb633035STom Caputi int ret = 0; 2436fa9e4066Sahrens zpool_handle_t *zhp; 2437fa9e4066Sahrens char *name; 2438eaca9bbdSeschrock uint64_t version; 2439fa9e4066Sahrens 2440e0f1c0afSOlaf Faaland name = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME); 2441e0f1c0afSOlaf Faaland version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION); 2442fa9e4066Sahrens 2443ad135b5dSChristopher Siden if (!SPA_VERSION_IS_SUPPORTED(version)) { 2444eaca9bbdSeschrock (void) fprintf(stderr, gettext("cannot import '%s': pool " 2445ad135b5dSChristopher Siden "is formatted using an unsupported ZFS version\n"), name); 2446eaca9bbdSeschrock return (1); 2447e0f1c0afSOlaf Faaland } else if (zfs_force_import_required(config) && 24484b964adaSGeorge Wilson !(flags & ZFS_IMPORT_ANY_HOST)) { 2449e0f1c0afSOlaf Faaland mmp_state_t mmp_state = MMP_STATE_INACTIVE; 2450e0f1c0afSOlaf Faaland nvlist_t *nvinfo; 2451e0f1c0afSOlaf Faaland 2452e0f1c0afSOlaf Faaland nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO); 2453e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) 2454e0f1c0afSOlaf Faaland mmp_state = fnvlist_lookup_uint64(nvinfo, 2455e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_STATE); 2456e0f1c0afSOlaf Faaland 2457e0f1c0afSOlaf Faaland if (mmp_state == MMP_STATE_ACTIVE) { 2458e0f1c0afSOlaf Faaland char *hostname = "<unknown>"; 2459e0f1c0afSOlaf Faaland uint64_t hostid = 0; 2460e0f1c0afSOlaf Faaland 2461e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME)) 2462e0f1c0afSOlaf Faaland hostname = fnvlist_lookup_string(nvinfo, 2463e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTNAME); 2464e0f1c0afSOlaf Faaland 2465e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID)) 2466e0f1c0afSOlaf Faaland hostid = fnvlist_lookup_uint64(nvinfo, 2467e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTID); 2468e0f1c0afSOlaf Faaland 2469e0f1c0afSOlaf Faaland (void) fprintf(stderr, gettext("cannot import '%s': " 2470e0f1c0afSOlaf Faaland "pool is imported on %s (hostid: " 2471e0f1c0afSOlaf Faaland "0x%lx)\nExport the pool on the other system, " 2472e0f1c0afSOlaf Faaland "then run 'zpool import'.\n"), 2473e0f1c0afSOlaf Faaland name, hostname, (unsigned long) hostid); 2474e0f1c0afSOlaf Faaland } else if (mmp_state == MMP_STATE_NO_HOSTID) { 2475e0f1c0afSOlaf Faaland (void) fprintf(stderr, gettext("Cannot import '%s': " 2476e0f1c0afSOlaf Faaland "pool has the multihost property on and the\n" 2477e0f1c0afSOlaf Faaland "system's hostid is not set.\n"), name); 247895173954Sek } else { 2479e0f1c0afSOlaf Faaland char *hostname = "<unknown>"; 2480e0f1c0afSOlaf Faaland uint64_t timestamp = 0; 2481e0f1c0afSOlaf Faaland uint64_t hostid = 0; 2482e0f1c0afSOlaf Faaland 2483e0f1c0afSOlaf Faaland if (nvlist_exists(config, ZPOOL_CONFIG_HOSTNAME)) 2484e0f1c0afSOlaf Faaland hostname = fnvlist_lookup_string(config, 2485e0f1c0afSOlaf Faaland ZPOOL_CONFIG_HOSTNAME); 2486e0f1c0afSOlaf Faaland 2487e0f1c0afSOlaf Faaland if (nvlist_exists(config, ZPOOL_CONFIG_TIMESTAMP)) 2488e0f1c0afSOlaf Faaland timestamp = fnvlist_lookup_uint64(config, 2489e0f1c0afSOlaf Faaland ZPOOL_CONFIG_TIMESTAMP); 2490e0f1c0afSOlaf Faaland 2491e0f1c0afSOlaf Faaland if (nvlist_exists(config, ZPOOL_CONFIG_HOSTID)) 2492e0f1c0afSOlaf Faaland hostid = fnvlist_lookup_uint64(config, 2493e0f1c0afSOlaf Faaland ZPOOL_CONFIG_HOSTID); 2494e0f1c0afSOlaf Faaland 249595173954Sek (void) fprintf(stderr, gettext("cannot import '%s': " 2496e0f1c0afSOlaf Faaland "pool was previously in use from another system.\n" 2497e0f1c0afSOlaf Faaland "Last accessed by %s (hostid=%lx) at %s" 2498e0f1c0afSOlaf Faaland "The pool can be imported, use 'zpool import -f' " 2499e0f1c0afSOlaf Faaland "to import the pool.\n"), name, hostname, 2500e0f1c0afSOlaf Faaland (unsigned long)hostid, ctime((time_t *)×tamp)); 2501e0f1c0afSOlaf Faaland 250295173954Sek } 2503e0f1c0afSOlaf Faaland 2504e0f1c0afSOlaf Faaland return (1); 2505fa9e4066Sahrens } 2506fa9e4066Sahrens 25074b964adaSGeorge Wilson if (zpool_import_props(g_zfs, config, newname, props, flags) != 0) 2508fa9e4066Sahrens return (1); 2509fa9e4066Sahrens 2510fa9e4066Sahrens if (newname != NULL) 2511fa9e4066Sahrens name = (char *)newname; 2512fa9e4066Sahrens 25134f0f5e5bSVictor Latushkin if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL) 25144f0f5e5bSVictor Latushkin return (1); 2515fa9e4066Sahrens 2516eb633035STom Caputi /* 2517eb633035STom Caputi * Loading keys is best effort. We don't want to return immediately 2518eb633035STom Caputi * if it fails but we do want to give the error to the caller. 2519eb633035STom Caputi */ 2520eb633035STom Caputi if (flags & ZFS_IMPORT_LOAD_KEYS) { 2521eb633035STom Caputi ret = zfs_crypto_attempt_load_keys(g_zfs, name); 2522eb633035STom Caputi if (ret != 0) 2523eb633035STom Caputi ret = 1; 2524eb633035STom Caputi } 2525eb633035STom Caputi 2526379c004dSEric Schrock if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 2527f9af39baSGeorge Wilson !(flags & ZFS_IMPORT_ONLY) && 2528379c004dSEric Schrock zpool_enable_datasets(zhp, mntopts, 0) != 0) { 2529fa9e4066Sahrens zpool_close(zhp); 2530fa9e4066Sahrens return (1); 2531fa9e4066Sahrens } 2532fa9e4066Sahrens 2533fa9e4066Sahrens zpool_close(zhp); 2534eb633035STom Caputi return (ret); 2535fa9e4066Sahrens } 2536fa9e4066Sahrens 253786714001SSerapheim Dimitropoulos /* 253886714001SSerapheim Dimitropoulos * zpool checkpoint <pool> 253986714001SSerapheim Dimitropoulos * checkpoint --discard <pool> 254086714001SSerapheim Dimitropoulos * 254104e56356SAndriy Gapon * -d Discard the checkpoint from a checkpointed 254204e56356SAndriy Gapon * --discard pool. 254386714001SSerapheim Dimitropoulos * 254486714001SSerapheim Dimitropoulos * Checkpoints the specified pool, by taking a "snapshot" of its 254586714001SSerapheim Dimitropoulos * current state. A pool can only have one checkpoint at a time. 254686714001SSerapheim Dimitropoulos */ 254786714001SSerapheim Dimitropoulos int 254886714001SSerapheim Dimitropoulos zpool_do_checkpoint(int argc, char **argv) 254986714001SSerapheim Dimitropoulos { 255086714001SSerapheim Dimitropoulos boolean_t discard; 255186714001SSerapheim Dimitropoulos char *pool; 255286714001SSerapheim Dimitropoulos zpool_handle_t *zhp; 255386714001SSerapheim Dimitropoulos int c, err; 255486714001SSerapheim Dimitropoulos 255586714001SSerapheim Dimitropoulos struct option long_options[] = { 255686714001SSerapheim Dimitropoulos {"discard", no_argument, NULL, 'd'}, 255786714001SSerapheim Dimitropoulos {0, 0, 0, 0} 255886714001SSerapheim Dimitropoulos }; 255986714001SSerapheim Dimitropoulos 256086714001SSerapheim Dimitropoulos discard = B_FALSE; 256186714001SSerapheim Dimitropoulos while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) { 256286714001SSerapheim Dimitropoulos switch (c) { 256386714001SSerapheim Dimitropoulos case 'd': 256486714001SSerapheim Dimitropoulos discard = B_TRUE; 256586714001SSerapheim Dimitropoulos break; 256686714001SSerapheim Dimitropoulos case '?': 256786714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("invalid option '%c'\n"), 256886714001SSerapheim Dimitropoulos optopt); 256986714001SSerapheim Dimitropoulos usage(B_FALSE); 257086714001SSerapheim Dimitropoulos } 257186714001SSerapheim Dimitropoulos } 257286714001SSerapheim Dimitropoulos 257386714001SSerapheim Dimitropoulos argc -= optind; 257486714001SSerapheim Dimitropoulos argv += optind; 257586714001SSerapheim Dimitropoulos 257686714001SSerapheim Dimitropoulos if (argc < 1) { 257786714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("missing pool argument\n")); 257886714001SSerapheim Dimitropoulos usage(B_FALSE); 257986714001SSerapheim Dimitropoulos } 258086714001SSerapheim Dimitropoulos 258186714001SSerapheim Dimitropoulos if (argc > 1) { 258286714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("too many arguments\n")); 258386714001SSerapheim Dimitropoulos usage(B_FALSE); 258486714001SSerapheim Dimitropoulos } 258586714001SSerapheim Dimitropoulos 258686714001SSerapheim Dimitropoulos pool = argv[0]; 258786714001SSerapheim Dimitropoulos 258886714001SSerapheim Dimitropoulos if ((zhp = zpool_open(g_zfs, pool)) == NULL) { 258986714001SSerapheim Dimitropoulos /* As a special case, check for use of '/' in the name */ 259086714001SSerapheim Dimitropoulos if (strchr(pool, '/') != NULL) 259186714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("'zpool checkpoint' " 259286714001SSerapheim Dimitropoulos "doesn't work on datasets. To save the state " 259386714001SSerapheim Dimitropoulos "of a dataset from a specific point in time " 259486714001SSerapheim Dimitropoulos "please use 'zfs snapshot'\n")); 259586714001SSerapheim Dimitropoulos return (1); 259686714001SSerapheim Dimitropoulos } 259786714001SSerapheim Dimitropoulos 259886714001SSerapheim Dimitropoulos if (discard) 259986714001SSerapheim Dimitropoulos err = (zpool_discard_checkpoint(zhp) != 0); 260086714001SSerapheim Dimitropoulos else 260186714001SSerapheim Dimitropoulos err = (zpool_checkpoint(zhp) != 0); 260286714001SSerapheim Dimitropoulos 260386714001SSerapheim Dimitropoulos zpool_close(zhp); 260486714001SSerapheim Dimitropoulos 260586714001SSerapheim Dimitropoulos return (err); 260686714001SSerapheim Dimitropoulos } 260786714001SSerapheim Dimitropoulos 260886714001SSerapheim Dimitropoulos #define CHECKPOINT_OPT 1024 260986714001SSerapheim Dimitropoulos 2610fa9e4066Sahrens /* 26114c58d714Sdarrenm * zpool import [-d dir] [-D] 2612eb633035STom Caputi * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l] 26132f8aaab3Seschrock * [-d dir | -c cachefile] [-f] -a 2614eb633035STom Caputi * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l] 261504e56356SAndriy Gapon * [-d dir | -c cachefile] [-f] [-n] [-F] [-t] 261604e56356SAndriy Gapon * <pool | id> [newpool] 26172f8aaab3Seschrock * 261804e56356SAndriy Gapon * -c Read pool information from a cachefile instead of searching 26192f8aaab3Seschrock * devices. 2620fa9e4066Sahrens * 262104e56356SAndriy Gapon * -d Scan in a specific directory, other than /dev/dsk. More than 2622fa9e4066Sahrens * one directory can be specified using multiple '-d' options. 2623fa9e4066Sahrens * 262404e56356SAndriy Gapon * -D Scan for previously destroyed pools or import all or only 262504e56356SAndriy Gapon * specified destroyed pools. 26264c58d714Sdarrenm * 262704e56356SAndriy Gapon * -R Temporarily import the pool, with all mountpoints relative to 2628fa9e4066Sahrens * the given root. The pool will remain exported when the machine 2629fa9e4066Sahrens * is rebooted. 2630fa9e4066Sahrens * 263104e56356SAndriy Gapon * -V Import even in the presence of faulted vdevs. This is an 263204e56356SAndriy Gapon * intentionally undocumented option for testing purposes, and 263304e56356SAndriy Gapon * treats the pool configuration as complete, leaving any bad 26344f0f5e5bSVictor Latushkin * vdevs in the FAULTED state. In other words, it does verbatim 26354f0f5e5bSVictor Latushkin * import. 2636c5904d13Seschrock * 263704e56356SAndriy Gapon * -f Force import, even if it appears that the pool is active. 263804e56356SAndriy Gapon * 263904e56356SAndriy Gapon * -F Attempt rewind if necessary. 2640468c413aSTim Haley * 264104e56356SAndriy Gapon * -n See if rewind would work, but don't actually rewind. 2642468c413aSTim Haley * 264304e56356SAndriy Gapon * -N Import the pool but don't mount datasets. 2644468c413aSTim Haley * 264504e56356SAndriy Gapon * -t Use newpool as a temporary pool name instead of renaming 264604e56356SAndriy Gapon * the pool. 2647f9af39baSGeorge Wilson * 264804e56356SAndriy Gapon * -T Specify a starting txg to use for import. This option is 264904e56356SAndriy Gapon * intentionally undocumented option for testing purposes. 2650f9af39baSGeorge Wilson * 265104e56356SAndriy Gapon * -a Import all pools found. 2652fa9e4066Sahrens * 265304e56356SAndriy Gapon * -o Set property=value and/or temporary mount options (without '='). 2654eb633035STom Caputi * -l Load encryption keys while importing. 2655ecd6cf80Smarks * 265604e56356SAndriy Gapon * --rewind-to-checkpoint 265704e56356SAndriy Gapon * Import the pool and revert back to the checkpoint. 265886714001SSerapheim Dimitropoulos * 2659fa9e4066Sahrens * The import command scans for pools to import, and import pools based on pool 2660fa9e4066Sahrens * name and GUID. The pool can also be renamed as part of the import process. 2661fa9e4066Sahrens */ 2662fa9e4066Sahrens int 2663fa9e4066Sahrens zpool_do_import(int argc, char **argv) 2664fa9e4066Sahrens { 2665fa9e4066Sahrens char **searchdirs = NULL; 2666fa9e4066Sahrens int nsearch = 0; 2667fa9e4066Sahrens int c; 2668d41c4376SMark J Musante int err = 0; 26692f8aaab3Seschrock nvlist_t *pools = NULL; 267099653d4eSeschrock boolean_t do_all = B_FALSE; 267199653d4eSeschrock boolean_t do_destroyed = B_FALSE; 2672fa9e4066Sahrens char *mntopts = NULL; 2673fa9e4066Sahrens nvpair_t *elem; 2674fa9e4066Sahrens nvlist_t *config; 267524e697d4Sck uint64_t searchguid = 0; 267624e697d4Sck char *searchname = NULL; 2677990b4856Slling char *propval; 2678fa9e4066Sahrens nvlist_t *found_config; 2679468c413aSTim Haley nvlist_t *policy = NULL; 2680ecd6cf80Smarks nvlist_t *props = NULL; 268199653d4eSeschrock boolean_t first; 26824b964adaSGeorge Wilson int flags = ZFS_IMPORT_NORMAL; 2683468c413aSTim Haley uint32_t rewind_policy = ZPOOL_NO_REWIND; 2684468c413aSTim Haley boolean_t dryrun = B_FALSE; 2685468c413aSTim Haley boolean_t do_rewind = B_FALSE; 2686468c413aSTim Haley boolean_t xtreme_rewind = B_FALSE; 2687f9af39baSGeorge Wilson uint64_t pool_state, txg = -1ULL; 26882f8aaab3Seschrock char *cachefile = NULL; 2689d41c4376SMark J Musante importargs_t idata = { 0 }; 2690f9af39baSGeorge Wilson char *endptr; 2691fa9e4066Sahrens 269286714001SSerapheim Dimitropoulos 269386714001SSerapheim Dimitropoulos struct option long_options[] = { 269486714001SSerapheim Dimitropoulos {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT}, 269586714001SSerapheim Dimitropoulos {0, 0, 0, 0} 269686714001SSerapheim Dimitropoulos }; 269786714001SSerapheim Dimitropoulos 2698fa9e4066Sahrens /* check options */ 2699eb633035STom Caputi while ((c = getopt_long(argc, argv, ":aCc:d:DEfFlmnNo:rR:tT:VX", 270086714001SSerapheim Dimitropoulos long_options, NULL)) != -1) { 2701fa9e4066Sahrens switch (c) { 2702fa9e4066Sahrens case 'a': 270399653d4eSeschrock do_all = B_TRUE; 2704fa9e4066Sahrens break; 27052f8aaab3Seschrock case 'c': 27062f8aaab3Seschrock cachefile = optarg; 27072f8aaab3Seschrock break; 2708fa9e4066Sahrens case 'd': 2709fa9e4066Sahrens if (searchdirs == NULL) { 2710fa9e4066Sahrens searchdirs = safe_malloc(sizeof (char *)); 2711fa9e4066Sahrens } else { 2712fa9e4066Sahrens char **tmp = safe_malloc((nsearch + 1) * 2713fa9e4066Sahrens sizeof (char *)); 2714fa9e4066Sahrens bcopy(searchdirs, tmp, nsearch * 2715fa9e4066Sahrens sizeof (char *)); 2716fa9e4066Sahrens free(searchdirs); 2717fa9e4066Sahrens searchdirs = tmp; 2718fa9e4066Sahrens } 2719fa9e4066Sahrens searchdirs[nsearch++] = optarg; 2720fa9e4066Sahrens break; 27214c58d714Sdarrenm case 'D': 272299653d4eSeschrock do_destroyed = B_TRUE; 27234c58d714Sdarrenm break; 2724fa9e4066Sahrens case 'f': 27254b964adaSGeorge Wilson flags |= ZFS_IMPORT_ANY_HOST; 2726fa9e4066Sahrens break; 2727c5904d13Seschrock case 'F': 2728468c413aSTim Haley do_rewind = B_TRUE; 2729468c413aSTim Haley break; 2730eb633035STom Caputi case 'l': 2731eb633035STom Caputi flags |= ZFS_IMPORT_LOAD_KEYS; 2732eb633035STom Caputi break; 27334b964adaSGeorge Wilson case 'm': 27344b964adaSGeorge Wilson flags |= ZFS_IMPORT_MISSING_LOG; 27354b964adaSGeorge Wilson break; 2736468c413aSTim Haley case 'n': 2737468c413aSTim Haley dryrun = B_TRUE; 2738c5904d13Seschrock break; 2739f9af39baSGeorge Wilson case 'N': 2740f9af39baSGeorge Wilson flags |= ZFS_IMPORT_ONLY; 2741f9af39baSGeorge Wilson break; 2742fa9e4066Sahrens case 'o': 2743990b4856Slling if ((propval = strchr(optarg, '=')) != NULL) { 2744990b4856Slling *propval = '\0'; 2745990b4856Slling propval++; 27460a48a24eStimh if (add_prop_list(optarg, propval, 27470a48a24eStimh &props, B_TRUE)) 2748990b4856Slling goto error; 2749990b4856Slling } else { 2750990b4856Slling mntopts = optarg; 2751990b4856Slling } 2752fa9e4066Sahrens break; 2753fa9e4066Sahrens case 'R': 2754990b4856Slling if (add_prop_list(zpool_prop_to_name( 27550a48a24eStimh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 2756990b4856Slling goto error; 275704e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name( 275804e56356SAndriy Gapon ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 275904e56356SAndriy Gapon goto error; 276004e56356SAndriy Gapon break; 276104e56356SAndriy Gapon case 't': 276204e56356SAndriy Gapon flags |= ZFS_IMPORT_TEMP_NAME; 276304e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name( 27640a48a24eStimh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 2765990b4856Slling goto error; 2766fa9e4066Sahrens break; 2767f9af39baSGeorge Wilson case 'T': 2768f9af39baSGeorge Wilson errno = 0; 2769e42d2059SMatthew Ahrens txg = strtoull(optarg, &endptr, 0); 2770f9af39baSGeorge Wilson if (errno != 0 || *endptr != '\0') { 2771f9af39baSGeorge Wilson (void) fprintf(stderr, 2772f9af39baSGeorge Wilson gettext("invalid txg value\n")); 2773f9af39baSGeorge Wilson usage(B_FALSE); 2774f9af39baSGeorge Wilson } 2775f9af39baSGeorge Wilson rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND; 2776f9af39baSGeorge Wilson break; 2777468c413aSTim Haley case 'V': 27784b964adaSGeorge Wilson flags |= ZFS_IMPORT_VERBATIM; 2779468c413aSTim Haley break; 2780468c413aSTim Haley case 'X': 2781468c413aSTim Haley xtreme_rewind = B_TRUE; 2782468c413aSTim Haley break; 278386714001SSerapheim Dimitropoulos case CHECKPOINT_OPT: 278486714001SSerapheim Dimitropoulos flags |= ZFS_IMPORT_CHECKPOINT; 278586714001SSerapheim Dimitropoulos break; 2786fa9e4066Sahrens case ':': 2787fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 2788fa9e4066Sahrens "'%c' option\n"), optopt); 278999653d4eSeschrock usage(B_FALSE); 2790fa9e4066Sahrens break; 2791fa9e4066Sahrens case '?': 2792fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2793fa9e4066Sahrens optopt); 279499653d4eSeschrock usage(B_FALSE); 2795fa9e4066Sahrens } 2796fa9e4066Sahrens } 2797fa9e4066Sahrens 2798fa9e4066Sahrens argc -= optind; 2799fa9e4066Sahrens argv += optind; 2800fa9e4066Sahrens 28012f8aaab3Seschrock if (cachefile && nsearch != 0) { 28022f8aaab3Seschrock (void) fprintf(stderr, gettext("-c is incompatible with -d\n")); 28032f8aaab3Seschrock usage(B_FALSE); 28042f8aaab3Seschrock } 28052f8aaab3Seschrock 2806eb633035STom Caputi if ((flags & ZFS_IMPORT_LOAD_KEYS) && (flags & ZFS_IMPORT_ONLY)) { 2807eb633035STom Caputi (void) fprintf(stderr, gettext("-l is incompatible with -N\n")); 2808eb633035STom Caputi usage(B_FALSE); 2809eb633035STom Caputi } 2810eb633035STom Caputi 2811eb633035STom Caputi if ((flags & ZFS_IMPORT_LOAD_KEYS) && !do_all && argc == 0) { 2812eb633035STom Caputi (void) fprintf(stderr, gettext("-l is only meaningful during " 2813eb633035STom Caputi "an import\n")); 2814eb633035STom Caputi usage(B_FALSE); 2815eb633035STom Caputi } 2816eb633035STom Caputi 2817468c413aSTim Haley if ((dryrun || xtreme_rewind) && !do_rewind) { 2818468c413aSTim Haley (void) fprintf(stderr, 2819468c413aSTim Haley gettext("-n or -X only meaningful with -F\n")); 2820468c413aSTim Haley usage(B_FALSE); 2821468c413aSTim Haley } 2822468c413aSTim Haley if (dryrun) 2823468c413aSTim Haley rewind_policy = ZPOOL_TRY_REWIND; 2824468c413aSTim Haley else if (do_rewind) 2825468c413aSTim Haley rewind_policy = ZPOOL_DO_REWIND; 2826468c413aSTim Haley if (xtreme_rewind) 2827468c413aSTim Haley rewind_policy |= ZPOOL_EXTREME_REWIND; 2828468c413aSTim Haley 2829468c413aSTim Haley /* In the future, we can capture further policy and include it here */ 2830468c413aSTim Haley if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 28315dafeea3SPavel Zakharov nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 || 28325dafeea3SPavel Zakharov nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, 28335dafeea3SPavel Zakharov rewind_policy) != 0) 2834468c413aSTim Haley goto error; 2835468c413aSTim Haley 2836fa9e4066Sahrens if (searchdirs == NULL) { 2837fa9e4066Sahrens searchdirs = safe_malloc(sizeof (char *)); 28386401734dSWill Andrews searchdirs[0] = ZFS_DISK_ROOT; 2839fa9e4066Sahrens nsearch = 1; 2840fa9e4066Sahrens } 2841fa9e4066Sahrens 2842fa9e4066Sahrens /* check argument count */ 2843fa9e4066Sahrens if (do_all) { 2844fa9e4066Sahrens if (argc != 0) { 2845fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 284699653d4eSeschrock usage(B_FALSE); 2847fa9e4066Sahrens } 2848fa9e4066Sahrens } else { 2849fa9e4066Sahrens if (argc > 2) { 2850fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 285199653d4eSeschrock usage(B_FALSE); 2852fa9e4066Sahrens } 2853fa9e4066Sahrens 2854fa9e4066Sahrens /* 2855fa9e4066Sahrens * Check for the SYS_CONFIG privilege. We do this explicitly 2856fa9e4066Sahrens * here because otherwise any attempt to discover pools will 2857fa9e4066Sahrens * silently fail. 2858fa9e4066Sahrens */ 2859fa9e4066Sahrens if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 2860fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot " 2861fa9e4066Sahrens "discover pools: permission denied\n")); 286299653d4eSeschrock free(searchdirs); 2863468c413aSTim Haley nvlist_free(policy); 2864fa9e4066Sahrens return (1); 2865fa9e4066Sahrens } 2866fa9e4066Sahrens } 2867fa9e4066Sahrens 2868fa9e4066Sahrens /* 2869fa9e4066Sahrens * Depending on the arguments given, we do one of the following: 2870fa9e4066Sahrens * 2871fa9e4066Sahrens * <none> Iterate through all pools and display information about 2872fa9e4066Sahrens * each one. 2873fa9e4066Sahrens * 2874fa9e4066Sahrens * -a Iterate through all pools and try to import each one. 2875fa9e4066Sahrens * 2876fa9e4066Sahrens * <id> Find the pool that corresponds to the given GUID/pool 2877fa9e4066Sahrens * name and import that one. 28784c58d714Sdarrenm * 28794c58d714Sdarrenm * -D Above options applies only to destroyed pools. 2880fa9e4066Sahrens */ 2881fa9e4066Sahrens if (argc != 0) { 2882fa9e4066Sahrens char *endptr; 2883fa9e4066Sahrens 2884fa9e4066Sahrens errno = 0; 2885fa9e4066Sahrens searchguid = strtoull(argv[0], &endptr, 10); 28869edf9ebdSPrasad Joshi if (errno != 0 || *endptr != '\0') { 2887fa9e4066Sahrens searchname = argv[0]; 28889edf9ebdSPrasad Joshi searchguid = 0; 28899edf9ebdSPrasad Joshi } 2890fa9e4066Sahrens found_config = NULL; 2891fa9e4066Sahrens 289224e697d4Sck /* 2893d41c4376SMark J Musante * User specified a name or guid. Ensure it's unique. 289424e697d4Sck */ 2895d41c4376SMark J Musante idata.unique = B_TRUE; 289624e697d4Sck } 289724e697d4Sck 2898d41c4376SMark J Musante 2899d41c4376SMark J Musante idata.path = searchdirs; 2900d41c4376SMark J Musante idata.paths = nsearch; 2901d41c4376SMark J Musante idata.poolname = searchname; 2902d41c4376SMark J Musante idata.guid = searchguid; 2903d41c4376SMark J Musante idata.cachefile = cachefile; 29046f793812SPavel Zakharov idata.policy = policy; 2905d41c4376SMark J Musante 2906d41c4376SMark J Musante pools = zpool_search_import(g_zfs, &idata); 2907d41c4376SMark J Musante 2908d41c4376SMark J Musante if (pools != NULL && idata.exists && 2909d41c4376SMark J Musante (argc == 1 || strcmp(argv[0], argv[1]) == 0)) { 2910d41c4376SMark J Musante (void) fprintf(stderr, gettext("cannot import '%s': " 2911d41c4376SMark J Musante "a pool with that name already exists\n"), 2912d41c4376SMark J Musante argv[0]); 291304e56356SAndriy Gapon (void) fprintf(stderr, gettext("use the form 'zpool import " 291404e56356SAndriy Gapon "[-t] <pool | id> <newpool>' to give it a new temporary " 291504e56356SAndriy Gapon "or permanent name\n")); 2916d41c4376SMark J Musante err = 1; 2917d41c4376SMark J Musante } else if (pools == NULL && idata.exists) { 2918d41c4376SMark J Musante (void) fprintf(stderr, gettext("cannot import '%s': " 2919d41c4376SMark J Musante "a pool with that name is already created/imported,\n"), 2920d41c4376SMark J Musante argv[0]); 2921d41c4376SMark J Musante (void) fprintf(stderr, gettext("and no additional pools " 2922d41c4376SMark J Musante "with that name were found\n")); 2923d41c4376SMark J Musante err = 1; 2924d41c4376SMark J Musante } else if (pools == NULL) { 292524e697d4Sck if (argc != 0) { 292624e697d4Sck (void) fprintf(stderr, gettext("cannot import '%s': " 292724e697d4Sck "no such pool available\n"), argv[0]); 292824e697d4Sck } 2929d41c4376SMark J Musante err = 1; 2930d41c4376SMark J Musante } 2931d41c4376SMark J Musante 2932d41c4376SMark J Musante if (err == 1) { 293324e697d4Sck free(searchdirs); 2934468c413aSTim Haley nvlist_free(policy); 293524e697d4Sck return (1); 293624e697d4Sck } 293724e697d4Sck 293824e697d4Sck /* 293924e697d4Sck * At this point we have a list of import candidate configs. Even if 294024e697d4Sck * we were searching by pool name or guid, we still need to 294124e697d4Sck * post-process the list to deal with pool state and possible 294224e697d4Sck * duplicate names. 294324e697d4Sck */ 2944fa9e4066Sahrens err = 0; 2945fa9e4066Sahrens elem = NULL; 294699653d4eSeschrock first = B_TRUE; 2947fa9e4066Sahrens while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 2948fa9e4066Sahrens 2949fa9e4066Sahrens verify(nvpair_value_nvlist(elem, &config) == 0); 2950fa9e4066Sahrens 29514c58d714Sdarrenm verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 29524c58d714Sdarrenm &pool_state) == 0); 29534c58d714Sdarrenm if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) 29544c58d714Sdarrenm continue; 29554c58d714Sdarrenm if (do_destroyed && pool_state != POOL_STATE_DESTROYED) 29564c58d714Sdarrenm continue; 29574c58d714Sdarrenm 29585dafeea3SPavel Zakharov verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY, 2959468c413aSTim Haley policy) == 0); 2960468c413aSTim Haley 2961fa9e4066Sahrens if (argc == 0) { 2962fa9e4066Sahrens if (first) 296399653d4eSeschrock first = B_FALSE; 29643bb79becSeschrock else if (!do_all) 2965fa9e4066Sahrens (void) printf("\n"); 2966fa9e4066Sahrens 2967468c413aSTim Haley if (do_all) { 2968fa9e4066Sahrens err |= do_import(config, NULL, mntopts, 29694b964adaSGeorge Wilson props, flags); 2970468c413aSTim Haley } else { 2971fa9e4066Sahrens show_import(config); 2972468c413aSTim Haley } 2973fa9e4066Sahrens } else if (searchname != NULL) { 2974fa9e4066Sahrens char *name; 2975fa9e4066Sahrens 2976fa9e4066Sahrens /* 2977fa9e4066Sahrens * We are searching for a pool based on name. 2978fa9e4066Sahrens */ 2979fa9e4066Sahrens verify(nvlist_lookup_string(config, 2980fa9e4066Sahrens ZPOOL_CONFIG_POOL_NAME, &name) == 0); 2981fa9e4066Sahrens 2982fa9e4066Sahrens if (strcmp(name, searchname) == 0) { 2983fa9e4066Sahrens if (found_config != NULL) { 2984fa9e4066Sahrens (void) fprintf(stderr, gettext( 2985fa9e4066Sahrens "cannot import '%s': more than " 2986fa9e4066Sahrens "one matching pool\n"), searchname); 2987fa9e4066Sahrens (void) fprintf(stderr, gettext( 2988fa9e4066Sahrens "import by numeric ID instead\n")); 298999653d4eSeschrock err = B_TRUE; 2990fa9e4066Sahrens } 2991fa9e4066Sahrens found_config = config; 2992fa9e4066Sahrens } 2993fa9e4066Sahrens } else { 2994fa9e4066Sahrens uint64_t guid; 2995fa9e4066Sahrens 2996fa9e4066Sahrens /* 2997fa9e4066Sahrens * Search for a pool by guid. 2998fa9e4066Sahrens */ 2999fa9e4066Sahrens verify(nvlist_lookup_uint64(config, 3000fa9e4066Sahrens ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 3001fa9e4066Sahrens 3002fa9e4066Sahrens if (guid == searchguid) 3003fa9e4066Sahrens found_config = config; 3004fa9e4066Sahrens } 3005fa9e4066Sahrens } 3006fa9e4066Sahrens 3007fa9e4066Sahrens /* 3008fa9e4066Sahrens * If we were searching for a specific pool, verify that we found a 3009fa9e4066Sahrens * pool, and then do the import. 3010fa9e4066Sahrens */ 3011fa9e4066Sahrens if (argc != 0 && err == 0) { 3012fa9e4066Sahrens if (found_config == NULL) { 3013fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot import '%s': " 3014fa9e4066Sahrens "no such pool available\n"), argv[0]); 301599653d4eSeschrock err = B_TRUE; 3016fa9e4066Sahrens } else { 3017fa9e4066Sahrens err |= do_import(found_config, argc == 1 ? NULL : 30184b964adaSGeorge Wilson argv[1], mntopts, props, flags); 3019fa9e4066Sahrens } 3020fa9e4066Sahrens } 3021fa9e4066Sahrens 3022fa9e4066Sahrens /* 3023fa9e4066Sahrens * If we were just looking for pools, report an error if none were 3024fa9e4066Sahrens * found. 3025fa9e4066Sahrens */ 3026fa9e4066Sahrens if (argc == 0 && first) 3027fa9e4066Sahrens (void) fprintf(stderr, 3028fa9e4066Sahrens gettext("no pools available to import\n")); 3029fa9e4066Sahrens 3030ecd6cf80Smarks error: 30312f8aaab3Seschrock nvlist_free(props); 3032fa9e4066Sahrens nvlist_free(pools); 3033468c413aSTim Haley nvlist_free(policy); 303499653d4eSeschrock free(searchdirs); 3035fa9e4066Sahrens 3036fa9e4066Sahrens return (err ? 1 : 0); 3037fa9e4066Sahrens } 3038fa9e4066Sahrens 30399c2acf00SAlek Pinchuk /* 30409c2acf00SAlek Pinchuk * zpool sync [-f] [pool] ... 30419c2acf00SAlek Pinchuk * 30429c2acf00SAlek Pinchuk * -f (undocumented) force uberblock (and config including zpool cache file) 30439c2acf00SAlek Pinchuk * update. 30449c2acf00SAlek Pinchuk * 30459c2acf00SAlek Pinchuk * Sync the specified pool(s). 30469c2acf00SAlek Pinchuk * Without arguments "zpool sync" will sync all pools. 30479c2acf00SAlek Pinchuk * This command initiates TXG sync(s) and will return after the TXG(s) commit. 30489c2acf00SAlek Pinchuk * 30499c2acf00SAlek Pinchuk */ 30509c2acf00SAlek Pinchuk static int 30519c2acf00SAlek Pinchuk zpool_do_sync(int argc, char **argv) 30529c2acf00SAlek Pinchuk { 30539c2acf00SAlek Pinchuk int ret; 30549c2acf00SAlek Pinchuk boolean_t force = B_FALSE; 30559c2acf00SAlek Pinchuk 30569c2acf00SAlek Pinchuk /* check options */ 30579c2acf00SAlek Pinchuk while ((ret = getopt(argc, argv, "f")) != -1) { 30589c2acf00SAlek Pinchuk switch (ret) { 30599c2acf00SAlek Pinchuk case 'f': 30609c2acf00SAlek Pinchuk force = B_TRUE; 30619c2acf00SAlek Pinchuk break; 30629c2acf00SAlek Pinchuk case '?': 30639c2acf00SAlek Pinchuk (void) fprintf(stderr, gettext("invalid option '%c'\n"), 30649c2acf00SAlek Pinchuk optopt); 30659c2acf00SAlek Pinchuk usage(B_FALSE); 30669c2acf00SAlek Pinchuk } 30679c2acf00SAlek Pinchuk } 30689c2acf00SAlek Pinchuk 30699c2acf00SAlek Pinchuk argc -= optind; 30709c2acf00SAlek Pinchuk argv += optind; 30719c2acf00SAlek Pinchuk 30729c2acf00SAlek Pinchuk /* if argc == 0 we will execute zpool_sync_one on all pools */ 30739c2acf00SAlek Pinchuk ret = for_each_pool(argc, argv, B_FALSE, NULL, zpool_sync_one, &force); 30749c2acf00SAlek Pinchuk 30759c2acf00SAlek Pinchuk return (ret); 30769c2acf00SAlek Pinchuk } 30779c2acf00SAlek Pinchuk 3078fa9e4066Sahrens typedef struct iostat_cbdata { 30794263d13fSGeorge Wilson boolean_t cb_verbose; 3080663207adSDon Brady int cb_name_flags; 3081fa9e4066Sahrens int cb_namewidth; 30824263d13fSGeorge Wilson int cb_iteration; 3083663207adSDon Brady boolean_t cb_scripted; 30844263d13fSGeorge Wilson zpool_list_t *cb_list; 3085fa9e4066Sahrens } iostat_cbdata_t; 3086fa9e4066Sahrens 3087fa9e4066Sahrens static void 3088fa9e4066Sahrens print_iostat_separator(iostat_cbdata_t *cb) 3089fa9e4066Sahrens { 3090fa9e4066Sahrens int i = 0; 3091fa9e4066Sahrens 3092fa9e4066Sahrens for (i = 0; i < cb->cb_namewidth; i++) 3093fa9e4066Sahrens (void) printf("-"); 3094fa9e4066Sahrens (void) printf(" ----- ----- ----- ----- ----- -----\n"); 3095fa9e4066Sahrens } 3096fa9e4066Sahrens 3097fa9e4066Sahrens static void 3098fa9e4066Sahrens print_iostat_header(iostat_cbdata_t *cb) 3099fa9e4066Sahrens { 3100fa9e4066Sahrens (void) printf("%*s capacity operations bandwidth\n", 3101fa9e4066Sahrens cb->cb_namewidth, ""); 3102485bbbf5SGeorge Wilson (void) printf("%-*s alloc free read write read write\n", 3103fa9e4066Sahrens cb->cb_namewidth, "pool"); 3104fa9e4066Sahrens print_iostat_separator(cb); 3105fa9e4066Sahrens } 3106fa9e4066Sahrens 3107fa9e4066Sahrens /* 3108fa9e4066Sahrens * Display a single statistic. 3109fa9e4066Sahrens */ 3110990b4856Slling static void 3111fa9e4066Sahrens print_one_stat(uint64_t value) 3112fa9e4066Sahrens { 3113fa9e4066Sahrens char buf[64]; 3114fa9e4066Sahrens 3115fa9e4066Sahrens zfs_nicenum(value, buf, sizeof (buf)); 3116fa9e4066Sahrens (void) printf(" %5s", buf); 3117fa9e4066Sahrens } 3118fa9e4066Sahrens 3119663207adSDon Brady static const char *class_name[] = { 3120663207adSDon Brady VDEV_ALLOC_BIAS_DEDUP, 3121663207adSDon Brady VDEV_ALLOC_BIAS_SPECIAL, 3122663207adSDon Brady VDEV_ALLOC_CLASS_LOGS 3123663207adSDon Brady }; 3124663207adSDon Brady 3125fa9e4066Sahrens /* 3126fa9e4066Sahrens * Print out all the statistics for the given vdev. This can either be the 3127fa9e4066Sahrens * toplevel configuration, or called recursively. If 'name' is NULL, then this 3128fa9e4066Sahrens * is a verbose output, and we don't want to display the toplevel pool stats. 3129fa9e4066Sahrens */ 313095fa23b1SJerry Jelinek static void 3131c67d9675Seschrock print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 3132c67d9675Seschrock nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 3133fa9e4066Sahrens { 3134fa9e4066Sahrens nvlist_t **oldchild, **newchild; 3135fa9e4066Sahrens uint_t c, children; 3136fa9e4066Sahrens vdev_stat_t *oldvs, *newvs; 3137fa9e4066Sahrens vdev_stat_t zerovs = { 0 }; 3138663207adSDon Brady char *vname; 3139fa9e4066Sahrens uint64_t tdelta; 3140fa9e4066Sahrens double scale; 3141fa9e4066Sahrens 31425cabbc6bSPrashanth Sreenivasa if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 314395fa23b1SJerry Jelinek return; 31445cabbc6bSPrashanth Sreenivasa 3145fa9e4066Sahrens if (oldnv != NULL) { 31463f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(oldnv, 31473f9d6ad7SLin Ling ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0); 3148fa9e4066Sahrens } else { 3149fa9e4066Sahrens oldvs = &zerovs; 3150fa9e4066Sahrens } 3151fa9e4066Sahrens 31523f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS, 3153fa9e4066Sahrens (uint64_t **)&newvs, &c) == 0); 3154fa9e4066Sahrens 3155fa9e4066Sahrens if (strlen(name) + depth > cb->cb_namewidth) 3156fa9e4066Sahrens (void) printf("%*s%s", depth, "", name); 3157fa9e4066Sahrens else 3158fa9e4066Sahrens (void) printf("%*s%s%*s", depth, "", name, 3159fa9e4066Sahrens (int)(cb->cb_namewidth - strlen(name) - depth), ""); 3160fa9e4066Sahrens 3161fa9e4066Sahrens tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 3162fa9e4066Sahrens 3163fa9e4066Sahrens if (tdelta == 0) 3164fa9e4066Sahrens scale = 1.0; 3165fa9e4066Sahrens else 3166fa9e4066Sahrens scale = (double)NANOSEC / tdelta; 3167fa9e4066Sahrens 3168fa9e4066Sahrens /* only toplevel vdevs have capacity stats */ 3169fa9e4066Sahrens if (newvs->vs_space == 0) { 3170fa9e4066Sahrens (void) printf(" - -"); 3171fa9e4066Sahrens } else { 3172fa9e4066Sahrens print_one_stat(newvs->vs_alloc); 3173fa9e4066Sahrens print_one_stat(newvs->vs_space - newvs->vs_alloc); 3174fa9e4066Sahrens } 3175fa9e4066Sahrens 3176fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] - 3177fa9e4066Sahrens oldvs->vs_ops[ZIO_TYPE_READ]))); 3178fa9e4066Sahrens 3179fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] - 3180fa9e4066Sahrens oldvs->vs_ops[ZIO_TYPE_WRITE]))); 3181fa9e4066Sahrens 3182fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] - 3183fa9e4066Sahrens oldvs->vs_bytes[ZIO_TYPE_READ]))); 3184fa9e4066Sahrens 3185fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] - 3186fa9e4066Sahrens oldvs->vs_bytes[ZIO_TYPE_WRITE]))); 3187fa9e4066Sahrens 3188fa9e4066Sahrens (void) printf("\n"); 3189fa9e4066Sahrens 3190fa9e4066Sahrens if (!cb->cb_verbose) 319195fa23b1SJerry Jelinek return; 3192fa9e4066Sahrens 3193fa9e4066Sahrens if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 3194fa9e4066Sahrens &newchild, &children) != 0) 319595fa23b1SJerry Jelinek return; 3196fa9e4066Sahrens 3197fa9e4066Sahrens if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 3198fa9e4066Sahrens &oldchild, &c) != 0) 319995fa23b1SJerry Jelinek return; 3200fa9e4066Sahrens 3201663207adSDon Brady /* 3202663207adSDon Brady * print normal top-level devices 3203663207adSDon Brady */ 3204afefbcddSeschrock for (c = 0; c < children; c++) { 32059d439f90SMike Harsch uint64_t ishole = B_FALSE, islog = B_FALSE; 32063f9d6ad7SLin Ling 32079d439f90SMike Harsch (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE, 32089d439f90SMike Harsch &ishole); 32099d439f90SMike Harsch 32109d439f90SMike Harsch (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG, 32119d439f90SMike Harsch &islog); 32129d439f90SMike Harsch 32139d439f90SMike Harsch if (ishole || islog) 32143f9d6ad7SLin Ling continue; 32153f9d6ad7SLin Ling 3216663207adSDon Brady if (nvlist_exists(newchild[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 3217663207adSDon Brady continue; 3218663207adSDon Brady 3219663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 3220663207adSDon Brady cb->cb_name_flags); 3221c67d9675Seschrock print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 3222afefbcddSeschrock newchild[c], cb, depth + 2); 3223afefbcddSeschrock free(vname); 3224afefbcddSeschrock } 3225fa94a07fSbrendan 32269d439f90SMike Harsch /* 3227663207adSDon Brady * print all other top-level devices 32289d439f90SMike Harsch */ 3229663207adSDon Brady for (uint_t n = 0; n < 3; n++) { 3230*c4e4d410SAndy Fiddaman boolean_t printed = B_FALSE; 32319d439f90SMike Harsch for (c = 0; c < children; c++) { 32329d439f90SMike Harsch uint64_t islog = B_FALSE; 3233663207adSDon Brady char *bias = NULL; 3234663207adSDon Brady char *type = NULL; 3235663207adSDon Brady 32369d439f90SMike Harsch (void) nvlist_lookup_uint64(newchild[c], 32379d439f90SMike Harsch ZPOOL_CONFIG_IS_LOG, &islog); 32389d439f90SMike Harsch if (islog) { 3239663207adSDon Brady bias = VDEV_ALLOC_CLASS_LOGS; 3240663207adSDon Brady } else { 3241663207adSDon Brady (void) nvlist_lookup_string(newchild[c], 3242663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &bias); 3243663207adSDon Brady (void) nvlist_lookup_string(newchild[c], 3244663207adSDon Brady ZPOOL_CONFIG_TYPE, &type); 32459d439f90SMike Harsch } 3246663207adSDon Brady if (bias == NULL || strcmp(bias, class_name[n]) != 0) 3247663207adSDon Brady continue; 3248663207adSDon Brady if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0) 3249663207adSDon Brady continue; 3250663207adSDon Brady 3251*c4e4d410SAndy Fiddaman if (!printed) { 3252*c4e4d410SAndy Fiddaman if (!cb->cb_scripted) { 3253*c4e4d410SAndy Fiddaman (void) printf( 3254*c4e4d410SAndy Fiddaman "%-*s - - - -" 3255*c4e4d410SAndy Fiddaman " - -", 3256*c4e4d410SAndy Fiddaman cb->cb_namewidth, class_name[n]); 3257*c4e4d410SAndy Fiddaman } 3258*c4e4d410SAndy Fiddaman printf("\n"); 3259*c4e4d410SAndy Fiddaman printed = B_TRUE; 3260*c4e4d410SAndy Fiddaman } 3261*c4e4d410SAndy Fiddaman 3262663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 3263663207adSDon Brady cb->cb_name_flags); 326495fa23b1SJerry Jelinek print_vdev_stats(zhp, vname, oldnv ? 3265663207adSDon Brady oldchild[c] : NULL, newchild[c], cb, depth + 2); 3266663207adSDon Brady free(vname); 32679d439f90SMike Harsch } 32689d439f90SMike Harsch 32699d439f90SMike Harsch } 32709d439f90SMike Harsch 3271fa94a07fSbrendan /* 3272fa94a07fSbrendan * Include level 2 ARC devices in iostat output 3273fa94a07fSbrendan */ 3274fa94a07fSbrendan if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, 3275fa94a07fSbrendan &newchild, &children) != 0) 327695fa23b1SJerry Jelinek return; 3277fa94a07fSbrendan 3278fa94a07fSbrendan if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, 3279fa94a07fSbrendan &oldchild, &c) != 0) 328095fa23b1SJerry Jelinek return; 3281fa94a07fSbrendan 3282fa94a07fSbrendan if (children > 0) { 3283fa94a07fSbrendan (void) printf("%-*s - - - - - " 3284fa94a07fSbrendan "-\n", cb->cb_namewidth, "cache"); 3285fa94a07fSbrendan for (c = 0; c < children; c++) { 328688ecc943SGeorge Wilson vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 3287663207adSDon Brady cb->cb_name_flags); 3288fa94a07fSbrendan print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 3289fa94a07fSbrendan newchild[c], cb, depth + 2); 3290fa94a07fSbrendan free(vname); 3291fa94a07fSbrendan } 3292fa94a07fSbrendan } 3293fa9e4066Sahrens } 3294fa9e4066Sahrens 3295088e9d47Seschrock static int 3296088e9d47Seschrock refresh_iostat(zpool_handle_t *zhp, void *data) 3297088e9d47Seschrock { 3298088e9d47Seschrock iostat_cbdata_t *cb = data; 329994de1d4cSeschrock boolean_t missing; 3300088e9d47Seschrock 3301088e9d47Seschrock /* 3302088e9d47Seschrock * If the pool has disappeared, remove it from the list and continue. 3303088e9d47Seschrock */ 330494de1d4cSeschrock if (zpool_refresh_stats(zhp, &missing) != 0) 330594de1d4cSeschrock return (-1); 330694de1d4cSeschrock 330794de1d4cSeschrock if (missing) 3308088e9d47Seschrock pool_list_remove(cb->cb_list, zhp); 3309088e9d47Seschrock 3310088e9d47Seschrock return (0); 3311088e9d47Seschrock } 3312088e9d47Seschrock 3313fa9e4066Sahrens /* 3314fa9e4066Sahrens * Callback to print out the iostats for the given pool. 3315fa9e4066Sahrens */ 3316fa9e4066Sahrens int 3317fa9e4066Sahrens print_iostat(zpool_handle_t *zhp, void *data) 3318fa9e4066Sahrens { 3319fa9e4066Sahrens iostat_cbdata_t *cb = data; 3320fa9e4066Sahrens nvlist_t *oldconfig, *newconfig; 3321fa9e4066Sahrens nvlist_t *oldnvroot, *newnvroot; 3322fa9e4066Sahrens 3323088e9d47Seschrock newconfig = zpool_get_config(zhp, &oldconfig); 3324fa9e4066Sahrens 3325088e9d47Seschrock if (cb->cb_iteration == 1) 3326fa9e4066Sahrens oldconfig = NULL; 3327fa9e4066Sahrens 3328fa9e4066Sahrens verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 3329fa9e4066Sahrens &newnvroot) == 0); 3330fa9e4066Sahrens 3331088e9d47Seschrock if (oldconfig == NULL) 3332fa9e4066Sahrens oldnvroot = NULL; 3333088e9d47Seschrock else 3334088e9d47Seschrock verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 3335088e9d47Seschrock &oldnvroot) == 0); 3336fa9e4066Sahrens 3337fa9e4066Sahrens /* 3338fa9e4066Sahrens * Print out the statistics for the pool. 3339fa9e4066Sahrens */ 3340c67d9675Seschrock print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 3341fa9e4066Sahrens 3342fa9e4066Sahrens if (cb->cb_verbose) 3343fa9e4066Sahrens print_iostat_separator(cb); 3344fa9e4066Sahrens 3345fa9e4066Sahrens return (0); 3346fa9e4066Sahrens } 3347fa9e4066Sahrens 3348fa9e4066Sahrens int 3349fa9e4066Sahrens get_namewidth(zpool_handle_t *zhp, void *data) 3350fa9e4066Sahrens { 3351fa9e4066Sahrens iostat_cbdata_t *cb = data; 3352fa9e4066Sahrens nvlist_t *config, *nvroot; 3353fa9e4066Sahrens 3354088e9d47Seschrock if ((config = zpool_get_config(zhp, NULL)) != NULL) { 3355fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 3356fa9e4066Sahrens &nvroot) == 0); 3357fa9e4066Sahrens if (!cb->cb_verbose) 3358fa9e4066Sahrens cb->cb_namewidth = strlen(zpool_get_name(zhp)); 3359fa9e4066Sahrens else 3360e1d5e507SFrederik Wessels cb->cb_namewidth = max_width(zhp, nvroot, 0, 3361663207adSDon Brady cb->cb_namewidth, cb->cb_name_flags); 3362fa9e4066Sahrens } 3363fa9e4066Sahrens 3364fa9e4066Sahrens /* 3365fa9e4066Sahrens * The width must fall into the range [10,38]. The upper limit is the 3366fa9e4066Sahrens * maximum we can have and still fit in 80 columns. 3367fa9e4066Sahrens */ 3368fa9e4066Sahrens if (cb->cb_namewidth < 10) 3369fa9e4066Sahrens cb->cb_namewidth = 10; 3370fa9e4066Sahrens if (cb->cb_namewidth > 38) 3371fa9e4066Sahrens cb->cb_namewidth = 38; 3372fa9e4066Sahrens 3373fa9e4066Sahrens return (0); 3374fa9e4066Sahrens } 3375fa9e4066Sahrens 3376fa9e4066Sahrens /* 33773f9d6ad7SLin Ling * Parse the input string, get the 'interval' and 'count' value if there is one. 3378fa9e4066Sahrens */ 33793f9d6ad7SLin Ling static void 33803f9d6ad7SLin Ling get_interval_count(int *argcp, char **argv, unsigned long *iv, 33813f9d6ad7SLin Ling unsigned long *cnt) 3382fa9e4066Sahrens { 3383fa9e4066Sahrens unsigned long interval = 0, count = 0; 33843f9d6ad7SLin Ling int argc = *argcp, errno; 3385fa9e4066Sahrens 3386fa9e4066Sahrens /* 3387fa9e4066Sahrens * Determine if the last argument is an integer or a pool name 3388fa9e4066Sahrens */ 3389fa9e4066Sahrens if (argc > 0 && isdigit(argv[argc - 1][0])) { 3390fa9e4066Sahrens char *end; 3391fa9e4066Sahrens 3392fa9e4066Sahrens errno = 0; 3393fa9e4066Sahrens interval = strtoul(argv[argc - 1], &end, 10); 3394fa9e4066Sahrens 3395fa9e4066Sahrens if (*end == '\0' && errno == 0) { 3396fa9e4066Sahrens if (interval == 0) { 3397fa9e4066Sahrens (void) fprintf(stderr, gettext("interval " 3398fa9e4066Sahrens "cannot be zero\n")); 339999653d4eSeschrock usage(B_FALSE); 3400fa9e4066Sahrens } 3401fa9e4066Sahrens /* 3402fa9e4066Sahrens * Ignore the last parameter 3403fa9e4066Sahrens */ 3404fa9e4066Sahrens argc--; 3405fa9e4066Sahrens } else { 3406fa9e4066Sahrens /* 3407fa9e4066Sahrens * If this is not a valid number, just plow on. The 3408fa9e4066Sahrens * user will get a more informative error message later 3409fa9e4066Sahrens * on. 3410fa9e4066Sahrens */ 3411fa9e4066Sahrens interval = 0; 3412fa9e4066Sahrens } 3413fa9e4066Sahrens } 3414fa9e4066Sahrens 3415fa9e4066Sahrens /* 3416fa9e4066Sahrens * If the last argument is also an integer, then we have both a count 34173f9d6ad7SLin Ling * and an interval. 3418fa9e4066Sahrens */ 3419fa9e4066Sahrens if (argc > 0 && isdigit(argv[argc - 1][0])) { 3420fa9e4066Sahrens char *end; 3421fa9e4066Sahrens 3422fa9e4066Sahrens errno = 0; 3423fa9e4066Sahrens count = interval; 3424fa9e4066Sahrens interval = strtoul(argv[argc - 1], &end, 10); 3425fa9e4066Sahrens 3426fa9e4066Sahrens if (*end == '\0' && errno == 0) { 3427fa9e4066Sahrens if (interval == 0) { 3428fa9e4066Sahrens (void) fprintf(stderr, gettext("interval " 3429fa9e4066Sahrens "cannot be zero\n")); 343099653d4eSeschrock usage(B_FALSE); 3431fa9e4066Sahrens } 3432fa9e4066Sahrens 3433fa9e4066Sahrens /* 3434fa9e4066Sahrens * Ignore the last parameter 3435fa9e4066Sahrens */ 3436fa9e4066Sahrens argc--; 3437fa9e4066Sahrens } else { 3438fa9e4066Sahrens interval = 0; 3439fa9e4066Sahrens } 3440fa9e4066Sahrens } 3441fa9e4066Sahrens 34423f9d6ad7SLin Ling *iv = interval; 34433f9d6ad7SLin Ling *cnt = count; 34443f9d6ad7SLin Ling *argcp = argc; 34453f9d6ad7SLin Ling } 34463f9d6ad7SLin Ling 34473f9d6ad7SLin Ling static void 34483f9d6ad7SLin Ling get_timestamp_arg(char c) 34493f9d6ad7SLin Ling { 34503f9d6ad7SLin Ling if (c == 'u') 34513f9d6ad7SLin Ling timestamp_fmt = UDATE; 34523f9d6ad7SLin Ling else if (c == 'd') 34533f9d6ad7SLin Ling timestamp_fmt = DDATE; 34543f9d6ad7SLin Ling else 34553f9d6ad7SLin Ling usage(B_FALSE); 34563f9d6ad7SLin Ling } 34573f9d6ad7SLin Ling 34583f9d6ad7SLin Ling /* 3459663207adSDon Brady * zpool iostat [-gLPv] [-T d|u] [pool] ... [interval [count]] 34603f9d6ad7SLin Ling * 3461663207adSDon Brady * -g Display guid for individual vdev name. 3462663207adSDon Brady * -L Follow links when resolving vdev path name. 3463663207adSDon Brady * -P Display full path for vdev name. 34643f9d6ad7SLin Ling * -v Display statistics for individual vdevs 34653f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format 34663f9d6ad7SLin Ling * 34673f9d6ad7SLin Ling * This command can be tricky because we want to be able to deal with pool 34683f9d6ad7SLin Ling * creation/destruction as well as vdev configuration changes. The bulk of this 34693f9d6ad7SLin Ling * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 34703f9d6ad7SLin Ling * on pool_list_update() to detect the addition of new pools. Configuration 34713f9d6ad7SLin Ling * changes are all handled within libzfs. 34723f9d6ad7SLin Ling */ 34733f9d6ad7SLin Ling int 34743f9d6ad7SLin Ling zpool_do_iostat(int argc, char **argv) 34753f9d6ad7SLin Ling { 34763f9d6ad7SLin Ling int c; 34773f9d6ad7SLin Ling int ret; 34783f9d6ad7SLin Ling int npools; 34793f9d6ad7SLin Ling unsigned long interval = 0, count = 0; 34803f9d6ad7SLin Ling zpool_list_t *list; 34813f9d6ad7SLin Ling boolean_t verbose = B_FALSE; 3482663207adSDon Brady boolean_t guid = B_FALSE; 3483663207adSDon Brady boolean_t follow_links = B_FALSE; 3484663207adSDon Brady boolean_t full_name = B_FALSE; 3485663207adSDon Brady iostat_cbdata_t cb = { 0 }; 34863f9d6ad7SLin Ling 34873f9d6ad7SLin Ling /* check options */ 3488663207adSDon Brady while ((c = getopt(argc, argv, "gLPT:v")) != -1) { 34893f9d6ad7SLin Ling switch (c) { 3490663207adSDon Brady case 'g': 3491663207adSDon Brady guid = B_TRUE; 3492663207adSDon Brady break; 3493663207adSDon Brady case 'L': 3494663207adSDon Brady follow_links = B_TRUE; 3495663207adSDon Brady break; 3496663207adSDon Brady case 'P': 3497663207adSDon Brady full_name = B_TRUE; 3498663207adSDon Brady break; 34993f9d6ad7SLin Ling case 'T': 35003f9d6ad7SLin Ling get_timestamp_arg(*optarg); 35013f9d6ad7SLin Ling break; 35023f9d6ad7SLin Ling case 'v': 35033f9d6ad7SLin Ling verbose = B_TRUE; 35043f9d6ad7SLin Ling break; 35053f9d6ad7SLin Ling case '?': 35063f9d6ad7SLin Ling (void) fprintf(stderr, gettext("invalid option '%c'\n"), 35073f9d6ad7SLin Ling optopt); 35083f9d6ad7SLin Ling usage(B_FALSE); 35093f9d6ad7SLin Ling } 35103f9d6ad7SLin Ling } 35113f9d6ad7SLin Ling 35123f9d6ad7SLin Ling argc -= optind; 35133f9d6ad7SLin Ling argv += optind; 35143f9d6ad7SLin Ling 35153f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count); 35163f9d6ad7SLin Ling 3517fa9e4066Sahrens /* 3518fa9e4066Sahrens * Construct the list of all interesting pools. 3519fa9e4066Sahrens */ 3520fa9e4066Sahrens ret = 0; 3521b1b8ab34Slling if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL) 3522fa9e4066Sahrens return (1); 3523fa9e4066Sahrens 352499653d4eSeschrock if (pool_list_count(list) == 0 && argc != 0) { 352599653d4eSeschrock pool_list_free(list); 3526fa9e4066Sahrens return (1); 352799653d4eSeschrock } 3528fa9e4066Sahrens 3529fa9e4066Sahrens if (pool_list_count(list) == 0 && interval == 0) { 353099653d4eSeschrock pool_list_free(list); 3531fa9e4066Sahrens (void) fprintf(stderr, gettext("no pools available\n")); 3532fa9e4066Sahrens return (1); 3533fa9e4066Sahrens } 3534fa9e4066Sahrens 3535fa9e4066Sahrens /* 3536fa9e4066Sahrens * Enter the main iostat loop. 3537fa9e4066Sahrens */ 3538fa9e4066Sahrens cb.cb_list = list; 3539fa9e4066Sahrens cb.cb_verbose = verbose; 3540663207adSDon Brady if (guid) 3541663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_GUID; 3542663207adSDon Brady if (follow_links) 3543663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS; 3544663207adSDon Brady if (full_name) 3545663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_PATH; 3546fa9e4066Sahrens cb.cb_iteration = 0; 3547fa9e4066Sahrens cb.cb_namewidth = 0; 3548fa9e4066Sahrens 3549fa9e4066Sahrens for (;;) { 3550fa9e4066Sahrens pool_list_update(list); 3551fa9e4066Sahrens 3552fa9e4066Sahrens if ((npools = pool_list_count(list)) == 0) 3553fa9e4066Sahrens break; 3554fa9e4066Sahrens 3555088e9d47Seschrock /* 3556088e9d47Seschrock * Refresh all statistics. This is done as an explicit step 3557088e9d47Seschrock * before calculating the maximum name width, so that any 3558088e9d47Seschrock * configuration changes are properly accounted for. 3559088e9d47Seschrock */ 356099653d4eSeschrock (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb); 3561088e9d47Seschrock 3562fa9e4066Sahrens /* 3563fa9e4066Sahrens * Iterate over all pools to determine the maximum width 3564fa9e4066Sahrens * for the pool / device name column across all pools. 3565fa9e4066Sahrens */ 3566fa9e4066Sahrens cb.cb_namewidth = 0; 356799653d4eSeschrock (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 3568fa9e4066Sahrens 356926fd7700SKrishnendu Sadhukhan - Sun Microsystems if (timestamp_fmt != NODATE) 357026fd7700SKrishnendu Sadhukhan - Sun Microsystems print_timestamp(timestamp_fmt); 357126fd7700SKrishnendu Sadhukhan - Sun Microsystems 3572fa9e4066Sahrens /* 3573fa9e4066Sahrens * If it's the first time, or verbose mode, print the header. 3574fa9e4066Sahrens */ 3575fa9e4066Sahrens if (++cb.cb_iteration == 1 || verbose) 3576fa9e4066Sahrens print_iostat_header(&cb); 3577fa9e4066Sahrens 357899653d4eSeschrock (void) pool_list_iter(list, B_FALSE, print_iostat, &cb); 3579fa9e4066Sahrens 3580fa9e4066Sahrens /* 3581fa9e4066Sahrens * If there's more than one pool, and we're not in verbose mode 3582fa9e4066Sahrens * (which prints a separator for us), then print a separator. 3583fa9e4066Sahrens */ 3584fa9e4066Sahrens if (npools > 1 && !verbose) 3585fa9e4066Sahrens print_iostat_separator(&cb); 3586fa9e4066Sahrens 3587fa9e4066Sahrens if (verbose) 3588fa9e4066Sahrens (void) printf("\n"); 3589fa9e4066Sahrens 359039c23413Seschrock /* 359139c23413Seschrock * Flush the output so that redirection to a file isn't buffered 359239c23413Seschrock * indefinitely. 359339c23413Seschrock */ 359439c23413Seschrock (void) fflush(stdout); 359539c23413Seschrock 3596fa9e4066Sahrens if (interval == 0) 3597fa9e4066Sahrens break; 3598fa9e4066Sahrens 3599fa9e4066Sahrens if (count != 0 && --count == 0) 3600fa9e4066Sahrens break; 3601fa9e4066Sahrens 3602fa9e4066Sahrens (void) sleep(interval); 3603fa9e4066Sahrens } 3604fa9e4066Sahrens 3605fa9e4066Sahrens pool_list_free(list); 3606fa9e4066Sahrens 3607fa9e4066Sahrens return (ret); 3608fa9e4066Sahrens } 3609fa9e4066Sahrens 3610fa9e4066Sahrens typedef struct list_cbdata { 36114263d13fSGeorge Wilson boolean_t cb_verbose; 3612663207adSDon Brady int cb_name_flags; 36134263d13fSGeorge Wilson int cb_namewidth; 361499653d4eSeschrock boolean_t cb_scripted; 3615990b4856Slling zprop_list_t *cb_proplist; 3616c58b3526SAdam Stevko boolean_t cb_literal; 3617fa9e4066Sahrens } list_cbdata_t; 3618fa9e4066Sahrens 3619663207adSDon Brady 3620fa9e4066Sahrens /* 3621fa9e4066Sahrens * Given a list of columns to display, output appropriate headers for each one. 3622fa9e4066Sahrens */ 3623990b4856Slling static void 36244263d13fSGeorge Wilson print_header(list_cbdata_t *cb) 3625fa9e4066Sahrens { 36264263d13fSGeorge Wilson zprop_list_t *pl = cb->cb_proplist; 3627ad135b5dSChristopher Siden char headerbuf[ZPOOL_MAXPROPLEN]; 3628990b4856Slling const char *header; 3629990b4856Slling boolean_t first = B_TRUE; 3630990b4856Slling boolean_t right_justify; 36314263d13fSGeorge Wilson size_t width = 0; 3632990b4856Slling 3633990b4856Slling for (; pl != NULL; pl = pl->pl_next) { 36344263d13fSGeorge Wilson width = pl->pl_width; 36354263d13fSGeorge Wilson if (first && cb->cb_verbose) { 36364263d13fSGeorge Wilson /* 36374263d13fSGeorge Wilson * Reset the width to accommodate the verbose listing 36384263d13fSGeorge Wilson * of devices. 36394263d13fSGeorge Wilson */ 36404263d13fSGeorge Wilson width = cb->cb_namewidth; 36414263d13fSGeorge Wilson } 36424263d13fSGeorge Wilson 3643990b4856Slling if (!first) 3644fa9e4066Sahrens (void) printf(" "); 3645fa9e4066Sahrens else 3646990b4856Slling first = B_FALSE; 3647990b4856Slling 3648ad135b5dSChristopher Siden right_justify = B_FALSE; 3649ad135b5dSChristopher Siden if (pl->pl_prop != ZPROP_INVAL) { 3650ad135b5dSChristopher Siden header = zpool_prop_column_name(pl->pl_prop); 3651ad135b5dSChristopher Siden right_justify = zpool_prop_align_right(pl->pl_prop); 3652ad135b5dSChristopher Siden } else { 3653ad135b5dSChristopher Siden int i; 3654ad135b5dSChristopher Siden 3655ad135b5dSChristopher Siden for (i = 0; pl->pl_user_prop[i] != '\0'; i++) 3656ad135b5dSChristopher Siden headerbuf[i] = toupper(pl->pl_user_prop[i]); 3657ad135b5dSChristopher Siden headerbuf[i] = '\0'; 3658ad135b5dSChristopher Siden header = headerbuf; 3659ad135b5dSChristopher Siden } 3660fa9e4066Sahrens 3661990b4856Slling if (pl->pl_next == NULL && !right_justify) 3662990b4856Slling (void) printf("%s", header); 3663990b4856Slling else if (right_justify) 36644263d13fSGeorge Wilson (void) printf("%*s", width, header); 3665990b4856Slling else 36664263d13fSGeorge Wilson (void) printf("%-*s", width, header); 36674263d13fSGeorge Wilson 3668fa9e4066Sahrens } 3669fa9e4066Sahrens 3670fa9e4066Sahrens (void) printf("\n"); 3671fa9e4066Sahrens } 3672fa9e4066Sahrens 3673990b4856Slling /* 3674990b4856Slling * Given a pool and a list of properties, print out all the properties according 3675663207adSDon Brady * to the described layout. Used by zpool_do_list(). 3676990b4856Slling */ 3677990b4856Slling static void 36784263d13fSGeorge Wilson print_pool(zpool_handle_t *zhp, list_cbdata_t *cb) 3679fa9e4066Sahrens { 36804263d13fSGeorge Wilson zprop_list_t *pl = cb->cb_proplist; 3681990b4856Slling boolean_t first = B_TRUE; 3682990b4856Slling char property[ZPOOL_MAXPROPLEN]; 3683990b4856Slling char *propstr; 3684990b4856Slling boolean_t right_justify; 36854263d13fSGeorge Wilson size_t width; 3686990b4856Slling 3687990b4856Slling for (; pl != NULL; pl = pl->pl_next) { 36884263d13fSGeorge Wilson 36894263d13fSGeorge Wilson width = pl->pl_width; 36904263d13fSGeorge Wilson if (first && cb->cb_verbose) { 36914263d13fSGeorge Wilson /* 36924263d13fSGeorge Wilson * Reset the width to accommodate the verbose listing 36934263d13fSGeorge Wilson * of devices. 36944263d13fSGeorge Wilson */ 36954263d13fSGeorge Wilson width = cb->cb_namewidth; 36964263d13fSGeorge Wilson } 36974263d13fSGeorge Wilson 3698990b4856Slling if (!first) { 36994263d13fSGeorge Wilson if (cb->cb_scripted) 3700fa9e4066Sahrens (void) printf("\t"); 3701fa9e4066Sahrens else 3702fa9e4066Sahrens (void) printf(" "); 3703990b4856Slling } else { 3704990b4856Slling first = B_FALSE; 3705fa9e4066Sahrens } 3706fa9e4066Sahrens 3707990b4856Slling right_justify = B_FALSE; 3708990b4856Slling if (pl->pl_prop != ZPROP_INVAL) { 37097a09f97bSGeorge Wilson if (zpool_get_prop(zhp, pl->pl_prop, property, 3710c58b3526SAdam Stevko sizeof (property), NULL, cb->cb_literal) != 0) 3711990b4856Slling propstr = "-"; 3712fa9e4066Sahrens else 3713990b4856Slling propstr = property; 3714fa9e4066Sahrens 3715990b4856Slling right_justify = zpool_prop_align_right(pl->pl_prop); 3716ad135b5dSChristopher Siden } else if ((zpool_prop_feature(pl->pl_user_prop) || 3717ad135b5dSChristopher Siden zpool_prop_unsupported(pl->pl_user_prop)) && 3718ad135b5dSChristopher Siden zpool_prop_get_feature(zhp, pl->pl_user_prop, property, 3719ad135b5dSChristopher Siden sizeof (property)) == 0) { 3720ad135b5dSChristopher Siden propstr = property; 3721990b4856Slling } else { 3722990b4856Slling propstr = "-"; 3723990b4856Slling } 3724fa9e4066Sahrens 3725fa9e4066Sahrens 3726990b4856Slling /* 3727990b4856Slling * If this is being called in scripted mode, or if this is the 3728990b4856Slling * last column and it is left-justified, don't include a width 3729990b4856Slling * format specifier. 3730990b4856Slling */ 37314263d13fSGeorge Wilson if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify)) 3732990b4856Slling (void) printf("%s", propstr); 3733990b4856Slling else if (right_justify) 3734990b4856Slling (void) printf("%*s", width, propstr); 3735990b4856Slling else 3736990b4856Slling (void) printf("%-*s", width, propstr); 3737990b4856Slling } 3738fa9e4066Sahrens 3739990b4856Slling (void) printf("\n"); 3740990b4856Slling } 3741fa9e4066Sahrens 37424263d13fSGeorge Wilson static void 37437a09f97bSGeorge Wilson print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted, 37447a09f97bSGeorge Wilson boolean_t valid) 37454263d13fSGeorge Wilson { 37464263d13fSGeorge Wilson char propval[64]; 37474263d13fSGeorge Wilson boolean_t fixed; 37484263d13fSGeorge Wilson size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL); 37494263d13fSGeorge Wilson 37507a09f97bSGeorge Wilson switch (prop) { 37517a09f97bSGeorge Wilson case ZPOOL_PROP_EXPANDSZ: 375286714001SSerapheim Dimitropoulos case ZPOOL_PROP_CHECKPOINT: 37537a09f97bSGeorge Wilson if (value == 0) 37547a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval)); 37557a09f97bSGeorge Wilson else 37567a09f97bSGeorge Wilson zfs_nicenum(value, propval, sizeof (propval)); 37577a09f97bSGeorge Wilson break; 37587a09f97bSGeorge Wilson case ZPOOL_PROP_FRAGMENTATION: 37597a09f97bSGeorge Wilson if (value == ZFS_FRAG_INVALID) { 37607a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval)); 37617a09f97bSGeorge Wilson } else { 37627a09f97bSGeorge Wilson (void) snprintf(propval, sizeof (propval), "%llu%%", 37637a09f97bSGeorge Wilson value); 37647a09f97bSGeorge Wilson } 37657a09f97bSGeorge Wilson break; 37667a09f97bSGeorge Wilson case ZPOOL_PROP_CAPACITY: 3767663207adSDon Brady (void) snprintf(propval, sizeof (propval), 3768663207adSDon Brady value < 1000 ? "%1.2f%%" : value < 10000 ? 3769663207adSDon Brady "%2.1f%%" : "%3.0f%%", value / 100.0); 37707a09f97bSGeorge Wilson break; 37717a09f97bSGeorge Wilson default: 37722e4c9986SGeorge Wilson zfs_nicenum(value, propval, sizeof (propval)); 37737a09f97bSGeorge Wilson } 37747a09f97bSGeorge Wilson 37757a09f97bSGeorge Wilson if (!valid) 37767a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval)); 37774263d13fSGeorge Wilson 37784263d13fSGeorge Wilson if (scripted) 37794263d13fSGeorge Wilson (void) printf("\t%s", propval); 37804263d13fSGeorge Wilson else 37814263d13fSGeorge Wilson (void) printf(" %*s", width, propval); 37824263d13fSGeorge Wilson } 37834263d13fSGeorge Wilson 3784663207adSDon Brady /* 3785663207adSDon Brady * print static default line per vdev 3786663207adSDon Brady */ 37874263d13fSGeorge Wilson void 37884263d13fSGeorge Wilson print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 37894263d13fSGeorge Wilson list_cbdata_t *cb, int depth) 37904263d13fSGeorge Wilson { 37914263d13fSGeorge Wilson nvlist_t **child; 37924263d13fSGeorge Wilson vdev_stat_t *vs; 37934263d13fSGeorge Wilson uint_t c, children; 37944263d13fSGeorge Wilson char *vname; 37954263d13fSGeorge Wilson boolean_t scripted = cb->cb_scripted; 379652244c09SJohn Wren Kennedy uint64_t islog = B_FALSE; 379752244c09SJohn Wren Kennedy char *dashes = "%-*s - - - - - -\n"; 37984263d13fSGeorge Wilson 37994263d13fSGeorge Wilson verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 38004263d13fSGeorge Wilson (uint64_t **)&vs, &c) == 0); 38014263d13fSGeorge Wilson 38024263d13fSGeorge Wilson if (name != NULL) { 38037a09f97bSGeorge Wilson boolean_t toplevel = (vs->vs_space != 0); 38047a09f97bSGeorge Wilson uint64_t cap; 38057a09f97bSGeorge Wilson 38065cabbc6bSPrashanth Sreenivasa if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 38075cabbc6bSPrashanth Sreenivasa return; 38085cabbc6bSPrashanth Sreenivasa 38094263d13fSGeorge Wilson if (scripted) 38104263d13fSGeorge Wilson (void) printf("\t%s", name); 38114263d13fSGeorge Wilson else if (strlen(name) + depth > cb->cb_namewidth) 38124263d13fSGeorge Wilson (void) printf("%*s%s", depth, "", name); 38134263d13fSGeorge Wilson else 38144263d13fSGeorge Wilson (void) printf("%*s%s%*s", depth, "", name, 38154263d13fSGeorge Wilson (int)(cb->cb_namewidth - strlen(name) - depth), ""); 38164263d13fSGeorge Wilson 38177a09f97bSGeorge Wilson /* 38187a09f97bSGeorge Wilson * Print the properties for the individual vdevs. Some 38197a09f97bSGeorge Wilson * properties are only applicable to toplevel vdevs. The 38207a09f97bSGeorge Wilson * 'toplevel' boolean value is passed to the print_one_column() 38217a09f97bSGeorge Wilson * to indicate that the value is valid. 38227a09f97bSGeorge Wilson */ 38237a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted, 38247a09f97bSGeorge Wilson toplevel); 38257a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted, 38267a09f97bSGeorge Wilson toplevel); 38277a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc, 38287a09f97bSGeorge Wilson scripted, toplevel); 382986714001SSerapheim Dimitropoulos print_one_column(ZPOOL_PROP_CHECKPOINT, 383086714001SSerapheim Dimitropoulos vs->vs_checkpoint_space, scripted, toplevel); 38317a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted, 38327a09f97bSGeorge Wilson B_TRUE); 38337a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_FRAGMENTATION, 38347a09f97bSGeorge Wilson vs->vs_fragmentation, scripted, 38357a09f97bSGeorge Wilson (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel)); 38367a09f97bSGeorge Wilson cap = (vs->vs_space == 0) ? 0 : 3837663207adSDon Brady (vs->vs_alloc * 10000 / vs->vs_space); 38387a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel); 38394263d13fSGeorge Wilson (void) printf("\n"); 38404263d13fSGeorge Wilson } 38414263d13fSGeorge Wilson 38424263d13fSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 38434263d13fSGeorge Wilson &child, &children) != 0) 38444263d13fSGeorge Wilson return; 38454263d13fSGeorge Wilson 3846663207adSDon Brady /* list the normal vdevs first */ 38474263d13fSGeorge Wilson for (c = 0; c < children; c++) { 38484263d13fSGeorge Wilson uint64_t ishole = B_FALSE; 38494263d13fSGeorge Wilson 38504263d13fSGeorge Wilson if (nvlist_lookup_uint64(child[c], 38514263d13fSGeorge Wilson ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole) 38524263d13fSGeorge Wilson continue; 38534263d13fSGeorge Wilson 385452244c09SJohn Wren Kennedy if (nvlist_lookup_uint64(child[c], 3855663207adSDon Brady ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) 385652244c09SJohn Wren Kennedy continue; 385752244c09SJohn Wren Kennedy 3858663207adSDon Brady if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 3859663207adSDon Brady continue; 3860663207adSDon Brady 3861663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 3862663207adSDon Brady cb->cb_name_flags); 38634263d13fSGeorge Wilson print_list_stats(zhp, vname, child[c], cb, depth + 2); 38644263d13fSGeorge Wilson free(vname); 38654263d13fSGeorge Wilson } 38664263d13fSGeorge Wilson 3867663207adSDon Brady /* list the classes: 'logs', 'dedup', and 'special' */ 3868663207adSDon Brady for (uint_t n = 0; n < 3; n++) { 3869663207adSDon Brady boolean_t printed = B_FALSE; 3870663207adSDon Brady 387152244c09SJohn Wren Kennedy for (c = 0; c < children; c++) { 3872663207adSDon Brady char *bias = NULL; 3873663207adSDon Brady char *type = NULL; 3874663207adSDon Brady 387552244c09SJohn Wren Kennedy if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 3876663207adSDon Brady &islog) == 0 && islog) { 3877663207adSDon Brady bias = VDEV_ALLOC_CLASS_LOGS; 3878663207adSDon Brady } else { 3879663207adSDon Brady (void) nvlist_lookup_string(child[c], 3880663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &bias); 3881663207adSDon Brady (void) nvlist_lookup_string(child[c], 3882663207adSDon Brady ZPOOL_CONFIG_TYPE, &type); 3883663207adSDon Brady } 3884663207adSDon Brady if (bias == NULL || strcmp(bias, class_name[n]) != 0) 3885663207adSDon Brady continue; 3886663207adSDon Brady if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0) 388752244c09SJohn Wren Kennedy continue; 3888663207adSDon Brady 3889663207adSDon Brady if (!printed) { 3890663207adSDon Brady /* LINTED E_SEC_PRINTF_VAR_FMT */ 3891663207adSDon Brady (void) printf(dashes, cb->cb_namewidth, 3892663207adSDon Brady class_name[n]); 3893663207adSDon Brady printed = B_TRUE; 3894663207adSDon Brady } 3895663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 3896663207adSDon Brady cb->cb_name_flags); 389752244c09SJohn Wren Kennedy print_list_stats(zhp, vname, child[c], cb, depth + 2); 389852244c09SJohn Wren Kennedy free(vname); 389952244c09SJohn Wren Kennedy } 390052244c09SJohn Wren Kennedy } 390152244c09SJohn Wren Kennedy 39024263d13fSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 390352244c09SJohn Wren Kennedy &child, &children) == 0 && children > 0) { 390452244c09SJohn Wren Kennedy /* LINTED E_SEC_PRINTF_VAR_FMT */ 390552244c09SJohn Wren Kennedy (void) printf(dashes, cb->cb_namewidth, "cache"); 390652244c09SJohn Wren Kennedy for (c = 0; c < children; c++) { 3907663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 3908663207adSDon Brady cb->cb_name_flags); 390952244c09SJohn Wren Kennedy print_list_stats(zhp, vname, child[c], cb, depth + 2); 391052244c09SJohn Wren Kennedy free(vname); 391152244c09SJohn Wren Kennedy } 391252244c09SJohn Wren Kennedy } 39134263d13fSGeorge Wilson 391452244c09SJohn Wren Kennedy if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child, 391552244c09SJohn Wren Kennedy &children) == 0 && children > 0) { 391652244c09SJohn Wren Kennedy /* LINTED E_SEC_PRINTF_VAR_FMT */ 391752244c09SJohn Wren Kennedy (void) printf(dashes, cb->cb_namewidth, "spare"); 39184263d13fSGeorge Wilson for (c = 0; c < children; c++) { 3919663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 3920663207adSDon Brady cb->cb_name_flags); 39214263d13fSGeorge Wilson print_list_stats(zhp, vname, child[c], cb, depth + 2); 39224263d13fSGeorge Wilson free(vname); 39234263d13fSGeorge Wilson } 39244263d13fSGeorge Wilson } 39254263d13fSGeorge Wilson } 39264263d13fSGeorge Wilson 3927990b4856Slling /* 3928990b4856Slling * Generic callback function to list a pool. 3929990b4856Slling */ 3930990b4856Slling int 3931990b4856Slling list_callback(zpool_handle_t *zhp, void *data) 3932990b4856Slling { 3933990b4856Slling list_cbdata_t *cbp = data; 39344263d13fSGeorge Wilson nvlist_t *config; 39354263d13fSGeorge Wilson nvlist_t *nvroot; 3936fa9e4066Sahrens 39374263d13fSGeorge Wilson config = zpool_get_config(zhp, NULL); 3938fa9e4066Sahrens 3939663207adSDon Brady if (cbp->cb_verbose) { 3940663207adSDon Brady config = zpool_get_config(zhp, NULL); 3941663207adSDon Brady 3942663207adSDon Brady verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 3943663207adSDon Brady &nvroot) == 0); 3944663207adSDon Brady } 3945663207adSDon Brady 3946663207adSDon Brady if (cbp->cb_verbose) 3947663207adSDon Brady cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0, 3948663207adSDon Brady cbp->cb_name_flags); 3949663207adSDon Brady 39504263d13fSGeorge Wilson print_pool(zhp, cbp); 39514263d13fSGeorge Wilson 3952663207adSDon Brady if (cbp->cb_verbose) 3953663207adSDon Brady print_list_stats(zhp, NULL, nvroot, cbp, 0); 3954fa9e4066Sahrens 3955fa9e4066Sahrens return (0); 3956fa9e4066Sahrens } 3957fa9e4066Sahrens 3958fa9e4066Sahrens /* 3959663207adSDon Brady * zpool list [-gHLP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]] 3960fa9e4066Sahrens * 3961663207adSDon Brady * -g Display guid for individual vdev name. 3962990b4856Slling * -H Scripted mode. Don't display headers, and separate properties 3963990b4856Slling * by a single tab. 3964663207adSDon Brady * -L Follow links when resolving vdev path name. 3965990b4856Slling * -o List of properties to display. Defaults to 39667a09f97bSGeorge Wilson * "name,size,allocated,free,expandsize,fragmentation,capacity," 39677a09f97bSGeorge Wilson * "dedupratio,health,altroot" 396804e56356SAndriy Gapon * -p Diplay values in parsable (exact) format. 3969663207adSDon Brady * -P Display full path for vdev name. 39703f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format 3971fa9e4066Sahrens * 3972fa9e4066Sahrens * List all pools in the system, whether or not they're healthy. Output space 3973fa9e4066Sahrens * statistics for each one, as well as health status summary. 3974fa9e4066Sahrens */ 3975fa9e4066Sahrens int 3976fa9e4066Sahrens zpool_do_list(int argc, char **argv) 3977fa9e4066Sahrens { 3978fa9e4066Sahrens int c; 3979fa9e4066Sahrens int ret; 3980fa9e4066Sahrens list_cbdata_t cb = { 0 }; 3981990b4856Slling static char default_props[] = 398286714001SSerapheim Dimitropoulos "name,size,allocated,free,checkpoint,expandsize,fragmentation," 398386714001SSerapheim Dimitropoulos "capacity,dedupratio,health,altroot"; 3984990b4856Slling char *props = default_props; 39853f9d6ad7SLin Ling unsigned long interval = 0, count = 0; 39864263d13fSGeorge Wilson zpool_list_t *list; 39874263d13fSGeorge Wilson boolean_t first = B_TRUE; 3988fa9e4066Sahrens 3989fa9e4066Sahrens /* check options */ 3990663207adSDon Brady while ((c = getopt(argc, argv, ":gHLo:pPT:v")) != -1) { 3991fa9e4066Sahrens switch (c) { 3992663207adSDon Brady case 'g': 3993663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_GUID; 3994663207adSDon Brady break; 3995fa9e4066Sahrens case 'H': 399699653d4eSeschrock cb.cb_scripted = B_TRUE; 3997fa9e4066Sahrens break; 3998663207adSDon Brady case 'L': 3999663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS; 4000663207adSDon Brady break; 4001fa9e4066Sahrens case 'o': 4002990b4856Slling props = optarg; 4003fa9e4066Sahrens break; 4004663207adSDon Brady case 'P': 4005663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_PATH; 4006663207adSDon Brady break; 4007c58b3526SAdam Stevko case 'p': 4008c58b3526SAdam Stevko cb.cb_literal = B_TRUE; 4009c58b3526SAdam Stevko break; 40103f9d6ad7SLin Ling case 'T': 40113f9d6ad7SLin Ling get_timestamp_arg(*optarg); 40123f9d6ad7SLin Ling break; 40134263d13fSGeorge Wilson case 'v': 40144263d13fSGeorge Wilson cb.cb_verbose = B_TRUE; 4015663207adSDon Brady cb.cb_namewidth = 8; /* 8 until precalc is avail */ 40164263d13fSGeorge Wilson break; 4017fa9e4066Sahrens case ':': 4018fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 4019fa9e4066Sahrens "'%c' option\n"), optopt); 402099653d4eSeschrock usage(B_FALSE); 4021fa9e4066Sahrens break; 4022fa9e4066Sahrens case '?': 4023fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4024fa9e4066Sahrens optopt); 402599653d4eSeschrock usage(B_FALSE); 4026fa9e4066Sahrens } 4027fa9e4066Sahrens } 4028fa9e4066Sahrens 4029fa9e4066Sahrens argc -= optind; 4030fa9e4066Sahrens argv += optind; 4031fa9e4066Sahrens 40323f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count); 40333f9d6ad7SLin Ling 4034990b4856Slling if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) 4035990b4856Slling usage(B_FALSE); 4036fa9e4066Sahrens 40373f9d6ad7SLin Ling for (;;) { 4038cd67d23dSGeorge Wilson if ((list = pool_list_get(argc, argv, &cb.cb_proplist, 4039cd67d23dSGeorge Wilson &ret)) == NULL) 4040cd67d23dSGeorge Wilson return (1); 40414263d13fSGeorge Wilson 40424263d13fSGeorge Wilson if (pool_list_count(list) == 0) 40434263d13fSGeorge Wilson break; 40444263d13fSGeorge Wilson 40454263d13fSGeorge Wilson cb.cb_namewidth = 0; 40464263d13fSGeorge Wilson (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 4047990b4856Slling 40483f9d6ad7SLin Ling if (timestamp_fmt != NODATE) 40493f9d6ad7SLin Ling print_timestamp(timestamp_fmt); 4050fa9e4066Sahrens 40514263d13fSGeorge Wilson if (!cb.cb_scripted && (first || cb.cb_verbose)) { 40524263d13fSGeorge Wilson print_header(&cb); 40534263d13fSGeorge Wilson first = B_FALSE; 40543f9d6ad7SLin Ling } 40554263d13fSGeorge Wilson ret = pool_list_iter(list, B_TRUE, list_callback, &cb); 40563f9d6ad7SLin Ling 40573f9d6ad7SLin Ling if (interval == 0) 40583f9d6ad7SLin Ling break; 40593f9d6ad7SLin Ling 40603f9d6ad7SLin Ling if (count != 0 && --count == 0) 40613f9d6ad7SLin Ling break; 40623f9d6ad7SLin Ling 4063cd67d23dSGeorge Wilson pool_list_free(list); 40643f9d6ad7SLin Ling (void) sleep(interval); 4065fa9e4066Sahrens } 4066fa9e4066Sahrens 4067cd67d23dSGeorge Wilson if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) { 4068cd67d23dSGeorge Wilson (void) printf(gettext("no pools available\n")); 4069cd67d23dSGeorge Wilson ret = 0; 4070cd67d23dSGeorge Wilson } 4071cd67d23dSGeorge Wilson 4072cd67d23dSGeorge Wilson pool_list_free(list); 40733f9d6ad7SLin Ling zprop_free_list(cb.cb_proplist); 4074fa9e4066Sahrens return (ret); 4075fa9e4066Sahrens } 4076fa9e4066Sahrens 4077fa9e4066Sahrens static int 4078fa9e4066Sahrens zpool_do_attach_or_replace(int argc, char **argv, int replacing) 4079fa9e4066Sahrens { 408099653d4eSeschrock boolean_t force = B_FALSE; 4081fa9e4066Sahrens int c; 4082fa9e4066Sahrens nvlist_t *nvroot; 4083fa9e4066Sahrens char *poolname, *old_disk, *new_disk; 4084fa9e4066Sahrens zpool_handle_t *zhp; 40857855d95bSToomas Soome zpool_boot_label_t boot_type; 40867855d95bSToomas Soome uint64_t boot_size; 40875711d393Sloli nvlist_t *props = NULL; 40885711d393Sloli char *propval; 408999653d4eSeschrock int ret; 4090fa9e4066Sahrens 4091fa9e4066Sahrens /* check options */ 40925711d393Sloli while ((c = getopt(argc, argv, "fo:")) != -1) { 4093fa9e4066Sahrens switch (c) { 4094fa9e4066Sahrens case 'f': 409599653d4eSeschrock force = B_TRUE; 4096fa9e4066Sahrens break; 40975711d393Sloli case 'o': 40985711d393Sloli if ((propval = strchr(optarg, '=')) == NULL) { 40995711d393Sloli (void) fprintf(stderr, gettext("missing " 41005711d393Sloli "'=' for -o option\n")); 41015711d393Sloli usage(B_FALSE); 41025711d393Sloli } 41035711d393Sloli *propval = '\0'; 41045711d393Sloli propval++; 41055711d393Sloli 41065711d393Sloli if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) || 41075711d393Sloli (add_prop_list(optarg, propval, &props, B_TRUE))) 41085711d393Sloli usage(B_FALSE); 41095711d393Sloli break; 4110fa9e4066Sahrens case '?': 4111fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4112fa9e4066Sahrens optopt); 411399653d4eSeschrock usage(B_FALSE); 4114fa9e4066Sahrens } 4115fa9e4066Sahrens } 4116fa9e4066Sahrens 4117fa9e4066Sahrens argc -= optind; 4118fa9e4066Sahrens argv += optind; 4119fa9e4066Sahrens 4120fa9e4066Sahrens /* get pool name and check number of arguments */ 4121fa9e4066Sahrens if (argc < 1) { 4122fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 412399653d4eSeschrock usage(B_FALSE); 4124fa9e4066Sahrens } 4125fa9e4066Sahrens 4126fa9e4066Sahrens poolname = argv[0]; 4127fa9e4066Sahrens 4128fa9e4066Sahrens if (argc < 2) { 4129fa9e4066Sahrens (void) fprintf(stderr, 4130fa9e4066Sahrens gettext("missing <device> specification\n")); 413199653d4eSeschrock usage(B_FALSE); 4132fa9e4066Sahrens } 4133fa9e4066Sahrens 4134fa9e4066Sahrens old_disk = argv[1]; 4135fa9e4066Sahrens 4136fa9e4066Sahrens if (argc < 3) { 4137fa9e4066Sahrens if (!replacing) { 4138fa9e4066Sahrens (void) fprintf(stderr, 4139fa9e4066Sahrens gettext("missing <new_device> specification\n")); 414099653d4eSeschrock usage(B_FALSE); 4141fa9e4066Sahrens } 4142fa9e4066Sahrens new_disk = old_disk; 4143fa9e4066Sahrens argc -= 1; 4144fa9e4066Sahrens argv += 1; 4145fa9e4066Sahrens } else { 4146fa9e4066Sahrens new_disk = argv[2]; 4147fa9e4066Sahrens argc -= 2; 4148fa9e4066Sahrens argv += 2; 4149fa9e4066Sahrens } 4150fa9e4066Sahrens 4151fa9e4066Sahrens if (argc > 1) { 4152fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 415399653d4eSeschrock usage(B_FALSE); 4154fa9e4066Sahrens } 4155fa9e4066Sahrens 415699653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 4157fa9e4066Sahrens return (1); 4158fa9e4066Sahrens 41598488aeb5Staylor if (zpool_get_config(zhp, NULL) == NULL) { 4160fa9e4066Sahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 4161fa9e4066Sahrens poolname); 4162fa9e4066Sahrens zpool_close(zhp); 4163fa9e4066Sahrens return (1); 4164fa9e4066Sahrens } 4165fa9e4066Sahrens 41667855d95bSToomas Soome if (zpool_is_bootable(zhp)) 41677855d95bSToomas Soome boot_type = ZPOOL_COPY_BOOT_LABEL; 41687855d95bSToomas Soome else 41697855d95bSToomas Soome boot_type = ZPOOL_NO_BOOT_LABEL; 41707855d95bSToomas Soome 41717855d95bSToomas Soome boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 41725711d393Sloli 41735711d393Sloli /* unless manually specified use "ashift" pool property (if set) */ 41745711d393Sloli if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) { 41755711d393Sloli int intval; 41765711d393Sloli zprop_source_t src; 41775711d393Sloli char strval[ZPOOL_MAXPROPLEN]; 41785711d393Sloli 41795711d393Sloli intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src); 41805711d393Sloli if (src != ZPROP_SRC_DEFAULT) { 41815711d393Sloli (void) sprintf(strval, "%" PRId32, intval); 41825711d393Sloli verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval, 41835711d393Sloli &props, B_TRUE) == 0); 41845711d393Sloli } 41855711d393Sloli } 41865711d393Sloli 41875711d393Sloli nvroot = make_root_vdev(zhp, props, force, B_FALSE, replacing, B_FALSE, 41887855d95bSToomas Soome boot_type, boot_size, argc, argv); 4189fa9e4066Sahrens if (nvroot == NULL) { 4190fa9e4066Sahrens zpool_close(zhp); 4191fa9e4066Sahrens return (1); 4192fa9e4066Sahrens } 4193fa9e4066Sahrens 419499653d4eSeschrock ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); 419599653d4eSeschrock 419699653d4eSeschrock nvlist_free(nvroot); 419799653d4eSeschrock zpool_close(zhp); 419899653d4eSeschrock 419999653d4eSeschrock return (ret); 4200fa9e4066Sahrens } 4201fa9e4066Sahrens 4202fa9e4066Sahrens /* 4203fa9e4066Sahrens * zpool replace [-f] <pool> <device> <new_device> 4204fa9e4066Sahrens * 4205fa9e4066Sahrens * -f Force attach, even if <new_device> appears to be in use. 4206fa9e4066Sahrens * 4207fa9e4066Sahrens * Replace <device> with <new_device>. 4208fa9e4066Sahrens */ 4209fa9e4066Sahrens /* ARGSUSED */ 4210fa9e4066Sahrens int 4211fa9e4066Sahrens zpool_do_replace(int argc, char **argv) 4212fa9e4066Sahrens { 4213fa9e4066Sahrens return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 4214fa9e4066Sahrens } 4215fa9e4066Sahrens 4216fa9e4066Sahrens /* 42175711d393Sloli * zpool attach [-f] [-o property=value] <pool> <device> <new_device> 4218fa9e4066Sahrens * 4219fa9e4066Sahrens * -f Force attach, even if <new_device> appears to be in use. 42205711d393Sloli * -o Set property=value. 4221fa9e4066Sahrens * 4222fa9e4066Sahrens * Attach <new_device> to the mirror containing <device>. If <device> is not 4223fa9e4066Sahrens * part of a mirror, then <device> will be transformed into a mirror of 4224fa9e4066Sahrens * <device> and <new_device>. In either case, <new_device> will begin life 4225fa9e4066Sahrens * with a DTL of [0, now], and will immediately begin to resilver itself. 4226fa9e4066Sahrens */ 4227fa9e4066Sahrens int 4228fa9e4066Sahrens zpool_do_attach(int argc, char **argv) 4229fa9e4066Sahrens { 4230fa9e4066Sahrens return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 4231fa9e4066Sahrens } 4232fa9e4066Sahrens 4233fa9e4066Sahrens /* 4234fa9e4066Sahrens * zpool detach [-f] <pool> <device> 4235fa9e4066Sahrens * 4236fa9e4066Sahrens * -f Force detach of <device>, even if DTLs argue against it 4237fa9e4066Sahrens * (not supported yet) 4238fa9e4066Sahrens * 4239fa9e4066Sahrens * Detach a device from a mirror. The operation will be refused if <device> 4240fa9e4066Sahrens * is the last device in the mirror, or if the DTLs indicate that this device 4241fa9e4066Sahrens * has the only valid copy of some data. 4242fa9e4066Sahrens */ 4243fa9e4066Sahrens /* ARGSUSED */ 4244fa9e4066Sahrens int 4245fa9e4066Sahrens zpool_do_detach(int argc, char **argv) 4246fa9e4066Sahrens { 4247fa9e4066Sahrens int c; 4248fa9e4066Sahrens char *poolname, *path; 4249fa9e4066Sahrens zpool_handle_t *zhp; 425099653d4eSeschrock int ret; 4251fa9e4066Sahrens 4252fa9e4066Sahrens /* check options */ 4253fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) { 4254fa9e4066Sahrens switch (c) { 4255fa9e4066Sahrens case 'f': 4256fa9e4066Sahrens case '?': 4257fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4258fa9e4066Sahrens optopt); 425999653d4eSeschrock usage(B_FALSE); 4260fa9e4066Sahrens } 4261fa9e4066Sahrens } 4262fa9e4066Sahrens 4263fa9e4066Sahrens argc -= optind; 4264fa9e4066Sahrens argv += optind; 4265fa9e4066Sahrens 4266fa9e4066Sahrens /* get pool name and check number of arguments */ 4267fa9e4066Sahrens if (argc < 1) { 4268fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 426999653d4eSeschrock usage(B_FALSE); 4270fa9e4066Sahrens } 4271fa9e4066Sahrens 4272fa9e4066Sahrens if (argc < 2) { 4273fa9e4066Sahrens (void) fprintf(stderr, 4274fa9e4066Sahrens gettext("missing <device> specification\n")); 427599653d4eSeschrock usage(B_FALSE); 4276fa9e4066Sahrens } 4277fa9e4066Sahrens 4278fa9e4066Sahrens poolname = argv[0]; 4279fa9e4066Sahrens path = argv[1]; 4280fa9e4066Sahrens 428199653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 4282fa9e4066Sahrens return (1); 4283fa9e4066Sahrens 428499653d4eSeschrock ret = zpool_vdev_detach(zhp, path); 428599653d4eSeschrock 428699653d4eSeschrock zpool_close(zhp); 428799653d4eSeschrock 428899653d4eSeschrock return (ret); 4289fa9e4066Sahrens } 4290fa9e4066Sahrens 42911195e687SMark J Musante /* 4292663207adSDon Brady * zpool split [-gLnP] [-o prop=val] ... 42931195e687SMark J Musante * [-o mntopt] ... 42941195e687SMark J Musante * [-R altroot] <pool> <newpool> [<device> ...] 42951195e687SMark J Musante * 4296663207adSDon Brady * -g Display guid for individual vdev name. 4297663207adSDon Brady * -L Follow links when resolving vdev path name. 42981195e687SMark J Musante * -n Do not split the pool, but display the resulting layout if 42991195e687SMark J Musante * it were to be split. 43001195e687SMark J Musante * -o Set property=value, or set mount options. 4301663207adSDon Brady * -P Display full path for vdev name. 43021195e687SMark J Musante * -R Mount the split-off pool under an alternate root. 4303eb633035STom Caputi * -l Load encryption keys while importing. 43041195e687SMark J Musante * 43051195e687SMark J Musante * Splits the named pool and gives it the new pool name. Devices to be split 43061195e687SMark J Musante * off may be listed, provided that no more than one device is specified 43071195e687SMark J Musante * per top-level vdev mirror. The newly split pool is left in an exported 43081195e687SMark J Musante * state unless -R is specified. 43091195e687SMark J Musante * 43101195e687SMark J Musante * Restrictions: the top-level of the pool pool must only be made up of 43111195e687SMark J Musante * mirrors; all devices in the pool must be healthy; no device may be 43121195e687SMark J Musante * undergoing a resilvering operation. 43131195e687SMark J Musante */ 43141195e687SMark J Musante int 43151195e687SMark J Musante zpool_do_split(int argc, char **argv) 43161195e687SMark J Musante { 43171195e687SMark J Musante char *srcpool, *newpool, *propval; 43181195e687SMark J Musante char *mntopts = NULL; 43191195e687SMark J Musante splitflags_t flags; 43201195e687SMark J Musante int c, ret = 0; 4321eb633035STom Caputi boolean_t loadkeys = B_FALSE; 43221195e687SMark J Musante zpool_handle_t *zhp; 43231195e687SMark J Musante nvlist_t *config, *props = NULL; 43241195e687SMark J Musante 43251195e687SMark J Musante flags.dryrun = B_FALSE; 43261195e687SMark J Musante flags.import = B_FALSE; 4327663207adSDon Brady flags.name_flags = 0; 43281195e687SMark J Musante 43291195e687SMark J Musante /* check options */ 4330eb633035STom Caputi while ((c = getopt(argc, argv, ":gLR:lno:P")) != -1) { 43311195e687SMark J Musante switch (c) { 4332663207adSDon Brady case 'g': 4333663207adSDon Brady flags.name_flags |= VDEV_NAME_GUID; 4334663207adSDon Brady break; 4335663207adSDon Brady case 'L': 4336663207adSDon Brady flags.name_flags |= VDEV_NAME_FOLLOW_LINKS; 4337663207adSDon Brady break; 43381195e687SMark J Musante case 'R': 43391195e687SMark J Musante flags.import = B_TRUE; 43401195e687SMark J Musante if (add_prop_list( 43411195e687SMark J Musante zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg, 43421195e687SMark J Musante &props, B_TRUE) != 0) { 4343aab83bb8SJosef 'Jeff' Sipek nvlist_free(props); 43441195e687SMark J Musante usage(B_FALSE); 43451195e687SMark J Musante } 43461195e687SMark J Musante break; 4347eb633035STom Caputi case 'l': 4348eb633035STom Caputi loadkeys = B_TRUE; 4349eb633035STom Caputi break; 43501195e687SMark J Musante case 'n': 43511195e687SMark J Musante flags.dryrun = B_TRUE; 43521195e687SMark J Musante break; 43531195e687SMark J Musante case 'o': 43541195e687SMark J Musante if ((propval = strchr(optarg, '=')) != NULL) { 43551195e687SMark J Musante *propval = '\0'; 43561195e687SMark J Musante propval++; 43571195e687SMark J Musante if (add_prop_list(optarg, propval, 43581195e687SMark J Musante &props, B_TRUE) != 0) { 4359aab83bb8SJosef 'Jeff' Sipek nvlist_free(props); 43601195e687SMark J Musante usage(B_FALSE); 43611195e687SMark J Musante } 43621195e687SMark J Musante } else { 43631195e687SMark J Musante mntopts = optarg; 43641195e687SMark J Musante } 43651195e687SMark J Musante break; 4366663207adSDon Brady case 'P': 4367663207adSDon Brady flags.name_flags |= VDEV_NAME_PATH; 4368663207adSDon Brady break; 43691195e687SMark J Musante case ':': 43701195e687SMark J Musante (void) fprintf(stderr, gettext("missing argument for " 43711195e687SMark J Musante "'%c' option\n"), optopt); 43721195e687SMark J Musante usage(B_FALSE); 43731195e687SMark J Musante break; 43741195e687SMark J Musante case '?': 43751195e687SMark J Musante (void) fprintf(stderr, gettext("invalid option '%c'\n"), 43761195e687SMark J Musante optopt); 43771195e687SMark J Musante usage(B_FALSE); 43781195e687SMark J Musante break; 43791195e687SMark J Musante } 43801195e687SMark J Musante } 43811195e687SMark J Musante 43821195e687SMark J Musante if (!flags.import && mntopts != NULL) { 43831195e687SMark J Musante (void) fprintf(stderr, gettext("setting mntopts is only " 43841195e687SMark J Musante "valid when importing the pool\n")); 43851195e687SMark J Musante usage(B_FALSE); 43861195e687SMark J Musante } 43871195e687SMark J Musante 4388eb633035STom Caputi if (!flags.import && loadkeys) { 4389eb633035STom Caputi (void) fprintf(stderr, gettext("loading keys is only " 4390eb633035STom Caputi "valid when importing the pool\n")); 4391eb633035STom Caputi usage(B_FALSE); 4392eb633035STom Caputi } 4393eb633035STom Caputi 43941195e687SMark J Musante argc -= optind; 43951195e687SMark J Musante argv += optind; 43961195e687SMark J Musante 43971195e687SMark J Musante if (argc < 1) { 43981195e687SMark J Musante (void) fprintf(stderr, gettext("Missing pool name\n")); 43991195e687SMark J Musante usage(B_FALSE); 44001195e687SMark J Musante } 44011195e687SMark J Musante if (argc < 2) { 44021195e687SMark J Musante (void) fprintf(stderr, gettext("Missing new pool name\n")); 44031195e687SMark J Musante usage(B_FALSE); 44041195e687SMark J Musante } 44051195e687SMark J Musante 44061195e687SMark J Musante srcpool = argv[0]; 44071195e687SMark J Musante newpool = argv[1]; 44081195e687SMark J Musante 44091195e687SMark J Musante argc -= 2; 44101195e687SMark J Musante argv += 2; 44111195e687SMark J Musante 44121195e687SMark J Musante if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) 44131195e687SMark J Musante return (1); 44141195e687SMark J Musante 44151195e687SMark J Musante config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv); 44161195e687SMark J Musante if (config == NULL) { 44171195e687SMark J Musante ret = 1; 44181195e687SMark J Musante } else { 44191195e687SMark J Musante if (flags.dryrun) { 44201195e687SMark J Musante (void) printf(gettext("would create '%s' with the " 44211195e687SMark J Musante "following layout:\n\n"), newpool); 4422663207adSDon Brady print_vdev_tree(NULL, newpool, config, 0, "", 4423663207adSDon Brady flags.name_flags); 44241195e687SMark J Musante } 44251195e687SMark J Musante nvlist_free(config); 44261195e687SMark J Musante } 44271195e687SMark J Musante 44281195e687SMark J Musante zpool_close(zhp); 44291195e687SMark J Musante 44301195e687SMark J Musante if (ret != 0 || flags.dryrun || !flags.import) 44311195e687SMark J Musante return (ret); 44321195e687SMark J Musante 44331195e687SMark J Musante /* 44341195e687SMark J Musante * The split was successful. Now we need to open the new 44351195e687SMark J Musante * pool and import it. 44361195e687SMark J Musante */ 44371195e687SMark J Musante if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) 44381195e687SMark J Musante return (1); 4439eb633035STom Caputi 4440eb633035STom Caputi if (loadkeys) { 4441eb633035STom Caputi ret = zfs_crypto_attempt_load_keys(g_zfs, newpool); 4442eb633035STom Caputi if (ret != 0) 4443eb633035STom Caputi ret = 1; 4444eb633035STom Caputi } 4445eb633035STom Caputi 44461195e687SMark J Musante if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 44471195e687SMark J Musante zpool_enable_datasets(zhp, mntopts, 0) != 0) { 44481195e687SMark J Musante ret = 1; 4449fe7cd8aaSCyril Plisko (void) fprintf(stderr, gettext("Split was successful, but " 44501195e687SMark J Musante "the datasets could not all be mounted\n")); 44511195e687SMark J Musante (void) fprintf(stderr, gettext("Try doing '%s' with a " 44521195e687SMark J Musante "different altroot\n"), "zpool import"); 44531195e687SMark J Musante } 44541195e687SMark J Musante zpool_close(zhp); 44551195e687SMark J Musante 44561195e687SMark J Musante return (ret); 44571195e687SMark J Musante } 44581195e687SMark J Musante 44591195e687SMark J Musante 44601195e687SMark J Musante 4461fa9e4066Sahrens /* 4462441d80aaSlling * zpool online <pool> <device> ... 4463fa9e4066Sahrens */ 4464fa9e4066Sahrens int 4465fa9e4066Sahrens zpool_do_online(int argc, char **argv) 4466fa9e4066Sahrens { 4467fa9e4066Sahrens int c, i; 4468fa9e4066Sahrens char *poolname; 4469fa9e4066Sahrens zpool_handle_t *zhp; 4470fa9e4066Sahrens int ret = 0; 44713d7072f8Seschrock vdev_state_t newstate; 4472573ca77eSGeorge Wilson int flags = 0; 4473fa9e4066Sahrens 4474fa9e4066Sahrens /* check options */ 4475573ca77eSGeorge Wilson while ((c = getopt(argc, argv, "et")) != -1) { 4476fa9e4066Sahrens switch (c) { 4477573ca77eSGeorge Wilson case 'e': 4478573ca77eSGeorge Wilson flags |= ZFS_ONLINE_EXPAND; 4479573ca77eSGeorge Wilson break; 4480fa9e4066Sahrens case 't': 4481fa9e4066Sahrens case '?': 4482fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4483fa9e4066Sahrens optopt); 448499653d4eSeschrock usage(B_FALSE); 4485fa9e4066Sahrens } 4486fa9e4066Sahrens } 4487fa9e4066Sahrens 4488fa9e4066Sahrens argc -= optind; 4489fa9e4066Sahrens argv += optind; 4490fa9e4066Sahrens 4491fa9e4066Sahrens /* get pool name and check number of arguments */ 4492fa9e4066Sahrens if (argc < 1) { 4493fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name\n")); 449499653d4eSeschrock usage(B_FALSE); 4495fa9e4066Sahrens } 4496fa9e4066Sahrens if (argc < 2) { 4497fa9e4066Sahrens (void) fprintf(stderr, gettext("missing device name\n")); 449899653d4eSeschrock usage(B_FALSE); 4499fa9e4066Sahrens } 4500fa9e4066Sahrens 4501fa9e4066Sahrens poolname = argv[0]; 4502fa9e4066Sahrens 450399653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 4504fa9e4066Sahrens return (1); 4505fa9e4066Sahrens 45063d7072f8Seschrock for (i = 1; i < argc; i++) { 4507573ca77eSGeorge Wilson if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) { 45083d7072f8Seschrock if (newstate != VDEV_STATE_HEALTHY) { 45093d7072f8Seschrock (void) printf(gettext("warning: device '%s' " 45103d7072f8Seschrock "onlined, but remains in faulted state\n"), 45113d7072f8Seschrock argv[i]); 45123d7072f8Seschrock if (newstate == VDEV_STATE_FAULTED) 45133d7072f8Seschrock (void) printf(gettext("use 'zpool " 45143d7072f8Seschrock "clear' to restore a faulted " 45153d7072f8Seschrock "device\n")); 45163d7072f8Seschrock else 45173d7072f8Seschrock (void) printf(gettext("use 'zpool " 45183d7072f8Seschrock "replace' to replace devices " 45193d7072f8Seschrock "that are no longer present\n")); 45203d7072f8Seschrock } 45213d7072f8Seschrock } else { 4522fa9e4066Sahrens ret = 1; 45233d7072f8Seschrock } 45243d7072f8Seschrock } 4525fa9e4066Sahrens 452699653d4eSeschrock zpool_close(zhp); 452799653d4eSeschrock 4528fa9e4066Sahrens return (ret); 4529fa9e4066Sahrens } 4530fa9e4066Sahrens 4531fa9e4066Sahrens /* 4532441d80aaSlling * zpool offline [-ft] <pool> <device> ... 4533fa9e4066Sahrens * 4534fa9e4066Sahrens * -f Force the device into the offline state, even if doing 4535fa9e4066Sahrens * so would appear to compromise pool availability. 4536fa9e4066Sahrens * (not supported yet) 4537fa9e4066Sahrens * 4538fa9e4066Sahrens * -t Only take the device off-line temporarily. The offline 4539fa9e4066Sahrens * state will not be persistent across reboots. 4540fa9e4066Sahrens */ 4541fa9e4066Sahrens /* ARGSUSED */ 4542fa9e4066Sahrens int 4543fa9e4066Sahrens zpool_do_offline(int argc, char **argv) 4544fa9e4066Sahrens { 4545fa9e4066Sahrens int c, i; 4546fa9e4066Sahrens char *poolname; 4547fa9e4066Sahrens zpool_handle_t *zhp; 454899653d4eSeschrock int ret = 0; 454999653d4eSeschrock boolean_t istmp = B_FALSE; 4550fa9e4066Sahrens 4551fa9e4066Sahrens /* check options */ 4552fa9e4066Sahrens while ((c = getopt(argc, argv, "ft")) != -1) { 4553fa9e4066Sahrens switch (c) { 4554fa9e4066Sahrens case 't': 455599653d4eSeschrock istmp = B_TRUE; 4556441d80aaSlling break; 4557441d80aaSlling case 'f': 4558fa9e4066Sahrens case '?': 4559fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4560fa9e4066Sahrens optopt); 456199653d4eSeschrock usage(B_FALSE); 4562fa9e4066Sahrens } 4563fa9e4066Sahrens } 4564fa9e4066Sahrens 4565fa9e4066Sahrens argc -= optind; 4566fa9e4066Sahrens argv += optind; 4567fa9e4066Sahrens 4568fa9e4066Sahrens /* get pool name and check number of arguments */ 4569fa9e4066Sahrens if (argc < 1) { 4570fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name\n")); 457199653d4eSeschrock usage(B_FALSE); 4572fa9e4066Sahrens } 4573fa9e4066Sahrens if (argc < 2) { 4574fa9e4066Sahrens (void) fprintf(stderr, gettext("missing device name\n")); 457599653d4eSeschrock usage(B_FALSE); 4576fa9e4066Sahrens } 4577fa9e4066Sahrens 4578fa9e4066Sahrens poolname = argv[0]; 4579fa9e4066Sahrens 458099653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 4581fa9e4066Sahrens return (1); 4582fa9e4066Sahrens 45833d7072f8Seschrock for (i = 1; i < argc; i++) { 45843d7072f8Seschrock if (zpool_vdev_offline(zhp, argv[i], istmp) != 0) 4585fa9e4066Sahrens ret = 1; 45863d7072f8Seschrock } 4587fa9e4066Sahrens 458899653d4eSeschrock zpool_close(zhp); 458999653d4eSeschrock 4590fa9e4066Sahrens return (ret); 4591fa9e4066Sahrens } 4592fa9e4066Sahrens 4593ea8dc4b6Seschrock /* 4594ea8dc4b6Seschrock * zpool clear <pool> [device] 4595ea8dc4b6Seschrock * 4596ea8dc4b6Seschrock * Clear all errors associated with a pool or a particular device. 4597ea8dc4b6Seschrock */ 4598ea8dc4b6Seschrock int 4599ea8dc4b6Seschrock zpool_do_clear(int argc, char **argv) 4600ea8dc4b6Seschrock { 4601468c413aSTim Haley int c; 4602ea8dc4b6Seschrock int ret = 0; 4603468c413aSTim Haley boolean_t dryrun = B_FALSE; 4604468c413aSTim Haley boolean_t do_rewind = B_FALSE; 4605468c413aSTim Haley boolean_t xtreme_rewind = B_FALSE; 4606468c413aSTim Haley uint32_t rewind_policy = ZPOOL_NO_REWIND; 4607468c413aSTim Haley nvlist_t *policy = NULL; 4608ea8dc4b6Seschrock zpool_handle_t *zhp; 4609ea8dc4b6Seschrock char *pool, *device; 4610ea8dc4b6Seschrock 4611468c413aSTim Haley /* check options */ 4612468c413aSTim Haley while ((c = getopt(argc, argv, "FnX")) != -1) { 4613468c413aSTim Haley switch (c) { 4614468c413aSTim Haley case 'F': 4615468c413aSTim Haley do_rewind = B_TRUE; 4616468c413aSTim Haley break; 4617468c413aSTim Haley case 'n': 4618468c413aSTim Haley dryrun = B_TRUE; 4619468c413aSTim Haley break; 4620468c413aSTim Haley case 'X': 4621468c413aSTim Haley xtreme_rewind = B_TRUE; 4622468c413aSTim Haley break; 4623468c413aSTim Haley case '?': 4624468c413aSTim Haley (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4625468c413aSTim Haley optopt); 4626468c413aSTim Haley usage(B_FALSE); 4627468c413aSTim Haley } 4628468c413aSTim Haley } 4629468c413aSTim Haley 4630468c413aSTim Haley argc -= optind; 4631468c413aSTim Haley argv += optind; 4632468c413aSTim Haley 4633468c413aSTim Haley if (argc < 1) { 4634ea8dc4b6Seschrock (void) fprintf(stderr, gettext("missing pool name\n")); 463599653d4eSeschrock usage(B_FALSE); 4636ea8dc4b6Seschrock } 4637ea8dc4b6Seschrock 4638468c413aSTim Haley if (argc > 2) { 4639ea8dc4b6Seschrock (void) fprintf(stderr, gettext("too many arguments\n")); 464099653d4eSeschrock usage(B_FALSE); 4641ea8dc4b6Seschrock } 4642ea8dc4b6Seschrock 4643468c413aSTim Haley if ((dryrun || xtreme_rewind) && !do_rewind) { 4644468c413aSTim Haley (void) fprintf(stderr, 4645468c413aSTim Haley gettext("-n or -X only meaningful with -F\n")); 4646468c413aSTim Haley usage(B_FALSE); 4647468c413aSTim Haley } 4648468c413aSTim Haley if (dryrun) 4649468c413aSTim Haley rewind_policy = ZPOOL_TRY_REWIND; 4650468c413aSTim Haley else if (do_rewind) 4651468c413aSTim Haley rewind_policy = ZPOOL_DO_REWIND; 4652468c413aSTim Haley if (xtreme_rewind) 4653468c413aSTim Haley rewind_policy |= ZPOOL_EXTREME_REWIND; 4654468c413aSTim Haley 4655468c413aSTim Haley /* In future, further rewind policy choices can be passed along here */ 4656468c413aSTim Haley if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 46575dafeea3SPavel Zakharov nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, 46585dafeea3SPavel Zakharov rewind_policy) != 0) { 4659468c413aSTim Haley return (1); 46605dafeea3SPavel Zakharov } 4661468c413aSTim Haley 4662468c413aSTim Haley pool = argv[0]; 4663468c413aSTim Haley device = argc == 2 ? argv[1] : NULL; 4664ea8dc4b6Seschrock 4665468c413aSTim Haley if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 4666468c413aSTim Haley nvlist_free(policy); 4667ea8dc4b6Seschrock return (1); 4668468c413aSTim Haley } 4669ea8dc4b6Seschrock 4670468c413aSTim Haley if (zpool_clear(zhp, device, policy) != 0) 4671ea8dc4b6Seschrock ret = 1; 4672ea8dc4b6Seschrock 4673ea8dc4b6Seschrock zpool_close(zhp); 4674ea8dc4b6Seschrock 4675468c413aSTim Haley nvlist_free(policy); 4676468c413aSTim Haley 4677ea8dc4b6Seschrock return (ret); 4678ea8dc4b6Seschrock } 4679ea8dc4b6Seschrock 4680e9103aaeSGarrett D'Amore /* 4681e9103aaeSGarrett D'Amore * zpool reguid <pool> 4682e9103aaeSGarrett D'Amore */ 4683e9103aaeSGarrett D'Amore int 4684e9103aaeSGarrett D'Amore zpool_do_reguid(int argc, char **argv) 4685e9103aaeSGarrett D'Amore { 4686e9103aaeSGarrett D'Amore int c; 4687e9103aaeSGarrett D'Amore char *poolname; 4688e9103aaeSGarrett D'Amore zpool_handle_t *zhp; 4689e9103aaeSGarrett D'Amore int ret = 0; 4690e9103aaeSGarrett D'Amore 4691e9103aaeSGarrett D'Amore /* check options */ 4692e9103aaeSGarrett D'Amore while ((c = getopt(argc, argv, "")) != -1) { 4693e9103aaeSGarrett D'Amore switch (c) { 4694e9103aaeSGarrett D'Amore case '?': 4695e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4696e9103aaeSGarrett D'Amore optopt); 4697e9103aaeSGarrett D'Amore usage(B_FALSE); 4698e9103aaeSGarrett D'Amore } 4699e9103aaeSGarrett D'Amore } 4700e9103aaeSGarrett D'Amore 4701e9103aaeSGarrett D'Amore argc -= optind; 4702e9103aaeSGarrett D'Amore argv += optind; 4703e9103aaeSGarrett D'Amore 4704e9103aaeSGarrett D'Amore /* get pool name and check number of arguments */ 4705e9103aaeSGarrett D'Amore if (argc < 1) { 4706e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("missing pool name\n")); 4707e9103aaeSGarrett D'Amore usage(B_FALSE); 4708e9103aaeSGarrett D'Amore } 4709e9103aaeSGarrett D'Amore 4710e9103aaeSGarrett D'Amore if (argc > 1) { 4711e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("too many arguments\n")); 4712e9103aaeSGarrett D'Amore usage(B_FALSE); 4713e9103aaeSGarrett D'Amore } 4714e9103aaeSGarrett D'Amore 4715e9103aaeSGarrett D'Amore poolname = argv[0]; 4716e9103aaeSGarrett D'Amore if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 4717e9103aaeSGarrett D'Amore return (1); 4718e9103aaeSGarrett D'Amore 4719e9103aaeSGarrett D'Amore ret = zpool_reguid(zhp); 4720e9103aaeSGarrett D'Amore 4721e9103aaeSGarrett D'Amore zpool_close(zhp); 4722e9103aaeSGarrett D'Amore return (ret); 4723e9103aaeSGarrett D'Amore } 4724e9103aaeSGarrett D'Amore 4725e9103aaeSGarrett D'Amore 47264263d13fSGeorge Wilson /* 47274263d13fSGeorge Wilson * zpool reopen <pool> 47284263d13fSGeorge Wilson * 47294263d13fSGeorge Wilson * Reopen the pool so that the kernel can update the sizes of all vdevs. 47304263d13fSGeorge Wilson */ 47314263d13fSGeorge Wilson int 47324263d13fSGeorge Wilson zpool_do_reopen(int argc, char **argv) 47334263d13fSGeorge Wilson { 473431d7e8faSGeorge Wilson int c; 47354263d13fSGeorge Wilson int ret = 0; 47364263d13fSGeorge Wilson zpool_handle_t *zhp; 47374263d13fSGeorge Wilson char *pool; 47384263d13fSGeorge Wilson 473931d7e8faSGeorge Wilson /* check options */ 474031d7e8faSGeorge Wilson while ((c = getopt(argc, argv, "")) != -1) { 474131d7e8faSGeorge Wilson switch (c) { 474231d7e8faSGeorge Wilson case '?': 474331d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("invalid option '%c'\n"), 474431d7e8faSGeorge Wilson optopt); 474531d7e8faSGeorge Wilson usage(B_FALSE); 474631d7e8faSGeorge Wilson } 474731d7e8faSGeorge Wilson } 474831d7e8faSGeorge Wilson 47494263d13fSGeorge Wilson argc--; 47504263d13fSGeorge Wilson argv++; 47514263d13fSGeorge Wilson 475231d7e8faSGeorge Wilson if (argc < 1) { 475331d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("missing pool name\n")); 475431d7e8faSGeorge Wilson usage(B_FALSE); 475531d7e8faSGeorge Wilson } 475631d7e8faSGeorge Wilson 475731d7e8faSGeorge Wilson if (argc > 1) { 475831d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("too many arguments\n")); 475931d7e8faSGeorge Wilson usage(B_FALSE); 476031d7e8faSGeorge Wilson } 47614263d13fSGeorge Wilson 47624263d13fSGeorge Wilson pool = argv[0]; 47634263d13fSGeorge Wilson if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) 47644263d13fSGeorge Wilson return (1); 47654263d13fSGeorge Wilson 47664263d13fSGeorge Wilson ret = zpool_reopen(zhp); 47674263d13fSGeorge Wilson zpool_close(zhp); 47684263d13fSGeorge Wilson return (ret); 47694263d13fSGeorge Wilson } 47704263d13fSGeorge Wilson 4771fa9e4066Sahrens typedef struct scrub_cbdata { 4772fa9e4066Sahrens int cb_type; 477306eeb2adSek int cb_argc; 477406eeb2adSek char **cb_argv; 47751702cce7SAlek Pinchuk pool_scrub_cmd_t cb_scrub_cmd; 4776fa9e4066Sahrens } scrub_cbdata_t; 4777fa9e4066Sahrens 477886714001SSerapheim Dimitropoulos static boolean_t 477986714001SSerapheim Dimitropoulos zpool_has_checkpoint(zpool_handle_t *zhp) 478086714001SSerapheim Dimitropoulos { 478186714001SSerapheim Dimitropoulos nvlist_t *config, *nvroot; 478286714001SSerapheim Dimitropoulos 478386714001SSerapheim Dimitropoulos config = zpool_get_config(zhp, NULL); 478486714001SSerapheim Dimitropoulos 478586714001SSerapheim Dimitropoulos if (config != NULL) { 478686714001SSerapheim Dimitropoulos pool_checkpoint_stat_t *pcs = NULL; 478786714001SSerapheim Dimitropoulos uint_t c; 478886714001SSerapheim Dimitropoulos 478986714001SSerapheim Dimitropoulos nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 479086714001SSerapheim Dimitropoulos (void) nvlist_lookup_uint64_array(nvroot, 479186714001SSerapheim Dimitropoulos ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 479286714001SSerapheim Dimitropoulos 479386714001SSerapheim Dimitropoulos if (pcs == NULL || pcs->pcs_state == CS_NONE) 479486714001SSerapheim Dimitropoulos return (B_FALSE); 479586714001SSerapheim Dimitropoulos 479686714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS || 479786714001SSerapheim Dimitropoulos pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 479886714001SSerapheim Dimitropoulos return (B_TRUE); 479986714001SSerapheim Dimitropoulos } 480086714001SSerapheim Dimitropoulos 480186714001SSerapheim Dimitropoulos return (B_FALSE); 480286714001SSerapheim Dimitropoulos } 480386714001SSerapheim Dimitropoulos 4804fa9e4066Sahrens int 4805fa9e4066Sahrens scrub_callback(zpool_handle_t *zhp, void *data) 4806fa9e4066Sahrens { 4807fa9e4066Sahrens scrub_cbdata_t *cb = data; 480806eeb2adSek int err; 4809fa9e4066Sahrens 4810ea8dc4b6Seschrock /* 4811ea8dc4b6Seschrock * Ignore faulted pools. 4812ea8dc4b6Seschrock */ 4813ea8dc4b6Seschrock if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 4814e4c795beSTom Caputi (void) fprintf(stderr, gettext("cannot scan '%s': pool is " 4815ea8dc4b6Seschrock "currently unavailable\n"), zpool_get_name(zhp)); 4816ea8dc4b6Seschrock return (1); 4817ea8dc4b6Seschrock } 4818ea8dc4b6Seschrock 48191702cce7SAlek Pinchuk err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd); 482006eeb2adSek 482186714001SSerapheim Dimitropoulos if (err == 0 && zpool_has_checkpoint(zhp) && 482286714001SSerapheim Dimitropoulos cb->cb_type == POOL_SCAN_SCRUB) { 482386714001SSerapheim Dimitropoulos (void) printf(gettext("warning: will not scrub state that " 482486714001SSerapheim Dimitropoulos "belongs to the checkpoint of pool '%s'\n"), 482586714001SSerapheim Dimitropoulos zpool_get_name(zhp)); 482686714001SSerapheim Dimitropoulos } 482786714001SSerapheim Dimitropoulos 482806eeb2adSek return (err != 0); 4829fa9e4066Sahrens } 4830fa9e4066Sahrens 4831fa9e4066Sahrens /* 48321702cce7SAlek Pinchuk * zpool scrub [-s | -p] <pool> ... 4833fa9e4066Sahrens * 4834fa9e4066Sahrens * -s Stop. Stops any in-progress scrub. 48351702cce7SAlek Pinchuk * -p Pause. Pause in-progress scrub. 4836fa9e4066Sahrens */ 4837fa9e4066Sahrens int 4838fa9e4066Sahrens zpool_do_scrub(int argc, char **argv) 4839fa9e4066Sahrens { 4840fa9e4066Sahrens int c; 4841fa9e4066Sahrens scrub_cbdata_t cb; 4842fa9e4066Sahrens 48433f9d6ad7SLin Ling cb.cb_type = POOL_SCAN_SCRUB; 48441702cce7SAlek Pinchuk cb.cb_scrub_cmd = POOL_SCRUB_NORMAL; 4845fa9e4066Sahrens 4846fa9e4066Sahrens /* check options */ 48471702cce7SAlek Pinchuk while ((c = getopt(argc, argv, "sp")) != -1) { 4848fa9e4066Sahrens switch (c) { 4849fa9e4066Sahrens case 's': 48503f9d6ad7SLin Ling cb.cb_type = POOL_SCAN_NONE; 4851fa9e4066Sahrens break; 48521702cce7SAlek Pinchuk case 'p': 48531702cce7SAlek Pinchuk cb.cb_scrub_cmd = POOL_SCRUB_PAUSE; 48541702cce7SAlek Pinchuk break; 4855fa9e4066Sahrens case '?': 4856fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4857fa9e4066Sahrens optopt); 485899653d4eSeschrock usage(B_FALSE); 4859fa9e4066Sahrens } 4860fa9e4066Sahrens } 4861fa9e4066Sahrens 48621702cce7SAlek Pinchuk if (cb.cb_type == POOL_SCAN_NONE && 48631702cce7SAlek Pinchuk cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) { 48641702cce7SAlek Pinchuk (void) fprintf(stderr, gettext("invalid option combination: " 48651702cce7SAlek Pinchuk "-s and -p are mutually exclusive\n")); 48661702cce7SAlek Pinchuk usage(B_FALSE); 48671702cce7SAlek Pinchuk } 48681702cce7SAlek Pinchuk 486906eeb2adSek cb.cb_argc = argc; 487006eeb2adSek cb.cb_argv = argv; 4871fa9e4066Sahrens argc -= optind; 4872fa9e4066Sahrens argv += optind; 4873fa9e4066Sahrens 4874e4c795beSTom Caputi if (argc < 1) { 4875e4c795beSTom Caputi (void) fprintf(stderr, gettext("missing pool name argument\n")); 4876e4c795beSTom Caputi usage(B_FALSE); 4877e4c795beSTom Caputi } 4878e4c795beSTom Caputi 4879e4c795beSTom Caputi return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 4880e4c795beSTom Caputi } 4881e4c795beSTom Caputi 4882e4c795beSTom Caputi /* 4883e4c795beSTom Caputi * zpool resilver <pool> ... 4884e4c795beSTom Caputi * 4885e4c795beSTom Caputi * Restarts any in-progress resilver 4886e4c795beSTom Caputi */ 4887e4c795beSTom Caputi int 4888e4c795beSTom Caputi zpool_do_resilver(int argc, char **argv) 4889e4c795beSTom Caputi { 4890e4c795beSTom Caputi int c; 4891e4c795beSTom Caputi scrub_cbdata_t cb; 4892e4c795beSTom Caputi 4893e4c795beSTom Caputi cb.cb_type = POOL_SCAN_RESILVER; 4894e4c795beSTom Caputi cb.cb_scrub_cmd = POOL_SCRUB_NORMAL; 4895e4c795beSTom Caputi cb.cb_argc = argc; 4896e4c795beSTom Caputi cb.cb_argv = argv; 4897e4c795beSTom Caputi 4898e4c795beSTom Caputi /* check options */ 4899e4c795beSTom Caputi while ((c = getopt(argc, argv, "")) != -1) { 4900e4c795beSTom Caputi switch (c) { 4901e4c795beSTom Caputi case '?': 4902e4c795beSTom Caputi (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4903e4c795beSTom Caputi optopt); 4904e4c795beSTom Caputi usage(B_FALSE); 4905e4c795beSTom Caputi } 4906e4c795beSTom Caputi } 4907e4c795beSTom Caputi 4908e4c795beSTom Caputi argc -= optind; 4909e4c795beSTom Caputi argv += optind; 4910e4c795beSTom Caputi 4911fa9e4066Sahrens if (argc < 1) { 4912fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 491399653d4eSeschrock usage(B_FALSE); 4914fa9e4066Sahrens } 4915fa9e4066Sahrens 4916b1b8ab34Slling return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 4917fa9e4066Sahrens } 4918fa9e4066Sahrens 4919084fd14fSBrian Behlendorf /* 4920084fd14fSBrian Behlendorf * zpool trim [-d] [-r <rate>] [-c | -s] <pool> [<device> ...] 4921084fd14fSBrian Behlendorf * 4922084fd14fSBrian Behlendorf * -c Cancel. Ends any in-progress trim. 4923084fd14fSBrian Behlendorf * -d Secure trim. Requires kernel and device support. 4924084fd14fSBrian Behlendorf * -r <rate> Sets the TRIM rate in bytes (per second). Supports 4925084fd14fSBrian Behlendorf * adding a multiplier suffix such as 'k' or 'm'. 4926084fd14fSBrian Behlendorf * -s Suspend. TRIM can then be restarted with no flags. 4927084fd14fSBrian Behlendorf */ 4928084fd14fSBrian Behlendorf int 4929084fd14fSBrian Behlendorf zpool_do_trim(int argc, char **argv) 4930094e47e9SGeorge Wilson { 4931084fd14fSBrian Behlendorf struct option long_options[] = { 4932084fd14fSBrian Behlendorf {"cancel", no_argument, NULL, 'c'}, 4933084fd14fSBrian Behlendorf {"secure", no_argument, NULL, 'd'}, 4934084fd14fSBrian Behlendorf {"rate", required_argument, NULL, 'r'}, 4935084fd14fSBrian Behlendorf {"suspend", no_argument, NULL, 's'}, 4936084fd14fSBrian Behlendorf {0, 0, 0, 0} 4937084fd14fSBrian Behlendorf }; 4938094e47e9SGeorge Wilson 4939084fd14fSBrian Behlendorf pool_trim_func_t cmd_type = POOL_TRIM_START; 4940084fd14fSBrian Behlendorf uint64_t rate = 0; 4941084fd14fSBrian Behlendorf boolean_t secure = B_FALSE; 4942094e47e9SGeorge Wilson 4943084fd14fSBrian Behlendorf int c; 4944084fd14fSBrian Behlendorf while ((c = getopt_long(argc, argv, "cdr:s", long_options, NULL)) 4945084fd14fSBrian Behlendorf != -1) { 4946084fd14fSBrian Behlendorf switch (c) { 4947084fd14fSBrian Behlendorf case 'c': 4948084fd14fSBrian Behlendorf if (cmd_type != POOL_TRIM_START && 4949084fd14fSBrian Behlendorf cmd_type != POOL_TRIM_CANCEL) { 4950084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("-c cannot be " 4951084fd14fSBrian Behlendorf "combined with other options\n")); 4952084fd14fSBrian Behlendorf usage(B_FALSE); 4953084fd14fSBrian Behlendorf } 4954084fd14fSBrian Behlendorf cmd_type = POOL_TRIM_CANCEL; 4955084fd14fSBrian Behlendorf break; 4956084fd14fSBrian Behlendorf case 'd': 4957084fd14fSBrian Behlendorf if (cmd_type != POOL_TRIM_START) { 4958084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("-d cannot be " 4959084fd14fSBrian Behlendorf "combined with the -c or -s options\n")); 4960084fd14fSBrian Behlendorf usage(B_FALSE); 4961084fd14fSBrian Behlendorf } 4962084fd14fSBrian Behlendorf secure = B_TRUE; 4963084fd14fSBrian Behlendorf break; 4964084fd14fSBrian Behlendorf case 'r': 4965084fd14fSBrian Behlendorf if (cmd_type != POOL_TRIM_START) { 4966084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("-r cannot be " 4967084fd14fSBrian Behlendorf "combined with the -c or -s options\n")); 4968084fd14fSBrian Behlendorf usage(B_FALSE); 4969084fd14fSBrian Behlendorf } 4970084fd14fSBrian Behlendorf if (zfs_nicestrtonum(NULL, optarg, &rate) == -1) { 4971084fd14fSBrian Behlendorf (void) fprintf(stderr, 4972084fd14fSBrian Behlendorf gettext("invalid value for rate\n")); 4973084fd14fSBrian Behlendorf usage(B_FALSE); 4974084fd14fSBrian Behlendorf } 4975084fd14fSBrian Behlendorf break; 4976084fd14fSBrian Behlendorf case 's': 4977084fd14fSBrian Behlendorf if (cmd_type != POOL_TRIM_START && 4978084fd14fSBrian Behlendorf cmd_type != POOL_TRIM_SUSPEND) { 4979084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("-s cannot be " 4980084fd14fSBrian Behlendorf "combined with other options\n")); 4981084fd14fSBrian Behlendorf usage(B_FALSE); 4982084fd14fSBrian Behlendorf } 4983084fd14fSBrian Behlendorf cmd_type = POOL_TRIM_SUSPEND; 4984084fd14fSBrian Behlendorf break; 4985084fd14fSBrian Behlendorf case '?': 4986084fd14fSBrian Behlendorf if (optopt != 0) { 4987084fd14fSBrian Behlendorf (void) fprintf(stderr, 4988084fd14fSBrian Behlendorf gettext("invalid option '%c'\n"), optopt); 4989084fd14fSBrian Behlendorf } else { 4990084fd14fSBrian Behlendorf (void) fprintf(stderr, 4991084fd14fSBrian Behlendorf gettext("invalid option '%s'\n"), 4992084fd14fSBrian Behlendorf argv[optind - 1]); 4993084fd14fSBrian Behlendorf } 4994084fd14fSBrian Behlendorf usage(B_FALSE); 4995084fd14fSBrian Behlendorf } 4996094e47e9SGeorge Wilson } 4997094e47e9SGeorge Wilson 4998084fd14fSBrian Behlendorf argc -= optind; 4999084fd14fSBrian Behlendorf argv += optind; 5000084fd14fSBrian Behlendorf 5001084fd14fSBrian Behlendorf if (argc < 1) { 5002084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("missing pool name argument\n")); 5003084fd14fSBrian Behlendorf usage(B_FALSE); 5004084fd14fSBrian Behlendorf return (-1); 5005084fd14fSBrian Behlendorf } 5006084fd14fSBrian Behlendorf 5007084fd14fSBrian Behlendorf char *poolname = argv[0]; 5008084fd14fSBrian Behlendorf zpool_handle_t *zhp = zpool_open(g_zfs, poolname); 5009084fd14fSBrian Behlendorf if (zhp == NULL) 5010084fd14fSBrian Behlendorf return (-1); 5011084fd14fSBrian Behlendorf 5012084fd14fSBrian Behlendorf trimflags_t trim_flags = { 5013084fd14fSBrian Behlendorf .secure = secure, 5014084fd14fSBrian Behlendorf .rate = rate, 5015084fd14fSBrian Behlendorf }; 5016084fd14fSBrian Behlendorf 5017084fd14fSBrian Behlendorf nvlist_t *vdevs = fnvlist_alloc(); 5018084fd14fSBrian Behlendorf if (argc == 1) { 5019084fd14fSBrian Behlendorf /* no individual leaf vdevs specified, so add them all */ 5020084fd14fSBrian Behlendorf nvlist_t *config = zpool_get_config(zhp, NULL); 5021084fd14fSBrian Behlendorf nvlist_t *nvroot = fnvlist_lookup_nvlist(config, 5022084fd14fSBrian Behlendorf ZPOOL_CONFIG_VDEV_TREE); 5023084fd14fSBrian Behlendorf zpool_collect_leaves(zhp, nvroot, vdevs); 5024084fd14fSBrian Behlendorf trim_flags.fullpool = B_TRUE; 5025084fd14fSBrian Behlendorf } else { 5026084fd14fSBrian Behlendorf trim_flags.fullpool = B_FALSE; 5027084fd14fSBrian Behlendorf for (int i = 1; i < argc; i++) { 5028084fd14fSBrian Behlendorf fnvlist_add_boolean(vdevs, argv[i]); 5029084fd14fSBrian Behlendorf } 5030094e47e9SGeorge Wilson } 5031084fd14fSBrian Behlendorf 5032084fd14fSBrian Behlendorf int error = zpool_trim(zhp, cmd_type, vdevs, &trim_flags); 5033084fd14fSBrian Behlendorf 5034084fd14fSBrian Behlendorf fnvlist_free(vdevs); 5035084fd14fSBrian Behlendorf zpool_close(zhp); 5036084fd14fSBrian Behlendorf 5037084fd14fSBrian Behlendorf return (error); 5038094e47e9SGeorge Wilson } 5039094e47e9SGeorge Wilson 5040094e47e9SGeorge Wilson /* 5041084fd14fSBrian Behlendorf * zpool initialize [-c | -s] <pool> [<vdev> ...] 5042094e47e9SGeorge Wilson * Initialize all unused blocks in the specified vdevs, or all vdevs in the pool 5043094e47e9SGeorge Wilson * if none specified. 5044094e47e9SGeorge Wilson * 5045094e47e9SGeorge Wilson * -c Cancel. Ends active initializing. 5046094e47e9SGeorge Wilson * -s Suspend. Initializing can then be restarted with no flags. 5047094e47e9SGeorge Wilson */ 5048094e47e9SGeorge Wilson int 5049094e47e9SGeorge Wilson zpool_do_initialize(int argc, char **argv) 5050094e47e9SGeorge Wilson { 5051094e47e9SGeorge Wilson int c; 5052094e47e9SGeorge Wilson char *poolname; 5053094e47e9SGeorge Wilson zpool_handle_t *zhp; 5054094e47e9SGeorge Wilson nvlist_t *vdevs; 5055094e47e9SGeorge Wilson int err = 0; 5056094e47e9SGeorge Wilson 5057094e47e9SGeorge Wilson struct option long_options[] = { 5058094e47e9SGeorge Wilson {"cancel", no_argument, NULL, 'c'}, 5059094e47e9SGeorge Wilson {"suspend", no_argument, NULL, 's'}, 5060094e47e9SGeorge Wilson {0, 0, 0, 0} 5061094e47e9SGeorge Wilson }; 5062094e47e9SGeorge Wilson 5063084fd14fSBrian Behlendorf pool_initialize_func_t cmd_type = POOL_INITIALIZE_START; 5064094e47e9SGeorge Wilson while ((c = getopt_long(argc, argv, "cs", long_options, NULL)) != -1) { 5065094e47e9SGeorge Wilson switch (c) { 5066094e47e9SGeorge Wilson case 'c': 5067084fd14fSBrian Behlendorf if (cmd_type != POOL_INITIALIZE_START && 5068084fd14fSBrian Behlendorf cmd_type != POOL_INITIALIZE_CANCEL) { 5069094e47e9SGeorge Wilson (void) fprintf(stderr, gettext("-c cannot be " 5070094e47e9SGeorge Wilson "combined with other options\n")); 5071094e47e9SGeorge Wilson usage(B_FALSE); 5072094e47e9SGeorge Wilson } 5073094e47e9SGeorge Wilson cmd_type = POOL_INITIALIZE_CANCEL; 5074094e47e9SGeorge Wilson break; 5075094e47e9SGeorge Wilson case 's': 5076084fd14fSBrian Behlendorf if (cmd_type != POOL_INITIALIZE_START && 5077084fd14fSBrian Behlendorf cmd_type != POOL_INITIALIZE_SUSPEND) { 5078094e47e9SGeorge Wilson (void) fprintf(stderr, gettext("-s cannot be " 5079094e47e9SGeorge Wilson "combined with other options\n")); 5080094e47e9SGeorge Wilson usage(B_FALSE); 5081094e47e9SGeorge Wilson } 5082094e47e9SGeorge Wilson cmd_type = POOL_INITIALIZE_SUSPEND; 5083094e47e9SGeorge Wilson break; 5084094e47e9SGeorge Wilson case '?': 5085094e47e9SGeorge Wilson if (optopt != 0) { 5086094e47e9SGeorge Wilson (void) fprintf(stderr, 5087094e47e9SGeorge Wilson gettext("invalid option '%c'\n"), optopt); 5088094e47e9SGeorge Wilson } else { 5089094e47e9SGeorge Wilson (void) fprintf(stderr, 5090094e47e9SGeorge Wilson gettext("invalid option '%s'\n"), 5091094e47e9SGeorge Wilson argv[optind - 1]); 5092094e47e9SGeorge Wilson } 5093094e47e9SGeorge Wilson usage(B_FALSE); 5094094e47e9SGeorge Wilson } 5095094e47e9SGeorge Wilson } 5096094e47e9SGeorge Wilson 5097094e47e9SGeorge Wilson argc -= optind; 5098094e47e9SGeorge Wilson argv += optind; 5099094e47e9SGeorge Wilson 5100094e47e9SGeorge Wilson if (argc < 1) { 5101094e47e9SGeorge Wilson (void) fprintf(stderr, gettext("missing pool name argument\n")); 5102094e47e9SGeorge Wilson usage(B_FALSE); 5103094e47e9SGeorge Wilson return (-1); 5104094e47e9SGeorge Wilson } 5105094e47e9SGeorge Wilson 5106094e47e9SGeorge Wilson poolname = argv[0]; 5107094e47e9SGeorge Wilson zhp = zpool_open(g_zfs, poolname); 5108094e47e9SGeorge Wilson if (zhp == NULL) 5109094e47e9SGeorge Wilson return (-1); 5110094e47e9SGeorge Wilson 5111094e47e9SGeorge Wilson vdevs = fnvlist_alloc(); 5112094e47e9SGeorge Wilson if (argc == 1) { 5113094e47e9SGeorge Wilson /* no individual leaf vdevs specified, so add them all */ 5114094e47e9SGeorge Wilson nvlist_t *config = zpool_get_config(zhp, NULL); 5115094e47e9SGeorge Wilson nvlist_t *nvroot = fnvlist_lookup_nvlist(config, 5116094e47e9SGeorge Wilson ZPOOL_CONFIG_VDEV_TREE); 5117094e47e9SGeorge Wilson zpool_collect_leaves(zhp, nvroot, vdevs); 5118094e47e9SGeorge Wilson } else { 5119084fd14fSBrian Behlendorf for (int i = 1; i < argc; i++) { 5120094e47e9SGeorge Wilson fnvlist_add_boolean(vdevs, argv[i]); 5121094e47e9SGeorge Wilson } 5122094e47e9SGeorge Wilson } 5123094e47e9SGeorge Wilson 5124094e47e9SGeorge Wilson err = zpool_initialize(zhp, cmd_type, vdevs); 5125094e47e9SGeorge Wilson 5126094e47e9SGeorge Wilson fnvlist_free(vdevs); 5127094e47e9SGeorge Wilson zpool_close(zhp); 5128094e47e9SGeorge Wilson 5129094e47e9SGeorge Wilson return (err); 5130094e47e9SGeorge Wilson } 5131094e47e9SGeorge Wilson 5132fa9e4066Sahrens /* 5133fa9e4066Sahrens * Print out detailed scrub status. 5134fa9e4066Sahrens */ 51355cabbc6bSPrashanth Sreenivasa static void 51363f9d6ad7SLin Ling print_scan_status(pool_scan_stat_t *ps) 5137fa9e4066Sahrens { 51381702cce7SAlek Pinchuk time_t start, end, pause; 5139a3874b8bSToomas Soome uint64_t total_secs_left; 5140a3874b8bSToomas Soome uint64_t elapsed, secs_left, mins_left, hours_left, days_left; 5141a3874b8bSToomas Soome uint64_t pass_scanned, scanned, pass_issued, issued, total; 5142a3874b8bSToomas Soome uint_t scan_rate, issue_rate; 5143fa9e4066Sahrens double fraction_done; 5144a3874b8bSToomas Soome char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7]; 5145a3874b8bSToomas Soome char srate_buf[7], irate_buf[7]; 5146fa9e4066Sahrens 5147ce72e614SYuri Pankov (void) printf(gettext(" scan: ")); 5148fa9e4066Sahrens 51493f9d6ad7SLin Ling /* If there's never been a scan, there's not much to say. */ 51503f9d6ad7SLin Ling if (ps == NULL || ps->pss_func == POOL_SCAN_NONE || 51513f9d6ad7SLin Ling ps->pss_func >= POOL_SCAN_FUNCS) { 5152fa9e4066Sahrens (void) printf(gettext("none requested\n")); 5153fa9e4066Sahrens return; 5154fa9e4066Sahrens } 5155fa9e4066Sahrens 51563f9d6ad7SLin Ling start = ps->pss_start_time; 51573f9d6ad7SLin Ling end = ps->pss_end_time; 51581702cce7SAlek Pinchuk pause = ps->pss_pass_scrub_pause; 5159a3874b8bSToomas Soome 51603f9d6ad7SLin Ling zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf)); 5161fa9e4066Sahrens 51623f9d6ad7SLin Ling assert(ps->pss_func == POOL_SCAN_SCRUB || 51633f9d6ad7SLin Ling ps->pss_func == POOL_SCAN_RESILVER); 5164a3874b8bSToomas Soome 51653f9d6ad7SLin Ling /* 51663f9d6ad7SLin Ling * Scan is finished or canceled. 51673f9d6ad7SLin Ling */ 51683f9d6ad7SLin Ling if (ps->pss_state == DSS_FINISHED) { 5169a3874b8bSToomas Soome total_secs_left = end - start; 5170a3874b8bSToomas Soome days_left = total_secs_left / 60 / 60 / 24; 5171a3874b8bSToomas Soome hours_left = (total_secs_left / 60 / 60) % 24; 5172a3874b8bSToomas Soome mins_left = (total_secs_left / 60) % 60; 5173a3874b8bSToomas Soome secs_left = (total_secs_left % 60); 51743f9d6ad7SLin Ling 51753f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) { 5176a3874b8bSToomas Soome (void) printf(gettext("scrub repaired %s " 5177a3874b8bSToomas Soome "in %llu days %02llu:%02llu:%02llu " 5178a3874b8bSToomas Soome "with %llu errors on %s"), processed_buf, 5179a3874b8bSToomas Soome (u_longlong_t)days_left, (u_longlong_t)hours_left, 5180a3874b8bSToomas Soome (u_longlong_t)mins_left, (u_longlong_t)secs_left, 5181a3874b8bSToomas Soome (u_longlong_t)ps->pss_errors, ctime(&end)); 51823f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) { 5183a3874b8bSToomas Soome (void) printf(gettext("resilvered %s " 5184a3874b8bSToomas Soome "in %llu days %02llu:%02llu:%02llu " 5185a3874b8bSToomas Soome "with %llu errors on %s"), processed_buf, 5186a3874b8bSToomas Soome (u_longlong_t)days_left, (u_longlong_t)hours_left, 5187a3874b8bSToomas Soome (u_longlong_t)mins_left, (u_longlong_t)secs_left, 5188a3874b8bSToomas Soome (u_longlong_t)ps->pss_errors, ctime(&end)); 51893f9d6ad7SLin Ling } 51903f9d6ad7SLin Ling return; 51913f9d6ad7SLin Ling } else if (ps->pss_state == DSS_CANCELED) { 51923f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) { 51933f9d6ad7SLin Ling (void) printf(gettext("scrub canceled on %s"), 51943f9d6ad7SLin Ling ctime(&end)); 51953f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) { 51963f9d6ad7SLin Ling (void) printf(gettext("resilver canceled on %s"), 51973f9d6ad7SLin Ling ctime(&end)); 51983f9d6ad7SLin Ling } 5199fa9e4066Sahrens return; 5200fa9e4066Sahrens } 5201fa9e4066Sahrens 52023f9d6ad7SLin Ling assert(ps->pss_state == DSS_SCANNING); 52033f9d6ad7SLin Ling 5204a3874b8bSToomas Soome /* Scan is in progress. Resilvers can't be paused. */ 52053f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) { 52061702cce7SAlek Pinchuk if (pause == 0) { 52071702cce7SAlek Pinchuk (void) printf(gettext("scrub in progress since %s"), 52081702cce7SAlek Pinchuk ctime(&start)); 52091702cce7SAlek Pinchuk } else { 5210a3874b8bSToomas Soome (void) printf(gettext("scrub paused since %s"), 5211a3874b8bSToomas Soome ctime(&pause)); 5212a3874b8bSToomas Soome (void) printf(gettext("\tscrub started on %s"), 52131702cce7SAlek Pinchuk ctime(&start)); 52141702cce7SAlek Pinchuk } 52153f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) { 52163f9d6ad7SLin Ling (void) printf(gettext("resilver in progress since %s"), 52173f9d6ad7SLin Ling ctime(&start)); 52183f9d6ad7SLin Ling } 5219fa9e4066Sahrens 5220a3874b8bSToomas Soome scanned = ps->pss_examined; 5221a3874b8bSToomas Soome pass_scanned = ps->pss_pass_exam; 5222a3874b8bSToomas Soome issued = ps->pss_issued; 5223a3874b8bSToomas Soome pass_issued = ps->pss_pass_issued; 52243f9d6ad7SLin Ling total = ps->pss_to_examine; 52253f9d6ad7SLin Ling 5226a3874b8bSToomas Soome /* we are only done with a block once we have issued the IO for it */ 5227a3874b8bSToomas Soome fraction_done = (double)issued / total; 5228a3874b8bSToomas Soome 5229a3874b8bSToomas Soome /* elapsed time for this pass, rounding up to 1 if it's 0 */ 52303f9d6ad7SLin Ling elapsed = time(NULL) - ps->pss_pass_start; 52311702cce7SAlek Pinchuk elapsed -= ps->pss_pass_scrub_spent_paused; 5232a3874b8bSToomas Soome elapsed = (elapsed != 0) ? elapsed : 1; 5233a3874b8bSToomas Soome 5234a3874b8bSToomas Soome scan_rate = pass_scanned / elapsed; 5235a3874b8bSToomas Soome issue_rate = pass_issued / elapsed; 52363db6627cSTom Caputi total_secs_left = (issue_rate != 0 && total >= issued) ? 5237a3874b8bSToomas Soome ((total - issued) / issue_rate) : UINT64_MAX; 5238a3874b8bSToomas Soome 5239a3874b8bSToomas Soome days_left = total_secs_left / 60 / 60 / 24; 5240a3874b8bSToomas Soome hours_left = (total_secs_left / 60 / 60) % 24; 5241a3874b8bSToomas Soome mins_left = (total_secs_left / 60) % 60; 5242a3874b8bSToomas Soome secs_left = (total_secs_left % 60); 5243a3874b8bSToomas Soome 5244a3874b8bSToomas Soome /* format all of the numbers we will be reporting */ 5245a3874b8bSToomas Soome zfs_nicenum(scanned, scanned_buf, sizeof (scanned_buf)); 5246a3874b8bSToomas Soome zfs_nicenum(issued, issued_buf, sizeof (issued_buf)); 52473f9d6ad7SLin Ling zfs_nicenum(total, total_buf, sizeof (total_buf)); 5248a3874b8bSToomas Soome zfs_nicenum(scan_rate, srate_buf, sizeof (srate_buf)); 5249a3874b8bSToomas Soome zfs_nicenum(issue_rate, irate_buf, sizeof (irate_buf)); 52503f9d6ad7SLin Ling 5251a3874b8bSToomas Soome /* do not print estimated time if we have a paused scrub */ 52521702cce7SAlek Pinchuk if (pause == 0) { 5253a3874b8bSToomas Soome (void) printf(gettext("\t%s scanned at %s/s, " 5254a3874b8bSToomas Soome "%s issued at %s/s, %s total\n"), 5255a3874b8bSToomas Soome scanned_buf, srate_buf, issued_buf, irate_buf, total_buf); 525673d314ceSLin Ling } else { 5257a3874b8bSToomas Soome (void) printf(gettext("\t%s scanned, %s issued, %s total\n"), 5258a3874b8bSToomas Soome scanned_buf, issued_buf, total_buf); 525973d314ceSLin Ling } 52603f9d6ad7SLin Ling 52613f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_RESILVER) { 5262a3874b8bSToomas Soome (void) printf(gettext("\t%s resilvered, %.2f%% done"), 52633f9d6ad7SLin Ling processed_buf, 100 * fraction_done); 52643f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_SCRUB) { 5265a3874b8bSToomas Soome (void) printf(gettext("\t%s repaired, %.2f%% done"), 52663f9d6ad7SLin Ling processed_buf, 100 * fraction_done); 52673f9d6ad7SLin Ling } 5268a3874b8bSToomas Soome 5269a3874b8bSToomas Soome if (pause == 0) { 52703db6627cSTom Caputi if (total_secs_left != UINT64_MAX && 52713db6627cSTom Caputi issue_rate >= 10 * 1024 * 1024) { 5272a3874b8bSToomas Soome (void) printf(gettext(", %llu days " 5273a3874b8bSToomas Soome "%02llu:%02llu:%02llu to go\n"), 5274a3874b8bSToomas Soome (u_longlong_t)days_left, (u_longlong_t)hours_left, 5275a3874b8bSToomas Soome (u_longlong_t)mins_left, (u_longlong_t)secs_left); 5276a3874b8bSToomas Soome } else { 5277a3874b8bSToomas Soome (void) printf(gettext(", no estimated " 5278a3874b8bSToomas Soome "completion time\n")); 5279a3874b8bSToomas Soome } 5280a3874b8bSToomas Soome } else { 5281a3874b8bSToomas Soome (void) printf(gettext("\n")); 5282a3874b8bSToomas Soome } 5283fa9e4066Sahrens } 5284fa9e4066Sahrens 528586714001SSerapheim Dimitropoulos /* 528686714001SSerapheim Dimitropoulos * As we don't scrub checkpointed blocks, we want to warn the 528786714001SSerapheim Dimitropoulos * user that we skipped scanning some blocks if a checkpoint exists 528886714001SSerapheim Dimitropoulos * or existed at any time during the scan. 528986714001SSerapheim Dimitropoulos */ 529086714001SSerapheim Dimitropoulos static void 529186714001SSerapheim Dimitropoulos print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs) 529286714001SSerapheim Dimitropoulos { 529386714001SSerapheim Dimitropoulos if (ps == NULL || pcs == NULL) 529486714001SSerapheim Dimitropoulos return; 529586714001SSerapheim Dimitropoulos 529686714001SSerapheim Dimitropoulos if (pcs->pcs_state == CS_NONE || 529786714001SSerapheim Dimitropoulos pcs->pcs_state == CS_CHECKPOINT_DISCARDING) 529886714001SSerapheim Dimitropoulos return; 529986714001SSerapheim Dimitropoulos 530086714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS); 530186714001SSerapheim Dimitropoulos 530286714001SSerapheim Dimitropoulos if (ps->pss_state == DSS_NONE) 530386714001SSerapheim Dimitropoulos return; 530486714001SSerapheim Dimitropoulos 530586714001SSerapheim Dimitropoulos if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) && 530686714001SSerapheim Dimitropoulos ps->pss_end_time < pcs->pcs_start_time) 530786714001SSerapheim Dimitropoulos return; 530886714001SSerapheim Dimitropoulos 530986714001SSerapheim Dimitropoulos if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) { 531086714001SSerapheim Dimitropoulos (void) printf(gettext(" scan warning: skipped blocks " 531186714001SSerapheim Dimitropoulos "that are only referenced by the checkpoint.\n")); 531286714001SSerapheim Dimitropoulos } else { 531386714001SSerapheim Dimitropoulos assert(ps->pss_state == DSS_SCANNING); 531486714001SSerapheim Dimitropoulos (void) printf(gettext(" scan warning: skipping blocks " 531586714001SSerapheim Dimitropoulos "that are only referenced by the checkpoint.\n")); 531686714001SSerapheim Dimitropoulos } 531786714001SSerapheim Dimitropoulos } 531886714001SSerapheim Dimitropoulos 53195cabbc6bSPrashanth Sreenivasa /* 53205cabbc6bSPrashanth Sreenivasa * Print out detailed removal status. 53215cabbc6bSPrashanth Sreenivasa */ 53225cabbc6bSPrashanth Sreenivasa static void 53235cabbc6bSPrashanth Sreenivasa print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs) 53245cabbc6bSPrashanth Sreenivasa { 53255cabbc6bSPrashanth Sreenivasa char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7]; 53265cabbc6bSPrashanth Sreenivasa time_t start, end; 53275cabbc6bSPrashanth Sreenivasa nvlist_t *config, *nvroot; 53285cabbc6bSPrashanth Sreenivasa nvlist_t **child; 53295cabbc6bSPrashanth Sreenivasa uint_t children; 53305cabbc6bSPrashanth Sreenivasa char *vdev_name; 53315cabbc6bSPrashanth Sreenivasa 53325cabbc6bSPrashanth Sreenivasa if (prs == NULL || prs->prs_state == DSS_NONE) 53335cabbc6bSPrashanth Sreenivasa return; 53345cabbc6bSPrashanth Sreenivasa 53355cabbc6bSPrashanth Sreenivasa /* 53365cabbc6bSPrashanth Sreenivasa * Determine name of vdev. 53375cabbc6bSPrashanth Sreenivasa */ 53385cabbc6bSPrashanth Sreenivasa config = zpool_get_config(zhp, NULL); 53395cabbc6bSPrashanth Sreenivasa nvroot = fnvlist_lookup_nvlist(config, 53405cabbc6bSPrashanth Sreenivasa ZPOOL_CONFIG_VDEV_TREE); 53415cabbc6bSPrashanth Sreenivasa verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 53425cabbc6bSPrashanth Sreenivasa &child, &children) == 0); 53435cabbc6bSPrashanth Sreenivasa assert(prs->prs_removing_vdev < children); 53445cabbc6bSPrashanth Sreenivasa vdev_name = zpool_vdev_name(g_zfs, zhp, 53455cabbc6bSPrashanth Sreenivasa child[prs->prs_removing_vdev], B_TRUE); 53465cabbc6bSPrashanth Sreenivasa 53475cabbc6bSPrashanth Sreenivasa (void) printf(gettext("remove: ")); 53485cabbc6bSPrashanth Sreenivasa 53495cabbc6bSPrashanth Sreenivasa start = prs->prs_start_time; 53505cabbc6bSPrashanth Sreenivasa end = prs->prs_end_time; 53515cabbc6bSPrashanth Sreenivasa zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf)); 53525cabbc6bSPrashanth Sreenivasa 53535cabbc6bSPrashanth Sreenivasa /* 53545cabbc6bSPrashanth Sreenivasa * Removal is finished or canceled. 53555cabbc6bSPrashanth Sreenivasa */ 53565cabbc6bSPrashanth Sreenivasa if (prs->prs_state == DSS_FINISHED) { 53575cabbc6bSPrashanth Sreenivasa uint64_t minutes_taken = (end - start) / 60; 53585cabbc6bSPrashanth Sreenivasa 53595cabbc6bSPrashanth Sreenivasa (void) printf(gettext("Removal of vdev %llu copied %s " 53605cabbc6bSPrashanth Sreenivasa "in %lluh%um, completed on %s"), 53615cabbc6bSPrashanth Sreenivasa (longlong_t)prs->prs_removing_vdev, 53625cabbc6bSPrashanth Sreenivasa copied_buf, 53635cabbc6bSPrashanth Sreenivasa (u_longlong_t)(minutes_taken / 60), 53645cabbc6bSPrashanth Sreenivasa (uint_t)(minutes_taken % 60), 53655cabbc6bSPrashanth Sreenivasa ctime((time_t *)&end)); 53665cabbc6bSPrashanth Sreenivasa } else if (prs->prs_state == DSS_CANCELED) { 53675cabbc6bSPrashanth Sreenivasa (void) printf(gettext("Removal of %s canceled on %s"), 53685cabbc6bSPrashanth Sreenivasa vdev_name, ctime(&end)); 53695cabbc6bSPrashanth Sreenivasa } else { 53705cabbc6bSPrashanth Sreenivasa uint64_t copied, total, elapsed, mins_left, hours_left; 53715cabbc6bSPrashanth Sreenivasa double fraction_done; 53725cabbc6bSPrashanth Sreenivasa uint_t rate; 53735cabbc6bSPrashanth Sreenivasa 53745cabbc6bSPrashanth Sreenivasa assert(prs->prs_state == DSS_SCANNING); 53755cabbc6bSPrashanth Sreenivasa 53765cabbc6bSPrashanth Sreenivasa /* 53775cabbc6bSPrashanth Sreenivasa * Removal is in progress. 53785cabbc6bSPrashanth Sreenivasa */ 53795cabbc6bSPrashanth Sreenivasa (void) printf(gettext( 53805cabbc6bSPrashanth Sreenivasa "Evacuation of %s in progress since %s"), 53815cabbc6bSPrashanth Sreenivasa vdev_name, ctime(&start)); 53825cabbc6bSPrashanth Sreenivasa 53835cabbc6bSPrashanth Sreenivasa copied = prs->prs_copied > 0 ? prs->prs_copied : 1; 53845cabbc6bSPrashanth Sreenivasa total = prs->prs_to_copy; 53855cabbc6bSPrashanth Sreenivasa fraction_done = (double)copied / total; 53865cabbc6bSPrashanth Sreenivasa 53875cabbc6bSPrashanth Sreenivasa /* elapsed time for this pass */ 53885cabbc6bSPrashanth Sreenivasa elapsed = time(NULL) - prs->prs_start_time; 53895cabbc6bSPrashanth Sreenivasa elapsed = elapsed > 0 ? elapsed : 1; 53905cabbc6bSPrashanth Sreenivasa rate = copied / elapsed; 53915cabbc6bSPrashanth Sreenivasa rate = rate > 0 ? rate : 1; 53925cabbc6bSPrashanth Sreenivasa mins_left = ((total - copied) / rate) / 60; 53935cabbc6bSPrashanth Sreenivasa hours_left = mins_left / 60; 53945cabbc6bSPrashanth Sreenivasa 53955cabbc6bSPrashanth Sreenivasa zfs_nicenum(copied, examined_buf, sizeof (examined_buf)); 53965cabbc6bSPrashanth Sreenivasa zfs_nicenum(total, total_buf, sizeof (total_buf)); 53975cabbc6bSPrashanth Sreenivasa zfs_nicenum(rate, rate_buf, sizeof (rate_buf)); 53985cabbc6bSPrashanth Sreenivasa 53995cabbc6bSPrashanth Sreenivasa /* 54005cabbc6bSPrashanth Sreenivasa * do not print estimated time if hours_left is more than 54015cabbc6bSPrashanth Sreenivasa * 30 days 54025cabbc6bSPrashanth Sreenivasa */ 54035cabbc6bSPrashanth Sreenivasa (void) printf(gettext(" %s copied out of %s at %s/s, " 54045cabbc6bSPrashanth Sreenivasa "%.2f%% done"), 54055cabbc6bSPrashanth Sreenivasa examined_buf, total_buf, rate_buf, 100 * fraction_done); 54065cabbc6bSPrashanth Sreenivasa if (hours_left < (30 * 24)) { 54075cabbc6bSPrashanth Sreenivasa (void) printf(gettext(", %lluh%um to go\n"), 54085cabbc6bSPrashanth Sreenivasa (u_longlong_t)hours_left, (uint_t)(mins_left % 60)); 54095cabbc6bSPrashanth Sreenivasa } else { 54105cabbc6bSPrashanth Sreenivasa (void) printf(gettext( 54115cabbc6bSPrashanth Sreenivasa ", (copy is slow, no estimated time)\n")); 54125cabbc6bSPrashanth Sreenivasa } 54135cabbc6bSPrashanth Sreenivasa } 54145cabbc6bSPrashanth Sreenivasa 54155cabbc6bSPrashanth Sreenivasa if (prs->prs_mapping_memory > 0) { 54165cabbc6bSPrashanth Sreenivasa char mem_buf[7]; 54175cabbc6bSPrashanth Sreenivasa zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf)); 54185cabbc6bSPrashanth Sreenivasa (void) printf(gettext(" %s memory used for " 54195cabbc6bSPrashanth Sreenivasa "removed device mappings\n"), 54205cabbc6bSPrashanth Sreenivasa mem_buf); 54215cabbc6bSPrashanth Sreenivasa } 54225cabbc6bSPrashanth Sreenivasa } 54235cabbc6bSPrashanth Sreenivasa 542486714001SSerapheim Dimitropoulos static void 542586714001SSerapheim Dimitropoulos print_checkpoint_status(pool_checkpoint_stat_t *pcs) 542686714001SSerapheim Dimitropoulos { 542786714001SSerapheim Dimitropoulos time_t start; 542886714001SSerapheim Dimitropoulos char space_buf[7]; 542986714001SSerapheim Dimitropoulos 543086714001SSerapheim Dimitropoulos if (pcs == NULL || pcs->pcs_state == CS_NONE) 543186714001SSerapheim Dimitropoulos return; 543286714001SSerapheim Dimitropoulos 543386714001SSerapheim Dimitropoulos (void) printf(gettext("checkpoint: ")); 543486714001SSerapheim Dimitropoulos 543586714001SSerapheim Dimitropoulos start = pcs->pcs_start_time; 543686714001SSerapheim Dimitropoulos zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf)); 543786714001SSerapheim Dimitropoulos 543886714001SSerapheim Dimitropoulos if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) { 543986714001SSerapheim Dimitropoulos char *date = ctime(&start); 544086714001SSerapheim Dimitropoulos 544186714001SSerapheim Dimitropoulos /* 544286714001SSerapheim Dimitropoulos * ctime() adds a newline at the end of the generated 544386714001SSerapheim Dimitropoulos * string, thus the weird format specifier and the 544486714001SSerapheim Dimitropoulos * strlen() call used to chop it off from the output. 544586714001SSerapheim Dimitropoulos */ 544686714001SSerapheim Dimitropoulos (void) printf(gettext("created %.*s, consumes %s\n"), 544786714001SSerapheim Dimitropoulos strlen(date) - 1, date, space_buf); 544886714001SSerapheim Dimitropoulos return; 544986714001SSerapheim Dimitropoulos } 545086714001SSerapheim Dimitropoulos 545186714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 545286714001SSerapheim Dimitropoulos 545386714001SSerapheim Dimitropoulos (void) printf(gettext("discarding, %s remaining.\n"), 545486714001SSerapheim Dimitropoulos space_buf); 545586714001SSerapheim Dimitropoulos } 545686714001SSerapheim Dimitropoulos 5457ea8dc4b6Seschrock static void 5458ea8dc4b6Seschrock print_error_log(zpool_handle_t *zhp) 5459ea8dc4b6Seschrock { 546075519f38Sek nvlist_t *nverrlist = NULL; 546155434c77Sek nvpair_t *elem; 546255434c77Sek char *pathname; 546355434c77Sek size_t len = MAXPATHLEN * 2; 5464ea8dc4b6Seschrock 546555434c77Sek if (zpool_get_errlog(zhp, &nverrlist) != 0) { 5466ea8dc4b6Seschrock (void) printf("errors: List of errors unavailable " 5467ea8dc4b6Seschrock "(insufficient privileges)\n"); 5468ea8dc4b6Seschrock return; 5469ea8dc4b6Seschrock } 5470ea8dc4b6Seschrock 547155434c77Sek (void) printf("errors: Permanent errors have been " 547255434c77Sek "detected in the following files:\n\n"); 5473ea8dc4b6Seschrock 547455434c77Sek pathname = safe_malloc(len); 547555434c77Sek elem = NULL; 547655434c77Sek while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 547755434c77Sek nvlist_t *nv; 547855434c77Sek uint64_t dsobj, obj; 547955434c77Sek 548055434c77Sek verify(nvpair_value_nvlist(elem, &nv) == 0); 548155434c77Sek verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 548255434c77Sek &dsobj) == 0); 548355434c77Sek verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 548455434c77Sek &obj) == 0); 548555434c77Sek zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 548655434c77Sek (void) printf("%7s %s\n", "", pathname); 548755434c77Sek } 548855434c77Sek free(pathname); 548955434c77Sek nvlist_free(nverrlist); 5490ea8dc4b6Seschrock } 5491ea8dc4b6Seschrock 549299653d4eSeschrock static void 5493663207adSDon Brady print_spares(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **spares, 5494663207adSDon Brady uint_t nspares) 549599653d4eSeschrock { 549699653d4eSeschrock uint_t i; 549799653d4eSeschrock char *name; 549899653d4eSeschrock 549999653d4eSeschrock if (nspares == 0) 550099653d4eSeschrock return; 550199653d4eSeschrock 550299653d4eSeschrock (void) printf(gettext("\tspares\n")); 550399653d4eSeschrock 550499653d4eSeschrock for (i = 0; i < nspares; i++) { 5505663207adSDon Brady name = zpool_vdev_name(g_zfs, zhp, spares[i], 5506663207adSDon Brady cb->cb_name_flags); 5507663207adSDon Brady print_status_config(zhp, cb, name, spares[i], 2, B_TRUE); 550899653d4eSeschrock free(name); 550999653d4eSeschrock } 551099653d4eSeschrock } 551199653d4eSeschrock 5512fa94a07fSbrendan static void 5513663207adSDon Brady print_l2cache(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **l2cache, 5514663207adSDon Brady uint_t nl2cache) 5515fa94a07fSbrendan { 5516fa94a07fSbrendan uint_t i; 5517fa94a07fSbrendan char *name; 5518fa94a07fSbrendan 5519fa94a07fSbrendan if (nl2cache == 0) 5520fa94a07fSbrendan return; 5521fa94a07fSbrendan 5522fa94a07fSbrendan (void) printf(gettext("\tcache\n")); 5523fa94a07fSbrendan 5524fa94a07fSbrendan for (i = 0; i < nl2cache; i++) { 5525663207adSDon Brady name = zpool_vdev_name(g_zfs, zhp, l2cache[i], 5526663207adSDon Brady cb->cb_name_flags); 5527663207adSDon Brady print_status_config(zhp, cb, name, l2cache[i], 2, B_FALSE); 5528aa8cf21aSNeil Perrin free(name); 5529aa8cf21aSNeil Perrin } 5530aa8cf21aSNeil Perrin } 5531aa8cf21aSNeil Perrin 55329eb19f4dSGeorge Wilson static void 55339eb19f4dSGeorge Wilson print_dedup_stats(nvlist_t *config) 55349eb19f4dSGeorge Wilson { 55359eb19f4dSGeorge Wilson ddt_histogram_t *ddh; 55369eb19f4dSGeorge Wilson ddt_stat_t *dds; 55379eb19f4dSGeorge Wilson ddt_object_t *ddo; 55389eb19f4dSGeorge Wilson uint_t c; 55399eb19f4dSGeorge Wilson 55409eb19f4dSGeorge Wilson /* 55419eb19f4dSGeorge Wilson * If the pool was faulted then we may not have been able to 55422384d9f8SGeorge Wilson * obtain the config. Otherwise, if we have anything in the dedup 55439eb19f4dSGeorge Wilson * table continue processing the stats. 55449eb19f4dSGeorge Wilson */ 55459eb19f4dSGeorge Wilson if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS, 5546ce72e614SYuri Pankov (uint64_t **)&ddo, &c) != 0) 55479eb19f4dSGeorge Wilson return; 55489eb19f4dSGeorge Wilson 55499eb19f4dSGeorge Wilson (void) printf("\n"); 5550ce72e614SYuri Pankov (void) printf(gettext(" dedup: ")); 5551ce72e614SYuri Pankov if (ddo->ddo_count == 0) { 5552ce72e614SYuri Pankov (void) printf(gettext("no DDT entries\n")); 5553ce72e614SYuri Pankov return; 5554ce72e614SYuri Pankov } 5555ce72e614SYuri Pankov 55569eb19f4dSGeorge Wilson (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n", 55579eb19f4dSGeorge Wilson (u_longlong_t)ddo->ddo_count, 55589eb19f4dSGeorge Wilson (u_longlong_t)ddo->ddo_dspace, 55599eb19f4dSGeorge Wilson (u_longlong_t)ddo->ddo_mspace); 55609eb19f4dSGeorge Wilson 55619eb19f4dSGeorge Wilson verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS, 55629eb19f4dSGeorge Wilson (uint64_t **)&dds, &c) == 0); 55639eb19f4dSGeorge Wilson verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM, 55649eb19f4dSGeorge Wilson (uint64_t **)&ddh, &c) == 0); 55659eb19f4dSGeorge Wilson zpool_dump_ddt(dds, ddh); 55669eb19f4dSGeorge Wilson } 55679eb19f4dSGeorge Wilson 5568fa9e4066Sahrens /* 5569fa9e4066Sahrens * Display a summary of pool status. Displays a summary such as: 5570fa9e4066Sahrens * 5571fa9e4066Sahrens * pool: tank 5572fa9e4066Sahrens * status: DEGRADED 5573fa9e4066Sahrens * reason: One or more devices ... 5574654b400cSJoshua M. Clulow * see: http://illumos.org/msg/ZFS-xxxx-01 5575fa9e4066Sahrens * config: 5576fa9e4066Sahrens * mirror DEGRADED 5577fa9e4066Sahrens * c1t0d0 OK 5578ea8dc4b6Seschrock * c2t0d0 UNAVAIL 5579fa9e4066Sahrens * 5580fa9e4066Sahrens * When given the '-v' option, we print out the complete config. If the '-e' 5581fa9e4066Sahrens * option is specified, then we print out error rate information as well. 5582fa9e4066Sahrens */ 5583fa9e4066Sahrens int 5584fa9e4066Sahrens status_callback(zpool_handle_t *zhp, void *data) 5585fa9e4066Sahrens { 5586fa9e4066Sahrens status_cbdata_t *cbp = data; 5587fa9e4066Sahrens nvlist_t *config, *nvroot; 5588fa9e4066Sahrens char *msgid; 5589fa9e4066Sahrens int reason; 5590eb633035STom Caputi zpool_errata_t errata; 559146657f8dSmmusante const char *health; 559246657f8dSmmusante uint_t c; 559346657f8dSmmusante vdev_stat_t *vs; 5594fa9e4066Sahrens 5595088e9d47Seschrock config = zpool_get_config(zhp, NULL); 5596eb633035STom Caputi reason = zpool_get_status(zhp, &msgid, &errata); 5597fa9e4066Sahrens 5598fa9e4066Sahrens cbp->cb_count++; 5599fa9e4066Sahrens 5600fa9e4066Sahrens /* 5601fa9e4066Sahrens * If we were given 'zpool status -x', only report those pools with 5602fa9e4066Sahrens * problems. 5603fa9e4066Sahrens */ 5604b3a6f804STim Connors if (cbp->cb_explain && 5605b3a6f804STim Connors (reason == ZPOOL_STATUS_OK || 5606b3a6f804STim Connors reason == ZPOOL_STATUS_VERSION_OLDER || 5607b3a6f804STim Connors reason == ZPOOL_STATUS_FEAT_DISABLED)) { 5608e9dbad6fSeschrock if (!cbp->cb_allpools) { 5609e9dbad6fSeschrock (void) printf(gettext("pool '%s' is healthy\n"), 5610e9dbad6fSeschrock zpool_get_name(zhp)); 5611e9dbad6fSeschrock if (cbp->cb_first) 5612e9dbad6fSeschrock cbp->cb_first = B_FALSE; 5613e9dbad6fSeschrock } 5614fa9e4066Sahrens return (0); 5615e9dbad6fSeschrock } 5616fa9e4066Sahrens 5617fa9e4066Sahrens if (cbp->cb_first) 561899653d4eSeschrock cbp->cb_first = B_FALSE; 5619fa9e4066Sahrens else 5620fa9e4066Sahrens (void) printf("\n"); 5621fa9e4066Sahrens 56225cabbc6bSPrashanth Sreenivasa nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 56233f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 562446657f8dSmmusante (uint64_t **)&vs, &c) == 0); 5625990b4856Slling health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 5626fa9e4066Sahrens 5627fa9e4066Sahrens (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 5628fa9e4066Sahrens (void) printf(gettext(" state: %s\n"), health); 5629fa9e4066Sahrens 5630fa9e4066Sahrens switch (reason) { 5631fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_R: 5632fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 5633fa9e4066Sahrens "be opened. Sufficient replicas exist for\n\tthe pool to " 5634fa9e4066Sahrens "continue functioning in a degraded state.\n")); 5635fa9e4066Sahrens (void) printf(gettext("action: Attach the missing device and " 5636fa9e4066Sahrens "online it using 'zpool online'.\n")); 5637fa9e4066Sahrens break; 5638fa9e4066Sahrens 5639fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_NR: 5640fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 5641fa9e4066Sahrens "be opened. There are insufficient\n\treplicas for the " 5642fa9e4066Sahrens "pool to continue functioning.\n")); 5643fa9e4066Sahrens (void) printf(gettext("action: Attach the missing device and " 5644fa9e4066Sahrens "online it using 'zpool online'.\n")); 5645fa9e4066Sahrens break; 5646fa9e4066Sahrens 5647fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_R: 5648fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 5649fa9e4066Sahrens "be used because the label is missing or\n\tinvalid. " 5650fa9e4066Sahrens "Sufficient replicas exist for the pool to continue\n\t" 5651fa9e4066Sahrens "functioning in a degraded state.\n")); 5652fa9e4066Sahrens (void) printf(gettext("action: Replace the device using " 5653fa9e4066Sahrens "'zpool replace'.\n")); 5654fa9e4066Sahrens break; 5655fa9e4066Sahrens 5656fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_NR: 5657fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 5658b1b8ab34Slling "be used because the label is missing \n\tor invalid. " 5659fa9e4066Sahrens "There are insufficient replicas for the pool to " 5660fa9e4066Sahrens "continue\n\tfunctioning.\n")); 5661468c413aSTim Haley zpool_explain_recover(zpool_get_handle(zhp), 5662468c413aSTim Haley zpool_get_name(zhp), reason, config); 5663fa9e4066Sahrens break; 5664fa9e4066Sahrens 5665fa9e4066Sahrens case ZPOOL_STATUS_FAILING_DEV: 5666fa9e4066Sahrens (void) printf(gettext("status: One or more devices has " 5667fa9e4066Sahrens "experienced an unrecoverable error. An\n\tattempt was " 5668fa9e4066Sahrens "made to correct the error. Applications are " 5669fa9e4066Sahrens "unaffected.\n")); 5670fa9e4066Sahrens (void) printf(gettext("action: Determine if the device needs " 5671fa9e4066Sahrens "to be replaced, and clear the errors\n\tusing " 5672ea8dc4b6Seschrock "'zpool clear' or replace the device with 'zpool " 5673fa9e4066Sahrens "replace'.\n")); 5674fa9e4066Sahrens break; 5675fa9e4066Sahrens 5676fa9e4066Sahrens case ZPOOL_STATUS_OFFLINE_DEV: 5677fa9e4066Sahrens (void) printf(gettext("status: One or more devices has " 5678d7d4af51Smmusante "been taken offline by the administrator.\n\tSufficient " 5679fa9e4066Sahrens "replicas exist for the pool to continue functioning in " 5680fa9e4066Sahrens "a\n\tdegraded state.\n")); 5681fa9e4066Sahrens (void) printf(gettext("action: Online the device using " 5682fa9e4066Sahrens "'zpool online' or replace the device with\n\t'zpool " 5683fa9e4066Sahrens "replace'.\n")); 5684fa9e4066Sahrens break; 5685fa9e4066Sahrens 5686c25309d4SGeorge Wilson case ZPOOL_STATUS_REMOVED_DEV: 5687c25309d4SGeorge Wilson (void) printf(gettext("status: One or more devices has " 5688c25309d4SGeorge Wilson "been removed by the administrator.\n\tSufficient " 5689c25309d4SGeorge Wilson "replicas exist for the pool to continue functioning in " 5690c25309d4SGeorge Wilson "a\n\tdegraded state.\n")); 5691c25309d4SGeorge Wilson (void) printf(gettext("action: Online the device using " 5692c25309d4SGeorge Wilson "'zpool online' or replace the device with\n\t'zpool " 5693c25309d4SGeorge Wilson "replace'.\n")); 5694c25309d4SGeorge Wilson break; 5695c25309d4SGeorge Wilson 5696fa9e4066Sahrens case ZPOOL_STATUS_RESILVERING: 5697fa9e4066Sahrens (void) printf(gettext("status: One or more devices is " 5698fa9e4066Sahrens "currently being resilvered. The pool will\n\tcontinue " 5699fa9e4066Sahrens "to function, possibly in a degraded state.\n")); 5700fa9e4066Sahrens (void) printf(gettext("action: Wait for the resilver to " 5701fa9e4066Sahrens "complete.\n")); 5702fa9e4066Sahrens break; 5703fa9e4066Sahrens 5704ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_DATA: 5705ea8dc4b6Seschrock (void) printf(gettext("status: One or more devices has " 5706ea8dc4b6Seschrock "experienced an error resulting in data\n\tcorruption. " 5707ea8dc4b6Seschrock "Applications may be affected.\n")); 5708ea8dc4b6Seschrock (void) printf(gettext("action: Restore the file in question " 5709ea8dc4b6Seschrock "if possible. Otherwise restore the\n\tentire pool from " 5710ea8dc4b6Seschrock "backup.\n")); 5711ea8dc4b6Seschrock break; 5712ea8dc4b6Seschrock 5713ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_POOL: 5714ea8dc4b6Seschrock (void) printf(gettext("status: The pool metadata is corrupted " 5715ea8dc4b6Seschrock "and the pool cannot be opened.\n")); 5716468c413aSTim Haley zpool_explain_recover(zpool_get_handle(zhp), 5717468c413aSTim Haley zpool_get_name(zhp), reason, config); 5718ea8dc4b6Seschrock break; 5719ea8dc4b6Seschrock 5720eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_OLDER: 572157221772SChristopher Siden (void) printf(gettext("status: The pool is formatted using a " 572257221772SChristopher Siden "legacy on-disk format. The pool can\n\tstill be used, " 572357221772SChristopher Siden "but some features are unavailable.\n")); 5724eaca9bbdSeschrock (void) printf(gettext("action: Upgrade the pool using 'zpool " 5725eaca9bbdSeschrock "upgrade'. Once this is done, the\n\tpool will no longer " 572657221772SChristopher Siden "be accessible on software that does not support feature\n" 572757221772SChristopher Siden "\tflags.\n")); 5728eaca9bbdSeschrock break; 5729eaca9bbdSeschrock 5730eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 5731eaca9bbdSeschrock (void) printf(gettext("status: The pool has been upgraded to a " 5732eaca9bbdSeschrock "newer, incompatible on-disk version.\n\tThe pool cannot " 5733eaca9bbdSeschrock "be accessed on this system.\n")); 5734eaca9bbdSeschrock (void) printf(gettext("action: Access the pool from a system " 5735eaca9bbdSeschrock "running more recent software, or\n\trestore the pool from " 5736eaca9bbdSeschrock "backup.\n")); 5737eaca9bbdSeschrock break; 5738eaca9bbdSeschrock 573957221772SChristopher Siden case ZPOOL_STATUS_FEAT_DISABLED: 574057221772SChristopher Siden (void) printf(gettext("status: Some supported features are not " 574157221772SChristopher Siden "enabled on the pool. The pool can\n\tstill be used, but " 574257221772SChristopher Siden "some features are unavailable.\n")); 574357221772SChristopher Siden (void) printf(gettext("action: Enable all features using " 574457221772SChristopher Siden "'zpool upgrade'. Once this is done,\n\tthe pool may no " 574557221772SChristopher Siden "longer be accessible by software that does not support\n\t" 574657221772SChristopher Siden "the features. See zpool-features(5) for details.\n")); 574757221772SChristopher Siden break; 574857221772SChristopher Siden 5749ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ: 5750ad135b5dSChristopher Siden (void) printf(gettext("status: The pool cannot be accessed on " 5751ad135b5dSChristopher Siden "this system because it uses the\n\tfollowing feature(s) " 5752ad135b5dSChristopher Siden "not supported on this system:\n")); 5753ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 5754ad135b5dSChristopher Siden (void) printf("\n"); 5755ad135b5dSChristopher Siden (void) printf(gettext("action: Access the pool from a system " 5756ad135b5dSChristopher Siden "that supports the required feature(s),\n\tor restore the " 5757ad135b5dSChristopher Siden "pool from backup.\n")); 5758ad135b5dSChristopher Siden break; 5759ad135b5dSChristopher Siden 5760ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 5761ad135b5dSChristopher Siden (void) printf(gettext("status: The pool can only be accessed " 5762ad135b5dSChristopher Siden "in read-only mode on this system. It\n\tcannot be " 5763ad135b5dSChristopher Siden "accessed in read-write mode because it uses the " 5764ad135b5dSChristopher Siden "following\n\tfeature(s) not supported on this system:\n")); 5765ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 5766ad135b5dSChristopher Siden (void) printf("\n"); 5767ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be accessed in " 5768ad135b5dSChristopher Siden "read-write mode. Import the pool with\n" 5769ad135b5dSChristopher Siden "\t\"-o readonly=on\", access the pool from a system that " 5770ad135b5dSChristopher Siden "supports the\n\trequired feature(s), or restore the " 5771ad135b5dSChristopher Siden "pool from backup.\n")); 5772ad135b5dSChristopher Siden break; 5773ad135b5dSChristopher Siden 57743d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_R: 57753d7072f8Seschrock (void) printf(gettext("status: One or more devices are " 57763d7072f8Seschrock "faulted in response to persistent errors.\n\tSufficient " 57773d7072f8Seschrock "replicas exist for the pool to continue functioning " 57783d7072f8Seschrock "in a\n\tdegraded state.\n")); 57793d7072f8Seschrock (void) printf(gettext("action: Replace the faulted device, " 57803d7072f8Seschrock "or use 'zpool clear' to mark the device\n\trepaired.\n")); 57813d7072f8Seschrock break; 57823d7072f8Seschrock 57833d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_NR: 57843d7072f8Seschrock (void) printf(gettext("status: One or more devices are " 57853d7072f8Seschrock "faulted in response to persistent errors. There are " 57863d7072f8Seschrock "insufficient replicas for the pool to\n\tcontinue " 57873d7072f8Seschrock "functioning.\n")); 57883d7072f8Seschrock (void) printf(gettext("action: Destroy and re-create the pool " 57893d7072f8Seschrock "from a backup source. Manually marking the device\n" 57903d7072f8Seschrock "\trepaired using 'zpool clear' may allow some data " 57913d7072f8Seschrock "to be recovered.\n")); 57923d7072f8Seschrock break; 57933d7072f8Seschrock 5794e0f1c0afSOlaf Faaland case ZPOOL_STATUS_IO_FAILURE_MMP: 5795e0f1c0afSOlaf Faaland (void) printf(gettext("status: The pool is suspended because " 5796e0f1c0afSOlaf Faaland "multihost writes failed or were delayed;\n\tanother " 5797e0f1c0afSOlaf Faaland "system could import the pool undetected.\n")); 5798e0f1c0afSOlaf Faaland (void) printf(gettext("action: Make sure the pool's devices " 5799e0f1c0afSOlaf Faaland "are connected, then reboot your system and\n\timport the " 5800e0f1c0afSOlaf Faaland "pool.\n")); 5801e0f1c0afSOlaf Faaland break; 5802e0f1c0afSOlaf Faaland 580332b87932Sek case ZPOOL_STATUS_IO_FAILURE_WAIT: 580432b87932Sek case ZPOOL_STATUS_IO_FAILURE_CONTINUE: 580532b87932Sek (void) printf(gettext("status: One or more devices are " 58068a79c1b5Sek "faulted in response to IO failures.\n")); 580732b87932Sek (void) printf(gettext("action: Make sure the affected devices " 580832b87932Sek "are connected, then run 'zpool clear'.\n")); 580932b87932Sek break; 581032b87932Sek 5811b87f3af3Sperrin case ZPOOL_STATUS_BAD_LOG: 5812b87f3af3Sperrin (void) printf(gettext("status: An intent log record " 5813b87f3af3Sperrin "could not be read.\n" 5814b87f3af3Sperrin "\tWaiting for adminstrator intervention to fix the " 5815b87f3af3Sperrin "faulted pool.\n")); 5816b87f3af3Sperrin (void) printf(gettext("action: Either restore the affected " 5817b87f3af3Sperrin "device(s) and run 'zpool online',\n" 5818b87f3af3Sperrin "\tor ignore the intent log records by running " 5819b87f3af3Sperrin "'zpool clear'.\n")); 5820b87f3af3Sperrin break; 5821b87f3af3Sperrin 5822eb633035STom Caputi case ZPOOL_STATUS_ERRATA: 5823eb633035STom Caputi (void) printf(gettext("status: Errata #%d detected.\n"), 5824eb633035STom Caputi errata); 5825eb633035STom Caputi 5826eb633035STom Caputi switch (errata) { 5827eb633035STom Caputi case ZPOOL_ERRATA_NONE: 5828eb633035STom Caputi break; 5829eb633035STom Caputi 5830eb633035STom Caputi case ZPOOL_ERRATA_ZOL_2094_SCRUB: 5831eb633035STom Caputi (void) printf(gettext("action: To correct the issue " 5832eb633035STom Caputi "run 'zpool scrub'.\n")); 5833eb633035STom Caputi break; 5834eb633035STom Caputi 5835eb633035STom Caputi case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION: 5836eb633035STom Caputi (void) printf(gettext("\tExisting encrypted datasets " 5837eb633035STom Caputi "contain an on-disk incompatibility\n\twhich " 5838eb633035STom Caputi "needs to be corrected.\n")); 5839eb633035STom Caputi (void) printf(gettext("action: To correct the issue " 5840eb633035STom Caputi "backup existing encrypted datasets to new\n\t" 5841eb633035STom Caputi "encrypted datasets and destroy the old ones. " 5842eb633035STom Caputi "'zfs mount -o ro' can\n\tbe used to temporarily " 5843eb633035STom Caputi "mount existing encrypted datasets readonly.\n")); 5844eb633035STom Caputi break; 5845eb633035STom Caputi 5846eb633035STom Caputi case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION: 5847eb633035STom Caputi (void) printf(gettext("\tExisting encrypted datasets " 5848eb633035STom Caputi "contain an on-disk incompatibility\n\twhich " 5849eb633035STom Caputi "needs to be corrected.\n")); 5850eb633035STom Caputi (void) printf(gettext("action: To correct the issue " 5851eb633035STom Caputi "enable the bookmark_v2 feature and " 5852eb633035STom Caputi "backup\n\tany existing encrypted datasets to " 5853eb633035STom Caputi "new encrypted datasets and\n\tdestroy the old " 5854eb633035STom Caputi "ones. If this pool does not contain any\n\t" 5855eb633035STom Caputi "encrypted datasets, simply enable the " 5856eb633035STom Caputi "bookmark_v2 feature\n")); 5857eb633035STom Caputi break; 5858eb633035STom Caputi 5859eb633035STom Caputi default: 5860eb633035STom Caputi /* 5861eb633035STom Caputi * All errata which allow the pool to be imported 5862eb633035STom Caputi * must contain an action message. 5863eb633035STom Caputi */ 5864eb633035STom Caputi assert(0); 5865eb633035STom Caputi } 5866eb633035STom Caputi break; 5867eb633035STom Caputi 5868fa9e4066Sahrens default: 5869fa9e4066Sahrens /* 5870fa9e4066Sahrens * The remaining errors can't actually be generated, yet. 5871fa9e4066Sahrens */ 5872fa9e4066Sahrens assert(reason == ZPOOL_STATUS_OK); 5873fa9e4066Sahrens } 5874fa9e4066Sahrens 5875fa9e4066Sahrens if (msgid != NULL) 5876654b400cSJoshua M. Clulow (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 5877fa9e4066Sahrens msgid); 5878fa9e4066Sahrens 5879fa9e4066Sahrens if (config != NULL) { 5880ea8dc4b6Seschrock uint64_t nerr; 5881fa94a07fSbrendan nvlist_t **spares, **l2cache; 5882fa94a07fSbrendan uint_t nspares, nl2cache; 588386714001SSerapheim Dimitropoulos pool_checkpoint_stat_t *pcs = NULL; 58843f9d6ad7SLin Ling pool_scan_stat_t *ps = NULL; 58855cabbc6bSPrashanth Sreenivasa pool_removal_stat_t *prs = NULL; 5886fa9e4066Sahrens 588786714001SSerapheim Dimitropoulos (void) nvlist_lookup_uint64_array(nvroot, 588886714001SSerapheim Dimitropoulos ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 58893f9d6ad7SLin Ling (void) nvlist_lookup_uint64_array(nvroot, 58903f9d6ad7SLin Ling ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c); 58915cabbc6bSPrashanth Sreenivasa (void) nvlist_lookup_uint64_array(nvroot, 58925cabbc6bSPrashanth Sreenivasa ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c); 589386714001SSerapheim Dimitropoulos 589486714001SSerapheim Dimitropoulos print_scan_status(ps); 589586714001SSerapheim Dimitropoulos print_checkpoint_scan_warning(ps, pcs); 58965cabbc6bSPrashanth Sreenivasa print_removal_status(zhp, prs); 589786714001SSerapheim Dimitropoulos print_checkpoint_status(pcs); 58985cabbc6bSPrashanth Sreenivasa 5899663207adSDon Brady cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0, 5900663207adSDon Brady cbp->cb_name_flags); 5901663207adSDon Brady if (cbp->cb_namewidth < 10) 5902663207adSDon Brady cbp->cb_namewidth = 10; 5903fa9e4066Sahrens 5904fa9e4066Sahrens (void) printf(gettext("config:\n\n")); 5905663207adSDon Brady (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), 5906663207adSDon Brady cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE", 5907663207adSDon Brady "CKSUM"); 5908663207adSDon Brady 5909663207adSDon Brady print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0, 5910663207adSDon Brady B_FALSE); 5911663207adSDon Brady 5912663207adSDon Brady print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_DEDUP); 5913663207adSDon Brady print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_SPECIAL); 5914663207adSDon Brady print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_CLASS_LOGS); 591599653d4eSeschrock 5916fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 5917fa94a07fSbrendan &l2cache, &nl2cache) == 0) 5918663207adSDon Brady print_l2cache(zhp, cbp, l2cache, nl2cache); 5919fa94a07fSbrendan 592099653d4eSeschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 592199653d4eSeschrock &spares, &nspares) == 0) 5922663207adSDon Brady print_spares(zhp, cbp, spares, nspares); 5923ea8dc4b6Seschrock 5924ea8dc4b6Seschrock if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 5925ea8dc4b6Seschrock &nerr) == 0) { 592655434c77Sek nvlist_t *nverrlist = NULL; 592755434c77Sek 5928ea8dc4b6Seschrock /* 5929ea8dc4b6Seschrock * If the approximate error count is small, get a 5930ea8dc4b6Seschrock * precise count by fetching the entire log and 5931ea8dc4b6Seschrock * uniquifying the results. 5932ea8dc4b6Seschrock */ 593375519f38Sek if (nerr > 0 && nerr < 100 && !cbp->cb_verbose && 593455434c77Sek zpool_get_errlog(zhp, &nverrlist) == 0) { 593555434c77Sek nvpair_t *elem; 593655434c77Sek 593755434c77Sek elem = NULL; 593855434c77Sek nerr = 0; 593955434c77Sek while ((elem = nvlist_next_nvpair(nverrlist, 594055434c77Sek elem)) != NULL) { 594155434c77Sek nerr++; 594255434c77Sek } 594355434c77Sek } 594455434c77Sek nvlist_free(nverrlist); 5945ea8dc4b6Seschrock 5946ea8dc4b6Seschrock (void) printf("\n"); 594799653d4eSeschrock 5948ea8dc4b6Seschrock if (nerr == 0) 5949ea8dc4b6Seschrock (void) printf(gettext("errors: No known data " 5950ea8dc4b6Seschrock "errors\n")); 5951ea8dc4b6Seschrock else if (!cbp->cb_verbose) 5952e9dbad6fSeschrock (void) printf(gettext("errors: %llu data " 59535ad82045Snd "errors, use '-v' for a list\n"), 59545ad82045Snd (u_longlong_t)nerr); 5955ea8dc4b6Seschrock else 5956ea8dc4b6Seschrock print_error_log(zhp); 5957ea8dc4b6Seschrock } 59589eb19f4dSGeorge Wilson 59599eb19f4dSGeorge Wilson if (cbp->cb_dedup_stats) 59609eb19f4dSGeorge Wilson print_dedup_stats(config); 5961fa9e4066Sahrens } else { 5962fa9e4066Sahrens (void) printf(gettext("config: The configuration cannot be " 5963fa9e4066Sahrens "determined.\n")); 5964fa9e4066Sahrens } 5965fa9e4066Sahrens 5966fa9e4066Sahrens return (0); 5967fa9e4066Sahrens } 5968fa9e4066Sahrens 5969fa9e4066Sahrens /* 5970084fd14fSBrian Behlendorf * zpool status [-igLPtvx] [-T d|u] [pool] ... [interval [count]] 5971fa9e4066Sahrens * 5972084fd14fSBrian Behlendorf * -i Display vdev initialization status. 5973663207adSDon Brady * -g Display guid for individual vdev name. 5974663207adSDon Brady * -L Follow links when resolving vdev path name. 5975663207adSDon Brady * -P Display full path for vdev name. 5976fa9e4066Sahrens * -v Display complete error logs 5977fa9e4066Sahrens * -x Display only pools with potential problems 59789eb19f4dSGeorge Wilson * -D Display dedup status (undocumented) 5979084fd14fSBrian Behlendorf * -t Display vdev TRIM status. 59803f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format 5981fa9e4066Sahrens * 5982fa9e4066Sahrens * Describes the health status of all pools or some subset. 5983fa9e4066Sahrens */ 5984fa9e4066Sahrens int 5985fa9e4066Sahrens zpool_do_status(int argc, char **argv) 5986fa9e4066Sahrens { 5987fa9e4066Sahrens int c; 5988fa9e4066Sahrens int ret; 59893f9d6ad7SLin Ling unsigned long interval = 0, count = 0; 5990fa9e4066Sahrens status_cbdata_t cb = { 0 }; 5991fa9e4066Sahrens 5992fa9e4066Sahrens /* check options */ 5993084fd14fSBrian Behlendorf while ((c = getopt(argc, argv, "igLPvxDtT:")) != -1) { 5994fa9e4066Sahrens switch (c) { 5995084fd14fSBrian Behlendorf case 'i': 5996084fd14fSBrian Behlendorf cb.cb_print_vdev_init = B_TRUE; 5997084fd14fSBrian Behlendorf break; 5998663207adSDon Brady case 'g': 5999663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_GUID; 6000663207adSDon Brady break; 6001663207adSDon Brady case 'L': 6002663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS; 6003663207adSDon Brady break; 6004663207adSDon Brady case 'P': 6005663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_PATH; 6006663207adSDon Brady break; 6007fa9e4066Sahrens case 'v': 600899653d4eSeschrock cb.cb_verbose = B_TRUE; 6009fa9e4066Sahrens break; 6010fa9e4066Sahrens case 'x': 601199653d4eSeschrock cb.cb_explain = B_TRUE; 6012fa9e4066Sahrens break; 60139eb19f4dSGeorge Wilson case 'D': 60149eb19f4dSGeorge Wilson cb.cb_dedup_stats = B_TRUE; 60159eb19f4dSGeorge Wilson break; 6016084fd14fSBrian Behlendorf case 't': 6017084fd14fSBrian Behlendorf cb.cb_print_vdev_trim = B_TRUE; 6018084fd14fSBrian Behlendorf break; 60193f9d6ad7SLin Ling case 'T': 60203f9d6ad7SLin Ling get_timestamp_arg(*optarg); 60213f9d6ad7SLin Ling break; 6022fa9e4066Sahrens case '?': 6023fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6024fa9e4066Sahrens optopt); 602599653d4eSeschrock usage(B_FALSE); 6026fa9e4066Sahrens } 6027fa9e4066Sahrens } 6028fa9e4066Sahrens 6029fa9e4066Sahrens argc -= optind; 6030fa9e4066Sahrens argv += optind; 6031fa9e4066Sahrens 60323f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count); 6033fa9e4066Sahrens 6034e9dbad6fSeschrock if (argc == 0) 6035e9dbad6fSeschrock cb.cb_allpools = B_TRUE; 6036e9dbad6fSeschrock 60373f9d6ad7SLin Ling cb.cb_first = B_TRUE; 6038663207adSDon Brady cb.cb_print_status = B_TRUE; 6039fa9e4066Sahrens 60403f9d6ad7SLin Ling for (;;) { 60413f9d6ad7SLin Ling if (timestamp_fmt != NODATE) 60423f9d6ad7SLin Ling print_timestamp(timestamp_fmt); 6043fa9e4066Sahrens 60443f9d6ad7SLin Ling ret = for_each_pool(argc, argv, B_TRUE, NULL, 60453f9d6ad7SLin Ling status_callback, &cb); 60463f9d6ad7SLin Ling 60473f9d6ad7SLin Ling if (argc == 0 && cb.cb_count == 0) 60483f9d6ad7SLin Ling (void) printf(gettext("no pools available\n")); 60493f9d6ad7SLin Ling else if (cb.cb_explain && cb.cb_first && cb.cb_allpools) 60503f9d6ad7SLin Ling (void) printf(gettext("all pools are healthy\n")); 60513f9d6ad7SLin Ling 60523f9d6ad7SLin Ling if (ret != 0) 60533f9d6ad7SLin Ling return (ret); 60543f9d6ad7SLin Ling 60553f9d6ad7SLin Ling if (interval == 0) 60563f9d6ad7SLin Ling break; 60573f9d6ad7SLin Ling 60583f9d6ad7SLin Ling if (count != 0 && --count == 0) 60593f9d6ad7SLin Ling break; 60603f9d6ad7SLin Ling 60613f9d6ad7SLin Ling (void) sleep(interval); 60623f9d6ad7SLin Ling } 60633f9d6ad7SLin Ling 60643f9d6ad7SLin Ling return (0); 6065fa9e4066Sahrens } 6066fa9e4066Sahrens 6067eaca9bbdSeschrock typedef struct upgrade_cbdata { 6068eaca9bbdSeschrock int cb_first; 606906eeb2adSek int cb_argc; 6070990b4856Slling uint64_t cb_version; 607106eeb2adSek char **cb_argv; 6072eaca9bbdSeschrock } upgrade_cbdata_t; 6073eaca9bbdSeschrock 607457221772SChristopher Siden static int 607557221772SChristopher Siden upgrade_version(zpool_handle_t *zhp, uint64_t version) 607657221772SChristopher Siden { 607757221772SChristopher Siden int ret; 607857221772SChristopher Siden nvlist_t *config; 607957221772SChristopher Siden uint64_t oldversion; 608057221772SChristopher Siden 608157221772SChristopher Siden config = zpool_get_config(zhp, NULL); 608257221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 608357221772SChristopher Siden &oldversion) == 0); 608457221772SChristopher Siden 608557221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(oldversion)); 608657221772SChristopher Siden assert(oldversion < version); 608757221772SChristopher Siden 608857221772SChristopher Siden ret = zpool_upgrade(zhp, version); 608957221772SChristopher Siden if (ret != 0) 609057221772SChristopher Siden return (ret); 609157221772SChristopher Siden 609257221772SChristopher Siden if (version >= SPA_VERSION_FEATURES) { 609357221772SChristopher Siden (void) printf(gettext("Successfully upgraded " 609457221772SChristopher Siden "'%s' from version %llu to feature flags.\n"), 609557221772SChristopher Siden zpool_get_name(zhp), oldversion); 609657221772SChristopher Siden } else { 609757221772SChristopher Siden (void) printf(gettext("Successfully upgraded " 609857221772SChristopher Siden "'%s' from version %llu to version %llu.\n"), 609957221772SChristopher Siden zpool_get_name(zhp), oldversion, version); 610057221772SChristopher Siden } 610157221772SChristopher Siden 610257221772SChristopher Siden return (0); 610357221772SChristopher Siden } 610457221772SChristopher Siden 610557221772SChristopher Siden static int 610657221772SChristopher Siden upgrade_enable_all(zpool_handle_t *zhp, int *countp) 610757221772SChristopher Siden { 610857221772SChristopher Siden int i, ret, count; 610957221772SChristopher Siden boolean_t firstff = B_TRUE; 611057221772SChristopher Siden nvlist_t *enabled = zpool_get_features(zhp); 611157221772SChristopher Siden 611257221772SChristopher Siden count = 0; 611357221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 611457221772SChristopher Siden const char *fname = spa_feature_table[i].fi_uname; 611557221772SChristopher Siden const char *fguid = spa_feature_table[i].fi_guid; 611657221772SChristopher Siden if (!nvlist_exists(enabled, fguid)) { 611757221772SChristopher Siden char *propname; 611857221772SChristopher Siden verify(-1 != asprintf(&propname, "feature@%s", fname)); 611957221772SChristopher Siden ret = zpool_set_prop(zhp, propname, 612057221772SChristopher Siden ZFS_FEATURE_ENABLED); 612157221772SChristopher Siden if (ret != 0) { 612257221772SChristopher Siden free(propname); 612357221772SChristopher Siden return (ret); 612457221772SChristopher Siden } 612557221772SChristopher Siden count++; 612657221772SChristopher Siden 612757221772SChristopher Siden if (firstff) { 612857221772SChristopher Siden (void) printf(gettext("Enabled the " 612957221772SChristopher Siden "following features on '%s':\n"), 613057221772SChristopher Siden zpool_get_name(zhp)); 613157221772SChristopher Siden firstff = B_FALSE; 613257221772SChristopher Siden } 613357221772SChristopher Siden (void) printf(gettext(" %s\n"), fname); 613457221772SChristopher Siden free(propname); 613557221772SChristopher Siden } 613657221772SChristopher Siden } 613757221772SChristopher Siden 613857221772SChristopher Siden if (countp != NULL) 613957221772SChristopher Siden *countp = count; 614057221772SChristopher Siden return (0); 614157221772SChristopher Siden } 614257221772SChristopher Siden 6143eaca9bbdSeschrock static int 6144eaca9bbdSeschrock upgrade_cb(zpool_handle_t *zhp, void *arg) 6145eaca9bbdSeschrock { 6146eaca9bbdSeschrock upgrade_cbdata_t *cbp = arg; 6147eaca9bbdSeschrock nvlist_t *config; 6148eaca9bbdSeschrock uint64_t version; 614957221772SChristopher Siden boolean_t printnl = B_FALSE; 615057221772SChristopher Siden int ret; 6151eaca9bbdSeschrock 6152eaca9bbdSeschrock config = zpool_get_config(zhp, NULL); 6153eaca9bbdSeschrock verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 6154eaca9bbdSeschrock &version) == 0); 6155eaca9bbdSeschrock 615657221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(version)); 6157eaca9bbdSeschrock 615857221772SChristopher Siden if (version < cbp->cb_version) { 615957221772SChristopher Siden cbp->cb_first = B_FALSE; 616057221772SChristopher Siden ret = upgrade_version(zhp, cbp->cb_version); 616157221772SChristopher Siden if (ret != 0) 616257221772SChristopher Siden return (ret); 616357221772SChristopher Siden printnl = B_TRUE; 616457221772SChristopher Siden 616557221772SChristopher Siden /* 616657221772SChristopher Siden * If they did "zpool upgrade -a", then we could 616757221772SChristopher Siden * be doing ioctls to different pools. We need 616857221772SChristopher Siden * to log this history once to each pool, and bypass 616957221772SChristopher Siden * the normal history logging that happens in main(). 617057221772SChristopher Siden */ 617157221772SChristopher Siden (void) zpool_log_history(g_zfs, history_str); 617257221772SChristopher Siden log_history = B_FALSE; 617357221772SChristopher Siden } 617457221772SChristopher Siden 617557221772SChristopher Siden if (cbp->cb_version >= SPA_VERSION_FEATURES) { 617657221772SChristopher Siden int count; 617757221772SChristopher Siden ret = upgrade_enable_all(zhp, &count); 617857221772SChristopher Siden if (ret != 0) 617957221772SChristopher Siden return (ret); 618057221772SChristopher Siden 618157221772SChristopher Siden if (count > 0) { 618299653d4eSeschrock cbp->cb_first = B_FALSE; 618357221772SChristopher Siden printnl = B_TRUE; 6184eaca9bbdSeschrock } 618557221772SChristopher Siden } 6186eaca9bbdSeschrock 618757221772SChristopher Siden if (printnl) { 618857221772SChristopher Siden (void) printf(gettext("\n")); 618957221772SChristopher Siden } 619057221772SChristopher Siden 619157221772SChristopher Siden return (0); 619257221772SChristopher Siden } 619357221772SChristopher Siden 619457221772SChristopher Siden static int 619557221772SChristopher Siden upgrade_list_older_cb(zpool_handle_t *zhp, void *arg) 619657221772SChristopher Siden { 619757221772SChristopher Siden upgrade_cbdata_t *cbp = arg; 619857221772SChristopher Siden nvlist_t *config; 619957221772SChristopher Siden uint64_t version; 620057221772SChristopher Siden 620157221772SChristopher Siden config = zpool_get_config(zhp, NULL); 620257221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 620357221772SChristopher Siden &version) == 0); 620457221772SChristopher Siden 620557221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(version)); 620657221772SChristopher Siden 620757221772SChristopher Siden if (version < SPA_VERSION_FEATURES) { 6208eaca9bbdSeschrock if (cbp->cb_first) { 6209eaca9bbdSeschrock (void) printf(gettext("The following pools are " 621057221772SChristopher Siden "formatted with legacy version numbers and can\n" 621157221772SChristopher Siden "be upgraded to use feature flags. After " 621257221772SChristopher Siden "being upgraded, these pools\nwill no " 621357221772SChristopher Siden "longer be accessible by software that does not " 621457221772SChristopher Siden "support feature\nflags.\n\n")); 6215eaca9bbdSeschrock (void) printf(gettext("VER POOL\n")); 6216eaca9bbdSeschrock (void) printf(gettext("--- ------------\n")); 621799653d4eSeschrock cbp->cb_first = B_FALSE; 6218eaca9bbdSeschrock } 6219eaca9bbdSeschrock 62205ad82045Snd (void) printf("%2llu %s\n", (u_longlong_t)version, 6221eaca9bbdSeschrock zpool_get_name(zhp)); 6222eaca9bbdSeschrock } 6223eaca9bbdSeschrock 622457221772SChristopher Siden return (0); 622557221772SChristopher Siden } 622657221772SChristopher Siden 622757221772SChristopher Siden static int 622857221772SChristopher Siden upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg) 622957221772SChristopher Siden { 623057221772SChristopher Siden upgrade_cbdata_t *cbp = arg; 623157221772SChristopher Siden nvlist_t *config; 623257221772SChristopher Siden uint64_t version; 623357221772SChristopher Siden 623457221772SChristopher Siden config = zpool_get_config(zhp, NULL); 623557221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 623657221772SChristopher Siden &version) == 0); 623757221772SChristopher Siden 623857221772SChristopher Siden if (version >= SPA_VERSION_FEATURES) { 623957221772SChristopher Siden int i; 624057221772SChristopher Siden boolean_t poolfirst = B_TRUE; 624157221772SChristopher Siden nvlist_t *enabled = zpool_get_features(zhp); 624257221772SChristopher Siden 624357221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 624457221772SChristopher Siden const char *fguid = spa_feature_table[i].fi_guid; 624557221772SChristopher Siden const char *fname = spa_feature_table[i].fi_uname; 624657221772SChristopher Siden if (!nvlist_exists(enabled, fguid)) { 624757221772SChristopher Siden if (cbp->cb_first) { 624857221772SChristopher Siden (void) printf(gettext("\nSome " 624957221772SChristopher Siden "supported features are not " 625057221772SChristopher Siden "enabled on the following pools. " 625157221772SChristopher Siden "Once a\nfeature is enabled the " 625257221772SChristopher Siden "pool may become incompatible with " 625357221772SChristopher Siden "software\nthat does not support " 625457221772SChristopher Siden "the feature. See " 625557221772SChristopher Siden "zpool-features(5) for " 625657221772SChristopher Siden "details.\n\n")); 625757221772SChristopher Siden (void) printf(gettext("POOL " 625857221772SChristopher Siden "FEATURE\n")); 625957221772SChristopher Siden (void) printf(gettext("------" 626057221772SChristopher Siden "---------\n")); 626157221772SChristopher Siden cbp->cb_first = B_FALSE; 626257221772SChristopher Siden } 626357221772SChristopher Siden 626457221772SChristopher Siden if (poolfirst) { 626557221772SChristopher Siden (void) printf(gettext("%s\n"), 626657221772SChristopher Siden zpool_get_name(zhp)); 626757221772SChristopher Siden poolfirst = B_FALSE; 626857221772SChristopher Siden } 626957221772SChristopher Siden 627057221772SChristopher Siden (void) printf(gettext(" %s\n"), fname); 627157221772SChristopher Siden } 627257221772SChristopher Siden } 627357221772SChristopher Siden } 627457221772SChristopher Siden 627557221772SChristopher Siden return (0); 6276eaca9bbdSeschrock } 6277eaca9bbdSeschrock 6278eaca9bbdSeschrock /* ARGSUSED */ 6279eaca9bbdSeschrock static int 628006eeb2adSek upgrade_one(zpool_handle_t *zhp, void *data) 6281eaca9bbdSeschrock { 628257221772SChristopher Siden boolean_t printnl = B_FALSE; 6283990b4856Slling upgrade_cbdata_t *cbp = data; 6284990b4856Slling uint64_t cur_version; 6285eaca9bbdSeschrock int ret; 6286eaca9bbdSeschrock 62878654d025Sperrin if (strcmp("log", zpool_get_name(zhp)) == 0) { 62888654d025Sperrin (void) printf(gettext("'log' is now a reserved word\n" 62898654d025Sperrin "Pool 'log' must be renamed using export and import" 62908654d025Sperrin " to upgrade.\n")); 62918654d025Sperrin return (1); 62928654d025Sperrin } 6293990b4856Slling 6294990b4856Slling cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 6295e6c728e1Sbrendan if (cur_version > cbp->cb_version) { 6296eaca9bbdSeschrock (void) printf(gettext("Pool '%s' is already formatted " 629757221772SChristopher Siden "using more current version '%llu'.\n\n"), 6298e6c728e1Sbrendan zpool_get_name(zhp), cur_version); 6299e6c728e1Sbrendan return (0); 6300e6c728e1Sbrendan } 630157221772SChristopher Siden 630257221772SChristopher Siden if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) { 6303e6c728e1Sbrendan (void) printf(gettext("Pool '%s' is already formatted " 630457221772SChristopher Siden "using version %llu.\n\n"), zpool_get_name(zhp), 630557221772SChristopher Siden cbp->cb_version); 6306eaca9bbdSeschrock return (0); 6307eaca9bbdSeschrock } 6308eaca9bbdSeschrock 630957221772SChristopher Siden if (cur_version != cbp->cb_version) { 631057221772SChristopher Siden printnl = B_TRUE; 631157221772SChristopher Siden ret = upgrade_version(zhp, cbp->cb_version); 631257221772SChristopher Siden if (ret != 0) 631357221772SChristopher Siden return (ret); 631457221772SChristopher Siden } 631506eeb2adSek 631657221772SChristopher Siden if (cbp->cb_version >= SPA_VERSION_FEATURES) { 631757221772SChristopher Siden int count = 0; 631857221772SChristopher Siden ret = upgrade_enable_all(zhp, &count); 631957221772SChristopher Siden if (ret != 0) 632057221772SChristopher Siden return (ret); 632157221772SChristopher Siden 632257221772SChristopher Siden if (count != 0) { 632357221772SChristopher Siden printnl = B_TRUE; 632457221772SChristopher Siden } else if (cur_version == SPA_VERSION) { 632557221772SChristopher Siden (void) printf(gettext("Pool '%s' already has all " 632657221772SChristopher Siden "supported features enabled.\n"), 632757221772SChristopher Siden zpool_get_name(zhp)); 632857221772SChristopher Siden } 632957221772SChristopher Siden } 633057221772SChristopher Siden 633157221772SChristopher Siden if (printnl) { 633257221772SChristopher Siden (void) printf(gettext("\n")); 633306eeb2adSek } 6334eaca9bbdSeschrock 633557221772SChristopher Siden return (0); 6336eaca9bbdSeschrock } 6337eaca9bbdSeschrock 6338eaca9bbdSeschrock /* 6339eaca9bbdSeschrock * zpool upgrade 6340eaca9bbdSeschrock * zpool upgrade -v 6341990b4856Slling * zpool upgrade [-V version] <-a | pool ...> 6342eaca9bbdSeschrock * 6343eaca9bbdSeschrock * With no arguments, display downrev'd ZFS pool available for upgrade. 6344eaca9bbdSeschrock * Individual pools can be upgraded by specifying the pool, and '-a' will 6345eaca9bbdSeschrock * upgrade all pools. 6346eaca9bbdSeschrock */ 6347eaca9bbdSeschrock int 6348eaca9bbdSeschrock zpool_do_upgrade(int argc, char **argv) 6349eaca9bbdSeschrock { 6350eaca9bbdSeschrock int c; 6351eaca9bbdSeschrock upgrade_cbdata_t cb = { 0 }; 6352eaca9bbdSeschrock int ret = 0; 6353eaca9bbdSeschrock boolean_t showversions = B_FALSE; 635457221772SChristopher Siden boolean_t upgradeall = B_FALSE; 6355990b4856Slling char *end; 6356990b4856Slling 6357eaca9bbdSeschrock 6358eaca9bbdSeschrock /* check options */ 6359478ed9adSEric Taylor while ((c = getopt(argc, argv, ":avV:")) != -1) { 6360eaca9bbdSeschrock switch (c) { 6361eaca9bbdSeschrock case 'a': 636257221772SChristopher Siden upgradeall = B_TRUE; 6363eaca9bbdSeschrock break; 6364eaca9bbdSeschrock case 'v': 6365eaca9bbdSeschrock showversions = B_TRUE; 6366eaca9bbdSeschrock break; 6367990b4856Slling case 'V': 6368990b4856Slling cb.cb_version = strtoll(optarg, &end, 10); 6369ad135b5dSChristopher Siden if (*end != '\0' || 6370ad135b5dSChristopher Siden !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) { 6371990b4856Slling (void) fprintf(stderr, 6372990b4856Slling gettext("invalid version '%s'\n"), optarg); 6373990b4856Slling usage(B_FALSE); 6374990b4856Slling } 6375990b4856Slling break; 6376478ed9adSEric Taylor case ':': 6377478ed9adSEric Taylor (void) fprintf(stderr, gettext("missing argument for " 6378478ed9adSEric Taylor "'%c' option\n"), optopt); 6379478ed9adSEric Taylor usage(B_FALSE); 6380478ed9adSEric Taylor break; 6381eaca9bbdSeschrock case '?': 6382eaca9bbdSeschrock (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6383eaca9bbdSeschrock optopt); 638499653d4eSeschrock usage(B_FALSE); 6385eaca9bbdSeschrock } 6386eaca9bbdSeschrock } 6387eaca9bbdSeschrock 638806eeb2adSek cb.cb_argc = argc; 638906eeb2adSek cb.cb_argv = argv; 6390eaca9bbdSeschrock argc -= optind; 6391eaca9bbdSeschrock argv += optind; 6392eaca9bbdSeschrock 6393351420b3Slling if (cb.cb_version == 0) { 6394351420b3Slling cb.cb_version = SPA_VERSION; 639557221772SChristopher Siden } else if (!upgradeall && argc == 0) { 6396351420b3Slling (void) fprintf(stderr, gettext("-V option is " 6397351420b3Slling "incompatible with other arguments\n")); 6398351420b3Slling usage(B_FALSE); 6399351420b3Slling } 6400351420b3Slling 6401eaca9bbdSeschrock if (showversions) { 640257221772SChristopher Siden if (upgradeall || argc != 0) { 6403eaca9bbdSeschrock (void) fprintf(stderr, gettext("-v option is " 6404eaca9bbdSeschrock "incompatible with other arguments\n")); 640599653d4eSeschrock usage(B_FALSE); 6406eaca9bbdSeschrock } 640757221772SChristopher Siden } else if (upgradeall) { 6408eaca9bbdSeschrock if (argc != 0) { 6409351420b3Slling (void) fprintf(stderr, gettext("-a option should not " 6410351420b3Slling "be used along with a pool name\n")); 641199653d4eSeschrock usage(B_FALSE); 6412eaca9bbdSeschrock } 6413eaca9bbdSeschrock } 6414eaca9bbdSeschrock 6415ad135b5dSChristopher Siden (void) printf(gettext("This system supports ZFS pool feature " 6416ad135b5dSChristopher Siden "flags.\n\n")); 6417eaca9bbdSeschrock if (showversions) { 641857221772SChristopher Siden int i; 641957221772SChristopher Siden 642057221772SChristopher Siden (void) printf(gettext("The following features are " 642157221772SChristopher Siden "supported:\n\n")); 642257221772SChristopher Siden (void) printf(gettext("FEAT DESCRIPTION\n")); 642357221772SChristopher Siden (void) printf("----------------------------------------------" 642457221772SChristopher Siden "---------------\n"); 642557221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 642657221772SChristopher Siden zfeature_info_t *fi = &spa_feature_table[i]; 6427ca0cc391SMatthew Ahrens const char *ro = 6428ca0cc391SMatthew Ahrens (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 642957221772SChristopher Siden " (read-only compatible)" : ""; 643057221772SChristopher Siden 643157221772SChristopher Siden (void) printf("%-37s%s\n", fi->fi_uname, ro); 643257221772SChristopher Siden (void) printf(" %s\n", fi->fi_desc); 643357221772SChristopher Siden } 643457221772SChristopher Siden (void) printf("\n"); 643557221772SChristopher Siden 643657221772SChristopher Siden (void) printf(gettext("The following legacy versions are also " 6437d7d4af51Smmusante "supported:\n\n")); 6438eaca9bbdSeschrock (void) printf(gettext("VER DESCRIPTION\n")); 6439eaca9bbdSeschrock (void) printf("--- -----------------------------------------" 6440eaca9bbdSeschrock "---------------\n"); 644199653d4eSeschrock (void) printf(gettext(" 1 Initial ZFS version\n")); 644244cd46caSbillm (void) printf(gettext(" 2 Ditto blocks " 644344cd46caSbillm "(replicated metadata)\n")); 644499653d4eSeschrock (void) printf(gettext(" 3 Hot spares and double parity " 644599653d4eSeschrock "RAID-Z\n")); 6446d7306b64Sek (void) printf(gettext(" 4 zpool history\n")); 6447c9431fa1Sahl (void) printf(gettext(" 5 Compression using the gzip " 6448c9431fa1Sahl "algorithm\n")); 6449990b4856Slling (void) printf(gettext(" 6 bootfs pool property\n")); 64508654d025Sperrin (void) printf(gettext(" 7 Separate intent log devices\n")); 6451ecd6cf80Smarks (void) printf(gettext(" 8 Delegated administration\n")); 64528eed72d4Sck (void) printf(gettext(" 9 refquota and refreservation " 6453a9799022Sck "properties\n")); 6454fa94a07fSbrendan (void) printf(gettext(" 10 Cache devices\n")); 6455088f3894Sahrens (void) printf(gettext(" 11 Improved scrub performance\n")); 6456bb0ade09Sahrens (void) printf(gettext(" 12 Snapshot properties\n")); 645774e7dc98SMatthew Ahrens (void) printf(gettext(" 13 snapused property\n")); 645814843421SMatthew Ahrens (void) printf(gettext(" 14 passthrough-x aclinherit\n")); 645914843421SMatthew Ahrens (void) printf(gettext(" 15 user/group space accounting\n")); 6460478ed9adSEric Taylor (void) printf(gettext(" 16 stmf property support\n")); 64617aeab329SAdam Leventhal (void) printf(gettext(" 17 Triple-parity RAID-Z\n")); 6462b24ab676SJeff Bonwick (void) printf(gettext(" 18 Snapshot user holds\n")); 646388ecc943SGeorge Wilson (void) printf(gettext(" 19 Log device removal\n")); 6464b24ab676SJeff Bonwick (void) printf(gettext(" 20 Compression using zle " 6465b24ab676SJeff Bonwick "(zero-length encoding)\n")); 6466b24ab676SJeff Bonwick (void) printf(gettext(" 21 Deduplication\n")); 646792241e0bSTom Erickson (void) printf(gettext(" 22 Received properties\n")); 64686e1f5caaSNeil Perrin (void) printf(gettext(" 23 Slim ZIL\n")); 64690a586ceaSMark Shellenbaum (void) printf(gettext(" 24 System attributes\n")); 64703f9d6ad7SLin Ling (void) printf(gettext(" 25 Improved scrub stats\n")); 6471cde58dbcSMatthew Ahrens (void) printf(gettext(" 26 Improved snapshot deletion " 6472cde58dbcSMatthew Ahrens "performance\n")); 64736e0cbcaaSMatthew Ahrens (void) printf(gettext(" 27 Improved snapshot creation " 64746e0cbcaaSMatthew Ahrens "performance\n")); 6475cb04b873SMark J Musante (void) printf(gettext(" 28 Multiple vdev replacements\n")); 6476b24ab676SJeff Bonwick (void) printf(gettext("\nFor more information on a particular " 64779a8685acSstephanie scheffler "version, including supported releases,\n")); 64789a8685acSstephanie scheffler (void) printf(gettext("see the ZFS Administration Guide.\n\n")); 647957221772SChristopher Siden } else if (argc == 0 && upgradeall) { 648057221772SChristopher Siden cb.cb_first = B_TRUE; 648199653d4eSeschrock ret = zpool_iter(g_zfs, upgrade_cb, &cb); 648257221772SChristopher Siden if (ret == 0 && cb.cb_first) { 648357221772SChristopher Siden if (cb.cb_version == SPA_VERSION) { 648457221772SChristopher Siden (void) printf(gettext("All pools are already " 648557221772SChristopher Siden "formatted using feature flags.\n\n")); 648657221772SChristopher Siden (void) printf(gettext("Every feature flags " 648757221772SChristopher Siden "pool already has all supported features " 648857221772SChristopher Siden "enabled.\n")); 648957221772SChristopher Siden } else { 649057221772SChristopher Siden (void) printf(gettext("All pools are already " 649157221772SChristopher Siden "formatted with version %llu or higher.\n"), 649257221772SChristopher Siden cb.cb_version); 6493eaca9bbdSeschrock } 6494eaca9bbdSeschrock } 649557221772SChristopher Siden } else if (argc == 0) { 649657221772SChristopher Siden cb.cb_first = B_TRUE; 649757221772SChristopher Siden ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb); 649857221772SChristopher Siden assert(ret == 0); 6499eaca9bbdSeschrock 650057221772SChristopher Siden if (cb.cb_first) { 650157221772SChristopher Siden (void) printf(gettext("All pools are formatted " 650257221772SChristopher Siden "using feature flags.\n\n")); 650357221772SChristopher Siden } else { 650457221772SChristopher Siden (void) printf(gettext("\nUse 'zpool upgrade -v' " 650557221772SChristopher Siden "for a list of available legacy versions.\n")); 650657221772SChristopher Siden } 650757221772SChristopher Siden 650857221772SChristopher Siden cb.cb_first = B_TRUE; 650957221772SChristopher Siden ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb); 651057221772SChristopher Siden assert(ret == 0); 651157221772SChristopher Siden 651257221772SChristopher Siden if (cb.cb_first) { 651357221772SChristopher Siden (void) printf(gettext("Every feature flags pool has " 651457221772SChristopher Siden "all supported features enabled.\n")); 651557221772SChristopher Siden } else { 651657221772SChristopher Siden (void) printf(gettext("\n")); 6517eaca9bbdSeschrock } 6518eaca9bbdSeschrock } else { 6519b1b8ab34Slling ret = for_each_pool(argc, argv, B_FALSE, NULL, 6520b1b8ab34Slling upgrade_one, &cb); 652106eeb2adSek } 652206eeb2adSek 652306eeb2adSek return (ret); 652406eeb2adSek } 652506eeb2adSek 6526ecd6cf80Smarks typedef struct hist_cbdata { 6527ecd6cf80Smarks boolean_t first; 65284445fffbSMatthew Ahrens boolean_t longfmt; 65294445fffbSMatthew Ahrens boolean_t internal; 6530ecd6cf80Smarks } hist_cbdata_t; 6531ecd6cf80Smarks 653206eeb2adSek /* 653306eeb2adSek * Print out the command history for a specific pool. 653406eeb2adSek */ 653506eeb2adSek static int 653606eeb2adSek get_history_one(zpool_handle_t *zhp, void *data) 653706eeb2adSek { 653806eeb2adSek nvlist_t *nvhis; 653906eeb2adSek nvlist_t **records; 654006eeb2adSek uint_t numrecords; 654106eeb2adSek int ret, i; 6542ecd6cf80Smarks hist_cbdata_t *cb = (hist_cbdata_t *)data; 654306eeb2adSek 6544ecd6cf80Smarks cb->first = B_FALSE; 654506eeb2adSek 654606eeb2adSek (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); 654706eeb2adSek 654806eeb2adSek if ((ret = zpool_get_history(zhp, &nvhis)) != 0) 654906eeb2adSek return (ret); 655006eeb2adSek 655106eeb2adSek verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, 655206eeb2adSek &records, &numrecords) == 0); 655306eeb2adSek for (i = 0; i < numrecords; i++) { 65544445fffbSMatthew Ahrens nvlist_t *rec = records[i]; 65554445fffbSMatthew Ahrens char tbuf[30] = ""; 6556ecd6cf80Smarks 65574445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_TIME)) { 65584445fffbSMatthew Ahrens time_t tsec; 65594445fffbSMatthew Ahrens struct tm t; 65604445fffbSMatthew Ahrens 65614445fffbSMatthew Ahrens tsec = fnvlist_lookup_uint64(records[i], 65624445fffbSMatthew Ahrens ZPOOL_HIST_TIME); 65634445fffbSMatthew Ahrens (void) localtime_r(&tsec, &t); 65644445fffbSMatthew Ahrens (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 65654445fffbSMatthew Ahrens } 6566ecd6cf80Smarks 65674445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_CMD)) { 65684445fffbSMatthew Ahrens (void) printf("%s %s", tbuf, 65694445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_CMD)); 65704445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) { 65714445fffbSMatthew Ahrens int ievent = 65724445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT); 65734445fffbSMatthew Ahrens if (!cb->internal) 65744445fffbSMatthew Ahrens continue; 65754445fffbSMatthew Ahrens if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) { 65764445fffbSMatthew Ahrens (void) printf("%s unrecognized record:\n", 65774445fffbSMatthew Ahrens tbuf); 65784445fffbSMatthew Ahrens dump_nvlist(rec, 4); 65794445fffbSMatthew Ahrens continue; 65804445fffbSMatthew Ahrens } 65814445fffbSMatthew Ahrens (void) printf("%s [internal %s txg:%lld] %s", tbuf, 65824445fffbSMatthew Ahrens zfs_history_event_names[ievent], 65834445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 65844445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR)); 65854445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) { 65864445fffbSMatthew Ahrens if (!cb->internal) 6587ecd6cf80Smarks continue; 65884445fffbSMatthew Ahrens (void) printf("%s [txg:%lld] %s", tbuf, 65894445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 65904445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME)); 65914445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) { 65924445fffbSMatthew Ahrens (void) printf(" %s (%llu)", 65934445fffbSMatthew Ahrens fnvlist_lookup_string(rec, 65944445fffbSMatthew Ahrens ZPOOL_HIST_DSNAME), 65954445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, 65964445fffbSMatthew Ahrens ZPOOL_HIST_DSID)); 65974445fffbSMatthew Ahrens } 65984445fffbSMatthew Ahrens (void) printf(" %s", fnvlist_lookup_string(rec, 65994445fffbSMatthew Ahrens ZPOOL_HIST_INT_STR)); 66004445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) { 66014445fffbSMatthew Ahrens if (!cb->internal) 66024445fffbSMatthew Ahrens continue; 66034445fffbSMatthew Ahrens (void) printf("%s ioctl %s\n", tbuf, 66044445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL)); 66054445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) { 66064445fffbSMatthew Ahrens (void) printf(" input:\n"); 66074445fffbSMatthew Ahrens dump_nvlist(fnvlist_lookup_nvlist(rec, 66084445fffbSMatthew Ahrens ZPOOL_HIST_INPUT_NVL), 8); 66094445fffbSMatthew Ahrens } 66104445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) { 66114445fffbSMatthew Ahrens (void) printf(" output:\n"); 66124445fffbSMatthew Ahrens dump_nvlist(fnvlist_lookup_nvlist(rec, 66134445fffbSMatthew Ahrens ZPOOL_HIST_OUTPUT_NVL), 8); 66144445fffbSMatthew Ahrens } 6615dfc11533SChris Williamson if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) { 6616dfc11533SChris Williamson (void) printf(" errno: %lld\n", 6617dfc11533SChris Williamson fnvlist_lookup_int64(rec, 6618dfc11533SChris Williamson ZPOOL_HIST_ERRNO)); 6619dfc11533SChris Williamson } 66204445fffbSMatthew Ahrens } else { 66214445fffbSMatthew Ahrens if (!cb->internal) 6622ecd6cf80Smarks continue; 66234445fffbSMatthew Ahrens (void) printf("%s unrecognized record:\n", tbuf); 66244445fffbSMatthew Ahrens dump_nvlist(rec, 4); 662506eeb2adSek } 6626ecd6cf80Smarks 6627ecd6cf80Smarks if (!cb->longfmt) { 6628ecd6cf80Smarks (void) printf("\n"); 6629ecd6cf80Smarks continue; 6630ecd6cf80Smarks } 6631ecd6cf80Smarks (void) printf(" ["); 66324445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_WHO)) { 66334445fffbSMatthew Ahrens uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO); 66344445fffbSMatthew Ahrens struct passwd *pwd = getpwuid(who); 66354445fffbSMatthew Ahrens (void) printf("user %d ", (int)who); 66364445fffbSMatthew Ahrens if (pwd != NULL) 66374445fffbSMatthew Ahrens (void) printf("(%s) ", pwd->pw_name); 6638ecd6cf80Smarks } 66394445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_HOST)) { 66404445fffbSMatthew Ahrens (void) printf("on %s", 66414445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_HOST)); 6642ecd6cf80Smarks } 66434445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) { 66444445fffbSMatthew Ahrens (void) printf(":%s", 66454445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE)); 6646ecd6cf80Smarks } 6647ecd6cf80Smarks (void) printf("]"); 6648ecd6cf80Smarks (void) printf("\n"); 664906eeb2adSek } 665006eeb2adSek (void) printf("\n"); 665106eeb2adSek nvlist_free(nvhis); 665206eeb2adSek 665306eeb2adSek return (ret); 665406eeb2adSek } 665506eeb2adSek 665606eeb2adSek /* 665706eeb2adSek * zpool history <pool> 665806eeb2adSek * 665906eeb2adSek * Displays the history of commands that modified pools. 666006eeb2adSek */ 666106eeb2adSek int 666206eeb2adSek zpool_do_history(int argc, char **argv) 666306eeb2adSek { 6664ecd6cf80Smarks hist_cbdata_t cbdata = { 0 }; 666506eeb2adSek int ret; 6666ecd6cf80Smarks int c; 666706eeb2adSek 6668ecd6cf80Smarks cbdata.first = B_TRUE; 6669ecd6cf80Smarks /* check options */ 6670ecd6cf80Smarks while ((c = getopt(argc, argv, "li")) != -1) { 6671ecd6cf80Smarks switch (c) { 6672ecd6cf80Smarks case 'l': 66734445fffbSMatthew Ahrens cbdata.longfmt = B_TRUE; 6674ecd6cf80Smarks break; 6675ecd6cf80Smarks case 'i': 66764445fffbSMatthew Ahrens cbdata.internal = B_TRUE; 6677ecd6cf80Smarks break; 6678ecd6cf80Smarks case '?': 6679ecd6cf80Smarks (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6680ecd6cf80Smarks optopt); 6681ecd6cf80Smarks usage(B_FALSE); 6682ecd6cf80Smarks } 6683ecd6cf80Smarks } 668406eeb2adSek argc -= optind; 668506eeb2adSek argv += optind; 668606eeb2adSek 6687b1b8ab34Slling ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one, 6688ecd6cf80Smarks &cbdata); 668906eeb2adSek 6690ecd6cf80Smarks if (argc == 0 && cbdata.first == B_TRUE) { 669106eeb2adSek (void) printf(gettext("no pools available\n")); 669206eeb2adSek return (0); 6693eaca9bbdSeschrock } 6694eaca9bbdSeschrock 6695eaca9bbdSeschrock return (ret); 6696eaca9bbdSeschrock } 6697eaca9bbdSeschrock 6698b1b8ab34Slling static int 6699b1b8ab34Slling get_callback(zpool_handle_t *zhp, void *data) 6700b1b8ab34Slling { 6701990b4856Slling zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; 6702b1b8ab34Slling char value[MAXNAMELEN]; 6703990b4856Slling zprop_source_t srctype; 6704990b4856Slling zprop_list_t *pl; 6705b1b8ab34Slling 6706b1b8ab34Slling for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 6707b1b8ab34Slling 6708b1b8ab34Slling /* 6709990b4856Slling * Skip the special fake placeholder. This will also skip 6710990b4856Slling * over the name property when 'all' is specified. 6711b1b8ab34Slling */ 6712990b4856Slling if (pl->pl_prop == ZPOOL_PROP_NAME && 6713b1b8ab34Slling pl == cbp->cb_proplist) 6714b1b8ab34Slling continue; 6715b1b8ab34Slling 6716ad135b5dSChristopher Siden if (pl->pl_prop == ZPROP_INVAL && 6717ad135b5dSChristopher Siden (zpool_prop_feature(pl->pl_user_prop) || 6718ad135b5dSChristopher Siden zpool_prop_unsupported(pl->pl_user_prop))) { 6719ad135b5dSChristopher Siden srctype = ZPROP_SRC_LOCAL; 6720b1b8ab34Slling 6721ad135b5dSChristopher Siden if (zpool_prop_get_feature(zhp, pl->pl_user_prop, 6722ad135b5dSChristopher Siden value, sizeof (value)) == 0) { 6723ad135b5dSChristopher Siden zprop_print_one_property(zpool_get_name(zhp), 6724ad135b5dSChristopher Siden cbp, pl->pl_user_prop, value, srctype, 6725ad135b5dSChristopher Siden NULL, NULL); 6726ad135b5dSChristopher Siden } 6727ad135b5dSChristopher Siden } else { 6728ad135b5dSChristopher Siden if (zpool_get_prop(zhp, pl->pl_prop, value, 6729c58b3526SAdam Stevko sizeof (value), &srctype, cbp->cb_literal) != 0) 6730ad135b5dSChristopher Siden continue; 6731ad135b5dSChristopher Siden 6732ad135b5dSChristopher Siden zprop_print_one_property(zpool_get_name(zhp), cbp, 6733ad135b5dSChristopher Siden zpool_prop_to_name(pl->pl_prop), value, srctype, 6734ad135b5dSChristopher Siden NULL, NULL); 6735ad135b5dSChristopher Siden } 6736b1b8ab34Slling } 6737b1b8ab34Slling return (0); 6738b1b8ab34Slling } 6739b1b8ab34Slling 6740c58b3526SAdam Stevko /* 6741c58b3526SAdam Stevko * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ... 6742c58b3526SAdam Stevko * 6743c58b3526SAdam Stevko * -H Scripted mode. Don't display headers, and separate properties 6744c58b3526SAdam Stevko * by a single tab. 6745c58b3526SAdam Stevko * -o List of columns to display. Defaults to 6746c58b3526SAdam Stevko * "name,property,value,source". 674704e56356SAndriy Gapon * -p Diplay values in parsable (exact) format. 6748c58b3526SAdam Stevko * 6749c58b3526SAdam Stevko * Get properties of pools in the system. Output space statistics 6750c58b3526SAdam Stevko * for each one as well as other attributes. 6751c58b3526SAdam Stevko */ 6752b1b8ab34Slling int 6753b1b8ab34Slling zpool_do_get(int argc, char **argv) 6754b1b8ab34Slling { 6755990b4856Slling zprop_get_cbdata_t cb = { 0 }; 6756990b4856Slling zprop_list_t fake_name = { 0 }; 6757b1b8ab34Slling int ret; 6758c58b3526SAdam Stevko int c, i; 6759c58b3526SAdam Stevko char *value; 6760b1b8ab34Slling 6761b1b8ab34Slling cb.cb_first = B_TRUE; 6762c58b3526SAdam Stevko 6763c58b3526SAdam Stevko /* 6764c58b3526SAdam Stevko * Set up default columns and sources. 6765c58b3526SAdam Stevko */ 6766990b4856Slling cb.cb_sources = ZPROP_SRC_ALL; 6767b1b8ab34Slling cb.cb_columns[0] = GET_COL_NAME; 6768b1b8ab34Slling cb.cb_columns[1] = GET_COL_PROPERTY; 6769b1b8ab34Slling cb.cb_columns[2] = GET_COL_VALUE; 6770b1b8ab34Slling cb.cb_columns[3] = GET_COL_SOURCE; 6771990b4856Slling cb.cb_type = ZFS_TYPE_POOL; 6772b1b8ab34Slling 6773c58b3526SAdam Stevko /* check options */ 6774c58b3526SAdam Stevko while ((c = getopt(argc, argv, ":Hpo:")) != -1) { 6775c58b3526SAdam Stevko switch (c) { 6776c58b3526SAdam Stevko case 'p': 6777c58b3526SAdam Stevko cb.cb_literal = B_TRUE; 6778c58b3526SAdam Stevko break; 6779c58b3526SAdam Stevko case 'H': 6780c58b3526SAdam Stevko cb.cb_scripted = B_TRUE; 6781c58b3526SAdam Stevko break; 6782c58b3526SAdam Stevko case 'o': 6783c58b3526SAdam Stevko bzero(&cb.cb_columns, sizeof (cb.cb_columns)); 6784c58b3526SAdam Stevko i = 0; 6785c58b3526SAdam Stevko while (*optarg != '\0') { 6786c58b3526SAdam Stevko static char *col_subopts[] = 6787c58b3526SAdam Stevko { "name", "property", "value", "source", 6788c58b3526SAdam Stevko "all", NULL }; 6789c58b3526SAdam Stevko 6790c58b3526SAdam Stevko if (i == ZFS_GET_NCOLS) { 6791c58b3526SAdam Stevko (void) fprintf(stderr, gettext("too " 6792c58b3526SAdam Stevko "many fields given to -o " 6793c58b3526SAdam Stevko "option\n")); 6794c58b3526SAdam Stevko usage(B_FALSE); 6795c58b3526SAdam Stevko } 6796c58b3526SAdam Stevko 6797c58b3526SAdam Stevko switch (getsubopt(&optarg, col_subopts, 6798c58b3526SAdam Stevko &value)) { 6799c58b3526SAdam Stevko case 0: 6800c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_NAME; 6801c58b3526SAdam Stevko break; 6802c58b3526SAdam Stevko case 1: 6803c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_PROPERTY; 6804c58b3526SAdam Stevko break; 6805c58b3526SAdam Stevko case 2: 6806c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_VALUE; 6807c58b3526SAdam Stevko break; 6808c58b3526SAdam Stevko case 3: 6809c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_SOURCE; 6810c58b3526SAdam Stevko break; 6811c58b3526SAdam Stevko case 4: 6812c58b3526SAdam Stevko if (i > 0) { 6813c58b3526SAdam Stevko (void) fprintf(stderr, 6814c58b3526SAdam Stevko gettext("\"all\" conflicts " 6815c58b3526SAdam Stevko "with specific fields " 6816c58b3526SAdam Stevko "given to -o option\n")); 6817c58b3526SAdam Stevko usage(B_FALSE); 6818c58b3526SAdam Stevko } 6819c58b3526SAdam Stevko cb.cb_columns[0] = GET_COL_NAME; 6820c58b3526SAdam Stevko cb.cb_columns[1] = GET_COL_PROPERTY; 6821c58b3526SAdam Stevko cb.cb_columns[2] = GET_COL_VALUE; 6822c58b3526SAdam Stevko cb.cb_columns[3] = GET_COL_SOURCE; 6823c58b3526SAdam Stevko i = ZFS_GET_NCOLS; 6824c58b3526SAdam Stevko break; 6825c58b3526SAdam Stevko default: 6826c58b3526SAdam Stevko (void) fprintf(stderr, 6827c58b3526SAdam Stevko gettext("invalid column name " 6828c58b3526SAdam Stevko "'%s'\n"), value); 6829c58b3526SAdam Stevko usage(B_FALSE); 6830c58b3526SAdam Stevko } 6831c58b3526SAdam Stevko } 6832c58b3526SAdam Stevko break; 6833c58b3526SAdam Stevko case '?': 6834c58b3526SAdam Stevko (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6835c58b3526SAdam Stevko optopt); 6836c58b3526SAdam Stevko usage(B_FALSE); 6837c58b3526SAdam Stevko } 6838c58b3526SAdam Stevko } 6839c58b3526SAdam Stevko 6840c58b3526SAdam Stevko argc -= optind; 6841c58b3526SAdam Stevko argv += optind; 6842c58b3526SAdam Stevko 6843c58b3526SAdam Stevko if (argc < 1) { 6844c58b3526SAdam Stevko (void) fprintf(stderr, gettext("missing property " 6845c58b3526SAdam Stevko "argument\n")); 6846c58b3526SAdam Stevko usage(B_FALSE); 6847c58b3526SAdam Stevko } 6848c58b3526SAdam Stevko 6849c58b3526SAdam Stevko if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist, 6850990b4856Slling ZFS_TYPE_POOL) != 0) 6851b1b8ab34Slling usage(B_FALSE); 6852b1b8ab34Slling 6853c58b3526SAdam Stevko argc--; 6854c58b3526SAdam Stevko argv++; 6855c58b3526SAdam Stevko 6856b1b8ab34Slling if (cb.cb_proplist != NULL) { 6857990b4856Slling fake_name.pl_prop = ZPOOL_PROP_NAME; 6858b1b8ab34Slling fake_name.pl_width = strlen(gettext("NAME")); 6859b1b8ab34Slling fake_name.pl_next = cb.cb_proplist; 6860b1b8ab34Slling cb.cb_proplist = &fake_name; 6861b1b8ab34Slling } 6862b1b8ab34Slling 6863c58b3526SAdam Stevko ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, 6864b1b8ab34Slling get_callback, &cb); 6865b1b8ab34Slling 6866b1b8ab34Slling if (cb.cb_proplist == &fake_name) 6867990b4856Slling zprop_free_list(fake_name.pl_next); 6868b1b8ab34Slling else 6869990b4856Slling zprop_free_list(cb.cb_proplist); 6870b1b8ab34Slling 6871b1b8ab34Slling return (ret); 6872b1b8ab34Slling } 6873b1b8ab34Slling 6874b1b8ab34Slling typedef struct set_cbdata { 6875b1b8ab34Slling char *cb_propname; 6876b1b8ab34Slling char *cb_value; 6877b1b8ab34Slling boolean_t cb_any_successful; 6878b1b8ab34Slling } set_cbdata_t; 6879b1b8ab34Slling 6880b1b8ab34Slling int 6881b1b8ab34Slling set_callback(zpool_handle_t *zhp, void *data) 6882b1b8ab34Slling { 6883b1b8ab34Slling int error; 6884b1b8ab34Slling set_cbdata_t *cb = (set_cbdata_t *)data; 6885b1b8ab34Slling 6886b1b8ab34Slling error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value); 6887b1b8ab34Slling 6888b1b8ab34Slling if (!error) 6889b1b8ab34Slling cb->cb_any_successful = B_TRUE; 6890b1b8ab34Slling 6891b1b8ab34Slling return (error); 6892b1b8ab34Slling } 6893b1b8ab34Slling 6894b1b8ab34Slling int 6895b1b8ab34Slling zpool_do_set(int argc, char **argv) 6896b1b8ab34Slling { 6897b1b8ab34Slling set_cbdata_t cb = { 0 }; 6898b1b8ab34Slling int error; 6899b1b8ab34Slling 6900b1b8ab34Slling if (argc > 1 && argv[1][0] == '-') { 6901b1b8ab34Slling (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6902b1b8ab34Slling argv[1][1]); 6903b1b8ab34Slling usage(B_FALSE); 6904b1b8ab34Slling } 6905b1b8ab34Slling 6906b1b8ab34Slling if (argc < 2) { 6907b1b8ab34Slling (void) fprintf(stderr, gettext("missing property=value " 6908b1b8ab34Slling "argument\n")); 6909b1b8ab34Slling usage(B_FALSE); 6910b1b8ab34Slling } 6911b1b8ab34Slling 6912b1b8ab34Slling if (argc < 3) { 6913b1b8ab34Slling (void) fprintf(stderr, gettext("missing pool name\n")); 6914b1b8ab34Slling usage(B_FALSE); 6915b1b8ab34Slling } 6916b1b8ab34Slling 6917b1b8ab34Slling if (argc > 3) { 6918b1b8ab34Slling (void) fprintf(stderr, gettext("too many pool names\n")); 6919b1b8ab34Slling usage(B_FALSE); 6920b1b8ab34Slling } 6921b1b8ab34Slling 6922b1b8ab34Slling cb.cb_propname = argv[1]; 6923b1b8ab34Slling cb.cb_value = strchr(cb.cb_propname, '='); 6924b1b8ab34Slling if (cb.cb_value == NULL) { 6925b1b8ab34Slling (void) fprintf(stderr, gettext("missing value in " 6926b1b8ab34Slling "property=value argument\n")); 6927b1b8ab34Slling usage(B_FALSE); 6928b1b8ab34Slling } 6929b1b8ab34Slling 6930b1b8ab34Slling *(cb.cb_value) = '\0'; 6931b1b8ab34Slling cb.cb_value++; 6932b1b8ab34Slling 6933b1b8ab34Slling error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, 6934b1b8ab34Slling set_callback, &cb); 6935b1b8ab34Slling 6936b1b8ab34Slling return (error); 6937b1b8ab34Slling } 6938b1b8ab34Slling 6939b1b8ab34Slling static int 6940b1b8ab34Slling find_command_idx(char *command, int *idx) 6941b1b8ab34Slling { 6942b1b8ab34Slling int i; 6943b1b8ab34Slling 6944b1b8ab34Slling for (i = 0; i < NCOMMAND; i++) { 6945b1b8ab34Slling if (command_table[i].name == NULL) 6946b1b8ab34Slling continue; 6947b1b8ab34Slling 6948b1b8ab34Slling if (strcmp(command, command_table[i].name) == 0) { 6949b1b8ab34Slling *idx = i; 6950b1b8ab34Slling return (0); 6951b1b8ab34Slling } 6952b1b8ab34Slling } 6953b1b8ab34Slling return (1); 6954b1b8ab34Slling } 6955b1b8ab34Slling 6956fa9e4066Sahrens int 6957fa9e4066Sahrens main(int argc, char **argv) 6958fa9e4066Sahrens { 6959b327cd3fSIgor Kozhukhov int ret = 0; 6960fa9e4066Sahrens int i; 6961fa9e4066Sahrens char *cmdname; 6962fa9e4066Sahrens 6963fa9e4066Sahrens (void) setlocale(LC_ALL, ""); 6964fa9e4066Sahrens (void) textdomain(TEXT_DOMAIN); 6965fa9e4066Sahrens 696699653d4eSeschrock if ((g_zfs = libzfs_init()) == NULL) { 696799653d4eSeschrock (void) fprintf(stderr, gettext("internal error: failed to " 6968203a47d8Snd "initialize ZFS library\n")); 696999653d4eSeschrock return (1); 697099653d4eSeschrock } 697199653d4eSeschrock 697299653d4eSeschrock libzfs_print_on_error(g_zfs, B_TRUE); 697399653d4eSeschrock 6974fa9e4066Sahrens opterr = 0; 6975fa9e4066Sahrens 6976fa9e4066Sahrens /* 6977fa9e4066Sahrens * Make sure the user has specified some command. 6978fa9e4066Sahrens */ 6979fa9e4066Sahrens if (argc < 2) { 6980fa9e4066Sahrens (void) fprintf(stderr, gettext("missing command\n")); 698199653d4eSeschrock usage(B_FALSE); 6982fa9e4066Sahrens } 6983fa9e4066Sahrens 6984fa9e4066Sahrens cmdname = argv[1]; 6985fa9e4066Sahrens 6986fa9e4066Sahrens /* 6987fa9e4066Sahrens * Special case '-?' 6988fa9e4066Sahrens */ 6989fa9e4066Sahrens if (strcmp(cmdname, "-?") == 0) 699099653d4eSeschrock usage(B_TRUE); 6991fa9e4066Sahrens 69924445fffbSMatthew Ahrens zfs_save_arguments(argc, argv, history_str, sizeof (history_str)); 69932a6b87f0Sek 6994fa9e4066Sahrens /* 6995fa9e4066Sahrens * Run the appropriate command. 6996fa9e4066Sahrens */ 6997b1b8ab34Slling if (find_command_idx(cmdname, &i) == 0) { 6998b1b8ab34Slling current_command = &command_table[i]; 6999b1b8ab34Slling ret = command_table[i].func(argc - 1, argv + 1); 700091ebeef5Sahrens } else if (strchr(cmdname, '=')) { 700191ebeef5Sahrens verify(find_command_idx("set", &i) == 0); 700291ebeef5Sahrens current_command = &command_table[i]; 700391ebeef5Sahrens ret = command_table[i].func(argc, argv); 700491ebeef5Sahrens } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 700591ebeef5Sahrens /* 700691ebeef5Sahrens * 'freeze' is a vile debugging abomination, so we treat 700791ebeef5Sahrens * it as such. 700891ebeef5Sahrens */ 7009ea8dc4b6Seschrock char buf[16384]; 7010ea8dc4b6Seschrock int fd = open(ZFS_DEV, O_RDWR); 7011fa9e4066Sahrens (void) strcpy((void *)buf, argv[2]); 7012fa9e4066Sahrens return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf)); 701391ebeef5Sahrens } else { 7014fa9e4066Sahrens (void) fprintf(stderr, gettext("unrecognized " 7015fa9e4066Sahrens "command '%s'\n"), cmdname); 701699653d4eSeschrock usage(B_FALSE); 7017fa9e4066Sahrens } 7018fa9e4066Sahrens 70194445fffbSMatthew Ahrens if (ret == 0 && log_history) 70204445fffbSMatthew Ahrens (void) zpool_log_history(g_zfs, history_str); 70214445fffbSMatthew Ahrens 702299653d4eSeschrock libzfs_fini(g_zfs); 702399653d4eSeschrock 7024fa9e4066Sahrens /* 7025fa9e4066Sahrens * The 'ZFS_ABORT' environment variable causes us to dump core on exit 7026fa9e4066Sahrens * for the purposes of running ::findleaks. 7027fa9e4066Sahrens */ 7028fa9e4066Sahrens if (getenv("ZFS_ABORT") != NULL) { 7029fa9e4066Sahrens (void) printf("dumping core by request\n"); 7030fa9e4066Sahrens abort(); 7031fa9e4066Sahrens } 7032fa9e4066Sahrens 7033fa9e4066Sahrens return (ret); 7034fa9e4066Sahrens } 7035