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> 32dd50e0ccSTony Hutter * Copyright 2020 Joyent, Inc. 335711d393Sloli * Copyright (c) 2012 by Cyril Plisko. All rights reserved. 34c4e4d410SAndy 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> 59dd50e0ccSTony Hutter #include <math.h> 60dd50e0ccSTony Hutter #include <sys/sysmacros.h> 61dd50e0ccSTony Hutter #include <sys/termios.h> 62fa9e4066Sahrens 63fa9e4066Sahrens #include <libzfs.h> 64d8ab6e12SDon Brady #include <libzutil.h> 65fa9e4066Sahrens 66fa9e4066Sahrens #include "zpool_util.h" 67b7b97454Sperrin #include "zfs_comutil.h" 68ad135b5dSChristopher Siden #include "zfeature_common.h" 69fa9e4066Sahrens 7026fd7700SKrishnendu Sadhukhan - Sun Microsystems #include "statcommon.h" 7126fd7700SKrishnendu Sadhukhan - Sun Microsystems 72fa9e4066Sahrens static int zpool_do_create(int, char **); 73fa9e4066Sahrens static int zpool_do_destroy(int, char **); 74fa9e4066Sahrens 75fa9e4066Sahrens static int zpool_do_add(int, char **); 7699653d4eSeschrock static int zpool_do_remove(int, char **); 776401734dSWill Andrews static int zpool_do_labelclear(int, char **); 78fa9e4066Sahrens 7986714001SSerapheim Dimitropoulos static int zpool_do_checkpoint(int, char **); 8086714001SSerapheim Dimitropoulos 81fa9e4066Sahrens static int zpool_do_list(int, char **); 82fa9e4066Sahrens static int zpool_do_iostat(int, char **); 83fa9e4066Sahrens static int zpool_do_status(int, char **); 84fa9e4066Sahrens 85fa9e4066Sahrens static int zpool_do_online(int, char **); 86fa9e4066Sahrens static int zpool_do_offline(int, char **); 87ea8dc4b6Seschrock static int zpool_do_clear(int, char **); 884263d13fSGeorge Wilson static int zpool_do_reopen(int, char **); 89fa9e4066Sahrens 90e9103aaeSGarrett D'Amore static int zpool_do_reguid(int, char **); 91e9103aaeSGarrett D'Amore 92fa9e4066Sahrens static int zpool_do_attach(int, char **); 93fa9e4066Sahrens static int zpool_do_detach(int, char **); 94fa9e4066Sahrens static int zpool_do_replace(int, char **); 951195e687SMark J Musante static int zpool_do_split(int, char **); 96fa9e4066Sahrens 97094e47e9SGeorge Wilson static int zpool_do_initialize(int, char **); 98fa9e4066Sahrens static int zpool_do_scrub(int, char **); 99e4c795beSTom Caputi static int zpool_do_resilver(int, char **); 100084fd14fSBrian Behlendorf static int zpool_do_trim(int, char **); 101fa9e4066Sahrens 102fa9e4066Sahrens static int zpool_do_import(int, char **); 103fa9e4066Sahrens static int zpool_do_export(int, char **); 104fa9e4066Sahrens 105eaca9bbdSeschrock static int zpool_do_upgrade(int, char **); 106eaca9bbdSeschrock 10706eeb2adSek static int zpool_do_history(int, char **); 10806eeb2adSek 109b1b8ab34Slling static int zpool_do_get(int, char **); 110b1b8ab34Slling static int zpool_do_set(int, char **); 111b1b8ab34Slling 1129c2acf00SAlek Pinchuk static int zpool_do_sync(int, char **); 1139c2acf00SAlek Pinchuk 114fa9e4066Sahrens /* 115fa9e4066Sahrens * These libumem hooks provide a reasonable set of defaults for the allocator's 116fa9e4066Sahrens * debugging facilities. 117fa9e4066Sahrens */ 11829ab75c9Srm 11929ab75c9Srm #ifdef DEBUG 120fa9e4066Sahrens const char * 12199653d4eSeschrock _umem_debug_init(void) 122fa9e4066Sahrens { 123fa9e4066Sahrens return ("default,verbose"); /* $UMEM_DEBUG setting */ 124fa9e4066Sahrens } 125fa9e4066Sahrens 126fa9e4066Sahrens const char * 127fa9e4066Sahrens _umem_logging_init(void) 128fa9e4066Sahrens { 129fa9e4066Sahrens return ("fail,contents"); /* $UMEM_LOGGING setting */ 130fa9e4066Sahrens } 13129ab75c9Srm #endif 132fa9e4066Sahrens 13365cd9f28Seschrock typedef enum { 13465cd9f28Seschrock HELP_ADD, 13565cd9f28Seschrock HELP_ATTACH, 136ea8dc4b6Seschrock HELP_CLEAR, 13765cd9f28Seschrock HELP_CREATE, 13886714001SSerapheim Dimitropoulos HELP_CHECKPOINT, 13965cd9f28Seschrock HELP_DESTROY, 14065cd9f28Seschrock HELP_DETACH, 14165cd9f28Seschrock HELP_EXPORT, 14206eeb2adSek HELP_HISTORY, 14365cd9f28Seschrock HELP_IMPORT, 14465cd9f28Seschrock HELP_IOSTAT, 1456401734dSWill Andrews HELP_LABELCLEAR, 14665cd9f28Seschrock HELP_LIST, 14765cd9f28Seschrock HELP_OFFLINE, 14865cd9f28Seschrock HELP_ONLINE, 14965cd9f28Seschrock HELP_REPLACE, 15099653d4eSeschrock HELP_REMOVE, 151094e47e9SGeorge Wilson HELP_INITIALIZE, 15265cd9f28Seschrock HELP_SCRUB, 153e4c795beSTom Caputi HELP_RESILVER, 154084fd14fSBrian Behlendorf HELP_TRIM, 155eaca9bbdSeschrock HELP_STATUS, 156b1b8ab34Slling HELP_UPGRADE, 157b1b8ab34Slling HELP_GET, 1581195e687SMark J Musante HELP_SET, 159e9103aaeSGarrett D'Amore HELP_SPLIT, 1609c2acf00SAlek Pinchuk HELP_SYNC, 1614263d13fSGeorge Wilson HELP_REGUID, 1624263d13fSGeorge Wilson HELP_REOPEN 16365cd9f28Seschrock } zpool_help_t; 16465cd9f28Seschrock 16565cd9f28Seschrock 166dd50e0ccSTony Hutter /* 167dd50e0ccSTony Hutter * Flags for stats to display with "zpool iostats" 168dd50e0ccSTony Hutter */ 169dd50e0ccSTony Hutter enum iostat_type { 170dd50e0ccSTony Hutter IOS_DEFAULT = 0, 171dd50e0ccSTony Hutter IOS_LATENCY = 1, 172dd50e0ccSTony Hutter IOS_QUEUES = 2, 173dd50e0ccSTony Hutter IOS_L_HISTO = 3, 174dd50e0ccSTony Hutter IOS_RQ_HISTO = 4, 175dd50e0ccSTony Hutter IOS_COUNT, /* always last element */ 176dd50e0ccSTony Hutter }; 177dd50e0ccSTony Hutter 178dd50e0ccSTony Hutter /* iostat_type entries as bitmasks */ 179dd50e0ccSTony Hutter #define IOS_DEFAULT_M (1ULL << IOS_DEFAULT) 180dd50e0ccSTony Hutter #define IOS_LATENCY_M (1ULL << IOS_LATENCY) 181dd50e0ccSTony Hutter #define IOS_QUEUES_M (1ULL << IOS_QUEUES) 182dd50e0ccSTony Hutter #define IOS_L_HISTO_M (1ULL << IOS_L_HISTO) 183dd50e0ccSTony Hutter #define IOS_RQ_HISTO_M (1ULL << IOS_RQ_HISTO) 184dd50e0ccSTony Hutter 185dd50e0ccSTony Hutter /* Mask of all the histo bits */ 186dd50e0ccSTony Hutter #define IOS_ANYHISTO_M (IOS_L_HISTO_M | IOS_RQ_HISTO_M) 187dd50e0ccSTony Hutter 188dd50e0ccSTony Hutter /* 189dd50e0ccSTony Hutter * Lookup table for iostat flags to nvlist names. Basically a list 190dd50e0ccSTony Hutter * of all the nvlists a flag requires. Also specifies the order in 191dd50e0ccSTony Hutter * which data gets printed in zpool iostat. 192dd50e0ccSTony Hutter */ 193dd50e0ccSTony Hutter static const char *vsx_type_to_nvlist[IOS_COUNT][13] = { 194dd50e0ccSTony Hutter [IOS_L_HISTO] = { 195dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO, 196dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO, 197dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO, 198dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO, 199dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO, 200dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO, 201dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO, 202dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO, 203dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO, 204dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO, 205dd50e0ccSTony Hutter NULL}, 206dd50e0ccSTony Hutter [IOS_LATENCY] = { 207dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO, 208dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO, 209dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO, 210dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO, 211dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO, 212dd50e0ccSTony Hutter NULL}, 213dd50e0ccSTony Hutter [IOS_QUEUES] = { 214dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE, 215dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE, 216dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE, 217dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE, 218dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE, 219dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE, 220dd50e0ccSTony Hutter NULL}, 221dd50e0ccSTony Hutter [IOS_RQ_HISTO] = { 222dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_IND_R_HISTO, 223dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_AGG_R_HISTO, 224dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_IND_W_HISTO, 225dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_AGG_W_HISTO, 226dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_IND_R_HISTO, 227dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_AGG_R_HISTO, 228dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_IND_W_HISTO, 229dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_AGG_W_HISTO, 230dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_IND_SCRUB_HISTO, 231dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_AGG_SCRUB_HISTO, 232dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_IND_TRIM_HISTO, 233dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_AGG_TRIM_HISTO, 234dd50e0ccSTony Hutter NULL}, 235dd50e0ccSTony Hutter }; 236dd50e0ccSTony Hutter 237dd50e0ccSTony Hutter 238dd50e0ccSTony Hutter /* 239dd50e0ccSTony Hutter * Given a cb->cb_flags with a histogram bit set, return the iostat_type. 240dd50e0ccSTony Hutter * Right now, only one histo bit is ever set at one time, so we can 241dd50e0ccSTony Hutter * just do a highbit64(a) 242dd50e0ccSTony Hutter */ 243dd50e0ccSTony Hutter #define IOS_HISTO_IDX(a) (highbit64(a & IOS_ANYHISTO_M) - 1) 244dd50e0ccSTony Hutter 245fa9e4066Sahrens typedef struct zpool_command { 246fa9e4066Sahrens const char *name; 247fa9e4066Sahrens int (*func)(int, char **); 24865cd9f28Seschrock zpool_help_t usage; 249fa9e4066Sahrens } zpool_command_t; 250fa9e4066Sahrens 251fa9e4066Sahrens /* 252fa9e4066Sahrens * Master command table. Each ZFS command has a name, associated function, and 253ea8dc4b6Seschrock * usage message. The usage messages need to be internationalized, so we have 254ea8dc4b6Seschrock * to have a function to return the usage message based on a command index. 25565cd9f28Seschrock * 25665cd9f28Seschrock * These commands are organized according to how they are displayed in the usage 25765cd9f28Seschrock * message. An empty command (one with a NULL name) indicates an empty line in 25865cd9f28Seschrock * the generic usage message. 259fa9e4066Sahrens */ 260fa9e4066Sahrens static zpool_command_t command_table[] = { 26165cd9f28Seschrock { "create", zpool_do_create, HELP_CREATE }, 26265cd9f28Seschrock { "destroy", zpool_do_destroy, HELP_DESTROY }, 263fa9e4066Sahrens { NULL }, 26465cd9f28Seschrock { "add", zpool_do_add, HELP_ADD }, 26599653d4eSeschrock { "remove", zpool_do_remove, HELP_REMOVE }, 266fa9e4066Sahrens { NULL }, 2676401734dSWill Andrews { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR }, 2686401734dSWill Andrews { NULL }, 26986714001SSerapheim Dimitropoulos { "checkpoint", zpool_do_checkpoint, HELP_CHECKPOINT }, 27086714001SSerapheim Dimitropoulos { NULL }, 27165cd9f28Seschrock { "list", zpool_do_list, HELP_LIST }, 27265cd9f28Seschrock { "iostat", zpool_do_iostat, HELP_IOSTAT }, 27365cd9f28Seschrock { "status", zpool_do_status, HELP_STATUS }, 274fa9e4066Sahrens { NULL }, 27565cd9f28Seschrock { "online", zpool_do_online, HELP_ONLINE }, 27665cd9f28Seschrock { "offline", zpool_do_offline, HELP_OFFLINE }, 277ea8dc4b6Seschrock { "clear", zpool_do_clear, HELP_CLEAR }, 2784263d13fSGeorge Wilson { "reopen", zpool_do_reopen, HELP_REOPEN }, 279fa9e4066Sahrens { NULL }, 28065cd9f28Seschrock { "attach", zpool_do_attach, HELP_ATTACH }, 28165cd9f28Seschrock { "detach", zpool_do_detach, HELP_DETACH }, 28265cd9f28Seschrock { "replace", zpool_do_replace, HELP_REPLACE }, 2831195e687SMark J Musante { "split", zpool_do_split, HELP_SPLIT }, 284fa9e4066Sahrens { NULL }, 285094e47e9SGeorge Wilson { "initialize", zpool_do_initialize, HELP_INITIALIZE }, 286e4c795beSTom Caputi { "resilver", zpool_do_resilver, HELP_RESILVER }, 28765cd9f28Seschrock { "scrub", zpool_do_scrub, HELP_SCRUB }, 288084fd14fSBrian Behlendorf { "trim", zpool_do_trim, HELP_TRIM }, 289fa9e4066Sahrens { NULL }, 29065cd9f28Seschrock { "import", zpool_do_import, HELP_IMPORT }, 29165cd9f28Seschrock { "export", zpool_do_export, HELP_EXPORT }, 29206eeb2adSek { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, 293e9103aaeSGarrett D'Amore { "reguid", zpool_do_reguid, HELP_REGUID }, 29406eeb2adSek { NULL }, 295b1b8ab34Slling { "history", zpool_do_history, HELP_HISTORY }, 296b1b8ab34Slling { "get", zpool_do_get, HELP_GET }, 297b1b8ab34Slling { "set", zpool_do_set, HELP_SET }, 2989c2acf00SAlek Pinchuk { "sync", zpool_do_sync, HELP_SYNC }, 299fa9e4066Sahrens }; 300fa9e4066Sahrens 301dd50e0ccSTony Hutter #define NCOMMAND (ARRAY_SIZE(command_table)) 302fa9e4066Sahrens 303663207adSDon Brady #define VDEV_ALLOC_CLASS_LOGS "logs" 304663207adSDon Brady 3054445fffbSMatthew Ahrens static zpool_command_t *current_command; 3062a6b87f0Sek static char history_str[HIS_MAX_RECORD_LEN]; 3074445fffbSMatthew Ahrens static boolean_t log_history = B_TRUE; 30826fd7700SKrishnendu Sadhukhan - Sun Microsystems static uint_t timestamp_fmt = NODATE; 30926fd7700SKrishnendu Sadhukhan - Sun Microsystems 31065cd9f28Seschrock static const char * 3119a686fbcSPaul Dagnelie get_usage(zpool_help_t idx) 3129a686fbcSPaul Dagnelie { 31365cd9f28Seschrock switch (idx) { 31465cd9f28Seschrock case HELP_ADD: 3155711d393Sloli return (gettext("\tadd [-fgLnP] [-o property=value] " 3165711d393Sloli "<pool> <vdev> ...\n")); 31765cd9f28Seschrock case HELP_ATTACH: 3185711d393Sloli return (gettext("\tattach [-f] [-o property=value] " 3195711d393Sloli "<pool> <device> <new-device>\n")); 320ea8dc4b6Seschrock case HELP_CLEAR: 321468c413aSTim Haley return (gettext("\tclear [-nF] <pool> [device]\n")); 32265cd9f28Seschrock case HELP_CREATE: 3237855d95bSToomas Soome return (gettext("\tcreate [-fnd] [-B] " 3247855d95bSToomas Soome "[-o property=value] ... \n" 32504e56356SAndriy Gapon "\t [-O file-system-property=value] ...\n" 32604e56356SAndriy Gapon "\t [-m mountpoint] [-R root] [-t tempname] " 32704e56356SAndriy Gapon "<pool> <vdev> ...\n")); 32886714001SSerapheim Dimitropoulos case HELP_CHECKPOINT: 32986714001SSerapheim Dimitropoulos return (gettext("\tcheckpoint [--discard] <pool> ...\n")); 33065cd9f28Seschrock case HELP_DESTROY: 33165cd9f28Seschrock return (gettext("\tdestroy [-f] <pool>\n")); 33265cd9f28Seschrock case HELP_DETACH: 33365cd9f28Seschrock return (gettext("\tdetach <pool> <device>\n")); 33465cd9f28Seschrock case HELP_EXPORT: 33565cd9f28Seschrock return (gettext("\texport [-f] <pool> ...\n")); 33606eeb2adSek case HELP_HISTORY: 337ecd6cf80Smarks return (gettext("\thistory [-il] [<pool>] ...\n")); 33865cd9f28Seschrock case HELP_IMPORT: 3394c58d714Sdarrenm return (gettext("\timport [-d dir] [-D]\n" 340eb633035STom Caputi "\timport [-d dir | -c cachefile] [-F [-n]] [-l] " 341eb633035STom Caputi "<pool | id>\n" 3422f8aaab3Seschrock "\timport [-o mntopts] [-o property=value] ... \n" 343eb633035STom Caputi "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] " 344f9af39baSGeorge Wilson "[-R root] [-F [-n]] -a\n" 3452f8aaab3Seschrock "\timport [-o mntopts] [-o property=value] ... \n" 346eb633035STom Caputi "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] " 34704e56356SAndriy Gapon "[-R root] [-F [-n]] [-t]\n" 34886714001SSerapheim Dimitropoulos "\t [--rewind-to-checkpoint] <pool | id> [newpool]\n")); 34965cd9f28Seschrock case HELP_IOSTAT: 350dd50e0ccSTony Hutter return (gettext("\tiostat " 351dd50e0ccSTony Hutter "[[-lq]|[-rw]] [-T d | u] [-ghHLpPvy]\n" 352*20f5062bSJerry Jelinek "\t [[pool] ...]|[pool vdev ...]|[vdev ...]]" 353dd50e0ccSTony Hutter " [[-n] interval [count]]\n")); 3546401734dSWill Andrews case HELP_LABELCLEAR: 3556401734dSWill Andrews return (gettext("\tlabelclear [-f] <vdev>\n")); 35665cd9f28Seschrock case HELP_LIST: 357663207adSDon Brady return (gettext("\tlist [-gHLpPv] [-o property[,...]] " 3583f9d6ad7SLin Ling "[-T d|u] [pool] ... [interval [count]]\n")); 35965cd9f28Seschrock case HELP_OFFLINE: 360441d80aaSlling return (gettext("\toffline [-t] <pool> <device> ...\n")); 36165cd9f28Seschrock case HELP_ONLINE: 362441d80aaSlling return (gettext("\tonline <pool> <device> ...\n")); 36365cd9f28Seschrock case HELP_REPLACE: 36465cd9f28Seschrock return (gettext("\treplace [-f] <pool> <device> " 365e45ce728Sahrens "[new-device]\n")); 36699653d4eSeschrock case HELP_REMOVE: 3675cabbc6bSPrashanth Sreenivasa return (gettext("\tremove [-nps] <pool> <device> ...\n")); 3684263d13fSGeorge Wilson case HELP_REOPEN: 36931d7e8faSGeorge Wilson return (gettext("\treopen <pool>\n")); 370094e47e9SGeorge Wilson case HELP_INITIALIZE: 371084fd14fSBrian Behlendorf return (gettext("\tinitialize [-c | -s] <pool> " 372084fd14fSBrian Behlendorf "[<device> ...]\n")); 37365cd9f28Seschrock case HELP_SCRUB: 3741702cce7SAlek Pinchuk return (gettext("\tscrub [-s | -p] <pool> ...\n")); 375e4c795beSTom Caputi case HELP_RESILVER: 376e4c795beSTom Caputi return (gettext("\tresilver <pool> ...\n")); 377084fd14fSBrian Behlendorf case HELP_TRIM: 378084fd14fSBrian Behlendorf return (gettext("\ttrim [-d] [-r <rate>] [-c | -s] <pool> " 379084fd14fSBrian Behlendorf "[<device> ...]\n")); 38065cd9f28Seschrock case HELP_STATUS: 381dd50e0ccSTony Hutter return (gettext("\tstatus " 382dd50e0ccSTony Hutter "[-igLpPsvxD] [-T d|u] [pool] ... " 383663207adSDon Brady "[interval [count]]\n")); 384eaca9bbdSeschrock case HELP_UPGRADE: 385eaca9bbdSeschrock return (gettext("\tupgrade\n" 386eaca9bbdSeschrock "\tupgrade -v\n" 387990b4856Slling "\tupgrade [-V version] <-a | pool ...>\n")); 388b1b8ab34Slling case HELP_GET: 389c58b3526SAdam Stevko return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] " 390c58b3526SAdam Stevko "<\"all\" | property[,...]> <pool> ...\n")); 391b1b8ab34Slling case HELP_SET: 392b1b8ab34Slling return (gettext("\tset <property=value> <pool> \n")); 3931195e687SMark J Musante case HELP_SPLIT: 394eb633035STom Caputi return (gettext("\tsplit [-gLlnP] [-R altroot] [-o mntopts]\n" 3951195e687SMark J Musante "\t [-o property=value] <pool> <newpool> " 3961195e687SMark J Musante "[<device> ...]\n")); 397e9103aaeSGarrett D'Amore case HELP_REGUID: 398e9103aaeSGarrett D'Amore return (gettext("\treguid <pool>\n")); 3999c2acf00SAlek Pinchuk case HELP_SYNC: 4009c2acf00SAlek Pinchuk return (gettext("\tsync [pool] ...\n")); 40165cd9f28Seschrock } 40265cd9f28Seschrock 40365cd9f28Seschrock abort(); 40465cd9f28Seschrock /* NOTREACHED */ 40565cd9f28Seschrock } 40665cd9f28Seschrock 407084fd14fSBrian Behlendorf static void 408084fd14fSBrian Behlendorf zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res) 409084fd14fSBrian Behlendorf { 410084fd14fSBrian Behlendorf uint_t children = 0; 411084fd14fSBrian Behlendorf nvlist_t **child; 412084fd14fSBrian Behlendorf uint_t i; 413084fd14fSBrian Behlendorf 414084fd14fSBrian Behlendorf (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 415084fd14fSBrian Behlendorf &child, &children); 416084fd14fSBrian Behlendorf 417084fd14fSBrian Behlendorf if (children == 0) { 418084fd14fSBrian Behlendorf char *path = zpool_vdev_name(g_zfs, zhp, nvroot, 0); 419084fd14fSBrian Behlendorf 420084fd14fSBrian Behlendorf if (strcmp(path, VDEV_TYPE_INDIRECT) != 0) 421084fd14fSBrian Behlendorf fnvlist_add_boolean(res, path); 422084fd14fSBrian Behlendorf 423084fd14fSBrian Behlendorf free(path); 424084fd14fSBrian Behlendorf return; 425084fd14fSBrian Behlendorf } 426084fd14fSBrian Behlendorf 427084fd14fSBrian Behlendorf for (i = 0; i < children; i++) { 428084fd14fSBrian Behlendorf zpool_collect_leaves(zhp, child[i], res); 429084fd14fSBrian Behlendorf } 430084fd14fSBrian Behlendorf } 431fa9e4066Sahrens 432b1b8ab34Slling /* 433b1b8ab34Slling * Callback routine that will print out a pool property value. 434b1b8ab34Slling */ 435990b4856Slling static int 436990b4856Slling print_prop_cb(int prop, void *cb) 437b1b8ab34Slling { 438b1b8ab34Slling FILE *fp = cb; 439b1b8ab34Slling 440663207adSDon Brady (void) fprintf(fp, "\t%-19s ", zpool_prop_to_name(prop)); 441b1b8ab34Slling 442990b4856Slling if (zpool_prop_readonly(prop)) 443990b4856Slling (void) fprintf(fp, " NO "); 444990b4856Slling else 445b24ab676SJeff Bonwick (void) fprintf(fp, " YES "); 446990b4856Slling 447b1b8ab34Slling if (zpool_prop_values(prop) == NULL) 448b1b8ab34Slling (void) fprintf(fp, "-\n"); 449b1b8ab34Slling else 450b1b8ab34Slling (void) fprintf(fp, "%s\n", zpool_prop_values(prop)); 451b1b8ab34Slling 452990b4856Slling return (ZPROP_CONT); 453b1b8ab34Slling } 454b1b8ab34Slling 455fa9e4066Sahrens /* 456fa9e4066Sahrens * Display usage message. If we're inside a command, display only the usage for 457fa9e4066Sahrens * that command. Otherwise, iterate over the entire command table and display 458fa9e4066Sahrens * a complete usage message. 459fa9e4066Sahrens */ 460fa9e4066Sahrens void 46199653d4eSeschrock usage(boolean_t requested) 462fa9e4066Sahrens { 463fa9e4066Sahrens FILE *fp = requested ? stdout : stderr; 464fa9e4066Sahrens 465fa9e4066Sahrens if (current_command == NULL) { 466fa9e4066Sahrens int i; 467fa9e4066Sahrens 468fa9e4066Sahrens (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 469fa9e4066Sahrens (void) fprintf(fp, 470fa9e4066Sahrens gettext("where 'command' is one of the following:\n\n")); 471fa9e4066Sahrens 472fa9e4066Sahrens for (i = 0; i < NCOMMAND; i++) { 473fa9e4066Sahrens if (command_table[i].name == NULL) 474fa9e4066Sahrens (void) fprintf(fp, "\n"); 475fa9e4066Sahrens else 476fa9e4066Sahrens (void) fprintf(fp, "%s", 47765cd9f28Seschrock get_usage(command_table[i].usage)); 478fa9e4066Sahrens } 479fa9e4066Sahrens } else { 480fa9e4066Sahrens (void) fprintf(fp, gettext("usage:\n")); 48165cd9f28Seschrock (void) fprintf(fp, "%s", get_usage(current_command->usage)); 482fa9e4066Sahrens } 483fa9e4066Sahrens 484b1b8ab34Slling if (current_command != NULL && 485b1b8ab34Slling ((strcmp(current_command->name, "set") == 0) || 486990b4856Slling (strcmp(current_command->name, "get") == 0) || 487990b4856Slling (strcmp(current_command->name, "list") == 0))) { 488b1b8ab34Slling 489b1b8ab34Slling (void) fprintf(fp, 490b1b8ab34Slling gettext("\nthe following properties are supported:\n")); 491b1b8ab34Slling 492663207adSDon Brady (void) fprintf(fp, "\n\t%-19s %s %s\n\n", 493990b4856Slling "PROPERTY", "EDIT", "VALUES"); 494b1b8ab34Slling 495b1b8ab34Slling /* Iterate over all properties */ 496990b4856Slling (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, 497990b4856Slling ZFS_TYPE_POOL); 498ad135b5dSChristopher Siden 499663207adSDon Brady (void) fprintf(fp, "\t%-19s ", "feature@..."); 500ad135b5dSChristopher Siden (void) fprintf(fp, "YES disabled | enabled | active\n"); 501ad135b5dSChristopher Siden 502ad135b5dSChristopher Siden (void) fprintf(fp, gettext("\nThe feature@ properties must be " 503ad135b5dSChristopher Siden "appended with a feature name.\nSee zpool-features(5).\n")); 504b1b8ab34Slling } 505b1b8ab34Slling 506e9dbad6fSeschrock /* 507e9dbad6fSeschrock * See comments at end of main(). 508e9dbad6fSeschrock */ 509e9dbad6fSeschrock if (getenv("ZFS_ABORT") != NULL) { 510e9dbad6fSeschrock (void) printf("dumping core by request\n"); 511e9dbad6fSeschrock abort(); 512e9dbad6fSeschrock } 513e9dbad6fSeschrock 514fa9e4066Sahrens exit(requested ? 0 : 2); 515fa9e4066Sahrens } 516fa9e4066Sahrens 517663207adSDon Brady /* 518663207adSDon Brady * print a pool vdev config for dry runs 519663207adSDon Brady */ 520663207adSDon Brady static void 5218654d025Sperrin print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, 522663207adSDon Brady const char *match, int name_flags) 523fa9e4066Sahrens { 524fa9e4066Sahrens nvlist_t **child; 525fa9e4066Sahrens uint_t c, children; 526afefbcddSeschrock char *vname; 527663207adSDon Brady boolean_t printed = B_FALSE; 528fa9e4066Sahrens 529fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 530663207adSDon Brady &child, &children) != 0) { 531663207adSDon Brady if (name != NULL) 532663207adSDon Brady (void) printf("\t%*s%s\n", indent, "", name); 533fa9e4066Sahrens return; 534663207adSDon Brady } 535fa9e4066Sahrens 536afefbcddSeschrock for (c = 0; c < children; c++) { 5378654d025Sperrin uint64_t is_log = B_FALSE; 538663207adSDon Brady char *class = ""; 5398654d025Sperrin 5408654d025Sperrin (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 5418654d025Sperrin &is_log); 542663207adSDon Brady if (is_log) 543663207adSDon Brady class = VDEV_ALLOC_BIAS_LOG; 544663207adSDon Brady (void) nvlist_lookup_string(child[c], 545663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &class); 546663207adSDon Brady if (strcmp(match, class) != 0) 5478654d025Sperrin continue; 5488654d025Sperrin 549663207adSDon Brady if (!printed && name != NULL) { 550663207adSDon Brady (void) printf("\t%*s%s\n", indent, "", name); 551663207adSDon Brady printed = B_TRUE; 552663207adSDon Brady } 553663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags); 554663207adSDon Brady print_vdev_tree(zhp, vname, child[c], indent + 2, "", 555663207adSDon Brady name_flags); 556afefbcddSeschrock free(vname); 557afefbcddSeschrock } 558fa9e4066Sahrens } 559fa9e4066Sahrens 56057221772SChristopher Siden static boolean_t 56157221772SChristopher Siden prop_list_contains_feature(nvlist_t *proplist) 56257221772SChristopher Siden { 56357221772SChristopher Siden nvpair_t *nvp; 56457221772SChristopher Siden for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp; 56557221772SChristopher Siden nvp = nvlist_next_nvpair(proplist, nvp)) { 56657221772SChristopher Siden if (zpool_prop_feature(nvpair_name(nvp))) 56757221772SChristopher Siden return (B_TRUE); 56857221772SChristopher Siden } 56957221772SChristopher Siden return (B_FALSE); 57057221772SChristopher Siden } 57157221772SChristopher Siden 572990b4856Slling /* 573990b4856Slling * Add a property pair (name, string-value) into a property nvlist. 574990b4856Slling */ 575990b4856Slling static int 5760a48a24eStimh add_prop_list(const char *propname, char *propval, nvlist_t **props, 5770a48a24eStimh boolean_t poolprop) 578990b4856Slling { 579d2aa06e8SAndrew Stormont zpool_prop_t prop = ZPOOL_PROP_INVAL; 5800a48a24eStimh zfs_prop_t fprop; 581990b4856Slling nvlist_t *proplist; 5820a48a24eStimh const char *normnm; 5830a48a24eStimh char *strval; 584990b4856Slling 585990b4856Slling if (*props == NULL && 586990b4856Slling nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) { 587990b4856Slling (void) fprintf(stderr, 588990b4856Slling gettext("internal error: out of memory\n")); 589990b4856Slling return (1); 590990b4856Slling } 591990b4856Slling 592990b4856Slling proplist = *props; 593990b4856Slling 5940a48a24eStimh if (poolprop) { 59557221772SChristopher Siden const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION); 59657221772SChristopher Siden 597d2aa06e8SAndrew Stormont if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL && 598ad135b5dSChristopher Siden !zpool_prop_feature(propname)) { 5990a48a24eStimh (void) fprintf(stderr, gettext("property '%s' is " 6000a48a24eStimh "not a valid pool property\n"), propname); 6010a48a24eStimh return (2); 6020a48a24eStimh } 60357221772SChristopher Siden 60457221772SChristopher Siden /* 60557221772SChristopher Siden * feature@ properties and version should not be specified 60657221772SChristopher Siden * at the same time. 60757221772SChristopher Siden */ 6084ae5f5f0SAlan Somers if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) && 60957221772SChristopher Siden nvlist_exists(proplist, vname)) || 61057221772SChristopher Siden (prop == ZPOOL_PROP_VERSION && 61157221772SChristopher Siden prop_list_contains_feature(proplist))) { 61257221772SChristopher Siden (void) fprintf(stderr, gettext("'feature@' and " 61357221772SChristopher Siden "'version' properties cannot be specified " 61457221772SChristopher Siden "together\n")); 61557221772SChristopher Siden return (2); 61657221772SChristopher Siden } 61757221772SChristopher Siden 61857221772SChristopher Siden 619ad135b5dSChristopher Siden if (zpool_prop_feature(propname)) 620ad135b5dSChristopher Siden normnm = propname; 621ad135b5dSChristopher Siden else 622ad135b5dSChristopher Siden normnm = zpool_prop_to_name(prop); 6230a48a24eStimh } else { 62414843421SMatthew Ahrens if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) { 62514843421SMatthew Ahrens normnm = zfs_prop_to_name(fprop); 62614843421SMatthew Ahrens } else { 62714843421SMatthew Ahrens normnm = propname; 6280a48a24eStimh } 629990b4856Slling } 630990b4856Slling 6310a48a24eStimh if (nvlist_lookup_string(proplist, normnm, &strval) == 0 && 6320a48a24eStimh prop != ZPOOL_PROP_CACHEFILE) { 633990b4856Slling (void) fprintf(stderr, gettext("property '%s' " 634990b4856Slling "specified multiple times\n"), propname); 635990b4856Slling return (2); 636990b4856Slling } 637990b4856Slling 6380a48a24eStimh if (nvlist_add_string(proplist, normnm, propval) != 0) { 639990b4856Slling (void) fprintf(stderr, gettext("internal " 640990b4856Slling "error: out of memory\n")); 641990b4856Slling return (1); 642990b4856Slling } 643990b4856Slling 644990b4856Slling return (0); 645990b4856Slling } 646990b4856Slling 64704e56356SAndriy Gapon /* 64804e56356SAndriy Gapon * Set a default property pair (name, string-value) in a property nvlist 64904e56356SAndriy Gapon */ 65004e56356SAndriy Gapon static int 65104e56356SAndriy Gapon add_prop_list_default(const char *propname, char *propval, nvlist_t **props, 65204e56356SAndriy Gapon boolean_t poolprop) 65304e56356SAndriy Gapon { 65404e56356SAndriy Gapon char *pval; 65504e56356SAndriy Gapon 65604e56356SAndriy Gapon if (nvlist_lookup_string(*props, propname, &pval) == 0) 65704e56356SAndriy Gapon return (0); 65804e56356SAndriy Gapon 65904e56356SAndriy Gapon return (add_prop_list(propname, propval, props, poolprop)); 66004e56356SAndriy Gapon } 66104e56356SAndriy Gapon 662fa9e4066Sahrens /* 663663207adSDon Brady * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ... 664fa9e4066Sahrens * 665fa9e4066Sahrens * -f Force addition of devices, even if they appear in use 666663207adSDon Brady * -g Display guid for individual vdev name. 667663207adSDon Brady * -L Follow links when resolving vdev path name. 668fa9e4066Sahrens * -n Do not add the devices, but display the resulting layout if 669fa9e4066Sahrens * they were to be added. 670663207adSDon Brady * -P Display full path for vdev name. 6715711d393Sloli * -o Set property=value. 672fa9e4066Sahrens * 673fa9e4066Sahrens * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 674fa9e4066Sahrens * handled by get_vdev_spec(), which constructs the nvlist needed to pass to 675fa9e4066Sahrens * libzfs. 676fa9e4066Sahrens */ 677fa9e4066Sahrens int 678fa9e4066Sahrens zpool_do_add(int argc, char **argv) 679fa9e4066Sahrens { 68099653d4eSeschrock boolean_t force = B_FALSE; 68199653d4eSeschrock boolean_t dryrun = B_FALSE; 682663207adSDon Brady int name_flags = 0; 683fa9e4066Sahrens int c; 684fa9e4066Sahrens nvlist_t *nvroot; 685fa9e4066Sahrens char *poolname; 6867855d95bSToomas Soome zpool_boot_label_t boot_type; 6877855d95bSToomas Soome uint64_t boot_size; 688fa9e4066Sahrens int ret; 689fa9e4066Sahrens zpool_handle_t *zhp; 690fa9e4066Sahrens nvlist_t *config; 6915711d393Sloli nvlist_t *props = NULL; 6925711d393Sloli char *propval; 693fa9e4066Sahrens 694fa9e4066Sahrens /* check options */ 6955711d393Sloli while ((c = getopt(argc, argv, "fgLnPo:")) != -1) { 696fa9e4066Sahrens switch (c) { 697fa9e4066Sahrens case 'f': 69899653d4eSeschrock force = B_TRUE; 699fa9e4066Sahrens break; 700663207adSDon Brady case 'g': 701663207adSDon Brady name_flags |= VDEV_NAME_GUID; 702663207adSDon Brady break; 703663207adSDon Brady case 'L': 704663207adSDon Brady name_flags |= VDEV_NAME_FOLLOW_LINKS; 705663207adSDon Brady break; 706fa9e4066Sahrens case 'n': 70799653d4eSeschrock dryrun = B_TRUE; 708fa9e4066Sahrens break; 709663207adSDon Brady case 'P': 710663207adSDon Brady name_flags |= VDEV_NAME_PATH; 711663207adSDon Brady break; 7125711d393Sloli case 'o': 7135711d393Sloli if ((propval = strchr(optarg, '=')) == NULL) { 7145711d393Sloli (void) fprintf(stderr, gettext("missing " 7155711d393Sloli "'=' for -o option\n")); 7165711d393Sloli usage(B_FALSE); 7175711d393Sloli } 7185711d393Sloli *propval = '\0'; 7195711d393Sloli propval++; 7205711d393Sloli 7215711d393Sloli if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) || 7225711d393Sloli (add_prop_list(optarg, propval, &props, B_TRUE))) 7235711d393Sloli usage(B_FALSE); 7245711d393Sloli break; 725fa9e4066Sahrens case '?': 726fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 727fa9e4066Sahrens optopt); 72899653d4eSeschrock usage(B_FALSE); 729fa9e4066Sahrens } 730fa9e4066Sahrens } 731fa9e4066Sahrens 732fa9e4066Sahrens argc -= optind; 733fa9e4066Sahrens argv += optind; 734fa9e4066Sahrens 735fa9e4066Sahrens /* get pool name and check number of arguments */ 736fa9e4066Sahrens if (argc < 1) { 737fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 73899653d4eSeschrock usage(B_FALSE); 739fa9e4066Sahrens } 740fa9e4066Sahrens if (argc < 2) { 741fa9e4066Sahrens (void) fprintf(stderr, gettext("missing vdev specification\n")); 74299653d4eSeschrock usage(B_FALSE); 743fa9e4066Sahrens } 744fa9e4066Sahrens 745fa9e4066Sahrens poolname = argv[0]; 746fa9e4066Sahrens 747fa9e4066Sahrens argc--; 748fa9e4066Sahrens argv++; 749fa9e4066Sahrens 75099653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 751fa9e4066Sahrens return (1); 752fa9e4066Sahrens 753088e9d47Seschrock if ((config = zpool_get_config(zhp, NULL)) == NULL) { 754fa9e4066Sahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 755fa9e4066Sahrens poolname); 756fa9e4066Sahrens zpool_close(zhp); 757fa9e4066Sahrens return (1); 758fa9e4066Sahrens } 759fa9e4066Sahrens 7607855d95bSToomas Soome if (zpool_is_bootable(zhp)) 7617855d95bSToomas Soome boot_type = ZPOOL_COPY_BOOT_LABEL; 7627855d95bSToomas Soome else 7637855d95bSToomas Soome boot_type = ZPOOL_NO_BOOT_LABEL; 7647855d95bSToomas Soome 7655711d393Sloli /* unless manually specified use "ashift" pool property (if set) */ 7665711d393Sloli if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) { 7675711d393Sloli int intval; 7685711d393Sloli zprop_source_t src; 7695711d393Sloli char strval[ZPOOL_MAXPROPLEN]; 7705711d393Sloli 7715711d393Sloli intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src); 7725711d393Sloli if (src != ZPROP_SRC_DEFAULT) { 7735711d393Sloli (void) sprintf(strval, "%" PRId32, intval); 7745711d393Sloli verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval, 7755711d393Sloli &props, B_TRUE) == 0); 7765711d393Sloli } 7775711d393Sloli } 7785711d393Sloli 779fa9e4066Sahrens /* pass off to get_vdev_spec for processing */ 7807855d95bSToomas Soome boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 7815711d393Sloli nvroot = make_root_vdev(zhp, props, force, !force, B_FALSE, dryrun, 7827855d95bSToomas Soome boot_type, boot_size, argc, argv); 783fa9e4066Sahrens if (nvroot == NULL) { 784fa9e4066Sahrens zpool_close(zhp); 785fa9e4066Sahrens return (1); 786fa9e4066Sahrens } 787fa9e4066Sahrens 788fa9e4066Sahrens if (dryrun) { 789fa9e4066Sahrens nvlist_t *poolnvroot; 790fa9e4066Sahrens 791fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 792fa9e4066Sahrens &poolnvroot) == 0); 793fa9e4066Sahrens 794fa9e4066Sahrens (void) printf(gettext("would update '%s' to the following " 795fa9e4066Sahrens "configuration:\n"), zpool_get_name(zhp)); 796fa9e4066Sahrens 7978654d025Sperrin /* print original main pool and new tree */ 798663207adSDon Brady print_vdev_tree(zhp, poolname, poolnvroot, 0, "", 799663207adSDon Brady name_flags | VDEV_NAME_TYPE_ID); 800663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, "", name_flags); 801663207adSDon Brady 802663207adSDon Brady /* print other classes: 'dedup', 'special', and 'log' */ 803663207adSDon Brady print_vdev_tree(zhp, "dedup", poolnvroot, 0, 804663207adSDon Brady VDEV_ALLOC_BIAS_DEDUP, name_flags); 805663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_DEDUP, 806663207adSDon Brady name_flags); 807663207adSDon Brady 808663207adSDon Brady print_vdev_tree(zhp, "special", poolnvroot, 0, 809663207adSDon Brady VDEV_ALLOC_BIAS_SPECIAL, name_flags); 810663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_SPECIAL, 811663207adSDon Brady name_flags); 812663207adSDon Brady 813663207adSDon Brady print_vdev_tree(zhp, "logs", poolnvroot, 0, VDEV_ALLOC_BIAS_LOG, 814663207adSDon Brady name_flags); 815663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_LOG, 816663207adSDon Brady name_flags); 817fa9e4066Sahrens 818fa9e4066Sahrens ret = 0; 819fa9e4066Sahrens } else { 820fa9e4066Sahrens ret = (zpool_add(zhp, nvroot) != 0); 821fa9e4066Sahrens } 822fa9e4066Sahrens 8235711d393Sloli nvlist_free(props); 82499653d4eSeschrock nvlist_free(nvroot); 82599653d4eSeschrock zpool_close(zhp); 82699653d4eSeschrock 82799653d4eSeschrock return (ret); 82899653d4eSeschrock } 82999653d4eSeschrock 83099653d4eSeschrock /* 8313f9d6ad7SLin Ling * zpool remove <pool> <vdev> ... 83299653d4eSeschrock * 8335cabbc6bSPrashanth Sreenivasa * Removes the given vdev from the pool. 83499653d4eSeschrock */ 83599653d4eSeschrock int 83699653d4eSeschrock zpool_do_remove(int argc, char **argv) 83799653d4eSeschrock { 83899653d4eSeschrock char *poolname; 839fa94a07fSbrendan int i, ret = 0; 84099653d4eSeschrock zpool_handle_t *zhp; 8415cabbc6bSPrashanth Sreenivasa boolean_t stop = B_FALSE; 8425cabbc6bSPrashanth Sreenivasa boolean_t noop = B_FALSE; 8435cabbc6bSPrashanth Sreenivasa boolean_t parsable = B_FALSE; 8445cabbc6bSPrashanth Sreenivasa char c; 84599653d4eSeschrock 8465cabbc6bSPrashanth Sreenivasa /* check options */ 8475cabbc6bSPrashanth Sreenivasa while ((c = getopt(argc, argv, "nps")) != -1) { 8485cabbc6bSPrashanth Sreenivasa switch (c) { 8495cabbc6bSPrashanth Sreenivasa case 'n': 8505cabbc6bSPrashanth Sreenivasa noop = B_TRUE; 8515cabbc6bSPrashanth Sreenivasa break; 8525cabbc6bSPrashanth Sreenivasa case 'p': 8535cabbc6bSPrashanth Sreenivasa parsable = B_TRUE; 8545cabbc6bSPrashanth Sreenivasa break; 8555cabbc6bSPrashanth Sreenivasa case 's': 8565cabbc6bSPrashanth Sreenivasa stop = B_TRUE; 8575cabbc6bSPrashanth Sreenivasa break; 8585cabbc6bSPrashanth Sreenivasa case '?': 8595cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("invalid option '%c'\n"), 8605cabbc6bSPrashanth Sreenivasa optopt); 8615cabbc6bSPrashanth Sreenivasa usage(B_FALSE); 8625cabbc6bSPrashanth Sreenivasa } 8635cabbc6bSPrashanth Sreenivasa } 8645cabbc6bSPrashanth Sreenivasa 8655cabbc6bSPrashanth Sreenivasa argc -= optind; 8665cabbc6bSPrashanth Sreenivasa argv += optind; 86799653d4eSeschrock 86899653d4eSeschrock /* get pool name and check number of arguments */ 86999653d4eSeschrock if (argc < 1) { 87099653d4eSeschrock (void) fprintf(stderr, gettext("missing pool name argument\n")); 87199653d4eSeschrock usage(B_FALSE); 87299653d4eSeschrock } 87399653d4eSeschrock 87499653d4eSeschrock poolname = argv[0]; 87599653d4eSeschrock 87699653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 87799653d4eSeschrock return (1); 87899653d4eSeschrock 8795cabbc6bSPrashanth Sreenivasa if (stop && noop) { 8805cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("stop request ignored\n")); 8815cabbc6bSPrashanth Sreenivasa return (0); 8825cabbc6bSPrashanth Sreenivasa } 8835cabbc6bSPrashanth Sreenivasa 8845cabbc6bSPrashanth Sreenivasa if (stop) { 8855cabbc6bSPrashanth Sreenivasa if (argc > 1) { 8865cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("too many arguments\n")); 8875cabbc6bSPrashanth Sreenivasa usage(B_FALSE); 8885cabbc6bSPrashanth Sreenivasa } 8895cabbc6bSPrashanth Sreenivasa if (zpool_vdev_remove_cancel(zhp) != 0) 890fa94a07fSbrendan ret = 1; 8915cabbc6bSPrashanth Sreenivasa } else { 8925cabbc6bSPrashanth Sreenivasa if (argc < 2) { 8935cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("missing device\n")); 8945cabbc6bSPrashanth Sreenivasa usage(B_FALSE); 8955cabbc6bSPrashanth Sreenivasa } 8965cabbc6bSPrashanth Sreenivasa 8975cabbc6bSPrashanth Sreenivasa for (i = 1; i < argc; i++) { 8985cabbc6bSPrashanth Sreenivasa if (noop) { 8995cabbc6bSPrashanth Sreenivasa uint64_t size; 9005cabbc6bSPrashanth Sreenivasa 9015cabbc6bSPrashanth Sreenivasa if (zpool_vdev_indirect_size(zhp, argv[i], 9025cabbc6bSPrashanth Sreenivasa &size) != 0) { 9035cabbc6bSPrashanth Sreenivasa ret = 1; 9045cabbc6bSPrashanth Sreenivasa break; 9055cabbc6bSPrashanth Sreenivasa } 9065cabbc6bSPrashanth Sreenivasa if (parsable) { 9075cabbc6bSPrashanth Sreenivasa (void) printf("%s %llu\n", 9085cabbc6bSPrashanth Sreenivasa argv[i], size); 9095cabbc6bSPrashanth Sreenivasa } else { 9105cabbc6bSPrashanth Sreenivasa char valstr[32]; 9115cabbc6bSPrashanth Sreenivasa zfs_nicenum(size, valstr, 9125cabbc6bSPrashanth Sreenivasa sizeof (valstr)); 9135cabbc6bSPrashanth Sreenivasa (void) printf("Memory that will be " 9145cabbc6bSPrashanth Sreenivasa "used after removing %s: %s\n", 9155cabbc6bSPrashanth Sreenivasa argv[i], valstr); 9165cabbc6bSPrashanth Sreenivasa } 9175cabbc6bSPrashanth Sreenivasa } else { 9185cabbc6bSPrashanth Sreenivasa if (zpool_vdev_remove(zhp, argv[i]) != 0) 9195cabbc6bSPrashanth Sreenivasa ret = 1; 9205cabbc6bSPrashanth Sreenivasa } 9215cabbc6bSPrashanth Sreenivasa } 922fa94a07fSbrendan } 92399653d4eSeschrock 924fa9e4066Sahrens return (ret); 925fa9e4066Sahrens } 926fa9e4066Sahrens 9276401734dSWill Andrews /* 9286401734dSWill Andrews * zpool labelclear [-f] <vdev> 9296401734dSWill Andrews * 9306401734dSWill Andrews * -f Force clearing the label for the vdevs which are members of 9316401734dSWill Andrews * the exported or foreign pools. 9326401734dSWill Andrews * 9336401734dSWill Andrews * Verifies that the vdev is not active and zeros out the label information 9346401734dSWill Andrews * on the device. 9356401734dSWill Andrews */ 9366401734dSWill Andrews int 9376401734dSWill Andrews zpool_do_labelclear(int argc, char **argv) 9386401734dSWill Andrews { 9396401734dSWill Andrews char vdev[MAXPATHLEN]; 9406401734dSWill Andrews char *name = NULL; 9416401734dSWill Andrews struct stat st; 9426401734dSWill Andrews int c, fd, ret = 0; 9436401734dSWill Andrews nvlist_t *config; 9446401734dSWill Andrews pool_state_t state; 9456401734dSWill Andrews boolean_t inuse = B_FALSE; 9466401734dSWill Andrews boolean_t force = B_FALSE; 9476401734dSWill Andrews 9486401734dSWill Andrews /* check options */ 9496401734dSWill Andrews while ((c = getopt(argc, argv, "f")) != -1) { 9506401734dSWill Andrews switch (c) { 9516401734dSWill Andrews case 'f': 9526401734dSWill Andrews force = B_TRUE; 9536401734dSWill Andrews break; 9546401734dSWill Andrews default: 9556401734dSWill Andrews (void) fprintf(stderr, gettext("invalid option '%c'\n"), 9566401734dSWill Andrews optopt); 9576401734dSWill Andrews usage(B_FALSE); 9586401734dSWill Andrews } 9596401734dSWill Andrews } 9606401734dSWill Andrews 9616401734dSWill Andrews argc -= optind; 9626401734dSWill Andrews argv += optind; 9636401734dSWill Andrews 9646401734dSWill Andrews /* get vdev name */ 9656401734dSWill Andrews if (argc < 1) { 9666401734dSWill Andrews (void) fprintf(stderr, gettext("missing vdev name\n")); 9676401734dSWill Andrews usage(B_FALSE); 9686401734dSWill Andrews } 9696401734dSWill Andrews if (argc > 1) { 9706401734dSWill Andrews (void) fprintf(stderr, gettext("too many arguments\n")); 9716401734dSWill Andrews usage(B_FALSE); 9726401734dSWill Andrews } 9736401734dSWill Andrews 9746401734dSWill Andrews /* 9756401734dSWill Andrews * Check if we were given absolute path and use it as is. 9766401734dSWill Andrews * Otherwise if the provided vdev name doesn't point to a file, 9776401734dSWill Andrews * try prepending dsk path and appending s0. 9786401734dSWill Andrews */ 9796401734dSWill Andrews (void) strlcpy(vdev, argv[0], sizeof (vdev)); 9806401734dSWill Andrews if (vdev[0] != '/' && stat(vdev, &st) != 0) { 9816401734dSWill Andrews char *s; 9826401734dSWill Andrews 9836401734dSWill Andrews (void) snprintf(vdev, sizeof (vdev), "%s/%s", 9846401734dSWill Andrews ZFS_DISK_ROOT, argv[0]); 9856401734dSWill Andrews if ((s = strrchr(argv[0], 's')) == NULL || 9866401734dSWill Andrews !isdigit(*(s + 1))) 9876401734dSWill Andrews (void) strlcat(vdev, "s0", sizeof (vdev)); 9886401734dSWill Andrews if (stat(vdev, &st) != 0) { 9896401734dSWill Andrews (void) fprintf(stderr, gettext( 9906401734dSWill Andrews "failed to find device %s, try specifying absolute " 9916401734dSWill Andrews "path instead\n"), argv[0]); 9926401734dSWill Andrews return (1); 9936401734dSWill Andrews } 9946401734dSWill Andrews } 9956401734dSWill Andrews 9966401734dSWill Andrews if ((fd = open(vdev, O_RDWR)) < 0) { 9976401734dSWill Andrews (void) fprintf(stderr, gettext("failed to open %s: %s\n"), 9986401734dSWill Andrews vdev, strerror(errno)); 9996401734dSWill Andrews return (1); 10006401734dSWill Andrews } 10016401734dSWill Andrews 1002d8ab6e12SDon Brady if (zpool_read_label(fd, &config, NULL) != 0) { 10036401734dSWill Andrews (void) fprintf(stderr, 10046401734dSWill Andrews gettext("failed to read label from %s\n"), vdev); 10056401734dSWill Andrews return (1); 10066401734dSWill Andrews } 10076401734dSWill Andrews nvlist_free(config); 10086401734dSWill Andrews 10096401734dSWill Andrews ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse); 10106401734dSWill Andrews if (ret != 0) { 10116401734dSWill Andrews (void) fprintf(stderr, 10126401734dSWill Andrews gettext("failed to check state for %s\n"), vdev); 10136401734dSWill Andrews return (1); 10146401734dSWill Andrews } 10156401734dSWill Andrews 10166401734dSWill Andrews if (!inuse) 10176401734dSWill Andrews goto wipe_label; 10186401734dSWill Andrews 10196401734dSWill Andrews switch (state) { 10206401734dSWill Andrews default: 10216401734dSWill Andrews case POOL_STATE_ACTIVE: 10226401734dSWill Andrews case POOL_STATE_SPARE: 10236401734dSWill Andrews case POOL_STATE_L2CACHE: 10246401734dSWill Andrews (void) fprintf(stderr, gettext( 10256401734dSWill Andrews "%s is a member (%s) of pool \"%s\"\n"), 10266401734dSWill Andrews vdev, zpool_pool_state_to_name(state), name); 10276401734dSWill Andrews ret = 1; 10286401734dSWill Andrews goto errout; 10296401734dSWill Andrews 10306401734dSWill Andrews case POOL_STATE_EXPORTED: 10316401734dSWill Andrews if (force) 10326401734dSWill Andrews break; 10336401734dSWill Andrews (void) fprintf(stderr, gettext( 10346401734dSWill Andrews "use '-f' to override the following error:\n" 10356401734dSWill Andrews "%s is a member of exported pool \"%s\"\n"), 10366401734dSWill Andrews vdev, name); 10376401734dSWill Andrews ret = 1; 10386401734dSWill Andrews goto errout; 10396401734dSWill Andrews 10406401734dSWill Andrews case POOL_STATE_POTENTIALLY_ACTIVE: 10416401734dSWill Andrews if (force) 10426401734dSWill Andrews break; 10436401734dSWill Andrews (void) fprintf(stderr, gettext( 10446401734dSWill Andrews "use '-f' to override the following error:\n" 10456401734dSWill Andrews "%s is a member of potentially active pool \"%s\"\n"), 10466401734dSWill Andrews vdev, name); 10476401734dSWill Andrews ret = 1; 10486401734dSWill Andrews goto errout; 10496401734dSWill Andrews 10506401734dSWill Andrews case POOL_STATE_DESTROYED: 10516401734dSWill Andrews /* inuse should never be set for a destroyed pool */ 10526401734dSWill Andrews assert(0); 10536401734dSWill Andrews break; 10546401734dSWill Andrews } 10556401734dSWill Andrews 10566401734dSWill Andrews wipe_label: 10576401734dSWill Andrews ret = zpool_clear_label(fd); 10586401734dSWill Andrews if (ret != 0) { 10596401734dSWill Andrews (void) fprintf(stderr, 10606401734dSWill Andrews gettext("failed to clear label for %s\n"), vdev); 10616401734dSWill Andrews } 10626401734dSWill Andrews 10636401734dSWill Andrews errout: 10646401734dSWill Andrews free(name); 10656401734dSWill Andrews (void) close(fd); 10666401734dSWill Andrews 10676401734dSWill Andrews return (ret); 10686401734dSWill Andrews } 10696401734dSWill Andrews 1070fa9e4066Sahrens /* 10717855d95bSToomas Soome * zpool create [-fnd] [-B] [-o property=value] ... 10720a48a24eStimh * [-O file-system-property=value] ... 107304e56356SAndriy Gapon * [-R root] [-m mountpoint] [-t tempname] <pool> <dev> ... 1074fa9e4066Sahrens * 10757855d95bSToomas Soome * -B Create boot partition. 1076fa9e4066Sahrens * -f Force creation, even if devices appear in use 1077fa9e4066Sahrens * -n Do not create the pool, but display the resulting layout if it 1078fa9e4066Sahrens * were to be created. 107904e56356SAndriy Gapon * -R Create a pool under an alternate root 108004e56356SAndriy Gapon * -m Set default mountpoint for the root dataset. By default it's 1081ad135b5dSChristopher Siden * '/<pool>' 108204e56356SAndriy Gapon * -t Use the temporary name until the pool is exported. 1083990b4856Slling * -o Set property=value. 1084ad135b5dSChristopher Siden * -d Don't automatically enable all supported pool features 1085ad135b5dSChristopher Siden * (individual features can be enabled with -o). 10860a48a24eStimh * -O Set fsproperty=value in the pool's root file system 1087fa9e4066Sahrens * 1088b1b8ab34Slling * Creates the named pool according to the given vdev specification. The 1089fa9e4066Sahrens * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once 1090fa9e4066Sahrens * we get the nvlist back from get_vdev_spec(), we either print out the contents 1091fa9e4066Sahrens * (if '-n' was specified), or pass it to libzfs to do the creation. 1092fa9e4066Sahrens */ 10937855d95bSToomas Soome 10947855d95bSToomas Soome #define SYSTEM256 (256 * 1024 * 1024) 1095fa9e4066Sahrens int 1096fa9e4066Sahrens zpool_do_create(int argc, char **argv) 1097fa9e4066Sahrens { 109899653d4eSeschrock boolean_t force = B_FALSE; 109999653d4eSeschrock boolean_t dryrun = B_FALSE; 1100ad135b5dSChristopher Siden boolean_t enable_all_pool_feat = B_TRUE; 11017855d95bSToomas Soome zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL; 11027855d95bSToomas Soome uint64_t boot_size = 0; 1103fa9e4066Sahrens int c; 1104990b4856Slling nvlist_t *nvroot = NULL; 1105fa9e4066Sahrens char *poolname; 110604e56356SAndriy Gapon char *tname = NULL; 1107990b4856Slling int ret = 1; 1108fa9e4066Sahrens char *altroot = NULL; 1109fa9e4066Sahrens char *mountpoint = NULL; 11100a48a24eStimh nvlist_t *fsprops = NULL; 1111990b4856Slling nvlist_t *props = NULL; 11122f8aaab3Seschrock char *propval; 1113fa9e4066Sahrens 1114fa9e4066Sahrens /* check options */ 111504e56356SAndriy Gapon while ((c = getopt(argc, argv, ":fndBR:m:o:O:t:")) != -1) { 1116fa9e4066Sahrens switch (c) { 1117fa9e4066Sahrens case 'f': 111899653d4eSeschrock force = B_TRUE; 1119fa9e4066Sahrens break; 1120fa9e4066Sahrens case 'n': 112199653d4eSeschrock dryrun = B_TRUE; 1122fa9e4066Sahrens break; 1123ad135b5dSChristopher Siden case 'd': 1124ad135b5dSChristopher Siden enable_all_pool_feat = B_FALSE; 1125ad135b5dSChristopher Siden break; 11267855d95bSToomas Soome case 'B': 11277855d95bSToomas Soome /* 11287855d95bSToomas Soome * We should create the system partition. 11297855d95bSToomas Soome * Also make sure the size is set. 11307855d95bSToomas Soome */ 11317855d95bSToomas Soome boot_type = ZPOOL_CREATE_BOOT_LABEL; 11327855d95bSToomas Soome if (boot_size == 0) 11337855d95bSToomas Soome boot_size = SYSTEM256; 11347855d95bSToomas Soome break; 1135fa9e4066Sahrens case 'R': 1136fa9e4066Sahrens altroot = optarg; 1137990b4856Slling if (add_prop_list(zpool_prop_to_name( 11380a48a24eStimh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 1139990b4856Slling goto errout; 114004e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name( 11410a48a24eStimh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 1142990b4856Slling goto errout; 1143fa9e4066Sahrens break; 1144fa9e4066Sahrens case 'm': 11458b713775SWill Andrews /* Equivalent to -O mountpoint=optarg */ 1146fa9e4066Sahrens mountpoint = optarg; 1147fa9e4066Sahrens break; 1148990b4856Slling case 'o': 1149990b4856Slling if ((propval = strchr(optarg, '=')) == NULL) { 1150990b4856Slling (void) fprintf(stderr, gettext("missing " 1151990b4856Slling "'=' for -o option\n")); 1152990b4856Slling goto errout; 1153990b4856Slling } 1154990b4856Slling *propval = '\0'; 1155990b4856Slling propval++; 1156990b4856Slling 11570a48a24eStimh if (add_prop_list(optarg, propval, &props, B_TRUE)) 11580a48a24eStimh goto errout; 1159ad135b5dSChristopher Siden 11607855d95bSToomas Soome /* 11617855d95bSToomas Soome * Get bootsize value for make_root_vdev(). 11627855d95bSToomas Soome */ 11637855d95bSToomas Soome if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) { 11647855d95bSToomas Soome if (zfs_nicestrtonum(g_zfs, propval, 11657855d95bSToomas Soome &boot_size) < 0 || boot_size == 0) { 11667855d95bSToomas Soome (void) fprintf(stderr, 11677855d95bSToomas Soome gettext("bad boot partition size " 11687855d95bSToomas Soome "'%s': %s\n"), propval, 11697855d95bSToomas Soome libzfs_error_description(g_zfs)); 11707855d95bSToomas Soome goto errout; 11717855d95bSToomas Soome } 11727855d95bSToomas Soome } 11737855d95bSToomas Soome 1174ad135b5dSChristopher Siden /* 1175ad135b5dSChristopher Siden * If the user is creating a pool that doesn't support 1176ad135b5dSChristopher Siden * feature flags, don't enable any features. 1177ad135b5dSChristopher Siden */ 1178ad135b5dSChristopher Siden if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) { 1179ad135b5dSChristopher Siden char *end; 1180ad135b5dSChristopher Siden u_longlong_t ver; 1181ad135b5dSChristopher Siden 1182ad135b5dSChristopher Siden ver = strtoull(propval, &end, 10); 1183ad135b5dSChristopher Siden if (*end == '\0' && 1184ad135b5dSChristopher Siden ver < SPA_VERSION_FEATURES) { 1185ad135b5dSChristopher Siden enable_all_pool_feat = B_FALSE; 1186ad135b5dSChristopher Siden } 1187ad135b5dSChristopher Siden } 1188c423721fSXin Li if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT) 1189c423721fSXin Li altroot = propval; 11900a48a24eStimh break; 11910a48a24eStimh case 'O': 11920a48a24eStimh if ((propval = strchr(optarg, '=')) == NULL) { 11930a48a24eStimh (void) fprintf(stderr, gettext("missing " 11940a48a24eStimh "'=' for -O option\n")); 11950a48a24eStimh goto errout; 11960a48a24eStimh } 11970a48a24eStimh *propval = '\0'; 11980a48a24eStimh propval++; 11990a48a24eStimh 12008b713775SWill Andrews /* 12018b713775SWill Andrews * Mountpoints are checked and then added later. 12028b713775SWill Andrews * Uniquely among properties, they can be specified 12038b713775SWill Andrews * more than once, to avoid conflict with -m. 12048b713775SWill Andrews */ 12058b713775SWill Andrews if (0 == strcmp(optarg, 12068b713775SWill Andrews zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) { 12078b713775SWill Andrews mountpoint = propval; 12088b713775SWill Andrews } else if (add_prop_list(optarg, propval, &fsprops, 12098b713775SWill Andrews B_FALSE)) { 1210990b4856Slling goto errout; 12118b713775SWill Andrews } 1212990b4856Slling break; 121304e56356SAndriy Gapon case 't': 121404e56356SAndriy Gapon /* 121504e56356SAndriy Gapon * Sanity check temporary pool name. 121604e56356SAndriy Gapon */ 121704e56356SAndriy Gapon if (strchr(optarg, '/') != NULL) { 121804e56356SAndriy Gapon (void) fprintf(stderr, gettext("cannot create " 121904e56356SAndriy Gapon "'%s': invalid character '/' in temporary " 122004e56356SAndriy Gapon "name\n"), optarg); 122104e56356SAndriy Gapon (void) fprintf(stderr, gettext("use 'zfs " 122204e56356SAndriy Gapon "create' to create a dataset\n")); 122304e56356SAndriy Gapon goto errout; 122404e56356SAndriy Gapon } 122504e56356SAndriy Gapon 122604e56356SAndriy Gapon if (add_prop_list(zpool_prop_to_name( 122704e56356SAndriy Gapon ZPOOL_PROP_TNAME), optarg, &props, B_TRUE)) 122804e56356SAndriy Gapon goto errout; 122904e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name( 123004e56356SAndriy Gapon ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 123104e56356SAndriy Gapon goto errout; 123204e56356SAndriy Gapon tname = optarg; 123304e56356SAndriy Gapon break; 1234fa9e4066Sahrens case ':': 1235fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 1236fa9e4066Sahrens "'%c' option\n"), optopt); 1237990b4856Slling goto badusage; 1238fa9e4066Sahrens case '?': 1239fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1240fa9e4066Sahrens optopt); 1241990b4856Slling goto badusage; 1242fa9e4066Sahrens } 1243fa9e4066Sahrens } 1244fa9e4066Sahrens 1245fa9e4066Sahrens argc -= optind; 1246fa9e4066Sahrens argv += optind; 1247fa9e4066Sahrens 1248fa9e4066Sahrens /* get pool name and check number of arguments */ 1249fa9e4066Sahrens if (argc < 1) { 1250fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 1251990b4856Slling goto badusage; 1252fa9e4066Sahrens } 1253fa9e4066Sahrens if (argc < 2) { 1254fa9e4066Sahrens (void) fprintf(stderr, gettext("missing vdev specification\n")); 1255990b4856Slling goto badusage; 1256fa9e4066Sahrens } 1257fa9e4066Sahrens 1258fa9e4066Sahrens poolname = argv[0]; 1259fa9e4066Sahrens 1260fa9e4066Sahrens /* 1261fa9e4066Sahrens * As a special case, check for use of '/' in the name, and direct the 1262fa9e4066Sahrens * user to use 'zfs create' instead. 1263fa9e4066Sahrens */ 1264fa9e4066Sahrens if (strchr(poolname, '/') != NULL) { 1265fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot create '%s': invalid " 1266fa9e4066Sahrens "character '/' in pool name\n"), poolname); 1267fa9e4066Sahrens (void) fprintf(stderr, gettext("use 'zfs create' to " 1268fa9e4066Sahrens "create a dataset\n")); 1269990b4856Slling goto errout; 1270fa9e4066Sahrens } 1271fa9e4066Sahrens 12727855d95bSToomas Soome /* 12737855d95bSToomas Soome * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used, 12747855d95bSToomas Soome * and not set otherwise. 12757855d95bSToomas Soome */ 12767855d95bSToomas Soome if (boot_type == ZPOOL_CREATE_BOOT_LABEL) { 12777855d95bSToomas Soome const char *propname; 12787855d95bSToomas Soome char *strptr, *buf = NULL; 12797855d95bSToomas Soome int rv; 12807855d95bSToomas Soome 12817855d95bSToomas Soome propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 12827855d95bSToomas Soome if (nvlist_lookup_string(props, propname, &strptr) != 0) { 12837855d95bSToomas Soome (void) asprintf(&buf, "%" PRIu64, boot_size); 12847855d95bSToomas Soome if (buf == NULL) { 12857855d95bSToomas Soome (void) fprintf(stderr, 12867855d95bSToomas Soome gettext("internal error: out of memory\n")); 12877855d95bSToomas Soome goto errout; 12887855d95bSToomas Soome } 12897855d95bSToomas Soome rv = add_prop_list(propname, buf, &props, B_TRUE); 12907855d95bSToomas Soome free(buf); 12917855d95bSToomas Soome if (rv != 0) 12927855d95bSToomas Soome goto errout; 12937855d95bSToomas Soome } 12947855d95bSToomas Soome } else { 12957855d95bSToomas Soome const char *propname; 12967855d95bSToomas Soome char *strptr; 12977855d95bSToomas Soome 12987855d95bSToomas Soome propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 12997855d95bSToomas Soome if (nvlist_lookup_string(props, propname, &strptr) == 0) { 13007855d95bSToomas Soome (void) fprintf(stderr, gettext("error: setting boot " 13017855d95bSToomas Soome "partition size requires option '-B'\n")); 13027855d95bSToomas Soome goto errout; 13037855d95bSToomas Soome } 13047855d95bSToomas Soome } 13057855d95bSToomas Soome 1306fa9e4066Sahrens /* pass off to get_vdev_spec for bulk processing */ 13075711d393Sloli nvroot = make_root_vdev(NULL, props, force, !force, B_FALSE, dryrun, 13087855d95bSToomas Soome boot_type, boot_size, argc - 1, argv + 1); 1309fa9e4066Sahrens if (nvroot == NULL) 13100a48a24eStimh goto errout; 1311fa9e4066Sahrens 131299653d4eSeschrock /* make_root_vdev() allows 0 toplevel children if there are spares */ 1313b7b97454Sperrin if (!zfs_allocatable_devs(nvroot)) { 131499653d4eSeschrock (void) fprintf(stderr, gettext("invalid vdev " 131599653d4eSeschrock "specification: at least one toplevel vdev must be " 131699653d4eSeschrock "specified\n")); 1317990b4856Slling goto errout; 131899653d4eSeschrock } 131999653d4eSeschrock 1320fa9e4066Sahrens if (altroot != NULL && altroot[0] != '/') { 1321fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid alternate root '%s': " 1322e9dbad6fSeschrock "must be an absolute path\n"), altroot); 1323990b4856Slling goto errout; 1324fa9e4066Sahrens } 1325fa9e4066Sahrens 1326fa9e4066Sahrens /* 1327fa9e4066Sahrens * Check the validity of the mountpoint and direct the user to use the 1328fa9e4066Sahrens * '-m' mountpoint option if it looks like its in use. 1329fa9e4066Sahrens */ 1330fa9e4066Sahrens if (mountpoint == NULL || 1331fa9e4066Sahrens (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 1332fa9e4066Sahrens strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) { 1333fa9e4066Sahrens char buf[MAXPATHLEN]; 133411022c7cStimh DIR *dirp; 1335fa9e4066Sahrens 1336fa9e4066Sahrens if (mountpoint && mountpoint[0] != '/') { 1337fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid mountpoint " 1338fa9e4066Sahrens "'%s': must be an absolute path, 'legacy', or " 1339fa9e4066Sahrens "'none'\n"), mountpoint); 1340990b4856Slling goto errout; 1341fa9e4066Sahrens } 1342fa9e4066Sahrens 1343fa9e4066Sahrens if (mountpoint == NULL) { 1344fa9e4066Sahrens if (altroot != NULL) 1345fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s/%s", 1346fa9e4066Sahrens altroot, poolname); 1347fa9e4066Sahrens else 1348fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "/%s", 1349fa9e4066Sahrens poolname); 1350fa9e4066Sahrens } else { 1351fa9e4066Sahrens if (altroot != NULL) 1352fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s%s", 1353fa9e4066Sahrens altroot, mountpoint); 1354fa9e4066Sahrens else 1355fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s", 1356fa9e4066Sahrens mountpoint); 1357fa9e4066Sahrens } 1358fa9e4066Sahrens 135911022c7cStimh if ((dirp = opendir(buf)) == NULL && errno != ENOENT) { 136011022c7cStimh (void) fprintf(stderr, gettext("mountpoint '%s' : " 136111022c7cStimh "%s\n"), buf, strerror(errno)); 1362fa9e4066Sahrens (void) fprintf(stderr, gettext("use '-m' " 1363fa9e4066Sahrens "option to provide a different default\n")); 1364990b4856Slling goto errout; 136511022c7cStimh } else if (dirp) { 136611022c7cStimh int count = 0; 136711022c7cStimh 136811022c7cStimh while (count < 3 && readdir(dirp) != NULL) 136911022c7cStimh count++; 137011022c7cStimh (void) closedir(dirp); 137111022c7cStimh 137211022c7cStimh if (count > 2) { 137311022c7cStimh (void) fprintf(stderr, gettext("mountpoint " 137411022c7cStimh "'%s' exists and is not empty\n"), buf); 137511022c7cStimh (void) fprintf(stderr, gettext("use '-m' " 137611022c7cStimh "option to provide a " 137711022c7cStimh "different default\n")); 137811022c7cStimh goto errout; 137911022c7cStimh } 1380fa9e4066Sahrens } 1381fa9e4066Sahrens } 1382fa9e4066Sahrens 13838b713775SWill Andrews /* 13848b713775SWill Andrews * Now that the mountpoint's validity has been checked, ensure that 13858b713775SWill Andrews * the property is set appropriately prior to creating the pool. 13868b713775SWill Andrews */ 13878b713775SWill Andrews if (mountpoint != NULL) { 13888b713775SWill Andrews ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 13898b713775SWill Andrews mountpoint, &fsprops, B_FALSE); 13908b713775SWill Andrews if (ret != 0) 13918b713775SWill Andrews goto errout; 13928b713775SWill Andrews } 13938b713775SWill Andrews 13948b713775SWill Andrews ret = 1; 1395fa9e4066Sahrens if (dryrun) { 1396fa9e4066Sahrens /* 1397fa9e4066Sahrens * For a dry run invocation, print out a basic message and run 1398fa9e4066Sahrens * through all the vdevs in the list and print out in an 1399fa9e4066Sahrens * appropriate hierarchy. 1400fa9e4066Sahrens */ 1401fa9e4066Sahrens (void) printf(gettext("would create '%s' with the " 1402fa9e4066Sahrens "following layout:\n\n"), poolname); 1403fa9e4066Sahrens 1404663207adSDon Brady print_vdev_tree(NULL, poolname, nvroot, 0, "", 0); 1405663207adSDon Brady print_vdev_tree(NULL, "dedup", nvroot, 0, 1406663207adSDon Brady VDEV_ALLOC_BIAS_DEDUP, 0); 1407663207adSDon Brady print_vdev_tree(NULL, "special", nvroot, 0, 1408663207adSDon Brady VDEV_ALLOC_BIAS_SPECIAL, 0); 1409663207adSDon Brady print_vdev_tree(NULL, "logs", nvroot, 0, 1410663207adSDon Brady VDEV_ALLOC_BIAS_LOG, 0); 1411fa9e4066Sahrens 1412fa9e4066Sahrens ret = 0; 1413fa9e4066Sahrens } else { 1414fa9e4066Sahrens /* 1415fa9e4066Sahrens * Hand off to libzfs. 1416fa9e4066Sahrens */ 1417ad135b5dSChristopher Siden if (enable_all_pool_feat) { 14182acef22dSMatthew Ahrens spa_feature_t i; 1419ad135b5dSChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 1420ad135b5dSChristopher Siden char propname[MAXPATHLEN]; 1421ad135b5dSChristopher Siden zfeature_info_t *feat = &spa_feature_table[i]; 1422ad135b5dSChristopher Siden 1423ad135b5dSChristopher Siden (void) snprintf(propname, sizeof (propname), 1424ad135b5dSChristopher Siden "feature@%s", feat->fi_uname); 1425ad135b5dSChristopher Siden 1426ad135b5dSChristopher Siden /* 1427ad135b5dSChristopher Siden * Skip feature if user specified it manually 1428ad135b5dSChristopher Siden * on the command line. 1429ad135b5dSChristopher Siden */ 1430ad135b5dSChristopher Siden if (nvlist_exists(props, propname)) 1431ad135b5dSChristopher Siden continue; 1432ad135b5dSChristopher Siden 14338b713775SWill Andrews ret = add_prop_list(propname, 14348b713775SWill Andrews ZFS_FEATURE_ENABLED, &props, B_TRUE); 14358b713775SWill Andrews if (ret != 0) 1436ad135b5dSChristopher Siden goto errout; 1437ad135b5dSChristopher Siden } 1438ad135b5dSChristopher Siden } 14398b713775SWill Andrews 14408b713775SWill Andrews ret = 1; 14410a48a24eStimh if (zpool_create(g_zfs, poolname, 14420a48a24eStimh nvroot, props, fsprops) == 0) { 144304e56356SAndriy Gapon zfs_handle_t *pool = zfs_open(g_zfs, 144404e56356SAndriy Gapon tname ? tname : poolname, ZFS_TYPE_FILESYSTEM); 1445fa9e4066Sahrens if (pool != NULL) { 1446fa9e4066Sahrens if (zfs_mount(pool, NULL, 0) == 0) 1447da6c28aaSamw ret = zfs_shareall(pool); 1448fa9e4066Sahrens zfs_close(pool); 1449fa9e4066Sahrens } 145099653d4eSeschrock } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { 145199653d4eSeschrock (void) fprintf(stderr, gettext("pool name may have " 145299653d4eSeschrock "been omitted\n")); 1453fa9e4066Sahrens } 1454fa9e4066Sahrens } 1455fa9e4066Sahrens 1456990b4856Slling errout: 14572f8aaab3Seschrock nvlist_free(nvroot); 14580a48a24eStimh nvlist_free(fsprops); 14592f8aaab3Seschrock nvlist_free(props); 1460fa9e4066Sahrens return (ret); 1461990b4856Slling badusage: 14620a48a24eStimh nvlist_free(fsprops); 1463990b4856Slling nvlist_free(props); 1464990b4856Slling usage(B_FALSE); 1465990b4856Slling return (2); 1466fa9e4066Sahrens } 1467fa9e4066Sahrens 1468fa9e4066Sahrens /* 1469fa9e4066Sahrens * zpool destroy <pool> 1470fa9e4066Sahrens * 147104e56356SAndriy Gapon * -f Forcefully unmount any datasets 1472fa9e4066Sahrens * 1473fa9e4066Sahrens * Destroy the given pool. Automatically unmounts any datasets in the pool. 1474fa9e4066Sahrens */ 1475fa9e4066Sahrens int 1476fa9e4066Sahrens zpool_do_destroy(int argc, char **argv) 1477fa9e4066Sahrens { 147899653d4eSeschrock boolean_t force = B_FALSE; 1479fa9e4066Sahrens int c; 1480fa9e4066Sahrens char *pool; 1481fa9e4066Sahrens zpool_handle_t *zhp; 1482fa9e4066Sahrens int ret; 1483fa9e4066Sahrens 1484fa9e4066Sahrens /* check options */ 1485fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) { 1486fa9e4066Sahrens switch (c) { 1487fa9e4066Sahrens case 'f': 148899653d4eSeschrock force = B_TRUE; 1489fa9e4066Sahrens break; 1490fa9e4066Sahrens case '?': 1491fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1492fa9e4066Sahrens optopt); 149399653d4eSeschrock usage(B_FALSE); 1494fa9e4066Sahrens } 1495fa9e4066Sahrens } 1496fa9e4066Sahrens 1497fa9e4066Sahrens argc -= optind; 1498fa9e4066Sahrens argv += optind; 1499fa9e4066Sahrens 1500fa9e4066Sahrens /* check arguments */ 1501fa9e4066Sahrens if (argc < 1) { 1502fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool argument\n")); 150399653d4eSeschrock usage(B_FALSE); 1504fa9e4066Sahrens } 1505fa9e4066Sahrens if (argc > 1) { 1506fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 150799653d4eSeschrock usage(B_FALSE); 1508fa9e4066Sahrens } 1509fa9e4066Sahrens 1510fa9e4066Sahrens pool = argv[0]; 1511fa9e4066Sahrens 151299653d4eSeschrock if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 1513fa9e4066Sahrens /* 1514fa9e4066Sahrens * As a special case, check for use of '/' in the name, and 1515fa9e4066Sahrens * direct the user to use 'zfs destroy' instead. 1516fa9e4066Sahrens */ 1517fa9e4066Sahrens if (strchr(pool, '/') != NULL) 1518fa9e4066Sahrens (void) fprintf(stderr, gettext("use 'zfs destroy' to " 1519fa9e4066Sahrens "destroy a dataset\n")); 1520fa9e4066Sahrens return (1); 1521fa9e4066Sahrens } 1522fa9e4066Sahrens 1523f3861e1aSahl if (zpool_disable_datasets(zhp, force) != 0) { 1524fa9e4066Sahrens (void) fprintf(stderr, gettext("could not destroy '%s': " 1525fa9e4066Sahrens "could not unmount datasets\n"), zpool_get_name(zhp)); 1526fa9e4066Sahrens return (1); 1527fa9e4066Sahrens } 1528fa9e4066Sahrens 15294445fffbSMatthew Ahrens /* The history must be logged as part of the export */ 15304445fffbSMatthew Ahrens log_history = B_FALSE; 15314445fffbSMatthew Ahrens 15324445fffbSMatthew Ahrens ret = (zpool_destroy(zhp, history_str) != 0); 1533fa9e4066Sahrens 1534fa9e4066Sahrens zpool_close(zhp); 1535fa9e4066Sahrens 1536fa9e4066Sahrens return (ret); 1537fa9e4066Sahrens } 1538fa9e4066Sahrens 1539fa9e4066Sahrens /* 1540fa9e4066Sahrens * zpool export [-f] <pool> ... 1541fa9e4066Sahrens * 1542fa9e4066Sahrens * -f Forcefully unmount datasets 1543fa9e4066Sahrens * 1544b1b8ab34Slling * Export the given pools. By default, the command will attempt to cleanly 1545fa9e4066Sahrens * unmount any active datasets within the pool. If the '-f' flag is specified, 1546fa9e4066Sahrens * then the datasets will be forcefully unmounted. 1547fa9e4066Sahrens */ 1548fa9e4066Sahrens int 1549fa9e4066Sahrens zpool_do_export(int argc, char **argv) 1550fa9e4066Sahrens { 155199653d4eSeschrock boolean_t force = B_FALSE; 1552394ab0cbSGeorge Wilson boolean_t hardforce = B_FALSE; 1553fa9e4066Sahrens int c; 1554fa9e4066Sahrens zpool_handle_t *zhp; 1555fa9e4066Sahrens int ret; 1556fa9e4066Sahrens int i; 1557fa9e4066Sahrens 1558fa9e4066Sahrens /* check options */ 1559394ab0cbSGeorge Wilson while ((c = getopt(argc, argv, "fF")) != -1) { 1560fa9e4066Sahrens switch (c) { 1561fa9e4066Sahrens case 'f': 156299653d4eSeschrock force = B_TRUE; 1563fa9e4066Sahrens break; 1564394ab0cbSGeorge Wilson case 'F': 1565394ab0cbSGeorge Wilson hardforce = B_TRUE; 1566394ab0cbSGeorge Wilson break; 1567fa9e4066Sahrens case '?': 1568fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1569fa9e4066Sahrens optopt); 157099653d4eSeschrock usage(B_FALSE); 1571fa9e4066Sahrens } 1572fa9e4066Sahrens } 1573fa9e4066Sahrens 1574fa9e4066Sahrens argc -= optind; 1575fa9e4066Sahrens argv += optind; 1576fa9e4066Sahrens 1577fa9e4066Sahrens /* check arguments */ 1578fa9e4066Sahrens if (argc < 1) { 1579fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool argument\n")); 158099653d4eSeschrock usage(B_FALSE); 1581fa9e4066Sahrens } 1582fa9e4066Sahrens 1583fa9e4066Sahrens ret = 0; 1584fa9e4066Sahrens for (i = 0; i < argc; i++) { 158599653d4eSeschrock if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) { 1586fa9e4066Sahrens ret = 1; 1587fa9e4066Sahrens continue; 1588fa9e4066Sahrens } 1589fa9e4066Sahrens 1590f3861e1aSahl if (zpool_disable_datasets(zhp, force) != 0) { 1591fa9e4066Sahrens ret = 1; 1592fa9e4066Sahrens zpool_close(zhp); 1593fa9e4066Sahrens continue; 1594fa9e4066Sahrens } 1595fa9e4066Sahrens 15964445fffbSMatthew Ahrens /* The history must be logged as part of the export */ 15974445fffbSMatthew Ahrens log_history = B_FALSE; 15984445fffbSMatthew Ahrens 1599394ab0cbSGeorge Wilson if (hardforce) { 16004445fffbSMatthew Ahrens if (zpool_export_force(zhp, history_str) != 0) 1601394ab0cbSGeorge Wilson ret = 1; 16024445fffbSMatthew Ahrens } else if (zpool_export(zhp, force, history_str) != 0) { 1603fa9e4066Sahrens ret = 1; 1604394ab0cbSGeorge Wilson } 1605fa9e4066Sahrens 1606fa9e4066Sahrens zpool_close(zhp); 1607fa9e4066Sahrens } 1608fa9e4066Sahrens 1609fa9e4066Sahrens return (ret); 1610fa9e4066Sahrens } 1611fa9e4066Sahrens 1612fa9e4066Sahrens /* 1613fa9e4066Sahrens * Given a vdev configuration, determine the maximum width needed for the device 1614fa9e4066Sahrens * name column. 1615fa9e4066Sahrens */ 1616fa9e4066Sahrens static int 1617663207adSDon Brady max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max, 1618663207adSDon Brady int name_flags) 1619fa9e4066Sahrens { 1620663207adSDon Brady char *name; 1621fa9e4066Sahrens nvlist_t **child; 1622fa9e4066Sahrens uint_t c, children; 1623fa9e4066Sahrens int ret; 1624fa9e4066Sahrens 1625663207adSDon Brady name = zpool_vdev_name(g_zfs, zhp, nv, name_flags | VDEV_NAME_TYPE_ID); 1626fa9e4066Sahrens if (strlen(name) + depth > max) 1627fa9e4066Sahrens max = strlen(name) + depth; 1628fa9e4066Sahrens 1629afefbcddSeschrock free(name); 1630afefbcddSeschrock 163199653d4eSeschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 163299653d4eSeschrock &child, &children) == 0) { 163399653d4eSeschrock for (c = 0; c < children; c++) 163499653d4eSeschrock if ((ret = max_width(zhp, child[c], depth + 2, 1635663207adSDon Brady max, name_flags)) > max) 163699653d4eSeschrock max = ret; 163799653d4eSeschrock } 163899653d4eSeschrock 1639fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1640fa94a07fSbrendan &child, &children) == 0) { 1641fa94a07fSbrendan for (c = 0; c < children; c++) 1642fa94a07fSbrendan if ((ret = max_width(zhp, child[c], depth + 2, 1643663207adSDon Brady max, name_flags)) > max) 1644fa94a07fSbrendan max = ret; 1645fa94a07fSbrendan } 1646fa94a07fSbrendan 1647fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 164899653d4eSeschrock &child, &children) == 0) { 164999653d4eSeschrock for (c = 0; c < children; c++) 165099653d4eSeschrock if ((ret = max_width(zhp, child[c], depth + 2, 1651663207adSDon Brady max, name_flags)) > max) 165299653d4eSeschrock max = ret; 165399653d4eSeschrock } 1654fa9e4066Sahrens 1655fa9e4066Sahrens return (max); 1656fa9e4066Sahrens } 1657fa9e4066Sahrens 1658e6ca193dSGeorge Wilson typedef struct spare_cbdata { 1659e6ca193dSGeorge Wilson uint64_t cb_guid; 1660e6ca193dSGeorge Wilson zpool_handle_t *cb_zhp; 1661e6ca193dSGeorge Wilson } spare_cbdata_t; 1662e6ca193dSGeorge Wilson 1663e6ca193dSGeorge Wilson static boolean_t 1664e6ca193dSGeorge Wilson find_vdev(nvlist_t *nv, uint64_t search) 1665e6ca193dSGeorge Wilson { 1666e6ca193dSGeorge Wilson uint64_t guid; 1667e6ca193dSGeorge Wilson nvlist_t **child; 1668e6ca193dSGeorge Wilson uint_t c, children; 1669e6ca193dSGeorge Wilson 1670e6ca193dSGeorge Wilson if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 1671e6ca193dSGeorge Wilson search == guid) 1672e6ca193dSGeorge Wilson return (B_TRUE); 1673e6ca193dSGeorge Wilson 1674e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1675e6ca193dSGeorge Wilson &child, &children) == 0) { 1676e6ca193dSGeorge Wilson for (c = 0; c < children; c++) 1677e6ca193dSGeorge Wilson if (find_vdev(child[c], search)) 1678e6ca193dSGeorge Wilson return (B_TRUE); 1679e6ca193dSGeorge Wilson } 1680e6ca193dSGeorge Wilson 1681e6ca193dSGeorge Wilson return (B_FALSE); 1682e6ca193dSGeorge Wilson } 1683e6ca193dSGeorge Wilson 1684e6ca193dSGeorge Wilson static int 1685e6ca193dSGeorge Wilson find_spare(zpool_handle_t *zhp, void *data) 1686e6ca193dSGeorge Wilson { 1687e6ca193dSGeorge Wilson spare_cbdata_t *cbp = data; 1688e6ca193dSGeorge Wilson nvlist_t *config, *nvroot; 1689e6ca193dSGeorge Wilson 1690e6ca193dSGeorge Wilson config = zpool_get_config(zhp, NULL); 1691e6ca193dSGeorge Wilson verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1692e6ca193dSGeorge Wilson &nvroot) == 0); 1693e6ca193dSGeorge Wilson 1694e6ca193dSGeorge Wilson if (find_vdev(nvroot, cbp->cb_guid)) { 1695e6ca193dSGeorge Wilson cbp->cb_zhp = zhp; 1696e6ca193dSGeorge Wilson return (1); 1697e6ca193dSGeorge Wilson } 1698e6ca193dSGeorge Wilson 1699e6ca193dSGeorge Wilson zpool_close(zhp); 1700e6ca193dSGeorge Wilson return (0); 1701e6ca193dSGeorge Wilson } 1702e6ca193dSGeorge Wilson 1703663207adSDon Brady typedef struct status_cbdata { 1704663207adSDon Brady int cb_count; 1705663207adSDon Brady int cb_name_flags; 1706663207adSDon Brady int cb_namewidth; 1707663207adSDon Brady boolean_t cb_allpools; 1708663207adSDon Brady boolean_t cb_verbose; 1709dd50e0ccSTony Hutter boolean_t cb_literal; 1710663207adSDon Brady boolean_t cb_explain; 1711663207adSDon Brady boolean_t cb_first; 1712663207adSDon Brady boolean_t cb_dedup_stats; 1713663207adSDon Brady boolean_t cb_print_status; 1714dd50e0ccSTony Hutter boolean_t cb_print_slow_ios; 1715084fd14fSBrian Behlendorf boolean_t cb_print_vdev_init; 1716084fd14fSBrian Behlendorf boolean_t cb_print_vdev_trim; 1717663207adSDon Brady } status_cbdata_t; 1718663207adSDon Brady 1719084fd14fSBrian Behlendorf /* 1720084fd14fSBrian Behlendorf * Print vdev initialization status for leaves 1721084fd14fSBrian Behlendorf */ 1722084fd14fSBrian Behlendorf static void 1723084fd14fSBrian Behlendorf print_status_initialize(vdev_stat_t *vs, boolean_t verbose) 1724084fd14fSBrian Behlendorf { 1725084fd14fSBrian Behlendorf if (verbose) { 1726084fd14fSBrian Behlendorf if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE || 1727084fd14fSBrian Behlendorf vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED || 1728084fd14fSBrian Behlendorf vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) && 1729084fd14fSBrian Behlendorf !vs->vs_scan_removing) { 1730084fd14fSBrian Behlendorf char zbuf[1024]; 1731084fd14fSBrian Behlendorf char tbuf[256]; 1732084fd14fSBrian Behlendorf struct tm zaction_ts; 1733084fd14fSBrian Behlendorf 1734084fd14fSBrian Behlendorf time_t t = vs->vs_initialize_action_time; 1735084fd14fSBrian Behlendorf int initialize_pct = 100; 1736084fd14fSBrian Behlendorf if (vs->vs_initialize_state != 1737084fd14fSBrian Behlendorf VDEV_INITIALIZE_COMPLETE) { 1738084fd14fSBrian Behlendorf initialize_pct = (vs->vs_initialize_bytes_done * 1739084fd14fSBrian Behlendorf 100 / (vs->vs_initialize_bytes_est + 1)); 1740084fd14fSBrian Behlendorf } 1741084fd14fSBrian Behlendorf 1742084fd14fSBrian Behlendorf (void) localtime_r(&t, &zaction_ts); 1743084fd14fSBrian Behlendorf (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts); 1744084fd14fSBrian Behlendorf 1745084fd14fSBrian Behlendorf switch (vs->vs_initialize_state) { 1746084fd14fSBrian Behlendorf case VDEV_INITIALIZE_SUSPENDED: 1747084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 1748084fd14fSBrian Behlendorf gettext("suspended, started at"), tbuf); 1749084fd14fSBrian Behlendorf break; 1750084fd14fSBrian Behlendorf case VDEV_INITIALIZE_ACTIVE: 1751084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 1752084fd14fSBrian Behlendorf gettext("started at"), tbuf); 1753084fd14fSBrian Behlendorf break; 1754084fd14fSBrian Behlendorf case VDEV_INITIALIZE_COMPLETE: 1755084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 1756084fd14fSBrian Behlendorf gettext("completed at"), tbuf); 1757084fd14fSBrian Behlendorf break; 1758084fd14fSBrian Behlendorf } 1759084fd14fSBrian Behlendorf 1760084fd14fSBrian Behlendorf (void) printf(gettext(" (%d%% initialized%s)"), 1761084fd14fSBrian Behlendorf initialize_pct, zbuf); 1762084fd14fSBrian Behlendorf } else { 1763084fd14fSBrian Behlendorf (void) printf(gettext(" (uninitialized)")); 1764084fd14fSBrian Behlendorf } 1765084fd14fSBrian Behlendorf } else if (vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE) { 1766084fd14fSBrian Behlendorf (void) printf(gettext(" (initializing)")); 1767084fd14fSBrian Behlendorf } 1768084fd14fSBrian Behlendorf } 1769084fd14fSBrian Behlendorf 1770084fd14fSBrian Behlendorf /* 1771084fd14fSBrian Behlendorf * Print vdev TRIM status for leaves 1772084fd14fSBrian Behlendorf */ 1773084fd14fSBrian Behlendorf static void 1774084fd14fSBrian Behlendorf print_status_trim(vdev_stat_t *vs, boolean_t verbose) 1775084fd14fSBrian Behlendorf { 1776084fd14fSBrian Behlendorf if (verbose) { 1777084fd14fSBrian Behlendorf if ((vs->vs_trim_state == VDEV_TRIM_ACTIVE || 1778084fd14fSBrian Behlendorf vs->vs_trim_state == VDEV_TRIM_SUSPENDED || 1779084fd14fSBrian Behlendorf vs->vs_trim_state == VDEV_TRIM_COMPLETE) && 1780084fd14fSBrian Behlendorf !vs->vs_scan_removing) { 1781084fd14fSBrian Behlendorf char zbuf[1024]; 1782084fd14fSBrian Behlendorf char tbuf[256]; 1783084fd14fSBrian Behlendorf struct tm zaction_ts; 1784084fd14fSBrian Behlendorf 1785084fd14fSBrian Behlendorf time_t t = vs->vs_trim_action_time; 1786084fd14fSBrian Behlendorf int trim_pct = 100; 1787084fd14fSBrian Behlendorf if (vs->vs_trim_state != VDEV_TRIM_COMPLETE) { 1788084fd14fSBrian Behlendorf trim_pct = (vs->vs_trim_bytes_done * 1789084fd14fSBrian Behlendorf 100 / (vs->vs_trim_bytes_est + 1)); 1790084fd14fSBrian Behlendorf } 1791084fd14fSBrian Behlendorf 1792084fd14fSBrian Behlendorf (void) localtime_r(&t, &zaction_ts); 1793084fd14fSBrian Behlendorf (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts); 1794084fd14fSBrian Behlendorf 1795084fd14fSBrian Behlendorf switch (vs->vs_trim_state) { 1796084fd14fSBrian Behlendorf case VDEV_TRIM_SUSPENDED: 1797084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 1798084fd14fSBrian Behlendorf gettext("suspended, started at"), tbuf); 1799084fd14fSBrian Behlendorf break; 1800084fd14fSBrian Behlendorf case VDEV_TRIM_ACTIVE: 1801084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 1802084fd14fSBrian Behlendorf gettext("started at"), tbuf); 1803084fd14fSBrian Behlendorf break; 1804084fd14fSBrian Behlendorf case VDEV_TRIM_COMPLETE: 1805084fd14fSBrian Behlendorf (void) snprintf(zbuf, sizeof (zbuf), ", %s %s", 1806084fd14fSBrian Behlendorf gettext("completed at"), tbuf); 1807084fd14fSBrian Behlendorf break; 1808084fd14fSBrian Behlendorf } 1809084fd14fSBrian Behlendorf 1810084fd14fSBrian Behlendorf (void) printf(gettext(" (%d%% trimmed%s)"), 1811084fd14fSBrian Behlendorf trim_pct, zbuf); 1812084fd14fSBrian Behlendorf } else if (vs->vs_trim_notsup) { 1813084fd14fSBrian Behlendorf (void) printf(gettext(" (trim unsupported)")); 1814084fd14fSBrian Behlendorf } else { 1815084fd14fSBrian Behlendorf (void) printf(gettext(" (untrimmed)")); 1816084fd14fSBrian Behlendorf } 1817084fd14fSBrian Behlendorf } else if (vs->vs_trim_state == VDEV_TRIM_ACTIVE) { 1818084fd14fSBrian Behlendorf (void) printf(gettext(" (trimming)")); 1819084fd14fSBrian Behlendorf } 1820084fd14fSBrian Behlendorf } 1821084fd14fSBrian Behlendorf 1822e6ca193dSGeorge Wilson /* 1823e6ca193dSGeorge Wilson * Print out configuration state as requested by status_callback. 1824e6ca193dSGeorge Wilson */ 1825663207adSDon Brady static void 1826663207adSDon Brady print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name, 1827663207adSDon Brady nvlist_t *nv, int depth, boolean_t isspare) 1828e6ca193dSGeorge Wilson { 182964dee23eSTony Hutter nvlist_t **child, *root; 1830e6ca193dSGeorge Wilson uint_t c, children; 18313f9d6ad7SLin Ling pool_scan_stat_t *ps = NULL; 1832e6ca193dSGeorge Wilson vdev_stat_t *vs; 18333f9d6ad7SLin Ling char rbuf[6], wbuf[6], cbuf[6]; 1834e6ca193dSGeorge Wilson char *vname; 1835e6ca193dSGeorge Wilson uint64_t notpresent; 1836663207adSDon Brady spare_cbdata_t spare_cb; 18376401734dSWill Andrews const char *state; 18385cabbc6bSPrashanth Sreenivasa char *type; 1839e6ca193dSGeorge Wilson 1840e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1841e6ca193dSGeorge Wilson &child, &children) != 0) 1842e6ca193dSGeorge Wilson children = 0; 1843e6ca193dSGeorge Wilson 18443f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 18453f9d6ad7SLin Ling (uint64_t **)&vs, &c) == 0); 18463f9d6ad7SLin Ling 18475cabbc6bSPrashanth Sreenivasa verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 18485cabbc6bSPrashanth Sreenivasa 18495cabbc6bSPrashanth Sreenivasa if (strcmp(type, VDEV_TYPE_INDIRECT) == 0) 18505cabbc6bSPrashanth Sreenivasa return; 18515cabbc6bSPrashanth Sreenivasa 1852e6ca193dSGeorge Wilson state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1853e6ca193dSGeorge Wilson if (isspare) { 1854e6ca193dSGeorge Wilson /* 1855e6ca193dSGeorge Wilson * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 1856e6ca193dSGeorge Wilson * online drives. 1857e6ca193dSGeorge Wilson */ 1858e6ca193dSGeorge Wilson if (vs->vs_aux == VDEV_AUX_SPARED) 1859e6ca193dSGeorge Wilson state = "INUSE"; 1860e6ca193dSGeorge Wilson else if (vs->vs_state == VDEV_STATE_HEALTHY) 1861e6ca193dSGeorge Wilson state = "AVAIL"; 1862e6ca193dSGeorge Wilson } 1863e6ca193dSGeorge Wilson 1864663207adSDon Brady (void) printf("\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth, 1865e6ca193dSGeorge Wilson name, state); 1866e6ca193dSGeorge Wilson 1867e6ca193dSGeorge Wilson if (!isspare) { 1868dd50e0ccSTony Hutter if (cb->cb_literal) { 1869dd50e0ccSTony Hutter printf(" %5llu %5llu %5llu", 1870dd50e0ccSTony Hutter (u_longlong_t)vs->vs_read_errors, 1871dd50e0ccSTony Hutter (u_longlong_t)vs->vs_write_errors, 1872dd50e0ccSTony Hutter (u_longlong_t)vs->vs_checksum_errors); 1873dd50e0ccSTony Hutter } else { 1874dd50e0ccSTony Hutter zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 1875dd50e0ccSTony Hutter zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 1876dd50e0ccSTony Hutter zfs_nicenum(vs->vs_checksum_errors, cbuf, 1877dd50e0ccSTony Hutter sizeof (cbuf)); 1878dd50e0ccSTony Hutter printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 1879dd50e0ccSTony Hutter } 1880dd50e0ccSTony Hutter 1881dd50e0ccSTony Hutter if (cb->cb_print_slow_ios) { 1882dd50e0ccSTony Hutter if (children == 0) { 1883dd50e0ccSTony Hutter /* Only leafs vdevs have slow IOs */ 1884dd50e0ccSTony Hutter zfs_nicenum(vs->vs_slow_ios, rbuf, 1885dd50e0ccSTony Hutter sizeof (rbuf)); 1886dd50e0ccSTony Hutter } else { 1887dd50e0ccSTony Hutter (void) snprintf(rbuf, sizeof (rbuf), "-"); 1888dd50e0ccSTony Hutter } 1889dd50e0ccSTony Hutter 1890dd50e0ccSTony Hutter if (cb->cb_literal) 1891dd50e0ccSTony Hutter printf(" %5llu", (u_longlong_t)vs->vs_slow_ios); 1892dd50e0ccSTony Hutter else 1893dd50e0ccSTony Hutter printf(" %5s", rbuf); 1894dd50e0ccSTony Hutter } 1895dd50e0ccSTony Hutter 1896e6ca193dSGeorge Wilson } 1897e6ca193dSGeorge Wilson 1898e6ca193dSGeorge Wilson if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1899e6ca193dSGeorge Wilson ¬present) == 0) { 1900e6ca193dSGeorge Wilson char *path; 1901e6ca193dSGeorge Wilson verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 1902e6ca193dSGeorge Wilson (void) printf(" was %s", path); 1903e6ca193dSGeorge Wilson } else if (vs->vs_aux != 0) { 1904e6ca193dSGeorge Wilson (void) printf(" "); 1905e6ca193dSGeorge Wilson 1906e6ca193dSGeorge Wilson switch (vs->vs_aux) { 1907e6ca193dSGeorge Wilson case VDEV_AUX_OPEN_FAILED: 1908e6ca193dSGeorge Wilson (void) printf(gettext("cannot open")); 1909e6ca193dSGeorge Wilson break; 1910e6ca193dSGeorge Wilson 1911e6ca193dSGeorge Wilson case VDEV_AUX_BAD_GUID_SUM: 1912e6ca193dSGeorge Wilson (void) printf(gettext("missing device")); 1913e6ca193dSGeorge Wilson break; 1914e6ca193dSGeorge Wilson 1915e6ca193dSGeorge Wilson case VDEV_AUX_NO_REPLICAS: 1916e6ca193dSGeorge Wilson (void) printf(gettext("insufficient replicas")); 1917e6ca193dSGeorge Wilson break; 1918e6ca193dSGeorge Wilson 1919e6ca193dSGeorge Wilson case VDEV_AUX_VERSION_NEWER: 1920e6ca193dSGeorge Wilson (void) printf(gettext("newer version")); 1921e6ca193dSGeorge Wilson break; 1922e6ca193dSGeorge Wilson 1923ad135b5dSChristopher Siden case VDEV_AUX_UNSUP_FEAT: 1924ad135b5dSChristopher Siden (void) printf(gettext("unsupported feature(s)")); 1925ad135b5dSChristopher Siden break; 1926ad135b5dSChristopher Siden 1927e6ca193dSGeorge Wilson case VDEV_AUX_SPARED: 1928e6ca193dSGeorge Wilson verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 1929663207adSDon Brady &spare_cb.cb_guid) == 0); 1930663207adSDon Brady if (zpool_iter(g_zfs, find_spare, &spare_cb) == 1) { 1931663207adSDon Brady if (strcmp(zpool_get_name(spare_cb.cb_zhp), 1932e6ca193dSGeorge Wilson zpool_get_name(zhp)) == 0) 1933e6ca193dSGeorge Wilson (void) printf(gettext("currently in " 1934e6ca193dSGeorge Wilson "use")); 1935e6ca193dSGeorge Wilson else 1936e6ca193dSGeorge Wilson (void) printf(gettext("in use by " 1937e6ca193dSGeorge Wilson "pool '%s'"), 1938663207adSDon Brady zpool_get_name(spare_cb.cb_zhp)); 1939663207adSDon Brady zpool_close(spare_cb.cb_zhp); 1940e6ca193dSGeorge Wilson } else { 1941e6ca193dSGeorge Wilson (void) printf(gettext("currently in use")); 1942e6ca193dSGeorge Wilson } 1943e6ca193dSGeorge Wilson break; 1944e6ca193dSGeorge Wilson 1945e6ca193dSGeorge Wilson case VDEV_AUX_ERR_EXCEEDED: 1946e6ca193dSGeorge Wilson (void) printf(gettext("too many errors")); 1947e6ca193dSGeorge Wilson break; 1948e6ca193dSGeorge Wilson 1949e6ca193dSGeorge Wilson case VDEV_AUX_IO_FAILURE: 1950e6ca193dSGeorge Wilson (void) printf(gettext("experienced I/O failures")); 1951e6ca193dSGeorge Wilson break; 1952e6ca193dSGeorge Wilson 1953e6ca193dSGeorge Wilson case VDEV_AUX_BAD_LOG: 1954e6ca193dSGeorge Wilson (void) printf(gettext("bad intent log")); 1955e6ca193dSGeorge Wilson break; 1956e6ca193dSGeorge Wilson 1957069f55e2SEric Schrock case VDEV_AUX_EXTERNAL: 1958069f55e2SEric Schrock (void) printf(gettext("external device fault")); 1959069f55e2SEric Schrock break; 1960069f55e2SEric Schrock 19611195e687SMark J Musante case VDEV_AUX_SPLIT_POOL: 19621195e687SMark J Musante (void) printf(gettext("split into new pool")); 19631195e687SMark J Musante break; 19641195e687SMark J Musante 1965e0f1c0afSOlaf Faaland case VDEV_AUX_ACTIVE: 1966e0f1c0afSOlaf Faaland (void) printf(gettext("currently in use")); 1967e0f1c0afSOlaf Faaland break; 1968e0f1c0afSOlaf Faaland 19696f793812SPavel Zakharov case VDEV_AUX_CHILDREN_OFFLINE: 19706f793812SPavel Zakharov (void) printf(gettext("all children offline")); 19716f793812SPavel Zakharov break; 19726f793812SPavel Zakharov 1973e6ca193dSGeorge Wilson default: 1974e6ca193dSGeorge Wilson (void) printf(gettext("corrupted data")); 1975e6ca193dSGeorge Wilson break; 1976e6ca193dSGeorge Wilson } 19773f9d6ad7SLin Ling } 19783f9d6ad7SLin Ling 197964dee23eSTony Hutter /* The root vdev has the scrub/resilver stats */ 198064dee23eSTony Hutter root = fnvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 198164dee23eSTony Hutter ZPOOL_CONFIG_VDEV_TREE); 198264dee23eSTony Hutter (void) nvlist_lookup_uint64_array(root, ZPOOL_CONFIG_SCAN_STATS, 19833f9d6ad7SLin Ling (uint64_t **)&ps, &c); 19843f9d6ad7SLin Ling 1985e4c795beSTom Caputi if (ps != NULL && ps->pss_state == DSS_SCANNING && children == 0) { 1986e4c795beSTom Caputi if (vs->vs_scan_processed != 0) { 1987e4c795beSTom Caputi (void) printf(gettext(" (%s)"), 1988e4c795beSTom Caputi (ps->pss_func == POOL_SCAN_RESILVER) ? 1989e4c795beSTom Caputi "resilvering" : "repairing"); 1990e4c795beSTom Caputi } else if (vs->vs_resilver_deferred) { 1991e4c795beSTom Caputi (void) printf(gettext(" (awaiting resilver)")); 1992e4c795beSTom Caputi } 1993e6ca193dSGeorge Wilson } 1994e6ca193dSGeorge Wilson 1995084fd14fSBrian Behlendorf /* Display vdev initialization and trim status for leaves */ 1996084fd14fSBrian Behlendorf if (children == 0) { 1997084fd14fSBrian Behlendorf print_status_initialize(vs, cb->cb_print_vdev_init); 1998084fd14fSBrian Behlendorf print_status_trim(vs, cb->cb_print_vdev_trim); 1999094e47e9SGeorge Wilson } 2000094e47e9SGeorge Wilson 2001e6ca193dSGeorge Wilson (void) printf("\n"); 2002e6ca193dSGeorge Wilson 2003e6ca193dSGeorge Wilson for (c = 0; c < children; c++) { 200488ecc943SGeorge Wilson uint64_t islog = B_FALSE, ishole = B_FALSE; 2005e6ca193dSGeorge Wilson 200688ecc943SGeorge Wilson /* Don't print logs or holes here */ 2007e6ca193dSGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 200888ecc943SGeorge Wilson &islog); 200988ecc943SGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, 201088ecc943SGeorge Wilson &ishole); 201188ecc943SGeorge Wilson if (islog || ishole) 2012e6ca193dSGeorge Wilson continue; 2013663207adSDon Brady /* Only print normal classes here */ 2014663207adSDon Brady if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 2015663207adSDon Brady continue; 2016663207adSDon Brady 2017663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 2018663207adSDon Brady cb->cb_name_flags | VDEV_NAME_TYPE_ID); 201964dee23eSTony Hutter 2020663207adSDon Brady print_status_config(zhp, cb, vname, child[c], depth + 2, 2021663207adSDon Brady isspare); 2022e6ca193dSGeorge Wilson free(vname); 2023e6ca193dSGeorge Wilson } 2024e6ca193dSGeorge Wilson } 2025e6ca193dSGeorge Wilson 2026fa9e4066Sahrens /* 2027fa9e4066Sahrens * Print the configuration of an exported pool. Iterate over all vdevs in the 2028fa9e4066Sahrens * pool, printing out the name and status for each one. 2029fa9e4066Sahrens */ 2030663207adSDon Brady static void 2031663207adSDon Brady print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv, 2032663207adSDon Brady int depth) 2033fa9e4066Sahrens { 2034fa9e4066Sahrens nvlist_t **child; 2035fa9e4066Sahrens uint_t c, children; 2036fa9e4066Sahrens vdev_stat_t *vs; 2037afefbcddSeschrock char *type, *vname; 2038fa9e4066Sahrens 2039fa9e4066Sahrens verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 204088ecc943SGeorge Wilson if (strcmp(type, VDEV_TYPE_MISSING) == 0 || 204188ecc943SGeorge Wilson strcmp(type, VDEV_TYPE_HOLE) == 0) 2042fa9e4066Sahrens return; 2043fa9e4066Sahrens 20443f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 2045fa9e4066Sahrens (uint64_t **)&vs, &c) == 0); 2046fa9e4066Sahrens 2047663207adSDon Brady (void) printf("\t%*s%-*s", depth, "", cb->cb_namewidth - depth, name); 2048990b4856Slling (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); 2049fa9e4066Sahrens 2050fa9e4066Sahrens if (vs->vs_aux != 0) { 20513d7072f8Seschrock (void) printf(" "); 2052fa9e4066Sahrens 2053fa9e4066Sahrens switch (vs->vs_aux) { 2054fa9e4066Sahrens case VDEV_AUX_OPEN_FAILED: 2055fa9e4066Sahrens (void) printf(gettext("cannot open")); 2056fa9e4066Sahrens break; 2057fa9e4066Sahrens 2058fa9e4066Sahrens case VDEV_AUX_BAD_GUID_SUM: 2059fa9e4066Sahrens (void) printf(gettext("missing device")); 2060fa9e4066Sahrens break; 2061fa9e4066Sahrens 2062fa9e4066Sahrens case VDEV_AUX_NO_REPLICAS: 2063fa9e4066Sahrens (void) printf(gettext("insufficient replicas")); 2064fa9e4066Sahrens break; 2065fa9e4066Sahrens 2066eaca9bbdSeschrock case VDEV_AUX_VERSION_NEWER: 2067eaca9bbdSeschrock (void) printf(gettext("newer version")); 2068eaca9bbdSeschrock break; 2069eaca9bbdSeschrock 2070ad135b5dSChristopher Siden case VDEV_AUX_UNSUP_FEAT: 2071ad135b5dSChristopher Siden (void) printf(gettext("unsupported feature(s)")); 2072ad135b5dSChristopher Siden break; 2073ad135b5dSChristopher Siden 20743d7072f8Seschrock case VDEV_AUX_ERR_EXCEEDED: 20753d7072f8Seschrock (void) printf(gettext("too many errors")); 20763d7072f8Seschrock break; 20773d7072f8Seschrock 2078e0f1c0afSOlaf Faaland case VDEV_AUX_ACTIVE: 2079e0f1c0afSOlaf Faaland (void) printf(gettext("currently in use")); 2080e0f1c0afSOlaf Faaland break; 2081e0f1c0afSOlaf Faaland 20826f793812SPavel Zakharov case VDEV_AUX_CHILDREN_OFFLINE: 20836f793812SPavel Zakharov (void) printf(gettext("all children offline")); 20846f793812SPavel Zakharov break; 20856f793812SPavel Zakharov 2086fa9e4066Sahrens default: 2087fa9e4066Sahrens (void) printf(gettext("corrupted data")); 2088fa9e4066Sahrens break; 2089fa9e4066Sahrens } 2090fa9e4066Sahrens } 2091fa9e4066Sahrens (void) printf("\n"); 2092fa9e4066Sahrens 2093fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2094fa9e4066Sahrens &child, &children) != 0) 2095fa9e4066Sahrens return; 2096fa9e4066Sahrens 2097afefbcddSeschrock for (c = 0; c < children; c++) { 20988654d025Sperrin uint64_t is_log = B_FALSE; 20998654d025Sperrin 21008654d025Sperrin (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 21018654d025Sperrin &is_log); 2102e6ca193dSGeorge Wilson if (is_log) 21038654d025Sperrin continue; 2104663207adSDon Brady if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 2105663207adSDon Brady continue; 21068654d025Sperrin 2107663207adSDon Brady vname = zpool_vdev_name(g_zfs, NULL, child[c], 2108663207adSDon Brady cb->cb_name_flags | VDEV_NAME_TYPE_ID); 2109663207adSDon Brady print_import_config(cb, vname, child[c], depth + 2); 2110afefbcddSeschrock free(vname); 2111afefbcddSeschrock } 211299653d4eSeschrock 2113fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 2114fa94a07fSbrendan &child, &children) == 0) { 2115fa94a07fSbrendan (void) printf(gettext("\tcache\n")); 2116fa94a07fSbrendan for (c = 0; c < children; c++) { 2117663207adSDon Brady vname = zpool_vdev_name(g_zfs, NULL, child[c], 2118663207adSDon Brady cb->cb_name_flags); 2119fa94a07fSbrendan (void) printf("\t %s\n", vname); 2120fa94a07fSbrendan free(vname); 2121fa94a07fSbrendan } 2122fa94a07fSbrendan } 212399653d4eSeschrock 2124fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 2125fa94a07fSbrendan &child, &children) == 0) { 2126fa94a07fSbrendan (void) printf(gettext("\tspares\n")); 2127fa94a07fSbrendan for (c = 0; c < children; c++) { 2128663207adSDon Brady vname = zpool_vdev_name(g_zfs, NULL, child[c], 2129663207adSDon Brady cb->cb_name_flags); 2130fa94a07fSbrendan (void) printf("\t %s\n", vname); 2131fa94a07fSbrendan free(vname); 2132fa94a07fSbrendan } 213399653d4eSeschrock } 2134fa9e4066Sahrens } 2135fa9e4066Sahrens 2136e6ca193dSGeorge Wilson /* 2137663207adSDon Brady * Print specialized class vdevs. 2138663207adSDon Brady * 2139663207adSDon Brady * These are recorded as top level vdevs in the main pool child array 2140663207adSDon Brady * but with "is_log" set to 1 or an "alloc_bias" string. We use either 2141663207adSDon Brady * print_status_config() or print_import_config() to print the top level 2142663207adSDon Brady * class vdevs then any of their children (eg mirrored slogs) are printed 2143663207adSDon Brady * recursively - which works because only the top level vdev is marked. 2144e6ca193dSGeorge Wilson */ 2145e6ca193dSGeorge Wilson static void 2146663207adSDon Brady print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv, 2147663207adSDon Brady const char *class) 2148e6ca193dSGeorge Wilson { 2149e6ca193dSGeorge Wilson uint_t c, children; 2150e6ca193dSGeorge Wilson nvlist_t **child; 2151663207adSDon Brady boolean_t printed = B_FALSE; 2152663207adSDon Brady 2153663207adSDon Brady assert(zhp != NULL || !cb->cb_verbose); 2154e6ca193dSGeorge Wilson 2155e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, 2156e6ca193dSGeorge Wilson &children) != 0) 2157e6ca193dSGeorge Wilson return; 2158e6ca193dSGeorge Wilson 2159e6ca193dSGeorge Wilson for (c = 0; c < children; c++) { 2160e6ca193dSGeorge Wilson uint64_t is_log = B_FALSE; 2161663207adSDon Brady char *bias = NULL; 2162663207adSDon Brady char *type = NULL; 2163e6ca193dSGeorge Wilson 2164e6ca193dSGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 2165e6ca193dSGeorge Wilson &is_log); 2166663207adSDon Brady 2167663207adSDon Brady if (is_log) { 2168663207adSDon Brady bias = VDEV_ALLOC_CLASS_LOGS; 2169663207adSDon Brady } else { 2170663207adSDon Brady (void) nvlist_lookup_string(child[c], 2171663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &bias); 2172663207adSDon Brady (void) nvlist_lookup_string(child[c], 2173663207adSDon Brady ZPOOL_CONFIG_TYPE, &type); 2174663207adSDon Brady } 2175663207adSDon Brady 2176663207adSDon Brady if (bias == NULL || strcmp(bias, class) != 0) 2177e6ca193dSGeorge Wilson continue; 2178663207adSDon Brady if (!is_log && strcmp(type, VDEV_TYPE_INDIRECT) == 0) 2179663207adSDon Brady continue; 2180663207adSDon Brady 2181663207adSDon Brady if (!printed) { 2182663207adSDon Brady (void) printf("\t%s\t\n", gettext(class)); 2183663207adSDon Brady printed = B_TRUE; 2184663207adSDon Brady } 2185663207adSDon Brady 2186663207adSDon Brady char *name = zpool_vdev_name(g_zfs, zhp, child[c], 2187663207adSDon Brady cb->cb_name_flags | VDEV_NAME_TYPE_ID); 2188663207adSDon Brady if (cb->cb_print_status) 2189663207adSDon Brady print_status_config(zhp, cb, name, child[c], 2, 2190663207adSDon Brady B_FALSE); 2191e6ca193dSGeorge Wilson else 2192663207adSDon Brady print_import_config(cb, name, child[c], 2); 2193e6ca193dSGeorge Wilson free(name); 2194e6ca193dSGeorge Wilson } 2195e6ca193dSGeorge Wilson } 2196468c413aSTim Haley 2197fa9e4066Sahrens /* 2198fa9e4066Sahrens * Display the status for the given pool. 2199fa9e4066Sahrens */ 2200fa9e4066Sahrens static void 2201fa9e4066Sahrens show_import(nvlist_t *config) 2202fa9e4066Sahrens { 2203fa9e4066Sahrens uint64_t pool_state; 2204fa9e4066Sahrens vdev_stat_t *vs; 2205fa9e4066Sahrens char *name; 2206fa9e4066Sahrens uint64_t guid; 2207e0f1c0afSOlaf Faaland uint64_t hostid = 0; 2208fa9e4066Sahrens char *msgid; 2209e0f1c0afSOlaf Faaland char *hostname = "unknown"; 2210e0f1c0afSOlaf Faaland nvlist_t *nvroot, *nvinfo; 2211fa9e4066Sahrens int reason; 2212eb633035STom Caputi zpool_errata_t errata; 221346657f8dSmmusante const char *health; 2214fa9e4066Sahrens uint_t vsc; 22158704186eSDan McDonald char *comment; 2216663207adSDon Brady status_cbdata_t cb = { 0 }; 2217fa9e4066Sahrens 2218fa9e4066Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 2219fa9e4066Sahrens &name) == 0); 2220fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 2221fa9e4066Sahrens &guid) == 0); 2222fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 2223fa9e4066Sahrens &pool_state) == 0); 2224fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2225fa9e4066Sahrens &nvroot) == 0); 2226fa9e4066Sahrens 22273f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 2228fa9e4066Sahrens (uint64_t **)&vs, &vsc) == 0); 2229990b4856Slling health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 2230fa9e4066Sahrens 2231eb633035STom Caputi reason = zpool_import_status(config, &msgid, &errata); 2232fa9e4066Sahrens 22338704186eSDan McDonald (void) printf(gettext(" pool: %s\n"), name); 22348704186eSDan McDonald (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); 22358704186eSDan McDonald (void) printf(gettext(" state: %s"), health); 22364c58d714Sdarrenm if (pool_state == POOL_STATE_DESTROYED) 2237b1b8ab34Slling (void) printf(gettext(" (DESTROYED)")); 22384c58d714Sdarrenm (void) printf("\n"); 2239fa9e4066Sahrens 2240fa9e4066Sahrens switch (reason) { 2241fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_R: 2242fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_NR: 2243fa9e4066Sahrens case ZPOOL_STATUS_BAD_GUID_SUM: 22448704186eSDan McDonald (void) printf(gettext(" status: One or more devices are " 22458704186eSDan McDonald "missing from the system.\n")); 2246fa9e4066Sahrens break; 2247fa9e4066Sahrens 2248fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_R: 2249fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_NR: 22508704186eSDan McDonald (void) printf(gettext(" status: One or more devices contains " 2251fa9e4066Sahrens "corrupted data.\n")); 2252fa9e4066Sahrens break; 2253fa9e4066Sahrens 2254fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_DATA: 22558704186eSDan McDonald (void) printf( 22568704186eSDan McDonald gettext(" status: The pool data is corrupted.\n")); 2257fa9e4066Sahrens break; 2258fa9e4066Sahrens 2259441d80aaSlling case ZPOOL_STATUS_OFFLINE_DEV: 22608704186eSDan McDonald (void) printf(gettext(" status: One or more devices " 2261441d80aaSlling "are offlined.\n")); 2262441d80aaSlling break; 2263441d80aaSlling 2264ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_POOL: 22658704186eSDan McDonald (void) printf(gettext(" status: The pool metadata is " 2266ea8dc4b6Seschrock "corrupted.\n")); 2267ea8dc4b6Seschrock break; 2268ea8dc4b6Seschrock 2269eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_OLDER: 227057221772SChristopher Siden (void) printf(gettext(" status: The pool is formatted using a " 227157221772SChristopher Siden "legacy on-disk version.\n")); 2272eaca9bbdSeschrock break; 2273eaca9bbdSeschrock 2274eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 22758704186eSDan McDonald (void) printf(gettext(" status: The pool is formatted using an " 2276eaca9bbdSeschrock "incompatible version.\n")); 2277eaca9bbdSeschrock break; 2278b87f3af3Sperrin 227957221772SChristopher Siden case ZPOOL_STATUS_FEAT_DISABLED: 228057221772SChristopher Siden (void) printf(gettext(" status: Some supported features are " 228157221772SChristopher Siden "not enabled on the pool.\n")); 228257221772SChristopher Siden break; 228357221772SChristopher Siden 2284ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ: 2285ad135b5dSChristopher Siden (void) printf(gettext("status: The pool uses the following " 2286edc8ef7dSToomas Soome "feature(s) not supported on this system:\n")); 2287ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 2288ad135b5dSChristopher Siden break; 2289ad135b5dSChristopher Siden 2290ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 2291ad135b5dSChristopher Siden (void) printf(gettext("status: The pool can only be accessed " 2292ad135b5dSChristopher Siden "in read-only mode on this system. It\n\tcannot be " 2293ad135b5dSChristopher Siden "accessed in read-write mode because it uses the " 2294ad135b5dSChristopher Siden "following\n\tfeature(s) not supported on this system:\n")); 2295ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 2296ad135b5dSChristopher Siden break; 2297ad135b5dSChristopher Siden 2298e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_ACTIVE: 2299e0f1c0afSOlaf Faaland (void) printf(gettext(" status: The pool is currently " 2300e0f1c0afSOlaf Faaland "imported by another system.\n")); 2301e0f1c0afSOlaf Faaland break; 2302e0f1c0afSOlaf Faaland 2303e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_REQUIRED: 2304e0f1c0afSOlaf Faaland (void) printf(gettext(" status: The pool has the " 2305e0f1c0afSOlaf Faaland "multihost property on. It cannot\n\tbe safely imported " 2306e0f1c0afSOlaf Faaland "when the system hostid is not set.\n")); 2307e0f1c0afSOlaf Faaland break; 2308e0f1c0afSOlaf Faaland 230995173954Sek case ZPOOL_STATUS_HOSTID_MISMATCH: 23108704186eSDan McDonald (void) printf(gettext(" status: The pool was last accessed by " 231195173954Sek "another system.\n")); 231295173954Sek break; 2313b87f3af3Sperrin 23143d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_R: 23153d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_NR: 23168704186eSDan McDonald (void) printf(gettext(" status: One or more devices are " 23173d7072f8Seschrock "faulted.\n")); 23183d7072f8Seschrock break; 23193d7072f8Seschrock 2320b87f3af3Sperrin case ZPOOL_STATUS_BAD_LOG: 23218704186eSDan McDonald (void) printf(gettext(" status: An intent log record cannot be " 2322b87f3af3Sperrin "read.\n")); 2323b87f3af3Sperrin break; 2324b87f3af3Sperrin 23253f9d6ad7SLin Ling case ZPOOL_STATUS_RESILVERING: 23268704186eSDan McDonald (void) printf(gettext(" status: One or more devices were being " 23273f9d6ad7SLin Ling "resilvered.\n")); 23283f9d6ad7SLin Ling break; 23293f9d6ad7SLin Ling 2330eb633035STom Caputi case ZPOOL_STATUS_ERRATA: 2331eb633035STom Caputi (void) printf(gettext(" status: Errata #%d detected.\n"), 2332eb633035STom Caputi errata); 2333eb633035STom Caputi break; 2334eb633035STom Caputi 2335fa9e4066Sahrens default: 2336fa9e4066Sahrens /* 2337fa9e4066Sahrens * No other status can be seen when importing pools. 2338fa9e4066Sahrens */ 2339fa9e4066Sahrens assert(reason == ZPOOL_STATUS_OK); 2340fa9e4066Sahrens } 2341fa9e4066Sahrens 2342fa9e4066Sahrens /* 2343fa9e4066Sahrens * Print out an action according to the overall state of the pool. 2344fa9e4066Sahrens */ 234546657f8dSmmusante if (vs->vs_state == VDEV_STATE_HEALTHY) { 234657221772SChristopher Siden if (reason == ZPOOL_STATUS_VERSION_OLDER || 234757221772SChristopher Siden reason == ZPOOL_STATUS_FEAT_DISABLED) { 23488704186eSDan McDonald (void) printf(gettext(" action: The pool can be " 2349eaca9bbdSeschrock "imported using its name or numeric identifier, " 2350eaca9bbdSeschrock "though\n\tsome features will not be available " 2351eaca9bbdSeschrock "without an explicit 'zpool upgrade'.\n")); 235257221772SChristopher Siden } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) { 23538704186eSDan McDonald (void) printf(gettext(" action: The pool can be " 235495173954Sek "imported using its name or numeric " 235595173954Sek "identifier and\n\tthe '-f' flag.\n")); 2356eb633035STom Caputi } else if (reason == ZPOOL_STATUS_ERRATA) { 2357eb633035STom Caputi switch (errata) { 2358eb633035STom Caputi case ZPOOL_ERRATA_NONE: 2359eb633035STom Caputi break; 2360eb633035STom Caputi 2361eb633035STom Caputi case ZPOOL_ERRATA_ZOL_2094_SCRUB: 2362eb633035STom Caputi (void) printf(gettext(" action: The pool can " 2363eb633035STom Caputi "be imported using its name or numeric " 2364eb633035STom Caputi "identifier,\n\thowever there is a compat" 2365eb633035STom Caputi "ibility issue which should be corrected" 2366eb633035STom Caputi "\n\tby running 'zpool scrub'\n")); 2367eb633035STom Caputi break; 2368eb633035STom Caputi 2369eb633035STom Caputi case ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY: 2370eb633035STom Caputi (void) printf(gettext(" action: The pool can" 2371eb633035STom Caputi "not be imported with this version of ZFS " 2372eb633035STom Caputi "due to\n\tan active asynchronous destroy. " 2373eb633035STom Caputi "Revert to an earlier version\n\tand " 2374eb633035STom Caputi "allow the destroy to complete before " 2375eb633035STom Caputi "updating.\n")); 2376eb633035STom Caputi break; 2377eb633035STom Caputi 2378eb633035STom Caputi case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION: 2379eb633035STom Caputi (void) printf(gettext(" action: Existing " 2380eb633035STom Caputi "encrypted datasets contain an on-disk " 2381eb633035STom Caputi "incompatibility, which\n\tneeds to be " 2382eb633035STom Caputi "corrected. Backup these datasets to new " 2383eb633035STom Caputi "encrypted datasets\n\tand destroy the " 2384eb633035STom Caputi "old ones.\n")); 2385eb633035STom Caputi break; 2386eb633035STom Caputi case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION: 2387eb633035STom Caputi (void) printf(gettext(" action: Any existing " 2388eb633035STom Caputi "encrypted datasets contain an on-disk " 2389eb633035STom Caputi "incompatibility which\n\tmay cause " 2390eb633035STom Caputi "on-disk corruption with 'zfs recv' and " 2391eb633035STom Caputi "which needs to be\n\tcorrected. Enable " 2392eb633035STom Caputi "the bookmark_v2 feature and backup " 2393eb633035STom Caputi "these datasets to new encrypted " 2394eb633035STom Caputi "datasets and\n\tdestroy the old ones. " 2395eb633035STom Caputi "If this pool does not contain any " 2396eb633035STom Caputi "encrypted datasets, simply enable\n\t" 2397eb633035STom Caputi "the bookmark_v2 feature.\n")); 2398eb633035STom Caputi break; 2399eb633035STom Caputi default: 2400eb633035STom Caputi /* 2401eb633035STom Caputi * All errata must contain an action message. 2402eb633035STom Caputi */ 2403eb633035STom Caputi assert(0); 2404eb633035STom Caputi } 240557221772SChristopher Siden } else { 24068704186eSDan McDonald (void) printf(gettext(" action: The pool can be " 2407eaca9bbdSeschrock "imported using its name or numeric " 2408eaca9bbdSeschrock "identifier.\n")); 240957221772SChristopher Siden } 241046657f8dSmmusante } else if (vs->vs_state == VDEV_STATE_DEGRADED) { 24118704186eSDan McDonald (void) printf(gettext(" action: The pool can be imported " 2412fa9e4066Sahrens "despite missing or damaged devices. The\n\tfault " 2413eaca9bbdSeschrock "tolerance of the pool may be compromised if imported.\n")); 2414fa9e4066Sahrens } else { 2415eaca9bbdSeschrock switch (reason) { 2416eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 24178704186eSDan McDonald (void) printf(gettext(" action: The pool cannot be " 2418eaca9bbdSeschrock "imported. Access the pool on a system running " 2419eaca9bbdSeschrock "newer\n\tsoftware, or recreate the pool from " 2420eaca9bbdSeschrock "backup.\n")); 2421eaca9bbdSeschrock break; 2422ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ: 2423ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be " 2424ad135b5dSChristopher Siden "imported. Access the pool on a system that " 2425ad135b5dSChristopher Siden "supports\n\tthe required feature(s), or recreate " 2426ad135b5dSChristopher Siden "the pool from backup.\n")); 2427ad135b5dSChristopher Siden break; 2428ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 2429ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be " 2430ad135b5dSChristopher Siden "imported in read-write mode. Import the pool " 2431ad135b5dSChristopher Siden "with\n" 2432ad135b5dSChristopher Siden "\t\"-o readonly=on\", access the pool on a system " 2433ad135b5dSChristopher Siden "that supports the\n\trequired feature(s), or " 2434ad135b5dSChristopher Siden "recreate the pool from backup.\n")); 2435ad135b5dSChristopher Siden break; 2436eaca9bbdSeschrock case ZPOOL_STATUS_MISSING_DEV_R: 2437eaca9bbdSeschrock case ZPOOL_STATUS_MISSING_DEV_NR: 2438eaca9bbdSeschrock case ZPOOL_STATUS_BAD_GUID_SUM: 24398704186eSDan McDonald (void) printf(gettext(" action: The pool cannot be " 2440fa9e4066Sahrens "imported. Attach the missing\n\tdevices and try " 2441fa9e4066Sahrens "again.\n")); 2442eaca9bbdSeschrock break; 2443e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_ACTIVE: 2444e0f1c0afSOlaf Faaland VERIFY0(nvlist_lookup_nvlist(config, 2445e0f1c0afSOlaf Faaland ZPOOL_CONFIG_LOAD_INFO, &nvinfo)); 2446e0f1c0afSOlaf Faaland 2447e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME)) 2448e0f1c0afSOlaf Faaland hostname = fnvlist_lookup_string(nvinfo, 2449e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTNAME); 2450e0f1c0afSOlaf Faaland 2451e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID)) 2452e0f1c0afSOlaf Faaland hostid = fnvlist_lookup_uint64(nvinfo, 2453e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTID); 2454e0f1c0afSOlaf Faaland 2455e0f1c0afSOlaf Faaland (void) printf(gettext(" action: The pool must be " 2456e0f1c0afSOlaf Faaland "exported from %s (hostid=%lx)\n\tbefore it " 2457e0f1c0afSOlaf Faaland "can be safely imported.\n"), hostname, 2458e0f1c0afSOlaf Faaland (unsigned long) hostid); 2459e0f1c0afSOlaf Faaland break; 2460e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_REQUIRED: 2461e0f1c0afSOlaf Faaland (void) printf(gettext(" action: Check the SMF " 2462e0f1c0afSOlaf Faaland "svc:/system/hostid service.\n")); 2463e0f1c0afSOlaf Faaland break; 2464eaca9bbdSeschrock default: 24658704186eSDan McDonald (void) printf(gettext(" action: The pool cannot be " 2466fa9e4066Sahrens "imported due to damaged devices or data.\n")); 2467eaca9bbdSeschrock } 2468eaca9bbdSeschrock } 2469eaca9bbdSeschrock 24708704186eSDan McDonald /* Print the comment attached to the pool. */ 24718704186eSDan McDonald if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0) 24728704186eSDan McDonald (void) printf(gettext("comment: %s\n"), comment); 24738704186eSDan McDonald 247446657f8dSmmusante /* 247546657f8dSmmusante * If the state is "closed" or "can't open", and the aux state 247646657f8dSmmusante * is "corrupt data": 247746657f8dSmmusante */ 247846657f8dSmmusante if (((vs->vs_state == VDEV_STATE_CLOSED) || 247946657f8dSmmusante (vs->vs_state == VDEV_STATE_CANT_OPEN)) && 248046657f8dSmmusante (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) { 2481eaca9bbdSeschrock if (pool_state == POOL_STATE_DESTROYED) 2482eaca9bbdSeschrock (void) printf(gettext("\tThe pool was destroyed, " 2483eaca9bbdSeschrock "but can be imported using the '-Df' flags.\n")); 2484eaca9bbdSeschrock else if (pool_state != POOL_STATE_EXPORTED) 2485eaca9bbdSeschrock (void) printf(gettext("\tThe pool may be active on " 248618ce54dfSek "another system, but can be imported using\n\t" 2487eaca9bbdSeschrock "the '-f' flag.\n")); 2488fa9e4066Sahrens } 2489fa9e4066Sahrens 2490fa9e4066Sahrens if (msgid != NULL) 2491654b400cSJoshua M. Clulow (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 2492fa9e4066Sahrens msgid); 2493fa9e4066Sahrens 24948704186eSDan McDonald (void) printf(gettext(" config:\n\n")); 2495fa9e4066Sahrens 2496dd50e0ccSTony Hutter cb.cb_namewidth = max_width(NULL, nvroot, 0, strlen(name), 2497dd50e0ccSTony Hutter VDEV_NAME_TYPE_ID); 2498663207adSDon Brady if (cb.cb_namewidth < 10) 2499663207adSDon Brady cb.cb_namewidth = 10; 25008654d025Sperrin 2501663207adSDon Brady print_import_config(&cb, name, nvroot, 0); 2502663207adSDon Brady 2503663207adSDon Brady print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_DEDUP); 2504663207adSDon Brady print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_SPECIAL); 2505663207adSDon Brady print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_CLASS_LOGS); 2506fa9e4066Sahrens 2507fa9e4066Sahrens if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 250846657f8dSmmusante (void) printf(gettext("\n\tAdditional devices are known to " 2509fa9e4066Sahrens "be part of this pool, though their\n\texact " 251046657f8dSmmusante "configuration cannot be determined.\n")); 2511fa9e4066Sahrens } 2512fa9e4066Sahrens } 2513fa9e4066Sahrens 2514e0f1c0afSOlaf Faaland static boolean_t 2515e0f1c0afSOlaf Faaland zfs_force_import_required(nvlist_t *config) 2516e0f1c0afSOlaf Faaland { 2517e0f1c0afSOlaf Faaland uint64_t state; 2518e0f1c0afSOlaf Faaland uint64_t hostid = 0; 2519e0f1c0afSOlaf Faaland nvlist_t *nvinfo; 2520e0f1c0afSOlaf Faaland 2521e0f1c0afSOlaf Faaland state = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE); 2522e0f1c0afSOlaf Faaland (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid); 2523e0f1c0afSOlaf Faaland 2524e0f1c0afSOlaf Faaland if (state != POOL_STATE_EXPORTED && hostid != get_system_hostid()) 2525e0f1c0afSOlaf Faaland return (B_TRUE); 2526e0f1c0afSOlaf Faaland 2527e0f1c0afSOlaf Faaland nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO); 2528e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) { 2529e0f1c0afSOlaf Faaland mmp_state_t mmp_state = fnvlist_lookup_uint64(nvinfo, 2530e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_STATE); 2531e0f1c0afSOlaf Faaland 2532e0f1c0afSOlaf Faaland if (mmp_state != MMP_STATE_INACTIVE) 2533e0f1c0afSOlaf Faaland return (B_TRUE); 2534e0f1c0afSOlaf Faaland } 2535e0f1c0afSOlaf Faaland 2536e0f1c0afSOlaf Faaland return (B_FALSE); 2537e0f1c0afSOlaf Faaland } 2538e0f1c0afSOlaf Faaland 2539fa9e4066Sahrens /* 2540fa9e4066Sahrens * Perform the import for the given configuration. This passes the heavy 2541990b4856Slling * lifting off to zpool_import_props(), and then mounts the datasets contained 2542990b4856Slling * within the pool. 2543fa9e4066Sahrens */ 2544fa9e4066Sahrens static int 2545fa9e4066Sahrens do_import(nvlist_t *config, const char *newname, const char *mntopts, 25464b964adaSGeorge Wilson nvlist_t *props, int flags) 2547fa9e4066Sahrens { 2548eb633035STom Caputi int ret = 0; 2549fa9e4066Sahrens zpool_handle_t *zhp; 2550fa9e4066Sahrens char *name; 2551eaca9bbdSeschrock uint64_t version; 2552fa9e4066Sahrens 2553e0f1c0afSOlaf Faaland name = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME); 2554e0f1c0afSOlaf Faaland version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION); 2555fa9e4066Sahrens 2556ad135b5dSChristopher Siden if (!SPA_VERSION_IS_SUPPORTED(version)) { 2557eaca9bbdSeschrock (void) fprintf(stderr, gettext("cannot import '%s': pool " 2558ad135b5dSChristopher Siden "is formatted using an unsupported ZFS version\n"), name); 2559eaca9bbdSeschrock return (1); 2560e0f1c0afSOlaf Faaland } else if (zfs_force_import_required(config) && 25614b964adaSGeorge Wilson !(flags & ZFS_IMPORT_ANY_HOST)) { 2562e0f1c0afSOlaf Faaland mmp_state_t mmp_state = MMP_STATE_INACTIVE; 2563e0f1c0afSOlaf Faaland nvlist_t *nvinfo; 2564e0f1c0afSOlaf Faaland 2565e0f1c0afSOlaf Faaland nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO); 2566e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) 2567e0f1c0afSOlaf Faaland mmp_state = fnvlist_lookup_uint64(nvinfo, 2568e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_STATE); 2569e0f1c0afSOlaf Faaland 2570e0f1c0afSOlaf Faaland if (mmp_state == MMP_STATE_ACTIVE) { 2571e0f1c0afSOlaf Faaland char *hostname = "<unknown>"; 2572e0f1c0afSOlaf Faaland uint64_t hostid = 0; 2573e0f1c0afSOlaf Faaland 2574e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME)) 2575e0f1c0afSOlaf Faaland hostname = fnvlist_lookup_string(nvinfo, 2576e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTNAME); 2577e0f1c0afSOlaf Faaland 2578e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID)) 2579e0f1c0afSOlaf Faaland hostid = fnvlist_lookup_uint64(nvinfo, 2580e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTID); 2581e0f1c0afSOlaf Faaland 2582e0f1c0afSOlaf Faaland (void) fprintf(stderr, gettext("cannot import '%s': " 2583e0f1c0afSOlaf Faaland "pool is imported on %s (hostid: " 2584e0f1c0afSOlaf Faaland "0x%lx)\nExport the pool on the other system, " 2585e0f1c0afSOlaf Faaland "then run 'zpool import'.\n"), 2586e0f1c0afSOlaf Faaland name, hostname, (unsigned long) hostid); 2587e0f1c0afSOlaf Faaland } else if (mmp_state == MMP_STATE_NO_HOSTID) { 2588e0f1c0afSOlaf Faaland (void) fprintf(stderr, gettext("Cannot import '%s': " 2589e0f1c0afSOlaf Faaland "pool has the multihost property on and the\n" 2590e0f1c0afSOlaf Faaland "system's hostid is not set.\n"), name); 259195173954Sek } else { 2592e0f1c0afSOlaf Faaland char *hostname = "<unknown>"; 2593e0f1c0afSOlaf Faaland uint64_t timestamp = 0; 2594e0f1c0afSOlaf Faaland uint64_t hostid = 0; 2595e0f1c0afSOlaf Faaland 2596e0f1c0afSOlaf Faaland if (nvlist_exists(config, ZPOOL_CONFIG_HOSTNAME)) 2597e0f1c0afSOlaf Faaland hostname = fnvlist_lookup_string(config, 2598e0f1c0afSOlaf Faaland ZPOOL_CONFIG_HOSTNAME); 2599e0f1c0afSOlaf Faaland 2600e0f1c0afSOlaf Faaland if (nvlist_exists(config, ZPOOL_CONFIG_TIMESTAMP)) 2601e0f1c0afSOlaf Faaland timestamp = fnvlist_lookup_uint64(config, 2602e0f1c0afSOlaf Faaland ZPOOL_CONFIG_TIMESTAMP); 2603e0f1c0afSOlaf Faaland 2604e0f1c0afSOlaf Faaland if (nvlist_exists(config, ZPOOL_CONFIG_HOSTID)) 2605e0f1c0afSOlaf Faaland hostid = fnvlist_lookup_uint64(config, 2606e0f1c0afSOlaf Faaland ZPOOL_CONFIG_HOSTID); 2607e0f1c0afSOlaf Faaland 260895173954Sek (void) fprintf(stderr, gettext("cannot import '%s': " 2609e0f1c0afSOlaf Faaland "pool was previously in use from another system.\n" 2610e0f1c0afSOlaf Faaland "Last accessed by %s (hostid=%lx) at %s" 2611e0f1c0afSOlaf Faaland "The pool can be imported, use 'zpool import -f' " 2612e0f1c0afSOlaf Faaland "to import the pool.\n"), name, hostname, 2613e0f1c0afSOlaf Faaland (unsigned long)hostid, ctime((time_t *)×tamp)); 2614e0f1c0afSOlaf Faaland 261595173954Sek } 2616e0f1c0afSOlaf Faaland 2617e0f1c0afSOlaf Faaland return (1); 2618fa9e4066Sahrens } 2619fa9e4066Sahrens 26204b964adaSGeorge Wilson if (zpool_import_props(g_zfs, config, newname, props, flags) != 0) 2621fa9e4066Sahrens return (1); 2622fa9e4066Sahrens 2623fa9e4066Sahrens if (newname != NULL) 2624fa9e4066Sahrens name = (char *)newname; 2625fa9e4066Sahrens 26264f0f5e5bSVictor Latushkin if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL) 26274f0f5e5bSVictor Latushkin return (1); 2628fa9e4066Sahrens 2629eb633035STom Caputi /* 2630eb633035STom Caputi * Loading keys is best effort. We don't want to return immediately 2631eb633035STom Caputi * if it fails but we do want to give the error to the caller. 2632eb633035STom Caputi */ 2633eb633035STom Caputi if (flags & ZFS_IMPORT_LOAD_KEYS) { 2634eb633035STom Caputi ret = zfs_crypto_attempt_load_keys(g_zfs, name); 2635eb633035STom Caputi if (ret != 0) 2636eb633035STom Caputi ret = 1; 2637eb633035STom Caputi } 2638eb633035STom Caputi 2639379c004dSEric Schrock if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 2640f9af39baSGeorge Wilson !(flags & ZFS_IMPORT_ONLY) && 2641379c004dSEric Schrock zpool_enable_datasets(zhp, mntopts, 0) != 0) { 2642fa9e4066Sahrens zpool_close(zhp); 2643fa9e4066Sahrens return (1); 2644fa9e4066Sahrens } 2645fa9e4066Sahrens 2646fa9e4066Sahrens zpool_close(zhp); 2647eb633035STom Caputi return (ret); 2648fa9e4066Sahrens } 2649fa9e4066Sahrens 2650d8ab6e12SDon Brady typedef struct target_exists_args { 2651d8ab6e12SDon Brady const char *poolname; 2652d8ab6e12SDon Brady uint64_t poolguid; 2653d8ab6e12SDon Brady } target_exists_args_t; 2654d8ab6e12SDon Brady 2655d8ab6e12SDon Brady static int 2656d8ab6e12SDon Brady name_or_guid_exists(zpool_handle_t *zhp, void *data) 2657d8ab6e12SDon Brady { 2658d8ab6e12SDon Brady target_exists_args_t *args = data; 2659d8ab6e12SDon Brady nvlist_t *config = zpool_get_config(zhp, NULL); 2660d8ab6e12SDon Brady int found = 0; 2661d8ab6e12SDon Brady 2662d8ab6e12SDon Brady if (config == NULL) 2663d8ab6e12SDon Brady return (0); 2664d8ab6e12SDon Brady 2665d8ab6e12SDon Brady if (args->poolname != NULL) { 2666d8ab6e12SDon Brady char *pool_name; 2667d8ab6e12SDon Brady 2668d8ab6e12SDon Brady verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 2669d8ab6e12SDon Brady &pool_name) == 0); 2670d8ab6e12SDon Brady if (strcmp(pool_name, args->poolname) == 0) 2671d8ab6e12SDon Brady found = 1; 2672d8ab6e12SDon Brady } else { 2673d8ab6e12SDon Brady uint64_t pool_guid; 2674d8ab6e12SDon Brady 2675d8ab6e12SDon Brady verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 2676d8ab6e12SDon Brady &pool_guid) == 0); 2677d8ab6e12SDon Brady if (pool_guid == args->poolguid) 2678d8ab6e12SDon Brady found = 1; 2679d8ab6e12SDon Brady } 2680d8ab6e12SDon Brady zpool_close(zhp); 2681d8ab6e12SDon Brady 2682d8ab6e12SDon Brady return (found); 2683d8ab6e12SDon Brady } 268486714001SSerapheim Dimitropoulos /* 268586714001SSerapheim Dimitropoulos * zpool checkpoint <pool> 268686714001SSerapheim Dimitropoulos * checkpoint --discard <pool> 268786714001SSerapheim Dimitropoulos * 268804e56356SAndriy Gapon * -d Discard the checkpoint from a checkpointed 268904e56356SAndriy Gapon * --discard pool. 269086714001SSerapheim Dimitropoulos * 269186714001SSerapheim Dimitropoulos * Checkpoints the specified pool, by taking a "snapshot" of its 269286714001SSerapheim Dimitropoulos * current state. A pool can only have one checkpoint at a time. 269386714001SSerapheim Dimitropoulos */ 269486714001SSerapheim Dimitropoulos int 269586714001SSerapheim Dimitropoulos zpool_do_checkpoint(int argc, char **argv) 269686714001SSerapheim Dimitropoulos { 269786714001SSerapheim Dimitropoulos boolean_t discard; 269886714001SSerapheim Dimitropoulos char *pool; 269986714001SSerapheim Dimitropoulos zpool_handle_t *zhp; 270086714001SSerapheim Dimitropoulos int c, err; 270186714001SSerapheim Dimitropoulos 270286714001SSerapheim Dimitropoulos struct option long_options[] = { 270386714001SSerapheim Dimitropoulos {"discard", no_argument, NULL, 'd'}, 270486714001SSerapheim Dimitropoulos {0, 0, 0, 0} 270586714001SSerapheim Dimitropoulos }; 270686714001SSerapheim Dimitropoulos 270786714001SSerapheim Dimitropoulos discard = B_FALSE; 270886714001SSerapheim Dimitropoulos while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) { 270986714001SSerapheim Dimitropoulos switch (c) { 271086714001SSerapheim Dimitropoulos case 'd': 271186714001SSerapheim Dimitropoulos discard = B_TRUE; 271286714001SSerapheim Dimitropoulos break; 271386714001SSerapheim Dimitropoulos case '?': 271486714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("invalid option '%c'\n"), 271586714001SSerapheim Dimitropoulos optopt); 271686714001SSerapheim Dimitropoulos usage(B_FALSE); 271786714001SSerapheim Dimitropoulos } 271886714001SSerapheim Dimitropoulos } 271986714001SSerapheim Dimitropoulos 272086714001SSerapheim Dimitropoulos argc -= optind; 272186714001SSerapheim Dimitropoulos argv += optind; 272286714001SSerapheim Dimitropoulos 272386714001SSerapheim Dimitropoulos if (argc < 1) { 272486714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("missing pool argument\n")); 272586714001SSerapheim Dimitropoulos usage(B_FALSE); 272686714001SSerapheim Dimitropoulos } 272786714001SSerapheim Dimitropoulos 272886714001SSerapheim Dimitropoulos if (argc > 1) { 272986714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("too many arguments\n")); 273086714001SSerapheim Dimitropoulos usage(B_FALSE); 273186714001SSerapheim Dimitropoulos } 273286714001SSerapheim Dimitropoulos 273386714001SSerapheim Dimitropoulos pool = argv[0]; 273486714001SSerapheim Dimitropoulos 273586714001SSerapheim Dimitropoulos if ((zhp = zpool_open(g_zfs, pool)) == NULL) { 273686714001SSerapheim Dimitropoulos /* As a special case, check for use of '/' in the name */ 273786714001SSerapheim Dimitropoulos if (strchr(pool, '/') != NULL) 273886714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("'zpool checkpoint' " 273986714001SSerapheim Dimitropoulos "doesn't work on datasets. To save the state " 274086714001SSerapheim Dimitropoulos "of a dataset from a specific point in time " 274186714001SSerapheim Dimitropoulos "please use 'zfs snapshot'\n")); 274286714001SSerapheim Dimitropoulos return (1); 274386714001SSerapheim Dimitropoulos } 274486714001SSerapheim Dimitropoulos 274586714001SSerapheim Dimitropoulos if (discard) 274686714001SSerapheim Dimitropoulos err = (zpool_discard_checkpoint(zhp) != 0); 274786714001SSerapheim Dimitropoulos else 274886714001SSerapheim Dimitropoulos err = (zpool_checkpoint(zhp) != 0); 274986714001SSerapheim Dimitropoulos 275086714001SSerapheim Dimitropoulos zpool_close(zhp); 275186714001SSerapheim Dimitropoulos 275286714001SSerapheim Dimitropoulos return (err); 275386714001SSerapheim Dimitropoulos } 275486714001SSerapheim Dimitropoulos 275586714001SSerapheim Dimitropoulos #define CHECKPOINT_OPT 1024 275686714001SSerapheim Dimitropoulos 2757fa9e4066Sahrens /* 27584c58d714Sdarrenm * zpool import [-d dir] [-D] 2759eb633035STom Caputi * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l] 27602f8aaab3Seschrock * [-d dir | -c cachefile] [-f] -a 2761eb633035STom Caputi * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l] 276204e56356SAndriy Gapon * [-d dir | -c cachefile] [-f] [-n] [-F] [-t] 276304e56356SAndriy Gapon * <pool | id> [newpool] 27642f8aaab3Seschrock * 276504e56356SAndriy Gapon * -c Read pool information from a cachefile instead of searching 27662f8aaab3Seschrock * devices. 2767fa9e4066Sahrens * 276804e56356SAndriy Gapon * -d Scan in a specific directory, other than /dev/dsk. More than 2769fa9e4066Sahrens * one directory can be specified using multiple '-d' options. 2770fa9e4066Sahrens * 277104e56356SAndriy Gapon * -D Scan for previously destroyed pools or import all or only 277204e56356SAndriy Gapon * specified destroyed pools. 27734c58d714Sdarrenm * 277404e56356SAndriy Gapon * -R Temporarily import the pool, with all mountpoints relative to 2775fa9e4066Sahrens * the given root. The pool will remain exported when the machine 2776fa9e4066Sahrens * is rebooted. 2777fa9e4066Sahrens * 277804e56356SAndriy Gapon * -V Import even in the presence of faulted vdevs. This is an 277904e56356SAndriy Gapon * intentionally undocumented option for testing purposes, and 278004e56356SAndriy Gapon * treats the pool configuration as complete, leaving any bad 27814f0f5e5bSVictor Latushkin * vdevs in the FAULTED state. In other words, it does verbatim 27824f0f5e5bSVictor Latushkin * import. 2783c5904d13Seschrock * 278404e56356SAndriy Gapon * -f Force import, even if it appears that the pool is active. 278504e56356SAndriy Gapon * 278604e56356SAndriy Gapon * -F Attempt rewind if necessary. 2787468c413aSTim Haley * 278804e56356SAndriy Gapon * -n See if rewind would work, but don't actually rewind. 2789468c413aSTim Haley * 279004e56356SAndriy Gapon * -N Import the pool but don't mount datasets. 2791468c413aSTim Haley * 279204e56356SAndriy Gapon * -t Use newpool as a temporary pool name instead of renaming 279304e56356SAndriy Gapon * the pool. 2794f9af39baSGeorge Wilson * 279504e56356SAndriy Gapon * -T Specify a starting txg to use for import. This option is 279604e56356SAndriy Gapon * intentionally undocumented option for testing purposes. 2797f9af39baSGeorge Wilson * 279804e56356SAndriy Gapon * -a Import all pools found. 2799fa9e4066Sahrens * 280004e56356SAndriy Gapon * -o Set property=value and/or temporary mount options (without '='). 2801eb633035STom Caputi * -l Load encryption keys while importing. 2802ecd6cf80Smarks * 280304e56356SAndriy Gapon * --rewind-to-checkpoint 280404e56356SAndriy Gapon * Import the pool and revert back to the checkpoint. 280586714001SSerapheim Dimitropoulos * 2806fa9e4066Sahrens * The import command scans for pools to import, and import pools based on pool 2807fa9e4066Sahrens * name and GUID. The pool can also be renamed as part of the import process. 2808fa9e4066Sahrens */ 2809fa9e4066Sahrens int 2810fa9e4066Sahrens zpool_do_import(int argc, char **argv) 2811fa9e4066Sahrens { 2812fa9e4066Sahrens char **searchdirs = NULL; 2813fa9e4066Sahrens int nsearch = 0; 2814fa9e4066Sahrens int c; 2815d41c4376SMark J Musante int err = 0; 28162f8aaab3Seschrock nvlist_t *pools = NULL; 281799653d4eSeschrock boolean_t do_all = B_FALSE; 281899653d4eSeschrock boolean_t do_destroyed = B_FALSE; 2819fa9e4066Sahrens char *mntopts = NULL; 2820fa9e4066Sahrens nvpair_t *elem; 2821fa9e4066Sahrens nvlist_t *config; 282224e697d4Sck uint64_t searchguid = 0; 282324e697d4Sck char *searchname = NULL; 2824990b4856Slling char *propval; 2825fa9e4066Sahrens nvlist_t *found_config; 2826468c413aSTim Haley nvlist_t *policy = NULL; 2827ecd6cf80Smarks nvlist_t *props = NULL; 282899653d4eSeschrock boolean_t first; 28294b964adaSGeorge Wilson int flags = ZFS_IMPORT_NORMAL; 2830468c413aSTim Haley uint32_t rewind_policy = ZPOOL_NO_REWIND; 2831468c413aSTim Haley boolean_t dryrun = B_FALSE; 2832468c413aSTim Haley boolean_t do_rewind = B_FALSE; 2833468c413aSTim Haley boolean_t xtreme_rewind = B_FALSE; 2834d8ab6e12SDon Brady boolean_t pool_exists = B_FALSE; 2835f9af39baSGeorge Wilson uint64_t pool_state, txg = -1ULL; 28362f8aaab3Seschrock char *cachefile = NULL; 2837d41c4376SMark J Musante importargs_t idata = { 0 }; 2838f9af39baSGeorge Wilson char *endptr; 2839fa9e4066Sahrens 284086714001SSerapheim Dimitropoulos 284186714001SSerapheim Dimitropoulos struct option long_options[] = { 284286714001SSerapheim Dimitropoulos {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT}, 284386714001SSerapheim Dimitropoulos {0, 0, 0, 0} 284486714001SSerapheim Dimitropoulos }; 284586714001SSerapheim Dimitropoulos 2846fa9e4066Sahrens /* check options */ 2847eb633035STom Caputi while ((c = getopt_long(argc, argv, ":aCc:d:DEfFlmnNo:rR:tT:VX", 284886714001SSerapheim Dimitropoulos long_options, NULL)) != -1) { 2849fa9e4066Sahrens switch (c) { 2850fa9e4066Sahrens case 'a': 285199653d4eSeschrock do_all = B_TRUE; 2852fa9e4066Sahrens break; 28532f8aaab3Seschrock case 'c': 28542f8aaab3Seschrock cachefile = optarg; 28552f8aaab3Seschrock break; 2856fa9e4066Sahrens case 'd': 2857fa9e4066Sahrens if (searchdirs == NULL) { 2858fa9e4066Sahrens searchdirs = safe_malloc(sizeof (char *)); 2859fa9e4066Sahrens } else { 2860fa9e4066Sahrens char **tmp = safe_malloc((nsearch + 1) * 2861fa9e4066Sahrens sizeof (char *)); 2862fa9e4066Sahrens bcopy(searchdirs, tmp, nsearch * 2863fa9e4066Sahrens sizeof (char *)); 2864fa9e4066Sahrens free(searchdirs); 2865fa9e4066Sahrens searchdirs = tmp; 2866fa9e4066Sahrens } 2867fa9e4066Sahrens searchdirs[nsearch++] = optarg; 2868fa9e4066Sahrens break; 28694c58d714Sdarrenm case 'D': 287099653d4eSeschrock do_destroyed = B_TRUE; 28714c58d714Sdarrenm break; 2872fa9e4066Sahrens case 'f': 28734b964adaSGeorge Wilson flags |= ZFS_IMPORT_ANY_HOST; 2874fa9e4066Sahrens break; 2875c5904d13Seschrock case 'F': 2876468c413aSTim Haley do_rewind = B_TRUE; 2877468c413aSTim Haley break; 2878eb633035STom Caputi case 'l': 2879eb633035STom Caputi flags |= ZFS_IMPORT_LOAD_KEYS; 2880eb633035STom Caputi break; 28814b964adaSGeorge Wilson case 'm': 28824b964adaSGeorge Wilson flags |= ZFS_IMPORT_MISSING_LOG; 28834b964adaSGeorge Wilson break; 2884468c413aSTim Haley case 'n': 2885468c413aSTim Haley dryrun = B_TRUE; 2886c5904d13Seschrock break; 2887f9af39baSGeorge Wilson case 'N': 2888f9af39baSGeorge Wilson flags |= ZFS_IMPORT_ONLY; 2889f9af39baSGeorge Wilson break; 2890fa9e4066Sahrens case 'o': 2891990b4856Slling if ((propval = strchr(optarg, '=')) != NULL) { 2892990b4856Slling *propval = '\0'; 2893990b4856Slling propval++; 28940a48a24eStimh if (add_prop_list(optarg, propval, 28950a48a24eStimh &props, B_TRUE)) 2896990b4856Slling goto error; 2897990b4856Slling } else { 2898990b4856Slling mntopts = optarg; 2899990b4856Slling } 2900fa9e4066Sahrens break; 2901fa9e4066Sahrens case 'R': 2902990b4856Slling if (add_prop_list(zpool_prop_to_name( 29030a48a24eStimh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 2904990b4856Slling goto error; 290504e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name( 290604e56356SAndriy Gapon ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 290704e56356SAndriy Gapon goto error; 290804e56356SAndriy Gapon break; 290904e56356SAndriy Gapon case 't': 291004e56356SAndriy Gapon flags |= ZFS_IMPORT_TEMP_NAME; 291104e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name( 29120a48a24eStimh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 2913990b4856Slling goto error; 2914fa9e4066Sahrens break; 2915f9af39baSGeorge Wilson case 'T': 2916f9af39baSGeorge Wilson errno = 0; 2917e42d2059SMatthew Ahrens txg = strtoull(optarg, &endptr, 0); 2918f9af39baSGeorge Wilson if (errno != 0 || *endptr != '\0') { 2919f9af39baSGeorge Wilson (void) fprintf(stderr, 2920f9af39baSGeorge Wilson gettext("invalid txg value\n")); 2921f9af39baSGeorge Wilson usage(B_FALSE); 2922f9af39baSGeorge Wilson } 2923f9af39baSGeorge Wilson rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND; 2924f9af39baSGeorge Wilson break; 2925468c413aSTim Haley case 'V': 29264b964adaSGeorge Wilson flags |= ZFS_IMPORT_VERBATIM; 2927468c413aSTim Haley break; 2928468c413aSTim Haley case 'X': 2929468c413aSTim Haley xtreme_rewind = B_TRUE; 2930468c413aSTim Haley break; 293186714001SSerapheim Dimitropoulos case CHECKPOINT_OPT: 293286714001SSerapheim Dimitropoulos flags |= ZFS_IMPORT_CHECKPOINT; 293386714001SSerapheim Dimitropoulos break; 2934fa9e4066Sahrens case ':': 2935fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 2936fa9e4066Sahrens "'%c' option\n"), optopt); 293799653d4eSeschrock usage(B_FALSE); 2938fa9e4066Sahrens break; 2939fa9e4066Sahrens case '?': 2940fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2941fa9e4066Sahrens optopt); 294299653d4eSeschrock usage(B_FALSE); 2943fa9e4066Sahrens } 2944fa9e4066Sahrens } 2945fa9e4066Sahrens 2946fa9e4066Sahrens argc -= optind; 2947fa9e4066Sahrens argv += optind; 2948fa9e4066Sahrens 29492f8aaab3Seschrock if (cachefile && nsearch != 0) { 29502f8aaab3Seschrock (void) fprintf(stderr, gettext("-c is incompatible with -d\n")); 29512f8aaab3Seschrock usage(B_FALSE); 29522f8aaab3Seschrock } 29532f8aaab3Seschrock 2954eb633035STom Caputi if ((flags & ZFS_IMPORT_LOAD_KEYS) && (flags & ZFS_IMPORT_ONLY)) { 2955eb633035STom Caputi (void) fprintf(stderr, gettext("-l is incompatible with -N\n")); 2956eb633035STom Caputi usage(B_FALSE); 2957eb633035STom Caputi } 2958eb633035STom Caputi 2959eb633035STom Caputi if ((flags & ZFS_IMPORT_LOAD_KEYS) && !do_all && argc == 0) { 2960eb633035STom Caputi (void) fprintf(stderr, gettext("-l is only meaningful during " 2961eb633035STom Caputi "an import\n")); 2962eb633035STom Caputi usage(B_FALSE); 2963eb633035STom Caputi } 2964eb633035STom Caputi 2965468c413aSTim Haley if ((dryrun || xtreme_rewind) && !do_rewind) { 2966468c413aSTim Haley (void) fprintf(stderr, 2967468c413aSTim Haley gettext("-n or -X only meaningful with -F\n")); 2968468c413aSTim Haley usage(B_FALSE); 2969468c413aSTim Haley } 2970468c413aSTim Haley if (dryrun) 2971468c413aSTim Haley rewind_policy = ZPOOL_TRY_REWIND; 2972468c413aSTim Haley else if (do_rewind) 2973468c413aSTim Haley rewind_policy = ZPOOL_DO_REWIND; 2974468c413aSTim Haley if (xtreme_rewind) 2975468c413aSTim Haley rewind_policy |= ZPOOL_EXTREME_REWIND; 2976468c413aSTim Haley 2977468c413aSTim Haley /* In the future, we can capture further policy and include it here */ 2978468c413aSTim Haley if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 29795dafeea3SPavel Zakharov nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 || 29805dafeea3SPavel Zakharov nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, 29815dafeea3SPavel Zakharov rewind_policy) != 0) 2982468c413aSTim Haley goto error; 2983468c413aSTim Haley 2984fa9e4066Sahrens if (searchdirs == NULL) { 2985fa9e4066Sahrens searchdirs = safe_malloc(sizeof (char *)); 29866401734dSWill Andrews searchdirs[0] = ZFS_DISK_ROOT; 2987fa9e4066Sahrens nsearch = 1; 2988fa9e4066Sahrens } 2989fa9e4066Sahrens 2990fa9e4066Sahrens /* check argument count */ 2991fa9e4066Sahrens if (do_all) { 2992fa9e4066Sahrens if (argc != 0) { 2993fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 299499653d4eSeschrock usage(B_FALSE); 2995fa9e4066Sahrens } 2996fa9e4066Sahrens } else { 2997fa9e4066Sahrens if (argc > 2) { 2998fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 299999653d4eSeschrock usage(B_FALSE); 3000fa9e4066Sahrens } 3001fa9e4066Sahrens 3002fa9e4066Sahrens /* 3003fa9e4066Sahrens * Check for the SYS_CONFIG privilege. We do this explicitly 3004fa9e4066Sahrens * here because otherwise any attempt to discover pools will 3005fa9e4066Sahrens * silently fail. 3006fa9e4066Sahrens */ 3007fa9e4066Sahrens if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 3008fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot " 3009fa9e4066Sahrens "discover pools: permission denied\n")); 301099653d4eSeschrock free(searchdirs); 3011468c413aSTim Haley nvlist_free(policy); 3012fa9e4066Sahrens return (1); 3013fa9e4066Sahrens } 3014fa9e4066Sahrens } 3015fa9e4066Sahrens 3016fa9e4066Sahrens /* 3017fa9e4066Sahrens * Depending on the arguments given, we do one of the following: 3018fa9e4066Sahrens * 3019fa9e4066Sahrens * <none> Iterate through all pools and display information about 3020fa9e4066Sahrens * each one. 3021fa9e4066Sahrens * 3022fa9e4066Sahrens * -a Iterate through all pools and try to import each one. 3023fa9e4066Sahrens * 3024fa9e4066Sahrens * <id> Find the pool that corresponds to the given GUID/pool 3025fa9e4066Sahrens * name and import that one. 30264c58d714Sdarrenm * 30274c58d714Sdarrenm * -D Above options applies only to destroyed pools. 3028fa9e4066Sahrens */ 3029fa9e4066Sahrens if (argc != 0) { 3030fa9e4066Sahrens char *endptr; 3031fa9e4066Sahrens 3032fa9e4066Sahrens errno = 0; 3033fa9e4066Sahrens searchguid = strtoull(argv[0], &endptr, 10); 30349edf9ebdSPrasad Joshi if (errno != 0 || *endptr != '\0') { 3035fa9e4066Sahrens searchname = argv[0]; 30369edf9ebdSPrasad Joshi searchguid = 0; 30379edf9ebdSPrasad Joshi } 3038fa9e4066Sahrens found_config = NULL; 3039fa9e4066Sahrens 304024e697d4Sck /* 3041d41c4376SMark J Musante * User specified a name or guid. Ensure it's unique. 304224e697d4Sck */ 3043d8ab6e12SDon Brady target_exists_args_t search = {searchname, searchguid}; 3044d8ab6e12SDon Brady pool_exists = zpool_iter(g_zfs, name_or_guid_exists, &search); 304524e697d4Sck } 304624e697d4Sck 3047d41c4376SMark J Musante idata.path = searchdirs; 3048d41c4376SMark J Musante idata.paths = nsearch; 3049d41c4376SMark J Musante idata.poolname = searchname; 3050d41c4376SMark J Musante idata.guid = searchguid; 3051d41c4376SMark J Musante idata.cachefile = cachefile; 30526f793812SPavel Zakharov idata.policy = policy; 3053d41c4376SMark J Musante 3054d8ab6e12SDon Brady pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops); 3055d41c4376SMark J Musante 3056d8ab6e12SDon Brady if (pools != NULL && pool_exists && 3057d41c4376SMark J Musante (argc == 1 || strcmp(argv[0], argv[1]) == 0)) { 3058d41c4376SMark J Musante (void) fprintf(stderr, gettext("cannot import '%s': " 3059d41c4376SMark J Musante "a pool with that name already exists\n"), 3060d41c4376SMark J Musante argv[0]); 306104e56356SAndriy Gapon (void) fprintf(stderr, gettext("use the form 'zpool import " 306204e56356SAndriy Gapon "[-t] <pool | id> <newpool>' to give it a new temporary " 306304e56356SAndriy Gapon "or permanent name\n")); 3064d41c4376SMark J Musante err = 1; 3065d8ab6e12SDon Brady } else if (pools == NULL && pool_exists) { 3066d41c4376SMark J Musante (void) fprintf(stderr, gettext("cannot import '%s': " 3067d41c4376SMark J Musante "a pool with that name is already created/imported,\n"), 3068d41c4376SMark J Musante argv[0]); 3069d41c4376SMark J Musante (void) fprintf(stderr, gettext("and no additional pools " 3070d41c4376SMark J Musante "with that name were found\n")); 3071d41c4376SMark J Musante err = 1; 3072d41c4376SMark J Musante } else if (pools == NULL) { 307324e697d4Sck if (argc != 0) { 307424e697d4Sck (void) fprintf(stderr, gettext("cannot import '%s': " 307524e697d4Sck "no such pool available\n"), argv[0]); 307624e697d4Sck } 3077d41c4376SMark J Musante err = 1; 3078d41c4376SMark J Musante } 3079d41c4376SMark J Musante 3080d41c4376SMark J Musante if (err == 1) { 308124e697d4Sck free(searchdirs); 3082468c413aSTim Haley nvlist_free(policy); 308324e697d4Sck return (1); 308424e697d4Sck } 308524e697d4Sck 308624e697d4Sck /* 308724e697d4Sck * At this point we have a list of import candidate configs. Even if 308824e697d4Sck * we were searching by pool name or guid, we still need to 308924e697d4Sck * post-process the list to deal with pool state and possible 309024e697d4Sck * duplicate names. 309124e697d4Sck */ 3092fa9e4066Sahrens err = 0; 3093fa9e4066Sahrens elem = NULL; 309499653d4eSeschrock first = B_TRUE; 3095fa9e4066Sahrens while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 3096fa9e4066Sahrens 3097fa9e4066Sahrens verify(nvpair_value_nvlist(elem, &config) == 0); 3098fa9e4066Sahrens 30994c58d714Sdarrenm verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 31004c58d714Sdarrenm &pool_state) == 0); 31014c58d714Sdarrenm if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) 31024c58d714Sdarrenm continue; 31034c58d714Sdarrenm if (do_destroyed && pool_state != POOL_STATE_DESTROYED) 31044c58d714Sdarrenm continue; 31054c58d714Sdarrenm 31065dafeea3SPavel Zakharov verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY, 3107468c413aSTim Haley policy) == 0); 3108468c413aSTim Haley 3109fa9e4066Sahrens if (argc == 0) { 3110fa9e4066Sahrens if (first) 311199653d4eSeschrock first = B_FALSE; 31123bb79becSeschrock else if (!do_all) 3113fa9e4066Sahrens (void) printf("\n"); 3114fa9e4066Sahrens 3115468c413aSTim Haley if (do_all) { 3116fa9e4066Sahrens err |= do_import(config, NULL, mntopts, 31174b964adaSGeorge Wilson props, flags); 3118468c413aSTim Haley } else { 3119fa9e4066Sahrens show_import(config); 3120468c413aSTim Haley } 3121fa9e4066Sahrens } else if (searchname != NULL) { 3122fa9e4066Sahrens char *name; 3123fa9e4066Sahrens 3124fa9e4066Sahrens /* 3125fa9e4066Sahrens * We are searching for a pool based on name. 3126fa9e4066Sahrens */ 3127fa9e4066Sahrens verify(nvlist_lookup_string(config, 3128fa9e4066Sahrens ZPOOL_CONFIG_POOL_NAME, &name) == 0); 3129fa9e4066Sahrens 3130fa9e4066Sahrens if (strcmp(name, searchname) == 0) { 3131fa9e4066Sahrens if (found_config != NULL) { 3132fa9e4066Sahrens (void) fprintf(stderr, gettext( 3133fa9e4066Sahrens "cannot import '%s': more than " 3134fa9e4066Sahrens "one matching pool\n"), searchname); 3135fa9e4066Sahrens (void) fprintf(stderr, gettext( 3136fa9e4066Sahrens "import by numeric ID instead\n")); 313799653d4eSeschrock err = B_TRUE; 3138fa9e4066Sahrens } 3139fa9e4066Sahrens found_config = config; 3140fa9e4066Sahrens } 3141fa9e4066Sahrens } else { 3142fa9e4066Sahrens uint64_t guid; 3143fa9e4066Sahrens 3144fa9e4066Sahrens /* 3145fa9e4066Sahrens * Search for a pool by guid. 3146fa9e4066Sahrens */ 3147fa9e4066Sahrens verify(nvlist_lookup_uint64(config, 3148fa9e4066Sahrens ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 3149fa9e4066Sahrens 3150fa9e4066Sahrens if (guid == searchguid) 3151fa9e4066Sahrens found_config = config; 3152fa9e4066Sahrens } 3153fa9e4066Sahrens } 3154fa9e4066Sahrens 3155fa9e4066Sahrens /* 3156fa9e4066Sahrens * If we were searching for a specific pool, verify that we found a 3157fa9e4066Sahrens * pool, and then do the import. 3158fa9e4066Sahrens */ 3159fa9e4066Sahrens if (argc != 0 && err == 0) { 3160fa9e4066Sahrens if (found_config == NULL) { 3161fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot import '%s': " 3162fa9e4066Sahrens "no such pool available\n"), argv[0]); 316399653d4eSeschrock err = B_TRUE; 3164fa9e4066Sahrens } else { 3165fa9e4066Sahrens err |= do_import(found_config, argc == 1 ? NULL : 31664b964adaSGeorge Wilson argv[1], mntopts, props, flags); 3167fa9e4066Sahrens } 3168fa9e4066Sahrens } 3169fa9e4066Sahrens 3170fa9e4066Sahrens /* 3171fa9e4066Sahrens * If we were just looking for pools, report an error if none were 3172fa9e4066Sahrens * found. 3173fa9e4066Sahrens */ 3174fa9e4066Sahrens if (argc == 0 && first) 3175fa9e4066Sahrens (void) fprintf(stderr, 3176fa9e4066Sahrens gettext("no pools available to import\n")); 3177fa9e4066Sahrens 3178ecd6cf80Smarks error: 31792f8aaab3Seschrock nvlist_free(props); 3180fa9e4066Sahrens nvlist_free(pools); 3181468c413aSTim Haley nvlist_free(policy); 318299653d4eSeschrock free(searchdirs); 3183fa9e4066Sahrens 3184fa9e4066Sahrens return (err ? 1 : 0); 3185fa9e4066Sahrens } 3186fa9e4066Sahrens 31879c2acf00SAlek Pinchuk /* 31889c2acf00SAlek Pinchuk * zpool sync [-f] [pool] ... 31899c2acf00SAlek Pinchuk * 31909c2acf00SAlek Pinchuk * -f (undocumented) force uberblock (and config including zpool cache file) 31919c2acf00SAlek Pinchuk * update. 31929c2acf00SAlek Pinchuk * 31939c2acf00SAlek Pinchuk * Sync the specified pool(s). 31949c2acf00SAlek Pinchuk * Without arguments "zpool sync" will sync all pools. 31959c2acf00SAlek Pinchuk * This command initiates TXG sync(s) and will return after the TXG(s) commit. 31969c2acf00SAlek Pinchuk * 31979c2acf00SAlek Pinchuk */ 31989c2acf00SAlek Pinchuk static int 31999c2acf00SAlek Pinchuk zpool_do_sync(int argc, char **argv) 32009c2acf00SAlek Pinchuk { 32019c2acf00SAlek Pinchuk int ret; 32029c2acf00SAlek Pinchuk boolean_t force = B_FALSE; 32039c2acf00SAlek Pinchuk 32049c2acf00SAlek Pinchuk /* check options */ 32059c2acf00SAlek Pinchuk while ((ret = getopt(argc, argv, "f")) != -1) { 32069c2acf00SAlek Pinchuk switch (ret) { 32079c2acf00SAlek Pinchuk case 'f': 32089c2acf00SAlek Pinchuk force = B_TRUE; 32099c2acf00SAlek Pinchuk break; 32109c2acf00SAlek Pinchuk case '?': 32119c2acf00SAlek Pinchuk (void) fprintf(stderr, gettext("invalid option '%c'\n"), 32129c2acf00SAlek Pinchuk optopt); 32139c2acf00SAlek Pinchuk usage(B_FALSE); 32149c2acf00SAlek Pinchuk } 32159c2acf00SAlek Pinchuk } 32169c2acf00SAlek Pinchuk 32179c2acf00SAlek Pinchuk argc -= optind; 32189c2acf00SAlek Pinchuk argv += optind; 32199c2acf00SAlek Pinchuk 32209c2acf00SAlek Pinchuk /* if argc == 0 we will execute zpool_sync_one on all pools */ 32219c2acf00SAlek Pinchuk ret = for_each_pool(argc, argv, B_FALSE, NULL, zpool_sync_one, &force); 32229c2acf00SAlek Pinchuk 32239c2acf00SAlek Pinchuk return (ret); 32249c2acf00SAlek Pinchuk } 32259c2acf00SAlek Pinchuk 3226fa9e4066Sahrens typedef struct iostat_cbdata { 3227dd50e0ccSTony Hutter uint64_t cb_flags; 3228663207adSDon Brady int cb_name_flags; 3229fa9e4066Sahrens int cb_namewidth; 32304263d13fSGeorge Wilson int cb_iteration; 3231dd50e0ccSTony Hutter char **cb_vdev_names; /* Only show these vdevs */ 3232dd50e0ccSTony Hutter unsigned int cb_vdev_names_count; 3233dd50e0ccSTony Hutter boolean_t cb_verbose; 3234dd50e0ccSTony Hutter boolean_t cb_literal; 3235663207adSDon Brady boolean_t cb_scripted; 32364263d13fSGeorge Wilson zpool_list_t *cb_list; 3237fa9e4066Sahrens } iostat_cbdata_t; 3238fa9e4066Sahrens 3239dd50e0ccSTony Hutter /* iostat labels */ 3240dd50e0ccSTony Hutter typedef struct name_and_columns { 3241dd50e0ccSTony Hutter const char *name; /* Column name */ 3242dd50e0ccSTony Hutter unsigned int columns; /* Center name to this number of columns */ 3243dd50e0ccSTony Hutter } name_and_columns_t; 3244dd50e0ccSTony Hutter 3245dd50e0ccSTony Hutter #define IOSTAT_MAX_LABELS 13 /* Max number of labels on one line */ 3246dd50e0ccSTony Hutter 3247dd50e0ccSTony Hutter static const name_and_columns_t iostat_top_labels[][IOSTAT_MAX_LABELS] = 3248dd50e0ccSTony Hutter { 3249dd50e0ccSTony Hutter [IOS_DEFAULT] = {{"capacity", 2}, {"operations", 2}, {"bandwidth", 2}, 3250dd50e0ccSTony Hutter {NULL}}, 3251dd50e0ccSTony Hutter [IOS_LATENCY] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2}, 3252dd50e0ccSTony Hutter {"asyncq_wait", 2}, {"scrub"}, {"trim", 1}, {NULL}}, 3253dd50e0ccSTony Hutter [IOS_QUEUES] = {{"syncq_read", 2}, {"syncq_write", 2}, 3254dd50e0ccSTony Hutter {"asyncq_read", 2}, {"asyncq_write", 2}, {"scrubq_read", 2}, 3255dd50e0ccSTony Hutter {"trimq_write", 2}, {NULL}}, 3256dd50e0ccSTony Hutter [IOS_L_HISTO] = {{"total_wait", 2}, {"disk_wait", 2}, {"syncq_wait", 2}, 3257dd50e0ccSTony Hutter {"asyncq_wait", 2}, {NULL}}, 3258dd50e0ccSTony Hutter [IOS_RQ_HISTO] = {{"sync_read", 2}, {"sync_write", 2}, 3259dd50e0ccSTony Hutter {"async_read", 2}, {"async_write", 2}, {"scrub", 2}, 3260dd50e0ccSTony Hutter {"trim", 2}, {NULL}}, 3261dd50e0ccSTony Hutter 3262dd50e0ccSTony Hutter }; 3263dd50e0ccSTony Hutter 3264dd50e0ccSTony Hutter /* Shorthand - if "columns" field not set, default to 1 column */ 3265dd50e0ccSTony Hutter static const name_and_columns_t iostat_bottom_labels[][IOSTAT_MAX_LABELS] = 3266dd50e0ccSTony Hutter { 3267dd50e0ccSTony Hutter [IOS_DEFAULT] = {{"alloc"}, {"free"}, {"read"}, {"write"}, {"read"}, 3268dd50e0ccSTony Hutter {"write"}, {NULL}}, 3269dd50e0ccSTony Hutter [IOS_LATENCY] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"}, 3270dd50e0ccSTony Hutter {"write"}, {"read"}, {"write"}, {"wait"}, {"wait"}, {NULL}}, 3271dd50e0ccSTony Hutter [IOS_QUEUES] = {{"pend"}, {"activ"}, {"pend"}, {"activ"}, {"pend"}, 3272dd50e0ccSTony Hutter {"activ"}, {"pend"}, {"activ"}, {"pend"}, {"activ"}, 3273dd50e0ccSTony Hutter {"pend"}, {"activ"}, {NULL}}, 3274dd50e0ccSTony Hutter [IOS_L_HISTO] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"}, 3275dd50e0ccSTony Hutter {"write"}, {"read"}, {"write"}, {"scrub"}, {"trim"}, {NULL}}, 3276dd50e0ccSTony Hutter [IOS_RQ_HISTO] = {{"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"}, 3277dd50e0ccSTony Hutter {"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"}, {NULL}}, 3278dd50e0ccSTony Hutter }; 3279dd50e0ccSTony Hutter 3280dd50e0ccSTony Hutter static const char *histo_to_title[] = { 3281dd50e0ccSTony Hutter [IOS_L_HISTO] = "latency", 3282dd50e0ccSTony Hutter [IOS_RQ_HISTO] = "req_size", 3283dd50e0ccSTony Hutter }; 3284dd50e0ccSTony Hutter 3285dd50e0ccSTony Hutter /* 3286dd50e0ccSTony Hutter * Return the number of labels in a null-terminated name_and_columns_t 3287dd50e0ccSTony Hutter * array. 3288dd50e0ccSTony Hutter * 3289dd50e0ccSTony Hutter */ 3290dd50e0ccSTony Hutter static unsigned int 3291dd50e0ccSTony Hutter label_array_len(const name_and_columns_t *labels) 3292fa9e4066Sahrens { 3293fa9e4066Sahrens int i = 0; 3294fa9e4066Sahrens 3295dd50e0ccSTony Hutter while (labels[i].name) 3296dd50e0ccSTony Hutter i++; 3297dd50e0ccSTony Hutter 3298dd50e0ccSTony Hutter return (i); 3299fa9e4066Sahrens } 3300fa9e4066Sahrens 3301dd50e0ccSTony Hutter /* 3302dd50e0ccSTony Hutter * Return the number of strings in a null-terminated string array. 3303dd50e0ccSTony Hutter * For example: 3304dd50e0ccSTony Hutter * 3305dd50e0ccSTony Hutter * const char foo[] = {"bar", "baz", NULL} 3306dd50e0ccSTony Hutter * 3307dd50e0ccSTony Hutter * returns 2 3308dd50e0ccSTony Hutter */ 3309dd50e0ccSTony Hutter static uint64_t 3310dd50e0ccSTony Hutter str_array_len(const char *array[]) 3311fa9e4066Sahrens { 3312dd50e0ccSTony Hutter uint64_t i = 0; 3313dd50e0ccSTony Hutter while (array[i]) 3314dd50e0ccSTony Hutter i++; 3315dd50e0ccSTony Hutter 3316dd50e0ccSTony Hutter return (i); 3317fa9e4066Sahrens } 3318fa9e4066Sahrens 3319dd50e0ccSTony Hutter 3320fa9e4066Sahrens /* 3321dd50e0ccSTony Hutter * Return a default column width for default/latency/queue columns. This does 3322dd50e0ccSTony Hutter * not include histograms, which have their columns autosized. 3323fa9e4066Sahrens */ 3324dd50e0ccSTony Hutter static unsigned int 3325dd50e0ccSTony Hutter default_column_width(iostat_cbdata_t *cb, enum iostat_type type) 3326fa9e4066Sahrens { 3327dd50e0ccSTony Hutter unsigned long column_width = 5; /* Normal niceprint */ 3328dd50e0ccSTony Hutter static unsigned long widths[] = { 3329dd50e0ccSTony Hutter /* 3330dd50e0ccSTony Hutter * Choose some sane default column sizes for printing the 3331dd50e0ccSTony Hutter * raw numbers. 3332dd50e0ccSTony Hutter */ 3333dd50e0ccSTony Hutter [IOS_DEFAULT] = 15, /* 1PB capacity */ 3334dd50e0ccSTony Hutter [IOS_LATENCY] = 10, /* 1B ns = 10sec */ 3335dd50e0ccSTony Hutter [IOS_QUEUES] = 6, /* 1M queue entries */ 3336dd50e0ccSTony Hutter [IOS_L_HISTO] = 10, /* 1B ns = 10sec */ 3337dd50e0ccSTony Hutter [IOS_RQ_HISTO] = 6, /* 1M queue entries */ 3338dd50e0ccSTony Hutter }; 3339fa9e4066Sahrens 3340dd50e0ccSTony Hutter if (cb->cb_literal) 3341dd50e0ccSTony Hutter column_width = widths[type]; 3342fa9e4066Sahrens 3343dd50e0ccSTony Hutter return (column_width); 3344dd50e0ccSTony Hutter } 3345663207adSDon Brady 3346fa9e4066Sahrens /* 3347dd50e0ccSTony Hutter * Print the column labels, i.e: 3348dd50e0ccSTony Hutter * 3349dd50e0ccSTony Hutter * capacity operations bandwidth 3350dd50e0ccSTony Hutter * alloc free read write read write ... 3351dd50e0ccSTony Hutter * 3352dd50e0ccSTony Hutter * If force_column_width is set, use it for the column width. If not set, use 3353dd50e0ccSTony Hutter * the default column width. 3354fa9e4066Sahrens */ 3355dd50e0ccSTony Hutter void 3356dd50e0ccSTony Hutter print_iostat_labels(iostat_cbdata_t *cb, unsigned int force_column_width, 3357dd50e0ccSTony Hutter const name_and_columns_t labels[][IOSTAT_MAX_LABELS]) 3358fa9e4066Sahrens { 3359dd50e0ccSTony Hutter int i, idx, s; 3360dd50e0ccSTony Hutter int text_start, rw_column_width, spaces_to_end; 3361dd50e0ccSTony Hutter uint64_t flags = cb->cb_flags; 3362dd50e0ccSTony Hutter uint64_t f; 3363dd50e0ccSTony Hutter unsigned int column_width = force_column_width; 3364dd50e0ccSTony Hutter 3365dd50e0ccSTony Hutter /* For each bit set in flags */ 3366dd50e0ccSTony Hutter for (f = flags; f; f &= ~(1ULL << idx)) { 3367dd50e0ccSTony Hutter idx = lowbit64(f) - 1; 3368dd50e0ccSTony Hutter if (!force_column_width) 3369dd50e0ccSTony Hutter column_width = default_column_width(cb, idx); 3370dd50e0ccSTony Hutter /* Print our top labels centered over "read write" label. */ 3371dd50e0ccSTony Hutter for (i = 0; i < label_array_len(labels[idx]); i++) { 3372dd50e0ccSTony Hutter const char *name = labels[idx][i].name; 3373dd50e0ccSTony Hutter /* 3374dd50e0ccSTony Hutter * We treat labels[][].columns == 0 as shorthand 3375dd50e0ccSTony Hutter * for one column. It makes writing out the label 3376dd50e0ccSTony Hutter * tables more concise. 3377dd50e0ccSTony Hutter */ 3378dd50e0ccSTony Hutter unsigned int columns = MAX(1, labels[idx][i].columns); 3379dd50e0ccSTony Hutter unsigned int slen = strlen(name); 3380fa9e4066Sahrens 3381dd50e0ccSTony Hutter rw_column_width = (column_width * columns) + 3382dd50e0ccSTony Hutter (2 * (columns - 1)); 33835cabbc6bSPrashanth Sreenivasa 3384dd50e0ccSTony Hutter text_start = (int)((rw_column_width) / columns - 3385dd50e0ccSTony Hutter slen / columns); 3386dd50e0ccSTony Hutter if (text_start < 0) 3387dd50e0ccSTony Hutter text_start = 0; 3388fa9e4066Sahrens 3389dd50e0ccSTony Hutter printf(" "); /* Two spaces between columns */ 3390fa9e4066Sahrens 3391dd50e0ccSTony Hutter /* Space from beginning of column to label */ 3392dd50e0ccSTony Hutter for (s = 0; s < text_start; s++) 3393dd50e0ccSTony Hutter printf(" "); 3394fa9e4066Sahrens 3395dd50e0ccSTony Hutter printf("%s", name); 3396fa9e4066Sahrens 3397dd50e0ccSTony Hutter /* Print space after label to end of column */ 3398dd50e0ccSTony Hutter spaces_to_end = rw_column_width - text_start - slen; 3399dd50e0ccSTony Hutter if (spaces_to_end < 0) 3400dd50e0ccSTony Hutter spaces_to_end = 0; 3401fa9e4066Sahrens 3402dd50e0ccSTony Hutter for (s = 0; s < spaces_to_end; s++) 3403dd50e0ccSTony Hutter printf(" "); 3404dd50e0ccSTony Hutter } 3405fa9e4066Sahrens } 3406dd50e0ccSTony Hutter } 3407fa9e4066Sahrens 3408dd50e0ccSTony Hutter /* 3409dd50e0ccSTony Hutter * Utility function to print out a line of dashes like: 3410dd50e0ccSTony Hutter * 3411dd50e0ccSTony Hutter * -------------------------------- ----- ----- ----- ----- ----- 3412dd50e0ccSTony Hutter * 3413dd50e0ccSTony Hutter * ...or a dashed named-row line like: 3414dd50e0ccSTony Hutter * 3415dd50e0ccSTony Hutter * logs - - - - - 3416dd50e0ccSTony Hutter * 3417dd50e0ccSTony Hutter * @cb: iostat data 3418dd50e0ccSTony Hutter * 3419dd50e0ccSTony Hutter * @force_column_width If non-zero, use the value as the column width. 3420dd50e0ccSTony Hutter * Otherwise use the default column widths. 3421dd50e0ccSTony Hutter * 3422dd50e0ccSTony Hutter * @name: Print a dashed named-row line starting 3423dd50e0ccSTony Hutter * with @name. Otherwise, print a regular 3424dd50e0ccSTony Hutter * dashed line. 3425dd50e0ccSTony Hutter */ 3426dd50e0ccSTony Hutter static void 3427dd50e0ccSTony Hutter print_iostat_dashes(iostat_cbdata_t *cb, unsigned int force_column_width, 3428dd50e0ccSTony Hutter const char *name) 3429dd50e0ccSTony Hutter { 3430dd50e0ccSTony Hutter int i; 3431dd50e0ccSTony Hutter unsigned int namewidth; 3432dd50e0ccSTony Hutter uint64_t flags = cb->cb_flags; 3433dd50e0ccSTony Hutter uint64_t f; 3434dd50e0ccSTony Hutter int idx; 3435dd50e0ccSTony Hutter const name_and_columns_t *labels; 3436dd50e0ccSTony Hutter const char *title; 3437fa9e4066Sahrens 3438fa9e4066Sahrens 3439dd50e0ccSTony Hutter if (cb->cb_flags & IOS_ANYHISTO_M) { 3440dd50e0ccSTony Hutter title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)]; 3441dd50e0ccSTony Hutter } else if (cb->cb_vdev_names_count) { 3442dd50e0ccSTony Hutter title = "vdev"; 3443dd50e0ccSTony Hutter } else { 3444dd50e0ccSTony Hutter title = "pool"; 3445dd50e0ccSTony Hutter } 3446fa9e4066Sahrens 3447dd50e0ccSTony Hutter namewidth = MAX(MAX(strlen(title), cb->cb_namewidth), 3448dd50e0ccSTony Hutter name ? strlen(name) : 0); 3449fa9e4066Sahrens 3450fa9e4066Sahrens 3451dd50e0ccSTony Hutter if (name) { 3452dd50e0ccSTony Hutter printf("%-*s", namewidth, name); 3453dd50e0ccSTony Hutter } else { 3454dd50e0ccSTony Hutter for (i = 0; i < namewidth; i++) 3455dd50e0ccSTony Hutter (void) printf("-"); 3456dd50e0ccSTony Hutter } 3457fa9e4066Sahrens 3458dd50e0ccSTony Hutter /* For each bit in flags */ 3459dd50e0ccSTony Hutter for (f = flags; f; f &= ~(1ULL << idx)) { 3460dd50e0ccSTony Hutter unsigned int column_width; 3461dd50e0ccSTony Hutter idx = lowbit64(f) - 1; 3462dd50e0ccSTony Hutter if (force_column_width) 3463dd50e0ccSTony Hutter column_width = force_column_width; 3464dd50e0ccSTony Hutter else 3465dd50e0ccSTony Hutter column_width = default_column_width(cb, idx); 3466fa9e4066Sahrens 3467dd50e0ccSTony Hutter labels = iostat_bottom_labels[idx]; 3468dd50e0ccSTony Hutter for (i = 0; i < label_array_len(labels); i++) { 3469dd50e0ccSTony Hutter if (name) 3470dd50e0ccSTony Hutter printf(" %*s-", column_width - 1, " "); 3471dd50e0ccSTony Hutter else 3472dd50e0ccSTony Hutter printf(" %.*s", column_width, 3473dd50e0ccSTony Hutter "--------------------"); 3474dd50e0ccSTony Hutter } 3475dd50e0ccSTony Hutter } 3476dd50e0ccSTony Hutter } 34773f9d6ad7SLin Ling 34789d439f90SMike Harsch 3479dd50e0ccSTony Hutter static void 3480dd50e0ccSTony Hutter print_iostat_separator_impl(iostat_cbdata_t *cb, 3481dd50e0ccSTony Hutter unsigned int force_column_width) 3482dd50e0ccSTony Hutter { 3483dd50e0ccSTony Hutter print_iostat_dashes(cb, force_column_width, NULL); 3484dd50e0ccSTony Hutter } 34859d439f90SMike Harsch 3486dd50e0ccSTony Hutter static void 3487dd50e0ccSTony Hutter print_iostat_separator(iostat_cbdata_t *cb) 3488dd50e0ccSTony Hutter { 3489dd50e0ccSTony Hutter print_iostat_separator_impl(cb, 0); 3490dd50e0ccSTony Hutter } 34913f9d6ad7SLin Ling 3492dd50e0ccSTony Hutter static void 3493dd50e0ccSTony Hutter print_iostat_header_impl(iostat_cbdata_t *cb, unsigned int force_column_width, 3494dd50e0ccSTony Hutter const char *histo_vdev_name) 3495dd50e0ccSTony Hutter { 3496dd50e0ccSTony Hutter unsigned int namewidth; 3497dd50e0ccSTony Hutter const char *title; 3498663207adSDon Brady 3499dd50e0ccSTony Hutter if (cb->cb_flags & IOS_ANYHISTO_M) { 3500dd50e0ccSTony Hutter title = histo_to_title[IOS_HISTO_IDX(cb->cb_flags)]; 3501dd50e0ccSTony Hutter } else if (cb->cb_vdev_names_count) { 3502dd50e0ccSTony Hutter title = "vdev"; 3503dd50e0ccSTony Hutter } else { 3504dd50e0ccSTony Hutter title = "pool"; 3505afefbcddSeschrock } 3506fa94a07fSbrendan 3507dd50e0ccSTony Hutter namewidth = MAX(MAX(strlen(title), cb->cb_namewidth), 3508dd50e0ccSTony Hutter histo_vdev_name ? strlen(histo_vdev_name) : 0); 3509663207adSDon Brady 3510dd50e0ccSTony Hutter if (histo_vdev_name) 3511dd50e0ccSTony Hutter printf("%-*s", namewidth, histo_vdev_name); 3512dd50e0ccSTony Hutter else 3513dd50e0ccSTony Hutter printf("%*s", namewidth, ""); 3514663207adSDon Brady 3515c4e4d410SAndy Fiddaman 3516dd50e0ccSTony Hutter print_iostat_labels(cb, force_column_width, iostat_top_labels); 3517dd50e0ccSTony Hutter printf("\n"); 35189d439f90SMike Harsch 3519dd50e0ccSTony Hutter printf("%-*s", namewidth, title); 35209d439f90SMike Harsch 3521dd50e0ccSTony Hutter print_iostat_labels(cb, force_column_width, iostat_bottom_labels); 3522fa94a07fSbrendan 3523dd50e0ccSTony Hutter printf("\n"); 3524fa94a07fSbrendan 3525dd50e0ccSTony Hutter print_iostat_separator_impl(cb, force_column_width); 3526dd50e0ccSTony Hutter 3527dd50e0ccSTony Hutter printf("\n"); 3528fa9e4066Sahrens } 3529fa9e4066Sahrens 3530dd50e0ccSTony Hutter static void 3531dd50e0ccSTony Hutter print_iostat_header(iostat_cbdata_t *cb) 3532088e9d47Seschrock { 3533dd50e0ccSTony Hutter print_iostat_header_impl(cb, 0, NULL); 3534dd50e0ccSTony Hutter } 3535088e9d47Seschrock 3536dd50e0ccSTony Hutter /* 3537dd50e0ccSTony Hutter * Display a single statistic. 3538dd50e0ccSTony Hutter */ 3539dd50e0ccSTony Hutter static void 3540dd50e0ccSTony Hutter print_one_stat(uint64_t value, enum zfs_nicenum_format format, 3541dd50e0ccSTony Hutter unsigned int column_size, boolean_t scripted) 3542dd50e0ccSTony Hutter { 3543dd50e0ccSTony Hutter char buf[64]; 354494de1d4cSeschrock 3545dd50e0ccSTony Hutter zfs_nicenum_format(value, buf, sizeof (buf), format); 3546088e9d47Seschrock 3547dd50e0ccSTony Hutter if (scripted) 3548dd50e0ccSTony Hutter printf("\t%s", buf); 3549dd50e0ccSTony Hutter else 3550dd50e0ccSTony Hutter printf(" %*s", column_size, buf); 3551088e9d47Seschrock } 3552088e9d47Seschrock 3553fa9e4066Sahrens /* 3554dd50e0ccSTony Hutter * Calculate the default vdev stats 3555dd50e0ccSTony Hutter * 3556dd50e0ccSTony Hutter * Subtract oldvs from newvs, apply a scaling factor, and save the resulting 3557dd50e0ccSTony Hutter * stats into calcvs. 3558fa9e4066Sahrens */ 3559dd50e0ccSTony Hutter static void 3560dd50e0ccSTony Hutter calc_default_iostats(vdev_stat_t *oldvs, vdev_stat_t *newvs, 3561dd50e0ccSTony Hutter vdev_stat_t *calcvs) 3562fa9e4066Sahrens { 3563dd50e0ccSTony Hutter int i; 3564fa9e4066Sahrens 3565dd50e0ccSTony Hutter memcpy(calcvs, newvs, sizeof (*calcvs)); 3566dd50e0ccSTony Hutter for (i = 0; i < ARRAY_SIZE(calcvs->vs_ops); i++) 3567dd50e0ccSTony Hutter calcvs->vs_ops[i] = (newvs->vs_ops[i] - oldvs->vs_ops[i]); 3568fa9e4066Sahrens 3569dd50e0ccSTony Hutter for (i = 0; i < ARRAY_SIZE(calcvs->vs_bytes); i++) 3570dd50e0ccSTony Hutter calcvs->vs_bytes[i] = (newvs->vs_bytes[i] - oldvs->vs_bytes[i]); 3571dd50e0ccSTony Hutter } 3572fa9e4066Sahrens 3573dd50e0ccSTony Hutter /* 3574dd50e0ccSTony Hutter * Internal representation of the extended iostats data. 3575dd50e0ccSTony Hutter * 3576dd50e0ccSTony Hutter * The extended iostat stats are exported in nvlists as either uint64_t arrays 3577dd50e0ccSTony Hutter * or single uint64_t's. We make both look like arrays to make them easier 3578dd50e0ccSTony Hutter * to process. In order to make single uint64_t's look like arrays, we set 3579dd50e0ccSTony Hutter * __data to the stat data, and then set *data = &__data with count = 1. Then, 3580dd50e0ccSTony Hutter * we can just use *data and count. 3581dd50e0ccSTony Hutter */ 3582dd50e0ccSTony Hutter struct stat_array { 3583dd50e0ccSTony Hutter uint64_t *data; 3584dd50e0ccSTony Hutter uint_t count; /* Number of entries in data[] */ 3585dd50e0ccSTony Hutter uint64_t __data; /* Only used when data is a single uint64_t */ 3586dd50e0ccSTony Hutter }; 3587fa9e4066Sahrens 3588dd50e0ccSTony Hutter static uint64_t 3589dd50e0ccSTony Hutter stat_histo_max(struct stat_array *nva, unsigned int len) 3590dd50e0ccSTony Hutter { 3591dd50e0ccSTony Hutter uint64_t max = 0; 3592dd50e0ccSTony Hutter int i; 3593dd50e0ccSTony Hutter for (i = 0; i < len; i++) 3594dd50e0ccSTony Hutter max = MAX(max, array64_max(nva[i].data, nva[i].count)); 3595fa9e4066Sahrens 3596dd50e0ccSTony Hutter return (max); 3597dd50e0ccSTony Hutter } 3598fa9e4066Sahrens 3599dd50e0ccSTony Hutter /* 3600dd50e0ccSTony Hutter * Helper function to lookup a uint64_t array or uint64_t value and store its 3601dd50e0ccSTony Hutter * data as a stat_array. If the nvpair is a single uint64_t value, then we make 3602dd50e0ccSTony Hutter * it look like a one element array to make it easier to process. 3603dd50e0ccSTony Hutter */ 3604dd50e0ccSTony Hutter static int 3605dd50e0ccSTony Hutter nvpair64_to_stat_array(nvlist_t *nvl, const char *name, 3606dd50e0ccSTony Hutter struct stat_array *nva) 3607dd50e0ccSTony Hutter { 3608dd50e0ccSTony Hutter nvpair_t *tmp; 3609dd50e0ccSTony Hutter int ret; 3610dd50e0ccSTony Hutter 3611dd50e0ccSTony Hutter verify(nvlist_lookup_nvpair(nvl, name, &tmp) == 0); 3612dd50e0ccSTony Hutter switch (nvpair_type(tmp)) { 3613dd50e0ccSTony Hutter case DATA_TYPE_UINT64_ARRAY: 3614dd50e0ccSTony Hutter ret = nvpair_value_uint64_array(tmp, &nva->data, &nva->count); 3615dd50e0ccSTony Hutter break; 3616dd50e0ccSTony Hutter case DATA_TYPE_UINT64: 3617dd50e0ccSTony Hutter ret = nvpair_value_uint64(tmp, &nva->__data); 3618dd50e0ccSTony Hutter nva->data = &nva->__data; 3619dd50e0ccSTony Hutter nva->count = 1; 3620dd50e0ccSTony Hutter break; 3621dd50e0ccSTony Hutter default: 3622dd50e0ccSTony Hutter /* Not a uint64_t */ 3623dd50e0ccSTony Hutter ret = EINVAL; 3624dd50e0ccSTony Hutter break; 3625dd50e0ccSTony Hutter } 3626dd50e0ccSTony Hutter 3627dd50e0ccSTony Hutter return (ret); 3628dd50e0ccSTony Hutter } 3629dd50e0ccSTony Hutter 3630dd50e0ccSTony Hutter /* 3631dd50e0ccSTony Hutter * Given a list of nvlist names, look up the extended stats in newnv and oldnv, 3632dd50e0ccSTony Hutter * subtract them, and return the results in a newly allocated stat_array. 3633dd50e0ccSTony Hutter * You must free the returned array after you are done with it with 3634dd50e0ccSTony Hutter * free_calc_stats(). 3635dd50e0ccSTony Hutter * 3636dd50e0ccSTony Hutter * Additionally, you can set "oldnv" to NULL if you simply want the newnv 3637dd50e0ccSTony Hutter * values. 3638dd50e0ccSTony Hutter */ 3639dd50e0ccSTony Hutter static struct stat_array * 3640dd50e0ccSTony Hutter calc_and_alloc_stats_ex(const char **names, unsigned int len, nvlist_t *oldnv, 3641dd50e0ccSTony Hutter nvlist_t *newnv) 3642dd50e0ccSTony Hutter { 3643dd50e0ccSTony Hutter nvlist_t *oldnvx = NULL, *newnvx; 3644dd50e0ccSTony Hutter struct stat_array *oldnva, *newnva, *calcnva; 3645dd50e0ccSTony Hutter int i, j; 3646dd50e0ccSTony Hutter unsigned int alloc_size = (sizeof (struct stat_array)) * len; 3647dd50e0ccSTony Hutter 3648dd50e0ccSTony Hutter /* Extract our extended stats nvlist from the main list */ 3649dd50e0ccSTony Hutter verify(nvlist_lookup_nvlist(newnv, ZPOOL_CONFIG_VDEV_STATS_EX, 3650dd50e0ccSTony Hutter &newnvx) == 0); 3651dd50e0ccSTony Hutter if (oldnv) { 3652dd50e0ccSTony Hutter verify(nvlist_lookup_nvlist(oldnv, ZPOOL_CONFIG_VDEV_STATS_EX, 3653dd50e0ccSTony Hutter &oldnvx) == 0); 3654dd50e0ccSTony Hutter } 3655dd50e0ccSTony Hutter 3656dd50e0ccSTony Hutter newnva = safe_malloc(alloc_size); 3657dd50e0ccSTony Hutter oldnva = safe_malloc(alloc_size); 3658dd50e0ccSTony Hutter calcnva = safe_malloc(alloc_size); 3659dd50e0ccSTony Hutter 3660dd50e0ccSTony Hutter for (j = 0; j < len; j++) { 3661dd50e0ccSTony Hutter verify(nvpair64_to_stat_array(newnvx, names[j], 3662dd50e0ccSTony Hutter &newnva[j]) == 0); 3663dd50e0ccSTony Hutter calcnva[j].count = newnva[j].count; 3664dd50e0ccSTony Hutter alloc_size = calcnva[j].count * sizeof (calcnva[j].data[0]); 3665dd50e0ccSTony Hutter calcnva[j].data = safe_malloc(alloc_size); 3666dd50e0ccSTony Hutter memcpy(calcnva[j].data, newnva[j].data, alloc_size); 3667dd50e0ccSTony Hutter 3668dd50e0ccSTony Hutter if (oldnvx) { 3669dd50e0ccSTony Hutter verify(nvpair64_to_stat_array(oldnvx, names[j], 3670dd50e0ccSTony Hutter &oldnva[j]) == 0); 3671dd50e0ccSTony Hutter for (i = 0; i < oldnva[j].count; i++) 3672dd50e0ccSTony Hutter calcnva[j].data[i] -= oldnva[j].data[i]; 3673dd50e0ccSTony Hutter } 3674dd50e0ccSTony Hutter } 3675dd50e0ccSTony Hutter free(newnva); 3676dd50e0ccSTony Hutter free(oldnva); 3677dd50e0ccSTony Hutter return (calcnva); 3678dd50e0ccSTony Hutter } 3679dd50e0ccSTony Hutter 3680dd50e0ccSTony Hutter static void 3681dd50e0ccSTony Hutter free_calc_stats(struct stat_array *nva, unsigned int len) 3682dd50e0ccSTony Hutter { 3683dd50e0ccSTony Hutter int i; 3684dd50e0ccSTony Hutter for (i = 0; i < len; i++) 3685dd50e0ccSTony Hutter free(nva[i].data); 3686dd50e0ccSTony Hutter 3687dd50e0ccSTony Hutter free(nva); 3688dd50e0ccSTony Hutter } 3689dd50e0ccSTony Hutter 3690dd50e0ccSTony Hutter static void 3691dd50e0ccSTony Hutter print_iostat_histo(struct stat_array *nva, unsigned int len, 3692dd50e0ccSTony Hutter iostat_cbdata_t *cb, unsigned int column_width, unsigned int namewidth, 3693dd50e0ccSTony Hutter double scale) 3694dd50e0ccSTony Hutter { 3695dd50e0ccSTony Hutter int i, j; 3696dd50e0ccSTony Hutter char buf[6]; 3697dd50e0ccSTony Hutter uint64_t val; 3698dd50e0ccSTony Hutter enum zfs_nicenum_format format; 3699dd50e0ccSTony Hutter unsigned int buckets; 3700dd50e0ccSTony Hutter unsigned int start_bucket; 3701dd50e0ccSTony Hutter 3702dd50e0ccSTony Hutter if (cb->cb_literal) 3703dd50e0ccSTony Hutter format = ZFS_NICENUM_RAW; 3704dd50e0ccSTony Hutter else 3705dd50e0ccSTony Hutter format = ZFS_NICENUM_1024; 3706dd50e0ccSTony Hutter 3707dd50e0ccSTony Hutter /* All these histos are the same size, so just use nva[0].count */ 3708dd50e0ccSTony Hutter buckets = nva[0].count; 3709dd50e0ccSTony Hutter 3710dd50e0ccSTony Hutter if (cb->cb_flags & IOS_RQ_HISTO_M) { 3711dd50e0ccSTony Hutter /* Start at 512 - req size should never be lower than this */ 3712dd50e0ccSTony Hutter start_bucket = 9; 3713dd50e0ccSTony Hutter } else { 3714dd50e0ccSTony Hutter start_bucket = 0; 3715dd50e0ccSTony Hutter } 3716dd50e0ccSTony Hutter 3717dd50e0ccSTony Hutter for (j = start_bucket; j < buckets; j++) { 3718dd50e0ccSTony Hutter /* Print histogram bucket label */ 3719dd50e0ccSTony Hutter if (cb->cb_flags & IOS_L_HISTO_M) { 3720dd50e0ccSTony Hutter /* Ending range of this bucket */ 3721dd50e0ccSTony Hutter val = (1ULL << (j + 1)) - 1; 3722dd50e0ccSTony Hutter zfs_nicetime(val, buf, sizeof (buf)); 3723dd50e0ccSTony Hutter } else { 3724dd50e0ccSTony Hutter /* Request size (starting range of bucket) */ 3725dd50e0ccSTony Hutter val = (1UL << j); 3726dd50e0ccSTony Hutter zfs_nicenum(val, buf, sizeof (buf)); 3727dd50e0ccSTony Hutter } 3728dd50e0ccSTony Hutter 3729dd50e0ccSTony Hutter if (cb->cb_scripted) 3730dd50e0ccSTony Hutter printf("%llu", (u_longlong_t)val); 3731dd50e0ccSTony Hutter else 3732dd50e0ccSTony Hutter printf("%-*s", namewidth, buf); 3733dd50e0ccSTony Hutter 3734dd50e0ccSTony Hutter /* Print the values on the line */ 3735dd50e0ccSTony Hutter for (i = 0; i < len; i++) { 3736dd50e0ccSTony Hutter print_one_stat(nva[i].data[j] * scale, format, 3737dd50e0ccSTony Hutter column_width, cb->cb_scripted); 3738dd50e0ccSTony Hutter } 3739dd50e0ccSTony Hutter printf("\n"); 3740dd50e0ccSTony Hutter } 3741dd50e0ccSTony Hutter } 3742dd50e0ccSTony Hutter 3743dd50e0ccSTony Hutter static void 3744dd50e0ccSTony Hutter print_solid_separator(unsigned int length) 3745dd50e0ccSTony Hutter { 3746dd50e0ccSTony Hutter while (length--) 3747dd50e0ccSTony Hutter printf("-"); 3748dd50e0ccSTony Hutter printf("\n"); 3749dd50e0ccSTony Hutter } 3750dd50e0ccSTony Hutter 3751dd50e0ccSTony Hutter static void 3752dd50e0ccSTony Hutter print_iostat_histos(iostat_cbdata_t *cb, nvlist_t *oldnv, 3753dd50e0ccSTony Hutter nvlist_t *newnv, double scale, const char *name) 3754dd50e0ccSTony Hutter { 3755dd50e0ccSTony Hutter unsigned int column_width; 3756dd50e0ccSTony Hutter unsigned int namewidth; 3757dd50e0ccSTony Hutter unsigned int entire_width; 3758dd50e0ccSTony Hutter enum iostat_type type; 3759dd50e0ccSTony Hutter struct stat_array *nva; 3760dd50e0ccSTony Hutter const char **names; 3761dd50e0ccSTony Hutter unsigned int names_len; 3762dd50e0ccSTony Hutter 3763dd50e0ccSTony Hutter /* What type of histo are we? */ 3764dd50e0ccSTony Hutter type = IOS_HISTO_IDX(cb->cb_flags); 3765dd50e0ccSTony Hutter 3766dd50e0ccSTony Hutter /* Get NULL-terminated array of nvlist names for our histo */ 3767dd50e0ccSTony Hutter names = vsx_type_to_nvlist[type]; 3768dd50e0ccSTony Hutter names_len = str_array_len(names); /* num of names */ 3769dd50e0ccSTony Hutter 3770dd50e0ccSTony Hutter nva = calc_and_alloc_stats_ex(names, names_len, oldnv, newnv); 3771dd50e0ccSTony Hutter 3772dd50e0ccSTony Hutter if (cb->cb_literal) { 3773dd50e0ccSTony Hutter column_width = MAX(5, 3774dd50e0ccSTony Hutter (unsigned int) log10(stat_histo_max(nva, names_len)) + 1); 3775dd50e0ccSTony Hutter } else { 3776dd50e0ccSTony Hutter column_width = 5; 3777dd50e0ccSTony Hutter } 3778dd50e0ccSTony Hutter 3779dd50e0ccSTony Hutter namewidth = MAX(cb->cb_namewidth, 3780dd50e0ccSTony Hutter strlen(histo_to_title[IOS_HISTO_IDX(cb->cb_flags)])); 3781dd50e0ccSTony Hutter 3782dd50e0ccSTony Hutter /* 3783dd50e0ccSTony Hutter * Calculate the entire line width of what we're printing. The 3784dd50e0ccSTony Hutter * +2 is for the two spaces between columns: 3785dd50e0ccSTony Hutter */ 3786dd50e0ccSTony Hutter /* read write */ 3787dd50e0ccSTony Hutter /* ----- ----- */ 3788dd50e0ccSTony Hutter /* |___| <---------- column_width */ 3789dd50e0ccSTony Hutter /* */ 3790dd50e0ccSTony Hutter /* |__________| <--- entire_width */ 3791dd50e0ccSTony Hutter /* */ 3792dd50e0ccSTony Hutter entire_width = namewidth + (column_width + 2) * 3793dd50e0ccSTony Hutter label_array_len(iostat_bottom_labels[type]); 3794dd50e0ccSTony Hutter 3795dd50e0ccSTony Hutter if (cb->cb_scripted) 3796dd50e0ccSTony Hutter printf("%s\n", name); 3797dd50e0ccSTony Hutter else 3798dd50e0ccSTony Hutter print_iostat_header_impl(cb, column_width, name); 3799dd50e0ccSTony Hutter 3800dd50e0ccSTony Hutter print_iostat_histo(nva, names_len, cb, column_width, 3801dd50e0ccSTony Hutter namewidth, scale); 3802dd50e0ccSTony Hutter 3803dd50e0ccSTony Hutter free_calc_stats(nva, names_len); 3804dd50e0ccSTony Hutter if (!cb->cb_scripted) 3805dd50e0ccSTony Hutter print_solid_separator(entire_width); 3806dd50e0ccSTony Hutter } 3807dd50e0ccSTony Hutter 3808dd50e0ccSTony Hutter /* 3809dd50e0ccSTony Hutter * Calculate the average latency of a power-of-two latency histogram 3810dd50e0ccSTony Hutter */ 3811dd50e0ccSTony Hutter static uint64_t 3812dd50e0ccSTony Hutter single_histo_average(uint64_t *histo, unsigned int buckets) 3813dd50e0ccSTony Hutter { 3814dd50e0ccSTony Hutter int i; 3815dd50e0ccSTony Hutter uint64_t count = 0, total = 0; 3816dd50e0ccSTony Hutter 3817dd50e0ccSTony Hutter for (i = 0; i < buckets; i++) { 3818dd50e0ccSTony Hutter /* 3819dd50e0ccSTony Hutter * Our buckets are power-of-two latency ranges. Use the 3820dd50e0ccSTony Hutter * midpoint latency of each bucket to calculate the average. 3821dd50e0ccSTony Hutter * For example: 3822dd50e0ccSTony Hutter * 3823dd50e0ccSTony Hutter * Bucket Midpoint 3824dd50e0ccSTony Hutter * 8ns-15ns: 12ns 3825dd50e0ccSTony Hutter * 16ns-31ns: 24ns 3826dd50e0ccSTony Hutter * ... 3827dd50e0ccSTony Hutter */ 3828dd50e0ccSTony Hutter if (histo[i] != 0) { 3829dd50e0ccSTony Hutter total += histo[i] * (((1UL << i) + ((1UL << i)/2))); 3830dd50e0ccSTony Hutter count += histo[i]; 3831dd50e0ccSTony Hutter } 3832dd50e0ccSTony Hutter } 3833dd50e0ccSTony Hutter 3834dd50e0ccSTony Hutter /* Prevent divide by zero */ 3835dd50e0ccSTony Hutter return (count == 0 ? 0 : total / count); 3836dd50e0ccSTony Hutter } 3837dd50e0ccSTony Hutter 3838dd50e0ccSTony Hutter static void 3839dd50e0ccSTony Hutter print_iostat_queues(iostat_cbdata_t *cb, nvlist_t *oldnv, 3840dd50e0ccSTony Hutter nvlist_t *newnv) 3841dd50e0ccSTony Hutter { 3842dd50e0ccSTony Hutter int i; 3843dd50e0ccSTony Hutter uint64_t val; 3844dd50e0ccSTony Hutter const char *names[] = { 3845dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_R_PEND_QUEUE, 3846dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE, 3847dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_W_PEND_QUEUE, 3848dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE, 3849dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_R_PEND_QUEUE, 3850dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE, 3851dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_W_PEND_QUEUE, 3852dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE, 3853dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SCRUB_PEND_QUEUE, 3854dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE, 3855dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TRIM_PEND_QUEUE, 3856dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE, 3857dd50e0ccSTony Hutter }; 3858dd50e0ccSTony Hutter 3859dd50e0ccSTony Hutter struct stat_array *nva; 3860dd50e0ccSTony Hutter 3861dd50e0ccSTony Hutter unsigned int column_width = default_column_width(cb, IOS_QUEUES); 3862dd50e0ccSTony Hutter enum zfs_nicenum_format format; 3863dd50e0ccSTony Hutter 3864dd50e0ccSTony Hutter nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), NULL, newnv); 3865dd50e0ccSTony Hutter 3866dd50e0ccSTony Hutter if (cb->cb_literal) 3867dd50e0ccSTony Hutter format = ZFS_NICENUM_RAW; 3868dd50e0ccSTony Hutter else 3869dd50e0ccSTony Hutter format = ZFS_NICENUM_1024; 3870dd50e0ccSTony Hutter 3871dd50e0ccSTony Hutter for (i = 0; i < ARRAY_SIZE(names); i++) { 3872dd50e0ccSTony Hutter val = nva[i].data[0]; 3873dd50e0ccSTony Hutter print_one_stat(val, format, column_width, cb->cb_scripted); 3874dd50e0ccSTony Hutter } 3875dd50e0ccSTony Hutter 3876dd50e0ccSTony Hutter free_calc_stats(nva, ARRAY_SIZE(names)); 3877dd50e0ccSTony Hutter } 3878dd50e0ccSTony Hutter 3879dd50e0ccSTony Hutter static void 3880dd50e0ccSTony Hutter print_iostat_latency(iostat_cbdata_t *cb, nvlist_t *oldnv, 3881dd50e0ccSTony Hutter nvlist_t *newnv) 3882dd50e0ccSTony Hutter { 3883dd50e0ccSTony Hutter int i; 3884dd50e0ccSTony Hutter uint64_t val; 3885dd50e0ccSTony Hutter const char *names[] = { 3886dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO, 3887dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO, 3888dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO, 3889dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO, 3890dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO, 3891dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO, 3892dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO, 3893dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO, 3894dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO, 3895dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO, 3896dd50e0ccSTony Hutter }; 3897dd50e0ccSTony Hutter struct stat_array *nva; 3898dd50e0ccSTony Hutter 3899dd50e0ccSTony Hutter unsigned int column_width = default_column_width(cb, IOS_LATENCY); 3900dd50e0ccSTony Hutter enum zfs_nicenum_format format; 3901dd50e0ccSTony Hutter 3902dd50e0ccSTony Hutter nva = calc_and_alloc_stats_ex(names, ARRAY_SIZE(names), oldnv, newnv); 3903dd50e0ccSTony Hutter 3904dd50e0ccSTony Hutter if (cb->cb_literal) 3905dd50e0ccSTony Hutter format = ZFS_NICENUM_RAWTIME; 3906dd50e0ccSTony Hutter else 3907dd50e0ccSTony Hutter format = ZFS_NICENUM_TIME; 3908dd50e0ccSTony Hutter 3909dd50e0ccSTony Hutter /* Print our avg latencies on the line */ 3910dd50e0ccSTony Hutter for (i = 0; i < ARRAY_SIZE(names); i++) { 3911dd50e0ccSTony Hutter /* Compute average latency for a latency histo */ 3912dd50e0ccSTony Hutter val = single_histo_average(nva[i].data, nva[i].count); 3913dd50e0ccSTony Hutter print_one_stat(val, format, column_width, cb->cb_scripted); 3914dd50e0ccSTony Hutter } 3915dd50e0ccSTony Hutter free_calc_stats(nva, ARRAY_SIZE(names)); 3916dd50e0ccSTony Hutter } 3917dd50e0ccSTony Hutter 3918dd50e0ccSTony Hutter /* 3919dd50e0ccSTony Hutter * Print default statistics (capacity/operations/bandwidth) 3920dd50e0ccSTony Hutter */ 3921dd50e0ccSTony Hutter static void 3922dd50e0ccSTony Hutter print_iostat_default(vdev_stat_t *vs, iostat_cbdata_t *cb, double scale) 3923dd50e0ccSTony Hutter { 3924dd50e0ccSTony Hutter unsigned int column_width = default_column_width(cb, IOS_DEFAULT); 3925dd50e0ccSTony Hutter enum zfs_nicenum_format format; 3926dd50e0ccSTony Hutter char na; /* char to print for "not applicable" values */ 3927dd50e0ccSTony Hutter 3928dd50e0ccSTony Hutter if (cb->cb_literal) { 3929dd50e0ccSTony Hutter format = ZFS_NICENUM_RAW; 3930dd50e0ccSTony Hutter na = '0'; 3931dd50e0ccSTony Hutter } else { 3932dd50e0ccSTony Hutter format = ZFS_NICENUM_1024; 3933dd50e0ccSTony Hutter na = '-'; 3934dd50e0ccSTony Hutter } 3935dd50e0ccSTony Hutter 3936dd50e0ccSTony Hutter /* only toplevel vdevs have capacity stats */ 3937dd50e0ccSTony Hutter if (vs->vs_space == 0) { 3938dd50e0ccSTony Hutter if (cb->cb_scripted) 3939dd50e0ccSTony Hutter printf("\t%c\t%c", na, na); 3940dd50e0ccSTony Hutter else 3941dd50e0ccSTony Hutter printf(" %*c %*c", column_width, na, column_width, 3942dd50e0ccSTony Hutter na); 3943dd50e0ccSTony Hutter } else { 3944dd50e0ccSTony Hutter print_one_stat(vs->vs_alloc, format, column_width, 3945dd50e0ccSTony Hutter cb->cb_scripted); 3946dd50e0ccSTony Hutter print_one_stat(vs->vs_space - vs->vs_alloc, format, 3947dd50e0ccSTony Hutter column_width, cb->cb_scripted); 3948dd50e0ccSTony Hutter } 3949dd50e0ccSTony Hutter 3950dd50e0ccSTony Hutter print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_READ] * scale), 3951dd50e0ccSTony Hutter format, column_width, cb->cb_scripted); 3952dd50e0ccSTony Hutter print_one_stat((uint64_t)(vs->vs_ops[ZIO_TYPE_WRITE] * scale), 3953dd50e0ccSTony Hutter format, column_width, cb->cb_scripted); 3954dd50e0ccSTony Hutter print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_READ] * scale), 3955dd50e0ccSTony Hutter format, column_width, cb->cb_scripted); 3956dd50e0ccSTony Hutter print_one_stat((uint64_t)(vs->vs_bytes[ZIO_TYPE_WRITE] * scale), 3957dd50e0ccSTony Hutter format, column_width, cb->cb_scripted); 3958dd50e0ccSTony Hutter } 3959dd50e0ccSTony Hutter 3960dd50e0ccSTony Hutter static const char *class_name[] = { 3961dd50e0ccSTony Hutter VDEV_ALLOC_BIAS_DEDUP, 3962dd50e0ccSTony Hutter VDEV_ALLOC_BIAS_SPECIAL, 3963dd50e0ccSTony Hutter VDEV_ALLOC_CLASS_LOGS 3964dd50e0ccSTony Hutter }; 3965dd50e0ccSTony Hutter 3966dd50e0ccSTony Hutter /* 3967dd50e0ccSTony Hutter * Print out all the statistics for the given vdev. This can either be the 3968dd50e0ccSTony Hutter * toplevel configuration, or called recursively. If 'name' is NULL, then this 3969dd50e0ccSTony Hutter * is a verbose output, and we don't want to display the toplevel pool stats. 3970dd50e0ccSTony Hutter * 3971dd50e0ccSTony Hutter * Returns the number of stat lines printed. 3972dd50e0ccSTony Hutter */ 3973dd50e0ccSTony Hutter unsigned int 3974dd50e0ccSTony Hutter print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 3975dd50e0ccSTony Hutter nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 3976dd50e0ccSTony Hutter { 3977dd50e0ccSTony Hutter nvlist_t **oldchild, **newchild; 3978dd50e0ccSTony Hutter uint_t c, children, oldchildren; 3979dd50e0ccSTony Hutter vdev_stat_t *oldvs, *newvs, *calcvs; 3980dd50e0ccSTony Hutter vdev_stat_t zerovs = { 0 }; 3981dd50e0ccSTony Hutter char *vname; 3982dd50e0ccSTony Hutter int i; 3983dd50e0ccSTony Hutter int ret = 0; 3984dd50e0ccSTony Hutter uint64_t tdelta; 3985dd50e0ccSTony Hutter double scale; 3986dd50e0ccSTony Hutter 3987dd50e0ccSTony Hutter if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 3988dd50e0ccSTony Hutter return (0); 3989dd50e0ccSTony Hutter 3990dd50e0ccSTony Hutter calcvs = safe_malloc(sizeof (*calcvs)); 3991dd50e0ccSTony Hutter 3992dd50e0ccSTony Hutter if (oldnv != NULL) { 3993dd50e0ccSTony Hutter verify(nvlist_lookup_uint64_array(oldnv, 3994dd50e0ccSTony Hutter ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0); 3995dd50e0ccSTony Hutter } else { 3996dd50e0ccSTony Hutter oldvs = &zerovs; 3997dd50e0ccSTony Hutter } 3998dd50e0ccSTony Hutter 3999dd50e0ccSTony Hutter /* Do we only want to see a specific vdev? */ 4000dd50e0ccSTony Hutter for (i = 0; i < cb->cb_vdev_names_count; i++) { 4001dd50e0ccSTony Hutter /* Yes we do. Is this the vdev? */ 4002dd50e0ccSTony Hutter if (strcmp(name, cb->cb_vdev_names[i]) == 0) { 4003dd50e0ccSTony Hutter /* 4004dd50e0ccSTony Hutter * This is our vdev. Since it is the only vdev we 4005dd50e0ccSTony Hutter * will be displaying, make depth = 0 so that it 4006dd50e0ccSTony Hutter * doesn't get indented. 4007dd50e0ccSTony Hutter */ 4008dd50e0ccSTony Hutter depth = 0; 4009dd50e0ccSTony Hutter break; 4010dd50e0ccSTony Hutter } 4011dd50e0ccSTony Hutter } 4012dd50e0ccSTony Hutter 4013dd50e0ccSTony Hutter if (cb->cb_vdev_names_count && (i == cb->cb_vdev_names_count)) { 4014dd50e0ccSTony Hutter /* Couldn't match the name */ 4015dd50e0ccSTony Hutter goto children; 4016dd50e0ccSTony Hutter } 4017dd50e0ccSTony Hutter 4018dd50e0ccSTony Hutter 4019dd50e0ccSTony Hutter verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS, 4020dd50e0ccSTony Hutter (uint64_t **)&newvs, &c) == 0); 4021dd50e0ccSTony Hutter 4022dd50e0ccSTony Hutter /* 4023dd50e0ccSTony Hutter * Print the vdev name unless it's is a histogram. Histograms 4024dd50e0ccSTony Hutter * display the vdev name in the header itself. 4025dd50e0ccSTony Hutter */ 4026dd50e0ccSTony Hutter if (!(cb->cb_flags & IOS_ANYHISTO_M)) { 4027dd50e0ccSTony Hutter if (cb->cb_scripted) { 4028dd50e0ccSTony Hutter printf("%s", name); 4029dd50e0ccSTony Hutter } else { 4030dd50e0ccSTony Hutter if (strlen(name) + depth > cb->cb_namewidth) 4031dd50e0ccSTony Hutter (void) printf("%*s%s", depth, "", name); 4032dd50e0ccSTony Hutter else 4033dd50e0ccSTony Hutter (void) printf("%*s%s%*s", depth, "", name, 4034dd50e0ccSTony Hutter (int)(cb->cb_namewidth - strlen(name) - 4035dd50e0ccSTony Hutter depth), ""); 4036dd50e0ccSTony Hutter } 4037dd50e0ccSTony Hutter } 4038dd50e0ccSTony Hutter 4039dd50e0ccSTony Hutter /* Calculate our scaling factor */ 4040dd50e0ccSTony Hutter tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 4041dd50e0ccSTony Hutter if ((oldvs->vs_timestamp == 0) && (cb->cb_flags & IOS_ANYHISTO_M)) { 4042dd50e0ccSTony Hutter /* 4043dd50e0ccSTony Hutter * If we specify printing histograms with no time interval, then 4044dd50e0ccSTony Hutter * print the histogram numbers over the entire lifetime of the 4045dd50e0ccSTony Hutter * vdev. 4046dd50e0ccSTony Hutter */ 4047dd50e0ccSTony Hutter scale = 1; 4048dd50e0ccSTony Hutter } else { 4049dd50e0ccSTony Hutter if (tdelta == 0) 4050dd50e0ccSTony Hutter scale = 1.0; 4051dd50e0ccSTony Hutter else 4052dd50e0ccSTony Hutter scale = (double)NANOSEC / tdelta; 4053dd50e0ccSTony Hutter } 4054dd50e0ccSTony Hutter 4055dd50e0ccSTony Hutter if (cb->cb_flags & IOS_DEFAULT_M) { 4056dd50e0ccSTony Hutter calc_default_iostats(oldvs, newvs, calcvs); 4057dd50e0ccSTony Hutter print_iostat_default(calcvs, cb, scale); 4058dd50e0ccSTony Hutter } 4059dd50e0ccSTony Hutter if (cb->cb_flags & IOS_LATENCY_M) 4060dd50e0ccSTony Hutter print_iostat_latency(cb, oldnv, newnv); 4061dd50e0ccSTony Hutter if (cb->cb_flags & IOS_QUEUES_M) 4062dd50e0ccSTony Hutter print_iostat_queues(cb, oldnv, newnv); 4063dd50e0ccSTony Hutter if (cb->cb_flags & IOS_ANYHISTO_M) { 4064dd50e0ccSTony Hutter printf("\n"); 4065dd50e0ccSTony Hutter print_iostat_histos(cb, oldnv, newnv, scale, name); 4066dd50e0ccSTony Hutter } 4067dd50e0ccSTony Hutter 4068dd50e0ccSTony Hutter if (!(cb->cb_flags & IOS_ANYHISTO_M)) 4069dd50e0ccSTony Hutter printf("\n"); 4070dd50e0ccSTony Hutter 4071dd50e0ccSTony Hutter ret++; 4072dd50e0ccSTony Hutter 4073dd50e0ccSTony Hutter children: 4074dd50e0ccSTony Hutter 4075dd50e0ccSTony Hutter free(calcvs); 4076dd50e0ccSTony Hutter 4077dd50e0ccSTony Hutter if (!cb->cb_verbose) 4078dd50e0ccSTony Hutter return (ret); 4079dd50e0ccSTony Hutter 4080dd50e0ccSTony Hutter if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 4081dd50e0ccSTony Hutter &newchild, &children) != 0) 4082dd50e0ccSTony Hutter return (ret); 4083dd50e0ccSTony Hutter 4084dd50e0ccSTony Hutter if (oldnv) { 4085dd50e0ccSTony Hutter if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 4086dd50e0ccSTony Hutter &oldchild, &oldchildren) != 0) 4087dd50e0ccSTony Hutter return (ret); 4088dd50e0ccSTony Hutter 4089dd50e0ccSTony Hutter children = MIN(oldchildren, children); 4090dd50e0ccSTony Hutter } 4091dd50e0ccSTony Hutter 4092dd50e0ccSTony Hutter /* 4093dd50e0ccSTony Hutter * print normal top-level devices 4094dd50e0ccSTony Hutter */ 4095dd50e0ccSTony Hutter for (c = 0; c < children; c++) { 4096dd50e0ccSTony Hutter uint64_t ishole = B_FALSE, islog = B_FALSE; 4097dd50e0ccSTony Hutter 4098dd50e0ccSTony Hutter (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE, 4099dd50e0ccSTony Hutter &ishole); 4100dd50e0ccSTony Hutter 4101dd50e0ccSTony Hutter (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG, 4102dd50e0ccSTony Hutter &islog); 4103dd50e0ccSTony Hutter 4104dd50e0ccSTony Hutter if (ishole || islog) 4105dd50e0ccSTony Hutter continue; 4106dd50e0ccSTony Hutter 4107dd50e0ccSTony Hutter if (nvlist_exists(newchild[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 4108dd50e0ccSTony Hutter continue; 4109dd50e0ccSTony Hutter 4110dd50e0ccSTony Hutter vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 4111dd50e0ccSTony Hutter cb->cb_name_flags); 4112dd50e0ccSTony Hutter ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 4113dd50e0ccSTony Hutter newchild[c], cb, depth + 2); 4114dd50e0ccSTony Hutter free(vname); 4115dd50e0ccSTony Hutter } 4116dd50e0ccSTony Hutter 4117dd50e0ccSTony Hutter /* 4118dd50e0ccSTony Hutter * print all other top-level devices 4119dd50e0ccSTony Hutter */ 4120dd50e0ccSTony Hutter for (uint_t n = 0; n < 3; n++) { 4121dd50e0ccSTony Hutter boolean_t printed = B_FALSE; 4122dd50e0ccSTony Hutter 4123dd50e0ccSTony Hutter for (c = 0; c < children; c++) { 4124dd50e0ccSTony Hutter uint64_t islog = B_FALSE; 4125dd50e0ccSTony Hutter char *bias = NULL; 4126dd50e0ccSTony Hutter char *type = NULL; 4127dd50e0ccSTony Hutter 4128dd50e0ccSTony Hutter (void) nvlist_lookup_uint64(newchild[c], 4129dd50e0ccSTony Hutter ZPOOL_CONFIG_IS_LOG, &islog); 4130dd50e0ccSTony Hutter if (islog) { 4131dd50e0ccSTony Hutter bias = VDEV_ALLOC_CLASS_LOGS; 4132dd50e0ccSTony Hutter } else { 4133dd50e0ccSTony Hutter (void) nvlist_lookup_string(newchild[c], 4134dd50e0ccSTony Hutter ZPOOL_CONFIG_ALLOCATION_BIAS, &bias); 4135dd50e0ccSTony Hutter (void) nvlist_lookup_string(newchild[c], 4136dd50e0ccSTony Hutter ZPOOL_CONFIG_TYPE, &type); 4137dd50e0ccSTony Hutter } 4138dd50e0ccSTony Hutter if (bias == NULL || strcmp(bias, class_name[n]) != 0) 4139dd50e0ccSTony Hutter continue; 4140dd50e0ccSTony Hutter if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0) 4141dd50e0ccSTony Hutter continue; 4142dd50e0ccSTony Hutter 4143dd50e0ccSTony Hutter if (!printed) { 4144dd50e0ccSTony Hutter if ((!(cb->cb_flags & IOS_ANYHISTO_M)) && 4145dd50e0ccSTony Hutter !cb->cb_scripted && !cb->cb_vdev_names) { 4146dd50e0ccSTony Hutter print_iostat_dashes(cb, 0, 4147dd50e0ccSTony Hutter class_name[n]); 4148dd50e0ccSTony Hutter } 4149dd50e0ccSTony Hutter printf("\n"); 4150dd50e0ccSTony Hutter printed = B_TRUE; 4151dd50e0ccSTony Hutter } 4152dd50e0ccSTony Hutter 4153dd50e0ccSTony Hutter vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 4154dd50e0ccSTony Hutter cb->cb_name_flags); 4155dd50e0ccSTony Hutter ret += print_vdev_stats(zhp, vname, oldnv ? 4156dd50e0ccSTony Hutter oldchild[c] : NULL, newchild[c], cb, depth + 2); 4157dd50e0ccSTony Hutter free(vname); 4158dd50e0ccSTony Hutter } 4159dd50e0ccSTony Hutter 4160dd50e0ccSTony Hutter } 4161dd50e0ccSTony Hutter 4162dd50e0ccSTony Hutter /* 4163dd50e0ccSTony Hutter * Include level 2 ARC devices in iostat output 4164dd50e0ccSTony Hutter */ 4165dd50e0ccSTony Hutter if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, 4166dd50e0ccSTony Hutter &newchild, &children) != 0) 4167dd50e0ccSTony Hutter return (ret); 4168dd50e0ccSTony Hutter 4169dd50e0ccSTony Hutter if (oldnv) { 4170dd50e0ccSTony Hutter if (nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, 4171dd50e0ccSTony Hutter &oldchild, &oldchildren) != 0) 4172dd50e0ccSTony Hutter return (ret); 4173dd50e0ccSTony Hutter 4174dd50e0ccSTony Hutter children = MIN(oldchildren, children); 4175dd50e0ccSTony Hutter } 4176dd50e0ccSTony Hutter 4177dd50e0ccSTony Hutter if (children > 0) { 4178dd50e0ccSTony Hutter if ((!(cb->cb_flags & IOS_ANYHISTO_M)) && !cb->cb_scripted && 4179dd50e0ccSTony Hutter !cb->cb_vdev_names) { 4180dd50e0ccSTony Hutter print_iostat_dashes(cb, 0, "cache"); 4181dd50e0ccSTony Hutter } 4182dd50e0ccSTony Hutter printf("\n"); 4183dd50e0ccSTony Hutter 4184dd50e0ccSTony Hutter for (c = 0; c < children; c++) { 4185dd50e0ccSTony Hutter vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 4186dd50e0ccSTony Hutter cb->cb_name_flags); 4187dd50e0ccSTony Hutter ret += print_vdev_stats(zhp, vname, oldnv ? oldchild[c] 4188dd50e0ccSTony Hutter : NULL, newchild[c], cb, depth + 2); 4189dd50e0ccSTony Hutter free(vname); 4190dd50e0ccSTony Hutter } 4191dd50e0ccSTony Hutter } 4192dd50e0ccSTony Hutter 4193dd50e0ccSTony Hutter return (ret); 4194dd50e0ccSTony Hutter } 4195dd50e0ccSTony Hutter 4196dd50e0ccSTony Hutter static int 4197dd50e0ccSTony Hutter refresh_iostat(zpool_handle_t *zhp, void *data) 4198dd50e0ccSTony Hutter { 4199dd50e0ccSTony Hutter iostat_cbdata_t *cb = data; 4200dd50e0ccSTony Hutter boolean_t missing; 4201dd50e0ccSTony Hutter 4202dd50e0ccSTony Hutter /* 4203dd50e0ccSTony Hutter * If the pool has disappeared, remove it from the list and continue. 4204dd50e0ccSTony Hutter */ 4205dd50e0ccSTony Hutter if (zpool_refresh_stats(zhp, &missing) != 0) 4206dd50e0ccSTony Hutter return (-1); 4207dd50e0ccSTony Hutter 4208dd50e0ccSTony Hutter if (missing) 4209dd50e0ccSTony Hutter pool_list_remove(cb->cb_list, zhp); 4210dd50e0ccSTony Hutter 4211dd50e0ccSTony Hutter return (0); 4212dd50e0ccSTony Hutter } 4213dd50e0ccSTony Hutter 4214dd50e0ccSTony Hutter /* 4215dd50e0ccSTony Hutter * Callback to print out the iostats for the given pool. 4216dd50e0ccSTony Hutter */ 4217dd50e0ccSTony Hutter int 4218dd50e0ccSTony Hutter print_iostat(zpool_handle_t *zhp, void *data) 4219dd50e0ccSTony Hutter { 4220dd50e0ccSTony Hutter iostat_cbdata_t *cb = data; 4221dd50e0ccSTony Hutter nvlist_t *oldconfig, *newconfig; 4222dd50e0ccSTony Hutter nvlist_t *oldnvroot, *newnvroot; 4223dd50e0ccSTony Hutter int ret; 4224dd50e0ccSTony Hutter 4225dd50e0ccSTony Hutter newconfig = zpool_get_config(zhp, &oldconfig); 4226dd50e0ccSTony Hutter 4227dd50e0ccSTony Hutter if (cb->cb_iteration == 1) 4228dd50e0ccSTony Hutter oldconfig = NULL; 4229dd50e0ccSTony Hutter 4230dd50e0ccSTony Hutter verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 4231dd50e0ccSTony Hutter &newnvroot) == 0); 4232dd50e0ccSTony Hutter 4233dd50e0ccSTony Hutter if (oldconfig == NULL) 4234dd50e0ccSTony Hutter oldnvroot = NULL; 4235dd50e0ccSTony Hutter else 4236dd50e0ccSTony Hutter verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 4237dd50e0ccSTony Hutter &oldnvroot) == 0); 4238dd50e0ccSTony Hutter 4239dd50e0ccSTony Hutter ret = print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, 4240dd50e0ccSTony Hutter cb, 0); 4241dd50e0ccSTony Hutter if ((ret != 0) && !(cb->cb_flags & IOS_ANYHISTO_M) && 4242dd50e0ccSTony Hutter !cb->cb_scripted && cb->cb_verbose && !cb->cb_vdev_names_count) { 4243dd50e0ccSTony Hutter print_iostat_separator(cb); 4244dd50e0ccSTony Hutter printf("\n"); 4245dd50e0ccSTony Hutter } 4246dd50e0ccSTony Hutter 4247dd50e0ccSTony Hutter return (ret); 4248dd50e0ccSTony Hutter } 4249dd50e0ccSTony Hutter 4250dd50e0ccSTony Hutter static int 4251dd50e0ccSTony Hutter get_columns(void) 4252dd50e0ccSTony Hutter { 4253dd50e0ccSTony Hutter struct winsize ws; 4254dd50e0ccSTony Hutter int columns = 80; 4255dd50e0ccSTony Hutter int error; 4256dd50e0ccSTony Hutter 4257dd50e0ccSTony Hutter if (isatty(STDOUT_FILENO)) { 4258dd50e0ccSTony Hutter error = ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws); 4259dd50e0ccSTony Hutter if (error == 0) 4260dd50e0ccSTony Hutter columns = ws.ws_col; 4261dd50e0ccSTony Hutter } else { 4262dd50e0ccSTony Hutter columns = 999; 4263dd50e0ccSTony Hutter } 4264dd50e0ccSTony Hutter 4265dd50e0ccSTony Hutter return (columns); 4266dd50e0ccSTony Hutter } 4267dd50e0ccSTony Hutter 4268dd50e0ccSTony Hutter /* 4269dd50e0ccSTony Hutter * Return the required length of the pool/vdev name column. The minimum 4270dd50e0ccSTony Hutter * allowed width and output formatting flags must be provided. 4271dd50e0ccSTony Hutter */ 4272dd50e0ccSTony Hutter static int 4273dd50e0ccSTony Hutter get_namewidth(zpool_handle_t *zhp, int min_width, int flags, boolean_t verbose) 4274dd50e0ccSTony Hutter { 4275dd50e0ccSTony Hutter nvlist_t *config, *nvroot; 4276dd50e0ccSTony Hutter int width = min_width; 4277dd50e0ccSTony Hutter 4278dd50e0ccSTony Hutter if ((config = zpool_get_config(zhp, NULL)) != NULL) { 4279dd50e0ccSTony Hutter verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 4280dd50e0ccSTony Hutter &nvroot) == 0); 4281dd50e0ccSTony Hutter unsigned int poolname_len = strlen(zpool_get_name(zhp)); 4282dd50e0ccSTony Hutter if (verbose == B_FALSE) { 4283dd50e0ccSTony Hutter width = MAX(poolname_len, min_width); 4284dd50e0ccSTony Hutter } else { 4285dd50e0ccSTony Hutter width = MAX(poolname_len, 4286dd50e0ccSTony Hutter max_width(zhp, nvroot, 0, min_width, flags)); 4287dd50e0ccSTony Hutter } 4288dd50e0ccSTony Hutter } 4289dd50e0ccSTony Hutter 4290dd50e0ccSTony Hutter return (width); 4291dd50e0ccSTony Hutter } 4292dd50e0ccSTony Hutter 4293dd50e0ccSTony Hutter /* 4294dd50e0ccSTony Hutter * Parse the input string, get the 'interval' and 'count' value if there is one. 4295dd50e0ccSTony Hutter */ 4296dd50e0ccSTony Hutter static void 4297dd50e0ccSTony Hutter get_interval_count(int *argcp, char **argv, float *iv, 4298dd50e0ccSTony Hutter unsigned long *cnt) 4299dd50e0ccSTony Hutter { 4300dd50e0ccSTony Hutter float interval = 0; 4301dd50e0ccSTony Hutter unsigned long count = 0; 4302dd50e0ccSTony Hutter int argc = *argcp, errno; 4303dd50e0ccSTony Hutter 4304dd50e0ccSTony Hutter /* 4305dd50e0ccSTony Hutter * Determine if the last argument is an integer or a pool name 4306dd50e0ccSTony Hutter */ 4307dd50e0ccSTony Hutter if (argc > 0 && isnumber(argv[argc - 1])) { 4308dd50e0ccSTony Hutter char *end; 4309dd50e0ccSTony Hutter 4310dd50e0ccSTony Hutter errno = 0; 4311dd50e0ccSTony Hutter interval = strtof(argv[argc - 1], &end); 4312dd50e0ccSTony Hutter 4313dd50e0ccSTony Hutter if (*end == '\0' && errno == 0) { 4314dd50e0ccSTony Hutter if (interval == 0) { 4315dd50e0ccSTony Hutter (void) fprintf(stderr, gettext("interval " 4316dd50e0ccSTony Hutter "cannot be zero\n")); 4317dd50e0ccSTony Hutter usage(B_FALSE); 4318dd50e0ccSTony Hutter } 4319dd50e0ccSTony Hutter /* 4320dd50e0ccSTony Hutter * Ignore the last parameter 4321dd50e0ccSTony Hutter */ 4322dd50e0ccSTony Hutter argc--; 4323dd50e0ccSTony Hutter } else { 4324dd50e0ccSTony Hutter /* 4325dd50e0ccSTony Hutter * If this is not a valid number, just plow on. The 4326dd50e0ccSTony Hutter * user will get a more informative error message later 4327dd50e0ccSTony Hutter * on. 4328dd50e0ccSTony Hutter */ 4329dd50e0ccSTony Hutter interval = 0; 4330dd50e0ccSTony Hutter } 4331dd50e0ccSTony Hutter } 4332dd50e0ccSTony Hutter 4333dd50e0ccSTony Hutter /* 4334dd50e0ccSTony Hutter * If the last argument is also an integer, then we have both a count 4335dd50e0ccSTony Hutter * and an interval. 4336dd50e0ccSTony Hutter */ 4337dd50e0ccSTony Hutter if (argc > 0 && isnumber(argv[argc - 1])) { 4338dd50e0ccSTony Hutter char *end; 4339dd50e0ccSTony Hutter 4340dd50e0ccSTony Hutter errno = 0; 4341dd50e0ccSTony Hutter count = interval; 4342dd50e0ccSTony Hutter interval = strtof(argv[argc - 1], &end); 4343dd50e0ccSTony Hutter 4344dd50e0ccSTony Hutter if (*end == '\0' && errno == 0) { 4345dd50e0ccSTony Hutter if (interval == 0) { 4346dd50e0ccSTony Hutter (void) fprintf(stderr, gettext("interval " 4347dd50e0ccSTony Hutter "cannot be zero\n")); 4348dd50e0ccSTony Hutter usage(B_FALSE); 4349dd50e0ccSTony Hutter } 4350dd50e0ccSTony Hutter 4351dd50e0ccSTony Hutter /* 4352dd50e0ccSTony Hutter * Ignore the last parameter 4353dd50e0ccSTony Hutter */ 4354dd50e0ccSTony Hutter argc--; 4355dd50e0ccSTony Hutter } else { 4356dd50e0ccSTony Hutter interval = 0; 4357dd50e0ccSTony Hutter } 4358dd50e0ccSTony Hutter } 4359fa9e4066Sahrens 4360dd50e0ccSTony Hutter *iv = interval; 4361dd50e0ccSTony Hutter *cnt = count; 4362dd50e0ccSTony Hutter *argcp = argc; 4363dd50e0ccSTony Hutter } 4364dd50e0ccSTony Hutter 4365dd50e0ccSTony Hutter static void 4366dd50e0ccSTony Hutter get_timestamp_arg(char c) 4367dd50e0ccSTony Hutter { 4368dd50e0ccSTony Hutter if (c == 'u') 4369dd50e0ccSTony Hutter timestamp_fmt = UDATE; 4370dd50e0ccSTony Hutter else if (c == 'd') 4371dd50e0ccSTony Hutter timestamp_fmt = DDATE; 4372dd50e0ccSTony Hutter else 4373dd50e0ccSTony Hutter usage(B_FALSE); 4374dd50e0ccSTony Hutter } 4375dd50e0ccSTony Hutter 4376dd50e0ccSTony Hutter /* 4377dd50e0ccSTony Hutter * Return stat flags that are supported by all pools by both the module and 4378dd50e0ccSTony Hutter * zpool iostat. "*data" should be initialized to all 0xFFs before running. 4379dd50e0ccSTony Hutter * It will get ANDed down until only the flags that are supported on all pools 4380dd50e0ccSTony Hutter * remain. 4381dd50e0ccSTony Hutter */ 4382dd50e0ccSTony Hutter static int 4383dd50e0ccSTony Hutter get_stat_flags_cb(zpool_handle_t *zhp, void *data) 4384dd50e0ccSTony Hutter { 4385dd50e0ccSTony Hutter uint64_t *mask = data; 4386dd50e0ccSTony Hutter nvlist_t *config, *nvroot, *nvx; 4387dd50e0ccSTony Hutter uint64_t flags = 0; 4388dd50e0ccSTony Hutter int i, j; 4389dd50e0ccSTony Hutter 4390dd50e0ccSTony Hutter config = zpool_get_config(zhp, NULL); 4391dd50e0ccSTony Hutter verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 4392dd50e0ccSTony Hutter &nvroot) == 0); 4393dd50e0ccSTony Hutter 4394dd50e0ccSTony Hutter /* Default stats are always supported, but for completeness.. */ 4395dd50e0ccSTony Hutter if (nvlist_exists(nvroot, ZPOOL_CONFIG_VDEV_STATS)) 4396dd50e0ccSTony Hutter flags |= IOS_DEFAULT_M; 4397dd50e0ccSTony Hutter 4398dd50e0ccSTony Hutter /* Get our extended stats nvlist from the main list */ 4399dd50e0ccSTony Hutter if (nvlist_lookup_nvlist(nvroot, ZPOOL_CONFIG_VDEV_STATS_EX, 4400dd50e0ccSTony Hutter &nvx) != 0) { 4401dd50e0ccSTony Hutter /* 4402dd50e0ccSTony Hutter * No extended stats; they're probably running an older 4403dd50e0ccSTony Hutter * module. No big deal, we support that too. 4404dd50e0ccSTony Hutter */ 4405dd50e0ccSTony Hutter goto end; 4406dd50e0ccSTony Hutter } 4407dd50e0ccSTony Hutter 4408dd50e0ccSTony Hutter /* For each extended stat, make sure all its nvpairs are supported */ 4409dd50e0ccSTony Hutter for (j = 0; j < ARRAY_SIZE(vsx_type_to_nvlist); j++) { 4410dd50e0ccSTony Hutter if (!vsx_type_to_nvlist[j][0]) 4411dd50e0ccSTony Hutter continue; 4412dd50e0ccSTony Hutter 4413dd50e0ccSTony Hutter /* Start off by assuming the flag is supported, then check */ 4414dd50e0ccSTony Hutter flags |= (1ULL << j); 4415dd50e0ccSTony Hutter for (i = 0; vsx_type_to_nvlist[j][i]; i++) { 4416dd50e0ccSTony Hutter if (!nvlist_exists(nvx, vsx_type_to_nvlist[j][i])) { 4417dd50e0ccSTony Hutter /* flag isn't supported */ 4418dd50e0ccSTony Hutter flags = flags & ~(1ULL << j); 4419dd50e0ccSTony Hutter break; 4420dd50e0ccSTony Hutter } 4421dd50e0ccSTony Hutter } 4422dd50e0ccSTony Hutter } 4423dd50e0ccSTony Hutter end: 4424dd50e0ccSTony Hutter *mask = *mask & flags; 4425fa9e4066Sahrens return (0); 4426fa9e4066Sahrens } 4427fa9e4066Sahrens 4428dd50e0ccSTony Hutter /* 4429dd50e0ccSTony Hutter * Return a bitmask of stats that are supported on all pools by both the module 4430dd50e0ccSTony Hutter * and zpool iostat. 4431dd50e0ccSTony Hutter */ 4432dd50e0ccSTony Hutter static uint64_t 4433dd50e0ccSTony Hutter get_stat_flags(zpool_list_t *list) 4434dd50e0ccSTony Hutter { 4435dd50e0ccSTony Hutter uint64_t mask = -1; 4436dd50e0ccSTony Hutter 4437dd50e0ccSTony Hutter /* 4438dd50e0ccSTony Hutter * get_stat_flags_cb() will lop off bits from "mask" until only the 4439dd50e0ccSTony Hutter * flags that are supported on all pools remain. 4440dd50e0ccSTony Hutter */ 4441dd50e0ccSTony Hutter (void) pool_list_iter(list, B_FALSE, get_stat_flags_cb, &mask); 4442dd50e0ccSTony Hutter return (mask); 4443dd50e0ccSTony Hutter } 4444dd50e0ccSTony Hutter 4445dd50e0ccSTony Hutter /* 4446dd50e0ccSTony Hutter * Return 1 if cb_data->cb_vdev_names[0] is this vdev's name, 0 otherwise. 4447dd50e0ccSTony Hutter */ 4448dd50e0ccSTony Hutter static int 4449dd50e0ccSTony Hutter is_vdev_cb(zpool_handle_t *zhp, nvlist_t *nv, void *cb_data) 4450dd50e0ccSTony Hutter { 4451dd50e0ccSTony Hutter iostat_cbdata_t *cb = cb_data; 4452dd50e0ccSTony Hutter char *name; 4453dd50e0ccSTony Hutter 4454dd50e0ccSTony Hutter name = zpool_vdev_name(g_zfs, zhp, nv, cb->cb_name_flags); 4455dd50e0ccSTony Hutter 4456dd50e0ccSTony Hutter if (strcmp(name, cb->cb_vdev_names[0]) == 0) 4457dd50e0ccSTony Hutter return (1); /* match */ 4458dd50e0ccSTony Hutter 4459dd50e0ccSTony Hutter return (0); 4460dd50e0ccSTony Hutter } 4461dd50e0ccSTony Hutter 4462dd50e0ccSTony Hutter /* 4463dd50e0ccSTony Hutter * Returns 1 if cb_data->cb_vdev_names[0] is a vdev name, 0 otherwise. 4464dd50e0ccSTony Hutter */ 4465dd50e0ccSTony Hutter static int 4466dd50e0ccSTony Hutter is_vdev(zpool_handle_t *zhp, void *cb_data) 4467dd50e0ccSTony Hutter { 4468dd50e0ccSTony Hutter return (for_each_vdev(zhp, is_vdev_cb, cb_data)); 4469dd50e0ccSTony Hutter } 4470dd50e0ccSTony Hutter 4471dd50e0ccSTony Hutter /* 4472dd50e0ccSTony Hutter * Check if vdevs are in a pool 4473dd50e0ccSTony Hutter * 4474dd50e0ccSTony Hutter * Return 1 if all argv[] strings are vdev names in pool "pool_name". Otherwise 4475dd50e0ccSTony Hutter * return 0. If pool_name is NULL, then search all pools. 4476dd50e0ccSTony Hutter */ 4477dd50e0ccSTony Hutter static int 4478dd50e0ccSTony Hutter are_vdevs_in_pool(int argc, char **argv, char *pool_name, 4479dd50e0ccSTony Hutter iostat_cbdata_t *cb) 4480fa9e4066Sahrens { 4481dd50e0ccSTony Hutter char **tmp_name; 4482dd50e0ccSTony Hutter int ret = 0; 4483dd50e0ccSTony Hutter int i; 4484dd50e0ccSTony Hutter int pool_count = 0; 4485fa9e4066Sahrens 4486dd50e0ccSTony Hutter if ((argc == 0) || !*argv) 4487dd50e0ccSTony Hutter return (0); 4488dd50e0ccSTony Hutter 4489dd50e0ccSTony Hutter if (pool_name) 4490dd50e0ccSTony Hutter pool_count = 1; 4491dd50e0ccSTony Hutter 4492dd50e0ccSTony Hutter /* Temporarily hijack cb_vdev_names for a second... */ 4493dd50e0ccSTony Hutter tmp_name = cb->cb_vdev_names; 4494dd50e0ccSTony Hutter 4495dd50e0ccSTony Hutter /* Go though our list of prospective vdev names */ 4496dd50e0ccSTony Hutter for (i = 0; i < argc; i++) { 4497dd50e0ccSTony Hutter cb->cb_vdev_names = argv + i; 4498dd50e0ccSTony Hutter 4499dd50e0ccSTony Hutter /* Is this name a vdev in our pools? */ 4500dd50e0ccSTony Hutter ret = for_each_pool(pool_count, &pool_name, B_TRUE, NULL, 4501dd50e0ccSTony Hutter is_vdev, cb); 4502dd50e0ccSTony Hutter if (!ret) { 4503dd50e0ccSTony Hutter /* No match */ 4504dd50e0ccSTony Hutter break; 4505dd50e0ccSTony Hutter } 4506fa9e4066Sahrens } 4507fa9e4066Sahrens 4508dd50e0ccSTony Hutter cb->cb_vdev_names = tmp_name; 4509dd50e0ccSTony Hutter 4510dd50e0ccSTony Hutter return (ret); 4511dd50e0ccSTony Hutter } 4512dd50e0ccSTony Hutter 4513dd50e0ccSTony Hutter static int 4514dd50e0ccSTony Hutter is_pool_cb(zpool_handle_t *zhp, void *data) 4515dd50e0ccSTony Hutter { 4516dd50e0ccSTony Hutter char *name = data; 4517dd50e0ccSTony Hutter if (strcmp(name, zpool_get_name(zhp)) == 0) 4518dd50e0ccSTony Hutter return (1); 4519fa9e4066Sahrens 4520fa9e4066Sahrens return (0); 4521fa9e4066Sahrens } 4522fa9e4066Sahrens 4523fa9e4066Sahrens /* 4524dd50e0ccSTony Hutter * Do we have a pool named *name? If so, return 1, otherwise 0. 4525fa9e4066Sahrens */ 4526dd50e0ccSTony Hutter static int 4527dd50e0ccSTony Hutter is_pool(char *name) 4528fa9e4066Sahrens { 4529dd50e0ccSTony Hutter return (for_each_pool(0, NULL, B_TRUE, NULL, is_pool_cb, name)); 4530dd50e0ccSTony Hutter } 4531fa9e4066Sahrens 4532dd50e0ccSTony Hutter /* Are all our argv[] strings pool names? If so return 1, 0 otherwise. */ 4533dd50e0ccSTony Hutter static int 4534dd50e0ccSTony Hutter are_all_pools(int argc, char **argv) 4535dd50e0ccSTony Hutter { 4536dd50e0ccSTony Hutter if ((argc == 0) || !*argv) 4537dd50e0ccSTony Hutter return (0); 4538fa9e4066Sahrens 4539dd50e0ccSTony Hutter while (--argc >= 0) 4540dd50e0ccSTony Hutter if (!is_pool(argv[argc])) 4541dd50e0ccSTony Hutter return (0); 4542fa9e4066Sahrens 4543dd50e0ccSTony Hutter return (1); 4544dd50e0ccSTony Hutter } 4545fa9e4066Sahrens 4546dd50e0ccSTony Hutter /* 4547dd50e0ccSTony Hutter * Helper function to print out vdev/pool names we can't resolve. Used for an 4548dd50e0ccSTony Hutter * error message. 4549dd50e0ccSTony Hutter */ 4550dd50e0ccSTony Hutter static void 4551dd50e0ccSTony Hutter error_list_unresolved_vdevs(int argc, char **argv, char *pool_name, 4552dd50e0ccSTony Hutter iostat_cbdata_t *cb) 4553dd50e0ccSTony Hutter { 4554dd50e0ccSTony Hutter int i; 4555dd50e0ccSTony Hutter char *name; 4556dd50e0ccSTony Hutter char *str; 4557dd50e0ccSTony Hutter for (i = 0; i < argc; i++) { 4558dd50e0ccSTony Hutter name = argv[i]; 4559dd50e0ccSTony Hutter 4560dd50e0ccSTony Hutter if (is_pool(name)) 4561dd50e0ccSTony Hutter str = gettext("pool"); 4562dd50e0ccSTony Hutter else if (are_vdevs_in_pool(1, &name, pool_name, cb)) 4563dd50e0ccSTony Hutter str = gettext("vdev in this pool"); 4564dd50e0ccSTony Hutter else if (are_vdevs_in_pool(1, &name, NULL, cb)) 4565dd50e0ccSTony Hutter str = gettext("vdev in another pool"); 4566dd50e0ccSTony Hutter else 4567dd50e0ccSTony Hutter str = gettext("unknown"); 4568fa9e4066Sahrens 4569dd50e0ccSTony Hutter fprintf(stderr, "\t%s (%s)\n", name, str); 4570dd50e0ccSTony Hutter } 4571dd50e0ccSTony Hutter } 4572fa9e4066Sahrens 4573dd50e0ccSTony Hutter /* 4574dd50e0ccSTony Hutter * Same as get_interval_count(), but with additional checks to not misinterpret 4575dd50e0ccSTony Hutter * guids as interval/count values. Assumes VDEV_NAME_GUID is set in 4576dd50e0ccSTony Hutter * cb.cb_name_flags. 4577dd50e0ccSTony Hutter */ 4578dd50e0ccSTony Hutter static void 4579dd50e0ccSTony Hutter get_interval_count_filter_guids(int *argc, char **argv, float *interval, 4580dd50e0ccSTony Hutter unsigned long *count, iostat_cbdata_t *cb) 4581dd50e0ccSTony Hutter { 4582dd50e0ccSTony Hutter char **tmpargv = argv; 4583dd50e0ccSTony Hutter int argc_for_interval = 0; 4584dd50e0ccSTony Hutter 4585dd50e0ccSTony Hutter /* Is the last arg an interval value? Or a guid? */ 4586dd50e0ccSTony Hutter if (*argc >= 1 && !are_vdevs_in_pool(1, &argv[*argc - 1], NULL, cb)) { 4587dd50e0ccSTony Hutter /* 4588dd50e0ccSTony Hutter * The last arg is not a guid, so it's probably an 4589dd50e0ccSTony Hutter * interval value. 4590dd50e0ccSTony Hutter */ 4591dd50e0ccSTony Hutter argc_for_interval++; 4592fa9e4066Sahrens 4593dd50e0ccSTony Hutter if (*argc >= 2 && 4594dd50e0ccSTony Hutter !are_vdevs_in_pool(1, &argv[*argc - 2], NULL, cb)) { 4595fa9e4066Sahrens /* 4596dd50e0ccSTony Hutter * The 2nd to last arg is not a guid, so it's probably 4597dd50e0ccSTony Hutter * an interval value. 4598fa9e4066Sahrens */ 4599dd50e0ccSTony Hutter argc_for_interval++; 4600fa9e4066Sahrens } 4601fa9e4066Sahrens } 4602fa9e4066Sahrens 4603dd50e0ccSTony Hutter /* Point to our list of possible intervals */ 4604dd50e0ccSTony Hutter tmpargv = &argv[*argc - argc_for_interval]; 4605dd50e0ccSTony Hutter 4606dd50e0ccSTony Hutter *argc = *argc - argc_for_interval; 4607dd50e0ccSTony Hutter get_interval_count(&argc_for_interval, tmpargv, 4608dd50e0ccSTony Hutter interval, count); 46093f9d6ad7SLin Ling } 46103f9d6ad7SLin Ling 4611dd50e0ccSTony Hutter /* 4612dd50e0ccSTony Hutter * Floating point sleep(). Allows you to pass in a floating point value for 4613dd50e0ccSTony Hutter * seconds. 4614dd50e0ccSTony Hutter */ 46153f9d6ad7SLin Ling static void 4616dd50e0ccSTony Hutter fsleep(float sec) 46173f9d6ad7SLin Ling { 4618dd50e0ccSTony Hutter struct timespec req; 4619dd50e0ccSTony Hutter req.tv_sec = floor(sec); 4620dd50e0ccSTony Hutter req.tv_nsec = (sec - (float)req.tv_sec) * NANOSEC; 4621dd50e0ccSTony Hutter (void) nanosleep(&req, NULL); 4622dd50e0ccSTony Hutter } 4623dd50e0ccSTony Hutter 4624dd50e0ccSTony Hutter /* 4625dd50e0ccSTony Hutter * Set the minimum pool/vdev name column width. The width must be at least 10, 4626dd50e0ccSTony Hutter * but may be as large as the column width - 42 so it still fits on one line. 4627dd50e0ccSTony Hutter */ 4628dd50e0ccSTony Hutter static int 4629dd50e0ccSTony Hutter get_namewidth_iostat(zpool_handle_t *zhp, void *data) 4630dd50e0ccSTony Hutter { 4631dd50e0ccSTony Hutter iostat_cbdata_t *cb = data; 4632dd50e0ccSTony Hutter int width, columns; 4633dd50e0ccSTony Hutter 4634dd50e0ccSTony Hutter width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_name_flags, 4635dd50e0ccSTony Hutter cb->cb_verbose); 4636dd50e0ccSTony Hutter columns = get_columns(); 4637dd50e0ccSTony Hutter 4638dd50e0ccSTony Hutter if (width < 10) 4639dd50e0ccSTony Hutter width = 10; 4640dd50e0ccSTony Hutter if (width > columns - 42) 4641dd50e0ccSTony Hutter width = columns - 42; 4642dd50e0ccSTony Hutter 4643dd50e0ccSTony Hutter cb->cb_namewidth = width; 4644dd50e0ccSTony Hutter 4645dd50e0ccSTony Hutter return (0); 46463f9d6ad7SLin Ling } 46473f9d6ad7SLin Ling 46483f9d6ad7SLin Ling /* 4649dd50e0ccSTony Hutter * zpool iostat [-ghHLpPvy] [[-lq]|[-r|-w]] [-n name] [-T d|u] 4650dd50e0ccSTony Hutter * [[ pool ...]|[pool vdev ...]|[vdev ...]] 4651dd50e0ccSTony Hutter * [interval [count]] 46523f9d6ad7SLin Ling * 4653663207adSDon Brady * -g Display guid for individual vdev name. 4654663207adSDon Brady * -L Follow links when resolving vdev path name. 4655663207adSDon Brady * -P Display full path for vdev name. 46563f9d6ad7SLin Ling * -v Display statistics for individual vdevs 4657dd50e0ccSTony Hutter * -h Display help 4658dd50e0ccSTony Hutter * -p Display values in parsable (exact) format. 4659dd50e0ccSTony Hutter * -H Scripted mode. Don't display headers, and separate properties 4660dd50e0ccSTony Hutter * by a single tab. 4661dd50e0ccSTony Hutter * -l Display average latency 4662dd50e0ccSTony Hutter * -q Display queue depths 4663dd50e0ccSTony Hutter * -w Display latency histograms 4664dd50e0ccSTony Hutter * -r Display request size histogram 46653f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format 4666dd50e0ccSTony Hutter * -n Only print headers once 46673f9d6ad7SLin Ling * 46683f9d6ad7SLin Ling * This command can be tricky because we want to be able to deal with pool 46693f9d6ad7SLin Ling * creation/destruction as well as vdev configuration changes. The bulk of this 46703f9d6ad7SLin Ling * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 46713f9d6ad7SLin Ling * on pool_list_update() to detect the addition of new pools. Configuration 46723f9d6ad7SLin Ling * changes are all handled within libzfs. 46733f9d6ad7SLin Ling */ 46743f9d6ad7SLin Ling int 46753f9d6ad7SLin Ling zpool_do_iostat(int argc, char **argv) 46763f9d6ad7SLin Ling { 46773f9d6ad7SLin Ling int c; 46783f9d6ad7SLin Ling int ret; 46793f9d6ad7SLin Ling int npools; 4680dd50e0ccSTony Hutter float interval = 0; 4681dd50e0ccSTony Hutter unsigned long count = 0; 4682dd50e0ccSTony Hutter int winheight = 24; 4683dd50e0ccSTony Hutter struct winsize win; 46843f9d6ad7SLin Ling zpool_list_t *list; 46853f9d6ad7SLin Ling boolean_t verbose = B_FALSE; 4686dd50e0ccSTony Hutter boolean_t latency = B_FALSE, l_histo = B_FALSE, rq_histo = B_FALSE; 4687dd50e0ccSTony Hutter boolean_t queues = B_FALSE, parseable = B_FALSE, scripted = B_FALSE; 4688dd50e0ccSTony Hutter boolean_t omit_since_boot = B_FALSE; 4689663207adSDon Brady boolean_t guid = B_FALSE; 4690663207adSDon Brady boolean_t follow_links = B_FALSE; 4691663207adSDon Brady boolean_t full_name = B_FALSE; 4692dd50e0ccSTony Hutter boolean_t headers_once = B_FALSE; 4693663207adSDon Brady iostat_cbdata_t cb = { 0 }; 46943f9d6ad7SLin Ling 4695dd50e0ccSTony Hutter /* Used for printing error message */ 4696dd50e0ccSTony Hutter const char flag_to_arg[] = {[IOS_LATENCY] = 'l', [IOS_QUEUES] = 'q', 4697dd50e0ccSTony Hutter [IOS_L_HISTO] = 'w', [IOS_RQ_HISTO] = 'r'}; 4698dd50e0ccSTony Hutter 4699dd50e0ccSTony Hutter uint64_t unsupported_flags; 4700dd50e0ccSTony Hutter 47013f9d6ad7SLin Ling /* check options */ 4702dd50e0ccSTony Hutter while ((c = getopt(argc, argv, "gLPT:vyhplqrwnH")) != -1) { 47033f9d6ad7SLin Ling switch (c) { 4704663207adSDon Brady case 'g': 4705663207adSDon Brady guid = B_TRUE; 4706663207adSDon Brady break; 4707663207adSDon Brady case 'L': 4708663207adSDon Brady follow_links = B_TRUE; 4709663207adSDon Brady break; 4710663207adSDon Brady case 'P': 4711663207adSDon Brady full_name = B_TRUE; 4712663207adSDon Brady break; 47133f9d6ad7SLin Ling case 'T': 47143f9d6ad7SLin Ling get_timestamp_arg(*optarg); 47153f9d6ad7SLin Ling break; 47163f9d6ad7SLin Ling case 'v': 47173f9d6ad7SLin Ling verbose = B_TRUE; 47183f9d6ad7SLin Ling break; 4719dd50e0ccSTony Hutter case 'p': 4720dd50e0ccSTony Hutter parseable = B_TRUE; 4721dd50e0ccSTony Hutter break; 4722dd50e0ccSTony Hutter case 'l': 4723dd50e0ccSTony Hutter latency = B_TRUE; 4724dd50e0ccSTony Hutter break; 4725dd50e0ccSTony Hutter case 'q': 4726dd50e0ccSTony Hutter queues = B_TRUE; 4727dd50e0ccSTony Hutter break; 4728dd50e0ccSTony Hutter case 'H': 4729dd50e0ccSTony Hutter scripted = B_TRUE; 4730dd50e0ccSTony Hutter break; 4731dd50e0ccSTony Hutter case 'w': 4732dd50e0ccSTony Hutter l_histo = B_TRUE; 4733dd50e0ccSTony Hutter break; 4734dd50e0ccSTony Hutter case 'r': 4735dd50e0ccSTony Hutter rq_histo = B_TRUE; 4736dd50e0ccSTony Hutter break; 4737dd50e0ccSTony Hutter case 'y': 4738dd50e0ccSTony Hutter omit_since_boot = B_TRUE; 4739dd50e0ccSTony Hutter break; 4740dd50e0ccSTony Hutter case 'n': 4741dd50e0ccSTony Hutter headers_once = B_TRUE; 4742dd50e0ccSTony Hutter break; 4743dd50e0ccSTony Hutter case 'h': 4744dd50e0ccSTony Hutter usage(B_FALSE); 4745dd50e0ccSTony Hutter break; 47463f9d6ad7SLin Ling case '?': 47473f9d6ad7SLin Ling (void) fprintf(stderr, gettext("invalid option '%c'\n"), 47483f9d6ad7SLin Ling optopt); 47493f9d6ad7SLin Ling usage(B_FALSE); 47503f9d6ad7SLin Ling } 47513f9d6ad7SLin Ling } 47523f9d6ad7SLin Ling 47533f9d6ad7SLin Ling argc -= optind; 47543f9d6ad7SLin Ling argv += optind; 47553f9d6ad7SLin Ling 4756dd50e0ccSTony Hutter cb.cb_literal = parseable; 4757dd50e0ccSTony Hutter cb.cb_scripted = scripted; 4758dd50e0ccSTony Hutter 4759dd50e0ccSTony Hutter if (guid) 4760dd50e0ccSTony Hutter cb.cb_name_flags |= VDEV_NAME_GUID; 4761dd50e0ccSTony Hutter if (follow_links) 4762dd50e0ccSTony Hutter cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS; 4763dd50e0ccSTony Hutter if (full_name) 4764dd50e0ccSTony Hutter cb.cb_name_flags |= VDEV_NAME_PATH; 4765dd50e0ccSTony Hutter cb.cb_iteration = 0; 4766dd50e0ccSTony Hutter cb.cb_namewidth = 0; 4767dd50e0ccSTony Hutter cb.cb_verbose = verbose; 4768dd50e0ccSTony Hutter 4769dd50e0ccSTony Hutter /* Get our interval and count values (if any) */ 4770dd50e0ccSTony Hutter if (guid) { 4771dd50e0ccSTony Hutter get_interval_count_filter_guids(&argc, argv, &interval, 4772dd50e0ccSTony Hutter &count, &cb); 4773dd50e0ccSTony Hutter } else { 4774dd50e0ccSTony Hutter get_interval_count(&argc, argv, &interval, &count); 4775dd50e0ccSTony Hutter } 4776dd50e0ccSTony Hutter 4777dd50e0ccSTony Hutter if (argc == 0) { 4778dd50e0ccSTony Hutter /* No args, so just print the defaults. */ 4779dd50e0ccSTony Hutter } else if (are_all_pools(argc, argv)) { 4780dd50e0ccSTony Hutter /* All the args are pool names */ 4781dd50e0ccSTony Hutter } else if (are_vdevs_in_pool(argc, argv, NULL, &cb)) { 4782dd50e0ccSTony Hutter /* All the args are vdevs */ 4783dd50e0ccSTony Hutter cb.cb_vdev_names = argv; 4784dd50e0ccSTony Hutter cb.cb_vdev_names_count = argc; 4785dd50e0ccSTony Hutter argc = 0; /* No pools to process */ 4786dd50e0ccSTony Hutter } else if (are_all_pools(1, argv)) { 4787dd50e0ccSTony Hutter /* The first arg is a pool name */ 4788dd50e0ccSTony Hutter if (are_vdevs_in_pool(argc - 1, argv + 1, argv[0], &cb)) { 4789dd50e0ccSTony Hutter /* ...and the rest are vdev names */ 4790dd50e0ccSTony Hutter cb.cb_vdev_names = argv + 1; 4791dd50e0ccSTony Hutter cb.cb_vdev_names_count = argc - 1; 4792dd50e0ccSTony Hutter argc = 1; /* One pool to process */ 4793dd50e0ccSTony Hutter } else { 4794dd50e0ccSTony Hutter fprintf(stderr, gettext("Expected either a list of ")); 4795dd50e0ccSTony Hutter fprintf(stderr, gettext("pools, or list of vdevs in")); 4796dd50e0ccSTony Hutter fprintf(stderr, " \"%s\", ", argv[0]); 4797dd50e0ccSTony Hutter fprintf(stderr, gettext("but got:\n")); 4798dd50e0ccSTony Hutter error_list_unresolved_vdevs(argc - 1, argv + 1, 4799dd50e0ccSTony Hutter argv[0], &cb); 4800dd50e0ccSTony Hutter fprintf(stderr, "\n"); 4801dd50e0ccSTony Hutter usage(B_FALSE); 4802dd50e0ccSTony Hutter return (1); 4803dd50e0ccSTony Hutter } 4804dd50e0ccSTony Hutter } else { 4805dd50e0ccSTony Hutter /* 4806dd50e0ccSTony Hutter * The args don't make sense. The first arg isn't a pool name, 4807dd50e0ccSTony Hutter * nor are all the args vdevs. 4808dd50e0ccSTony Hutter */ 4809dd50e0ccSTony Hutter fprintf(stderr, gettext("Unable to parse pools/vdevs list.\n")); 4810dd50e0ccSTony Hutter fprintf(stderr, "\n"); 4811dd50e0ccSTony Hutter return (1); 4812dd50e0ccSTony Hutter } 4813dd50e0ccSTony Hutter 4814dd50e0ccSTony Hutter if (cb.cb_vdev_names_count != 0) { 4815dd50e0ccSTony Hutter /* 4816dd50e0ccSTony Hutter * If user specified vdevs, it implies verbose. 4817dd50e0ccSTony Hutter */ 4818dd50e0ccSTony Hutter cb.cb_verbose = B_TRUE; 4819dd50e0ccSTony Hutter } 48203f9d6ad7SLin Ling 4821fa9e4066Sahrens /* 4822fa9e4066Sahrens * Construct the list of all interesting pools. 4823fa9e4066Sahrens */ 4824fa9e4066Sahrens ret = 0; 4825b1b8ab34Slling if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL) 4826fa9e4066Sahrens return (1); 4827fa9e4066Sahrens 482899653d4eSeschrock if (pool_list_count(list) == 0 && argc != 0) { 482999653d4eSeschrock pool_list_free(list); 4830fa9e4066Sahrens return (1); 483199653d4eSeschrock } 4832fa9e4066Sahrens 4833fa9e4066Sahrens if (pool_list_count(list) == 0 && interval == 0) { 483499653d4eSeschrock pool_list_free(list); 4835fa9e4066Sahrens (void) fprintf(stderr, gettext("no pools available\n")); 4836fa9e4066Sahrens return (1); 4837fa9e4066Sahrens } 4838fa9e4066Sahrens 4839dd50e0ccSTony Hutter if ((l_histo || rq_histo) && (queues || latency)) { 4840dd50e0ccSTony Hutter pool_list_free(list); 4841dd50e0ccSTony Hutter (void) fprintf(stderr, 4842dd50e0ccSTony Hutter gettext("[-r|-w] isn't allowed with [-q|-l]\n")); 4843dd50e0ccSTony Hutter usage(B_FALSE); 4844dd50e0ccSTony Hutter return (1); 4845dd50e0ccSTony Hutter } 4846dd50e0ccSTony Hutter 4847dd50e0ccSTony Hutter if (l_histo && rq_histo) { 4848dd50e0ccSTony Hutter pool_list_free(list); 4849dd50e0ccSTony Hutter (void) fprintf(stderr, 4850dd50e0ccSTony Hutter gettext("Only one of [-r|-w] can be passed at a time\n")); 4851dd50e0ccSTony Hutter usage(B_FALSE); 4852dd50e0ccSTony Hutter return (1); 4853dd50e0ccSTony Hutter } 4854dd50e0ccSTony Hutter 4855fa9e4066Sahrens /* 4856fa9e4066Sahrens * Enter the main iostat loop. 4857fa9e4066Sahrens */ 4858fa9e4066Sahrens cb.cb_list = list; 4859fa9e4066Sahrens 4860dd50e0ccSTony Hutter if (l_histo) { 4861dd50e0ccSTony Hutter /* 4862dd50e0ccSTony Hutter * Histograms tables look out of place when you try to display 4863dd50e0ccSTony Hutter * them with the other stats, so make a rule that you can only 4864dd50e0ccSTony Hutter * print histograms by themselves. 4865dd50e0ccSTony Hutter */ 4866dd50e0ccSTony Hutter cb.cb_flags = IOS_L_HISTO_M; 4867dd50e0ccSTony Hutter } else if (rq_histo) { 4868dd50e0ccSTony Hutter cb.cb_flags = IOS_RQ_HISTO_M; 4869dd50e0ccSTony Hutter } else { 4870dd50e0ccSTony Hutter cb.cb_flags = IOS_DEFAULT_M; 4871dd50e0ccSTony Hutter if (latency) 4872dd50e0ccSTony Hutter cb.cb_flags |= IOS_LATENCY_M; 4873dd50e0ccSTony Hutter if (queues) 4874dd50e0ccSTony Hutter cb.cb_flags |= IOS_QUEUES_M; 4875dd50e0ccSTony Hutter } 4876dd50e0ccSTony Hutter 4877dd50e0ccSTony Hutter /* 4878dd50e0ccSTony Hutter * See if the module supports all the stats we want to display. 4879dd50e0ccSTony Hutter */ 4880dd50e0ccSTony Hutter unsupported_flags = cb.cb_flags & ~get_stat_flags(list); 4881dd50e0ccSTony Hutter if (unsupported_flags) { 4882dd50e0ccSTony Hutter uint64_t f; 4883dd50e0ccSTony Hutter int idx; 4884dd50e0ccSTony Hutter fprintf(stderr, 4885dd50e0ccSTony Hutter gettext("The loaded zfs module doesn't support:")); 4886dd50e0ccSTony Hutter 4887dd50e0ccSTony Hutter /* for each bit set in unsupported_flags */ 4888dd50e0ccSTony Hutter for (f = unsupported_flags; f; f &= ~(1ULL << idx)) { 4889dd50e0ccSTony Hutter idx = lowbit64(f) - 1; 4890dd50e0ccSTony Hutter fprintf(stderr, " -%c", flag_to_arg[idx]); 4891dd50e0ccSTony Hutter } 4892dd50e0ccSTony Hutter 4893dd50e0ccSTony Hutter fprintf(stderr, ". Try running a newer module.\n"), 4894dd50e0ccSTony Hutter pool_list_free(list); 4895dd50e0ccSTony Hutter 4896dd50e0ccSTony Hutter return (1); 4897dd50e0ccSTony Hutter } 4898fa9e4066Sahrens 4899dd50e0ccSTony Hutter for (;;) { 4900fa9e4066Sahrens if ((npools = pool_list_count(list)) == 0) 4901dd50e0ccSTony Hutter (void) fprintf(stderr, gettext("no pools available\n")); 4902dd50e0ccSTony Hutter else { 4903dd50e0ccSTony Hutter /* 4904dd50e0ccSTony Hutter * If this is the first iteration and -y was supplied 4905dd50e0ccSTony Hutter * we skip any printing. 4906dd50e0ccSTony Hutter */ 4907dd50e0ccSTony Hutter boolean_t skip = (omit_since_boot && 4908dd50e0ccSTony Hutter cb.cb_iteration == 0); 4909fa9e4066Sahrens 4910dd50e0ccSTony Hutter /* 4911dd50e0ccSTony Hutter * Refresh all statistics. This is done as an 4912dd50e0ccSTony Hutter * explicit step before calculating the maximum name 4913dd50e0ccSTony Hutter * width, so that any configuration changes are 4914dd50e0ccSTony Hutter * properly accounted for. 4915dd50e0ccSTony Hutter */ 4916dd50e0ccSTony Hutter (void) pool_list_iter(list, B_FALSE, refresh_iostat, 4917dd50e0ccSTony Hutter &cb); 4918088e9d47Seschrock 4919dd50e0ccSTony Hutter /* 4920dd50e0ccSTony Hutter * Iterate over all pools to determine the maximum width 4921dd50e0ccSTony Hutter * for the pool / device name column across all pools. 4922dd50e0ccSTony Hutter */ 4923dd50e0ccSTony Hutter cb.cb_namewidth = 0; 4924dd50e0ccSTony Hutter (void) pool_list_iter(list, B_FALSE, 4925dd50e0ccSTony Hutter get_namewidth_iostat, &cb); 4926fa9e4066Sahrens 4927dd50e0ccSTony Hutter if (timestamp_fmt != NODATE) 4928dd50e0ccSTony Hutter print_timestamp(timestamp_fmt); 492926fd7700SKrishnendu Sadhukhan - Sun Microsystems 4930dd50e0ccSTony Hutter /* 4931dd50e0ccSTony Hutter * Check terminal size so we can print headers 4932dd50e0ccSTony Hutter * even when terminal window has its height 4933dd50e0ccSTony Hutter * changed. 4934dd50e0ccSTony Hutter */ 4935dd50e0ccSTony Hutter if (headers_once == B_FALSE) { 4936dd50e0ccSTony Hutter if (ioctl(1, TIOCGWINSZ, &win) != -1) { 4937dd50e0ccSTony Hutter if (win.ws_row <= 0) { 4938dd50e0ccSTony Hutter headers_once = B_TRUE; 4939dd50e0ccSTony Hutter } else { 4940dd50e0ccSTony Hutter winheight = win.ws_row; 4941dd50e0ccSTony Hutter } 4942dd50e0ccSTony Hutter } 4943dd50e0ccSTony Hutter } 4944dd50e0ccSTony Hutter /* 4945dd50e0ccSTony Hutter * Are we connected to TTY? If not, headers_once 4946dd50e0ccSTony Hutter * should be true, to avoid breaking scripts. 4947dd50e0ccSTony Hutter */ 4948dd50e0ccSTony Hutter if (isatty(fileno(stdout)) == 0) 4949dd50e0ccSTony Hutter headers_once = B_TRUE; 4950fa9e4066Sahrens 4951dd50e0ccSTony Hutter /* 4952dd50e0ccSTony Hutter * If it's the first time and we're not skipping it, 4953dd50e0ccSTony Hutter * or either skip or verbose mode, print the header. 4954dd50e0ccSTony Hutter * 4955dd50e0ccSTony Hutter * The histogram code explicitly prints its header on 4956dd50e0ccSTony Hutter * every vdev, so skip this for histograms. 4957dd50e0ccSTony Hutter */ 4958dd50e0ccSTony Hutter if (((++cb.cb_iteration == 1 && !skip) || 4959dd50e0ccSTony Hutter (skip != verbose) || 4960dd50e0ccSTony Hutter (!headers_once && 4961dd50e0ccSTony Hutter (cb.cb_iteration % winheight) == 0)) && 4962dd50e0ccSTony Hutter (!(cb.cb_flags & IOS_ANYHISTO_M)) && 4963dd50e0ccSTony Hutter !cb.cb_scripted) 4964dd50e0ccSTony Hutter print_iostat_header(&cb); 4965dd50e0ccSTony Hutter 4966dd50e0ccSTony Hutter if (skip) { 4967dd50e0ccSTony Hutter (void) fsleep(interval); 4968dd50e0ccSTony Hutter continue; 4969dd50e0ccSTony Hutter } 4970fa9e4066Sahrens 4971dd50e0ccSTony Hutter (void) pool_list_iter(list, B_FALSE, print_iostat, &cb); 4972fa9e4066Sahrens 4973dd50e0ccSTony Hutter /* 4974dd50e0ccSTony Hutter * If there's more than one pool, and we're not in 4975dd50e0ccSTony Hutter * verbose mode (which prints a separator for us), 4976dd50e0ccSTony Hutter * then print a separator. 4977dd50e0ccSTony Hutter * 4978dd50e0ccSTony Hutter * In addition, if we're printing specific vdevs then 4979dd50e0ccSTony Hutter * we also want an ending separator. 4980dd50e0ccSTony Hutter */ 4981dd50e0ccSTony Hutter if (((npools > 1 && !verbose && 4982dd50e0ccSTony Hutter !(cb.cb_flags & IOS_ANYHISTO_M)) || 4983dd50e0ccSTony Hutter (!(cb.cb_flags & IOS_ANYHISTO_M) && 4984dd50e0ccSTony Hutter cb.cb_vdev_names_count)) && 4985dd50e0ccSTony Hutter !cb.cb_scripted) { 4986dd50e0ccSTony Hutter print_iostat_separator(&cb); 4987*20f5062bSJerry Jelinek printf("\n"); 4988dd50e0ccSTony Hutter } 4989dd50e0ccSTony Hutter } 4990fa9e4066Sahrens 499139c23413Seschrock /* 499239c23413Seschrock * Flush the output so that redirection to a file isn't buffered 499339c23413Seschrock * indefinitely. 499439c23413Seschrock */ 499539c23413Seschrock (void) fflush(stdout); 499639c23413Seschrock 4997fa9e4066Sahrens if (interval == 0) 4998fa9e4066Sahrens break; 4999fa9e4066Sahrens 5000fa9e4066Sahrens if (count != 0 && --count == 0) 5001fa9e4066Sahrens break; 5002fa9e4066Sahrens 5003dd50e0ccSTony Hutter (void) fsleep(interval); 5004fa9e4066Sahrens } 5005fa9e4066Sahrens 5006fa9e4066Sahrens pool_list_free(list); 5007fa9e4066Sahrens 5008fa9e4066Sahrens return (ret); 5009fa9e4066Sahrens } 5010fa9e4066Sahrens 5011fa9e4066Sahrens typedef struct list_cbdata { 50124263d13fSGeorge Wilson boolean_t cb_verbose; 5013663207adSDon Brady int cb_name_flags; 50144263d13fSGeorge Wilson int cb_namewidth; 501599653d4eSeschrock boolean_t cb_scripted; 5016990b4856Slling zprop_list_t *cb_proplist; 5017c58b3526SAdam Stevko boolean_t cb_literal; 5018fa9e4066Sahrens } list_cbdata_t; 5019fa9e4066Sahrens 5020663207adSDon Brady 5021fa9e4066Sahrens /* 5022fa9e4066Sahrens * Given a list of columns to display, output appropriate headers for each one. 5023fa9e4066Sahrens */ 5024990b4856Slling static void 50254263d13fSGeorge Wilson print_header(list_cbdata_t *cb) 5026fa9e4066Sahrens { 50274263d13fSGeorge Wilson zprop_list_t *pl = cb->cb_proplist; 5028ad135b5dSChristopher Siden char headerbuf[ZPOOL_MAXPROPLEN]; 5029990b4856Slling const char *header; 5030990b4856Slling boolean_t first = B_TRUE; 5031990b4856Slling boolean_t right_justify; 50324263d13fSGeorge Wilson size_t width = 0; 5033990b4856Slling 5034990b4856Slling for (; pl != NULL; pl = pl->pl_next) { 50354263d13fSGeorge Wilson width = pl->pl_width; 50364263d13fSGeorge Wilson if (first && cb->cb_verbose) { 50374263d13fSGeorge Wilson /* 50384263d13fSGeorge Wilson * Reset the width to accommodate the verbose listing 50394263d13fSGeorge Wilson * of devices. 50404263d13fSGeorge Wilson */ 50414263d13fSGeorge Wilson width = cb->cb_namewidth; 50424263d13fSGeorge Wilson } 50434263d13fSGeorge Wilson 5044990b4856Slling if (!first) 5045fa9e4066Sahrens (void) printf(" "); 5046fa9e4066Sahrens else 5047990b4856Slling first = B_FALSE; 5048990b4856Slling 5049ad135b5dSChristopher Siden right_justify = B_FALSE; 5050ad135b5dSChristopher Siden if (pl->pl_prop != ZPROP_INVAL) { 5051ad135b5dSChristopher Siden header = zpool_prop_column_name(pl->pl_prop); 5052ad135b5dSChristopher Siden right_justify = zpool_prop_align_right(pl->pl_prop); 5053ad135b5dSChristopher Siden } else { 5054ad135b5dSChristopher Siden int i; 5055ad135b5dSChristopher Siden 5056ad135b5dSChristopher Siden for (i = 0; pl->pl_user_prop[i] != '\0'; i++) 5057ad135b5dSChristopher Siden headerbuf[i] = toupper(pl->pl_user_prop[i]); 5058ad135b5dSChristopher Siden headerbuf[i] = '\0'; 5059ad135b5dSChristopher Siden header = headerbuf; 5060ad135b5dSChristopher Siden } 5061fa9e4066Sahrens 5062990b4856Slling if (pl->pl_next == NULL && !right_justify) 5063990b4856Slling (void) printf("%s", header); 5064990b4856Slling else if (right_justify) 50654263d13fSGeorge Wilson (void) printf("%*s", width, header); 5066990b4856Slling else 50674263d13fSGeorge Wilson (void) printf("%-*s", width, header); 50684263d13fSGeorge Wilson 5069fa9e4066Sahrens } 5070fa9e4066Sahrens 5071fa9e4066Sahrens (void) printf("\n"); 5072fa9e4066Sahrens } 5073fa9e4066Sahrens 5074990b4856Slling /* 5075990b4856Slling * Given a pool and a list of properties, print out all the properties according 5076663207adSDon Brady * to the described layout. Used by zpool_do_list(). 5077990b4856Slling */ 5078990b4856Slling static void 50794263d13fSGeorge Wilson print_pool(zpool_handle_t *zhp, list_cbdata_t *cb) 5080fa9e4066Sahrens { 50814263d13fSGeorge Wilson zprop_list_t *pl = cb->cb_proplist; 5082990b4856Slling boolean_t first = B_TRUE; 5083990b4856Slling char property[ZPOOL_MAXPROPLEN]; 5084990b4856Slling char *propstr; 5085990b4856Slling boolean_t right_justify; 50864263d13fSGeorge Wilson size_t width; 5087990b4856Slling 5088990b4856Slling for (; pl != NULL; pl = pl->pl_next) { 50894263d13fSGeorge Wilson 50904263d13fSGeorge Wilson width = pl->pl_width; 50914263d13fSGeorge Wilson if (first && cb->cb_verbose) { 50924263d13fSGeorge Wilson /* 50934263d13fSGeorge Wilson * Reset the width to accommodate the verbose listing 50944263d13fSGeorge Wilson * of devices. 50954263d13fSGeorge Wilson */ 50964263d13fSGeorge Wilson width = cb->cb_namewidth; 50974263d13fSGeorge Wilson } 50984263d13fSGeorge Wilson 5099990b4856Slling if (!first) { 51004263d13fSGeorge Wilson if (cb->cb_scripted) 5101fa9e4066Sahrens (void) printf("\t"); 5102fa9e4066Sahrens else 5103fa9e4066Sahrens (void) printf(" "); 5104990b4856Slling } else { 5105990b4856Slling first = B_FALSE; 5106fa9e4066Sahrens } 5107fa9e4066Sahrens 5108990b4856Slling right_justify = B_FALSE; 5109990b4856Slling if (pl->pl_prop != ZPROP_INVAL) { 51107a09f97bSGeorge Wilson if (zpool_get_prop(zhp, pl->pl_prop, property, 5111c58b3526SAdam Stevko sizeof (property), NULL, cb->cb_literal) != 0) 5112990b4856Slling propstr = "-"; 5113fa9e4066Sahrens else 5114990b4856Slling propstr = property; 5115fa9e4066Sahrens 5116990b4856Slling right_justify = zpool_prop_align_right(pl->pl_prop); 5117ad135b5dSChristopher Siden } else if ((zpool_prop_feature(pl->pl_user_prop) || 5118ad135b5dSChristopher Siden zpool_prop_unsupported(pl->pl_user_prop)) && 5119ad135b5dSChristopher Siden zpool_prop_get_feature(zhp, pl->pl_user_prop, property, 5120ad135b5dSChristopher Siden sizeof (property)) == 0) { 5121ad135b5dSChristopher Siden propstr = property; 5122990b4856Slling } else { 5123990b4856Slling propstr = "-"; 5124990b4856Slling } 5125fa9e4066Sahrens 5126fa9e4066Sahrens 5127990b4856Slling /* 5128990b4856Slling * If this is being called in scripted mode, or if this is the 5129990b4856Slling * last column and it is left-justified, don't include a width 5130990b4856Slling * format specifier. 5131990b4856Slling */ 51324263d13fSGeorge Wilson if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify)) 5133990b4856Slling (void) printf("%s", propstr); 5134990b4856Slling else if (right_justify) 5135990b4856Slling (void) printf("%*s", width, propstr); 5136990b4856Slling else 5137990b4856Slling (void) printf("%-*s", width, propstr); 5138990b4856Slling } 5139fa9e4066Sahrens 5140990b4856Slling (void) printf("\n"); 5141990b4856Slling } 5142fa9e4066Sahrens 51434263d13fSGeorge Wilson static void 51447a09f97bSGeorge Wilson print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted, 51457a09f97bSGeorge Wilson boolean_t valid) 51464263d13fSGeorge Wilson { 51474263d13fSGeorge Wilson char propval[64]; 51484263d13fSGeorge Wilson boolean_t fixed; 51494263d13fSGeorge Wilson size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL); 51504263d13fSGeorge Wilson 51517a09f97bSGeorge Wilson switch (prop) { 51527a09f97bSGeorge Wilson case ZPOOL_PROP_EXPANDSZ: 515386714001SSerapheim Dimitropoulos case ZPOOL_PROP_CHECKPOINT: 51547a09f97bSGeorge Wilson if (value == 0) 51557a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval)); 51567a09f97bSGeorge Wilson else 51577a09f97bSGeorge Wilson zfs_nicenum(value, propval, sizeof (propval)); 51587a09f97bSGeorge Wilson break; 51597a09f97bSGeorge Wilson case ZPOOL_PROP_FRAGMENTATION: 51607a09f97bSGeorge Wilson if (value == ZFS_FRAG_INVALID) { 51617a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval)); 51627a09f97bSGeorge Wilson } else { 51637a09f97bSGeorge Wilson (void) snprintf(propval, sizeof (propval), "%llu%%", 51647a09f97bSGeorge Wilson value); 51657a09f97bSGeorge Wilson } 51667a09f97bSGeorge Wilson break; 51677a09f97bSGeorge Wilson case ZPOOL_PROP_CAPACITY: 5168663207adSDon Brady (void) snprintf(propval, sizeof (propval), 5169663207adSDon Brady value < 1000 ? "%1.2f%%" : value < 10000 ? 5170663207adSDon Brady "%2.1f%%" : "%3.0f%%", value / 100.0); 51717a09f97bSGeorge Wilson break; 51727a09f97bSGeorge Wilson default: 51732e4c9986SGeorge Wilson zfs_nicenum(value, propval, sizeof (propval)); 51747a09f97bSGeorge Wilson } 51757a09f97bSGeorge Wilson 51767a09f97bSGeorge Wilson if (!valid) 51777a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval)); 51784263d13fSGeorge Wilson 51794263d13fSGeorge Wilson if (scripted) 51804263d13fSGeorge Wilson (void) printf("\t%s", propval); 51814263d13fSGeorge Wilson else 51824263d13fSGeorge Wilson (void) printf(" %*s", width, propval); 51834263d13fSGeorge Wilson } 51844263d13fSGeorge Wilson 5185663207adSDon Brady /* 5186663207adSDon Brady * print static default line per vdev 5187663207adSDon Brady */ 51884263d13fSGeorge Wilson void 51894263d13fSGeorge Wilson print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 51904263d13fSGeorge Wilson list_cbdata_t *cb, int depth) 51914263d13fSGeorge Wilson { 51924263d13fSGeorge Wilson nvlist_t **child; 51934263d13fSGeorge Wilson vdev_stat_t *vs; 51944263d13fSGeorge Wilson uint_t c, children; 51954263d13fSGeorge Wilson char *vname; 51964263d13fSGeorge Wilson boolean_t scripted = cb->cb_scripted; 519752244c09SJohn Wren Kennedy uint64_t islog = B_FALSE; 519852244c09SJohn Wren Kennedy char *dashes = "%-*s - - - - - -\n"; 51994263d13fSGeorge Wilson 52004263d13fSGeorge Wilson verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 52014263d13fSGeorge Wilson (uint64_t **)&vs, &c) == 0); 52024263d13fSGeorge Wilson 52034263d13fSGeorge Wilson if (name != NULL) { 52047a09f97bSGeorge Wilson boolean_t toplevel = (vs->vs_space != 0); 52057a09f97bSGeorge Wilson uint64_t cap; 52067a09f97bSGeorge Wilson 52075cabbc6bSPrashanth Sreenivasa if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 52085cabbc6bSPrashanth Sreenivasa return; 52095cabbc6bSPrashanth Sreenivasa 52104263d13fSGeorge Wilson if (scripted) 52114263d13fSGeorge Wilson (void) printf("\t%s", name); 52124263d13fSGeorge Wilson else if (strlen(name) + depth > cb->cb_namewidth) 52134263d13fSGeorge Wilson (void) printf("%*s%s", depth, "", name); 52144263d13fSGeorge Wilson else 52154263d13fSGeorge Wilson (void) printf("%*s%s%*s", depth, "", name, 52164263d13fSGeorge Wilson (int)(cb->cb_namewidth - strlen(name) - depth), ""); 52174263d13fSGeorge Wilson 52187a09f97bSGeorge Wilson /* 52197a09f97bSGeorge Wilson * Print the properties for the individual vdevs. Some 52207a09f97bSGeorge Wilson * properties are only applicable to toplevel vdevs. The 52217a09f97bSGeorge Wilson * 'toplevel' boolean value is passed to the print_one_column() 52227a09f97bSGeorge Wilson * to indicate that the value is valid. 52237a09f97bSGeorge Wilson */ 52247a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted, 52257a09f97bSGeorge Wilson toplevel); 52267a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted, 52277a09f97bSGeorge Wilson toplevel); 52287a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc, 52297a09f97bSGeorge Wilson scripted, toplevel); 523086714001SSerapheim Dimitropoulos print_one_column(ZPOOL_PROP_CHECKPOINT, 523186714001SSerapheim Dimitropoulos vs->vs_checkpoint_space, scripted, toplevel); 52327a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted, 52337a09f97bSGeorge Wilson B_TRUE); 52347a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_FRAGMENTATION, 52357a09f97bSGeorge Wilson vs->vs_fragmentation, scripted, 52367a09f97bSGeorge Wilson (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel)); 52377a09f97bSGeorge Wilson cap = (vs->vs_space == 0) ? 0 : 5238663207adSDon Brady (vs->vs_alloc * 10000 / vs->vs_space); 52397a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel); 52404263d13fSGeorge Wilson (void) printf("\n"); 52414263d13fSGeorge Wilson } 52424263d13fSGeorge Wilson 52434263d13fSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 52444263d13fSGeorge Wilson &child, &children) != 0) 52454263d13fSGeorge Wilson return; 52464263d13fSGeorge Wilson 5247663207adSDon Brady /* list the normal vdevs first */ 52484263d13fSGeorge Wilson for (c = 0; c < children; c++) { 52494263d13fSGeorge Wilson uint64_t ishole = B_FALSE; 52504263d13fSGeorge Wilson 52514263d13fSGeorge Wilson if (nvlist_lookup_uint64(child[c], 52524263d13fSGeorge Wilson ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole) 52534263d13fSGeorge Wilson continue; 52544263d13fSGeorge Wilson 525552244c09SJohn Wren Kennedy if (nvlist_lookup_uint64(child[c], 5256663207adSDon Brady ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) 525752244c09SJohn Wren Kennedy continue; 525852244c09SJohn Wren Kennedy 5259663207adSDon Brady if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 5260663207adSDon Brady continue; 5261663207adSDon Brady 5262663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 5263663207adSDon Brady cb->cb_name_flags); 52644263d13fSGeorge Wilson print_list_stats(zhp, vname, child[c], cb, depth + 2); 52654263d13fSGeorge Wilson free(vname); 52664263d13fSGeorge Wilson } 52674263d13fSGeorge Wilson 5268663207adSDon Brady /* list the classes: 'logs', 'dedup', and 'special' */ 5269663207adSDon Brady for (uint_t n = 0; n < 3; n++) { 5270663207adSDon Brady boolean_t printed = B_FALSE; 5271663207adSDon Brady 527252244c09SJohn Wren Kennedy for (c = 0; c < children; c++) { 5273663207adSDon Brady char *bias = NULL; 5274663207adSDon Brady char *type = NULL; 5275663207adSDon Brady 527652244c09SJohn Wren Kennedy if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 5277663207adSDon Brady &islog) == 0 && islog) { 5278663207adSDon Brady bias = VDEV_ALLOC_CLASS_LOGS; 5279663207adSDon Brady } else { 5280663207adSDon Brady (void) nvlist_lookup_string(child[c], 5281663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &bias); 5282663207adSDon Brady (void) nvlist_lookup_string(child[c], 5283663207adSDon Brady ZPOOL_CONFIG_TYPE, &type); 5284663207adSDon Brady } 5285663207adSDon Brady if (bias == NULL || strcmp(bias, class_name[n]) != 0) 5286663207adSDon Brady continue; 5287663207adSDon Brady if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0) 528852244c09SJohn Wren Kennedy continue; 5289663207adSDon Brady 5290663207adSDon Brady if (!printed) { 5291663207adSDon Brady /* LINTED E_SEC_PRINTF_VAR_FMT */ 5292663207adSDon Brady (void) printf(dashes, cb->cb_namewidth, 5293663207adSDon Brady class_name[n]); 5294663207adSDon Brady printed = B_TRUE; 5295663207adSDon Brady } 5296663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 5297663207adSDon Brady cb->cb_name_flags); 529852244c09SJohn Wren Kennedy print_list_stats(zhp, vname, child[c], cb, depth + 2); 529952244c09SJohn Wren Kennedy free(vname); 530052244c09SJohn Wren Kennedy } 530152244c09SJohn Wren Kennedy } 530252244c09SJohn Wren Kennedy 53034263d13fSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 530452244c09SJohn Wren Kennedy &child, &children) == 0 && children > 0) { 530552244c09SJohn Wren Kennedy /* LINTED E_SEC_PRINTF_VAR_FMT */ 530652244c09SJohn Wren Kennedy (void) printf(dashes, cb->cb_namewidth, "cache"); 530752244c09SJohn Wren Kennedy for (c = 0; c < children; c++) { 5308663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 5309663207adSDon Brady cb->cb_name_flags); 531052244c09SJohn Wren Kennedy print_list_stats(zhp, vname, child[c], cb, depth + 2); 531152244c09SJohn Wren Kennedy free(vname); 531252244c09SJohn Wren Kennedy } 531352244c09SJohn Wren Kennedy } 53144263d13fSGeorge Wilson 531552244c09SJohn Wren Kennedy if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child, 531652244c09SJohn Wren Kennedy &children) == 0 && children > 0) { 531752244c09SJohn Wren Kennedy /* LINTED E_SEC_PRINTF_VAR_FMT */ 531852244c09SJohn Wren Kennedy (void) printf(dashes, cb->cb_namewidth, "spare"); 53194263d13fSGeorge Wilson for (c = 0; c < children; c++) { 5320663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 5321663207adSDon Brady cb->cb_name_flags); 53224263d13fSGeorge Wilson print_list_stats(zhp, vname, child[c], cb, depth + 2); 53234263d13fSGeorge Wilson free(vname); 53244263d13fSGeorge Wilson } 53254263d13fSGeorge Wilson } 53264263d13fSGeorge Wilson } 53274263d13fSGeorge Wilson 5328990b4856Slling /* 5329990b4856Slling * Generic callback function to list a pool. 5330990b4856Slling */ 5331990b4856Slling int 5332990b4856Slling list_callback(zpool_handle_t *zhp, void *data) 5333990b4856Slling { 5334990b4856Slling list_cbdata_t *cbp = data; 53354263d13fSGeorge Wilson nvlist_t *config; 53364263d13fSGeorge Wilson nvlist_t *nvroot; 5337fa9e4066Sahrens 53384263d13fSGeorge Wilson config = zpool_get_config(zhp, NULL); 5339fa9e4066Sahrens 5340663207adSDon Brady if (cbp->cb_verbose) { 5341663207adSDon Brady config = zpool_get_config(zhp, NULL); 5342663207adSDon Brady 5343663207adSDon Brady verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 5344663207adSDon Brady &nvroot) == 0); 5345663207adSDon Brady } 5346663207adSDon Brady 5347663207adSDon Brady if (cbp->cb_verbose) 5348663207adSDon Brady cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0, 5349663207adSDon Brady cbp->cb_name_flags); 5350663207adSDon Brady 53514263d13fSGeorge Wilson print_pool(zhp, cbp); 53524263d13fSGeorge Wilson 5353663207adSDon Brady if (cbp->cb_verbose) 5354663207adSDon Brady print_list_stats(zhp, NULL, nvroot, cbp, 0); 5355fa9e4066Sahrens 5356fa9e4066Sahrens return (0); 5357fa9e4066Sahrens } 5358fa9e4066Sahrens 5359dd50e0ccSTony Hutter /* 5360dd50e0ccSTony Hutter * Set the minimum pool/vdev name column width. The width must be at least 9, 5361dd50e0ccSTony Hutter * but may be as large as needed. 5362dd50e0ccSTony Hutter */ 5363dd50e0ccSTony Hutter static int 5364dd50e0ccSTony Hutter get_namewidth_list(zpool_handle_t *zhp, void *data) 5365dd50e0ccSTony Hutter { 5366dd50e0ccSTony Hutter list_cbdata_t *cb = data; 5367dd50e0ccSTony Hutter int width; 5368dd50e0ccSTony Hutter 5369dd50e0ccSTony Hutter width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_name_flags, 5370dd50e0ccSTony Hutter cb->cb_verbose); 5371dd50e0ccSTony Hutter 5372dd50e0ccSTony Hutter if (width < 9) 5373dd50e0ccSTony Hutter width = 9; 5374dd50e0ccSTony Hutter 5375dd50e0ccSTony Hutter cb->cb_namewidth = width; 5376dd50e0ccSTony Hutter 5377dd50e0ccSTony Hutter return (0); 5378dd50e0ccSTony Hutter } 5379dd50e0ccSTony Hutter 5380fa9e4066Sahrens /* 5381663207adSDon Brady * zpool list [-gHLP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]] 5382fa9e4066Sahrens * 5383663207adSDon Brady * -g Display guid for individual vdev name. 5384990b4856Slling * -H Scripted mode. Don't display headers, and separate properties 5385990b4856Slling * by a single tab. 5386663207adSDon Brady * -L Follow links when resolving vdev path name. 5387990b4856Slling * -o List of properties to display. Defaults to 53887a09f97bSGeorge Wilson * "name,size,allocated,free,expandsize,fragmentation,capacity," 53897a09f97bSGeorge Wilson * "dedupratio,health,altroot" 539004e56356SAndriy Gapon * -p Diplay values in parsable (exact) format. 5391663207adSDon Brady * -P Display full path for vdev name. 53923f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format 5393fa9e4066Sahrens * 5394fa9e4066Sahrens * List all pools in the system, whether or not they're healthy. Output space 5395fa9e4066Sahrens * statistics for each one, as well as health status summary. 5396fa9e4066Sahrens */ 5397fa9e4066Sahrens int 5398fa9e4066Sahrens zpool_do_list(int argc, char **argv) 5399fa9e4066Sahrens { 5400fa9e4066Sahrens int c; 5401fa9e4066Sahrens int ret; 5402fa9e4066Sahrens list_cbdata_t cb = { 0 }; 5403990b4856Slling static char default_props[] = 540486714001SSerapheim Dimitropoulos "name,size,allocated,free,checkpoint,expandsize,fragmentation," 540586714001SSerapheim Dimitropoulos "capacity,dedupratio,health,altroot"; 5406990b4856Slling char *props = default_props; 5407dd50e0ccSTony Hutter float interval = 0; 5408dd50e0ccSTony Hutter unsigned long count = 0; 54094263d13fSGeorge Wilson zpool_list_t *list; 54104263d13fSGeorge Wilson boolean_t first = B_TRUE; 5411fa9e4066Sahrens 5412fa9e4066Sahrens /* check options */ 5413663207adSDon Brady while ((c = getopt(argc, argv, ":gHLo:pPT:v")) != -1) { 5414fa9e4066Sahrens switch (c) { 5415663207adSDon Brady case 'g': 5416663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_GUID; 5417663207adSDon Brady break; 5418fa9e4066Sahrens case 'H': 541999653d4eSeschrock cb.cb_scripted = B_TRUE; 5420fa9e4066Sahrens break; 5421663207adSDon Brady case 'L': 5422663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS; 5423663207adSDon Brady break; 5424fa9e4066Sahrens case 'o': 5425990b4856Slling props = optarg; 5426fa9e4066Sahrens break; 5427663207adSDon Brady case 'P': 5428663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_PATH; 5429663207adSDon Brady break; 5430c58b3526SAdam Stevko case 'p': 5431c58b3526SAdam Stevko cb.cb_literal = B_TRUE; 5432c58b3526SAdam Stevko break; 54333f9d6ad7SLin Ling case 'T': 54343f9d6ad7SLin Ling get_timestamp_arg(*optarg); 54353f9d6ad7SLin Ling break; 54364263d13fSGeorge Wilson case 'v': 54374263d13fSGeorge Wilson cb.cb_verbose = B_TRUE; 5438663207adSDon Brady cb.cb_namewidth = 8; /* 8 until precalc is avail */ 54394263d13fSGeorge Wilson break; 5440fa9e4066Sahrens case ':': 5441fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 5442fa9e4066Sahrens "'%c' option\n"), optopt); 544399653d4eSeschrock usage(B_FALSE); 5444fa9e4066Sahrens break; 5445fa9e4066Sahrens case '?': 5446fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5447fa9e4066Sahrens optopt); 544899653d4eSeschrock usage(B_FALSE); 5449fa9e4066Sahrens } 5450fa9e4066Sahrens } 5451fa9e4066Sahrens 5452fa9e4066Sahrens argc -= optind; 5453fa9e4066Sahrens argv += optind; 5454fa9e4066Sahrens 54553f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count); 54563f9d6ad7SLin Ling 5457990b4856Slling if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) 5458990b4856Slling usage(B_FALSE); 5459fa9e4066Sahrens 54603f9d6ad7SLin Ling for (;;) { 5461cd67d23dSGeorge Wilson if ((list = pool_list_get(argc, argv, &cb.cb_proplist, 5462cd67d23dSGeorge Wilson &ret)) == NULL) 5463cd67d23dSGeorge Wilson return (1); 54644263d13fSGeorge Wilson 54654263d13fSGeorge Wilson if (pool_list_count(list) == 0) 54664263d13fSGeorge Wilson break; 54674263d13fSGeorge Wilson 54684263d13fSGeorge Wilson cb.cb_namewidth = 0; 5469dd50e0ccSTony Hutter (void) pool_list_iter(list, B_FALSE, get_namewidth_list, &cb); 5470990b4856Slling 54713f9d6ad7SLin Ling if (timestamp_fmt != NODATE) 54723f9d6ad7SLin Ling print_timestamp(timestamp_fmt); 5473fa9e4066Sahrens 54744263d13fSGeorge Wilson if (!cb.cb_scripted && (first || cb.cb_verbose)) { 54754263d13fSGeorge Wilson print_header(&cb); 54764263d13fSGeorge Wilson first = B_FALSE; 54773f9d6ad7SLin Ling } 54784263d13fSGeorge Wilson ret = pool_list_iter(list, B_TRUE, list_callback, &cb); 54793f9d6ad7SLin Ling 54803f9d6ad7SLin Ling if (interval == 0) 54813f9d6ad7SLin Ling break; 54823f9d6ad7SLin Ling 54833f9d6ad7SLin Ling if (count != 0 && --count == 0) 54843f9d6ad7SLin Ling break; 54853f9d6ad7SLin Ling 5486cd67d23dSGeorge Wilson pool_list_free(list); 5487dd50e0ccSTony Hutter (void) fsleep(interval); 5488fa9e4066Sahrens } 5489fa9e4066Sahrens 5490cd67d23dSGeorge Wilson if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) { 5491cd67d23dSGeorge Wilson (void) printf(gettext("no pools available\n")); 5492cd67d23dSGeorge Wilson ret = 0; 5493cd67d23dSGeorge Wilson } 5494cd67d23dSGeorge Wilson 5495cd67d23dSGeorge Wilson pool_list_free(list); 54963f9d6ad7SLin Ling zprop_free_list(cb.cb_proplist); 5497fa9e4066Sahrens return (ret); 5498fa9e4066Sahrens } 5499fa9e4066Sahrens 5500fa9e4066Sahrens static int 5501fa9e4066Sahrens zpool_do_attach_or_replace(int argc, char **argv, int replacing) 5502fa9e4066Sahrens { 550399653d4eSeschrock boolean_t force = B_FALSE; 5504fa9e4066Sahrens int c; 5505fa9e4066Sahrens nvlist_t *nvroot; 5506fa9e4066Sahrens char *poolname, *old_disk, *new_disk; 5507fa9e4066Sahrens zpool_handle_t *zhp; 55087855d95bSToomas Soome zpool_boot_label_t boot_type; 55097855d95bSToomas Soome uint64_t boot_size; 55105711d393Sloli nvlist_t *props = NULL; 55115711d393Sloli char *propval; 551299653d4eSeschrock int ret; 5513fa9e4066Sahrens 5514fa9e4066Sahrens /* check options */ 55155711d393Sloli while ((c = getopt(argc, argv, "fo:")) != -1) { 5516fa9e4066Sahrens switch (c) { 5517fa9e4066Sahrens case 'f': 551899653d4eSeschrock force = B_TRUE; 5519fa9e4066Sahrens break; 55205711d393Sloli case 'o': 55215711d393Sloli if ((propval = strchr(optarg, '=')) == NULL) { 55225711d393Sloli (void) fprintf(stderr, gettext("missing " 55235711d393Sloli "'=' for -o option\n")); 55245711d393Sloli usage(B_FALSE); 55255711d393Sloli } 55265711d393Sloli *propval = '\0'; 55275711d393Sloli propval++; 55285711d393Sloli 55295711d393Sloli if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) || 55305711d393Sloli (add_prop_list(optarg, propval, &props, B_TRUE))) 55315711d393Sloli usage(B_FALSE); 55325711d393Sloli break; 5533fa9e4066Sahrens case '?': 5534fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5535fa9e4066Sahrens optopt); 553699653d4eSeschrock usage(B_FALSE); 5537fa9e4066Sahrens } 5538fa9e4066Sahrens } 5539fa9e4066Sahrens 5540fa9e4066Sahrens argc -= optind; 5541fa9e4066Sahrens argv += optind; 5542fa9e4066Sahrens 5543fa9e4066Sahrens /* get pool name and check number of arguments */ 5544fa9e4066Sahrens if (argc < 1) { 5545fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 554699653d4eSeschrock usage(B_FALSE); 5547fa9e4066Sahrens } 5548fa9e4066Sahrens 5549fa9e4066Sahrens poolname = argv[0]; 5550fa9e4066Sahrens 5551fa9e4066Sahrens if (argc < 2) { 5552fa9e4066Sahrens (void) fprintf(stderr, 5553fa9e4066Sahrens gettext("missing <device> specification\n")); 555499653d4eSeschrock usage(B_FALSE); 5555fa9e4066Sahrens } 5556fa9e4066Sahrens 5557fa9e4066Sahrens old_disk = argv[1]; 5558fa9e4066Sahrens 5559fa9e4066Sahrens if (argc < 3) { 5560fa9e4066Sahrens if (!replacing) { 5561fa9e4066Sahrens (void) fprintf(stderr, 5562fa9e4066Sahrens gettext("missing <new_device> specification\n")); 556399653d4eSeschrock usage(B_FALSE); 5564fa9e4066Sahrens } 5565fa9e4066Sahrens new_disk = old_disk; 5566fa9e4066Sahrens argc -= 1; 5567fa9e4066Sahrens argv += 1; 5568fa9e4066Sahrens } else { 5569fa9e4066Sahrens new_disk = argv[2]; 5570fa9e4066Sahrens argc -= 2; 5571fa9e4066Sahrens argv += 2; 5572fa9e4066Sahrens } 5573fa9e4066Sahrens 5574fa9e4066Sahrens if (argc > 1) { 5575fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 557699653d4eSeschrock usage(B_FALSE); 5577fa9e4066Sahrens } 5578fa9e4066Sahrens 557999653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 5580fa9e4066Sahrens return (1); 5581fa9e4066Sahrens 55828488aeb5Staylor if (zpool_get_config(zhp, NULL) == NULL) { 5583fa9e4066Sahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 5584fa9e4066Sahrens poolname); 5585fa9e4066Sahrens zpool_close(zhp); 5586fa9e4066Sahrens return (1); 5587fa9e4066Sahrens } 5588fa9e4066Sahrens 55897855d95bSToomas Soome if (zpool_is_bootable(zhp)) 55907855d95bSToomas Soome boot_type = ZPOOL_COPY_BOOT_LABEL; 55917855d95bSToomas Soome else 55927855d95bSToomas Soome boot_type = ZPOOL_NO_BOOT_LABEL; 55937855d95bSToomas Soome 55947855d95bSToomas Soome boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 55955711d393Sloli 55965711d393Sloli /* unless manually specified use "ashift" pool property (if set) */ 55975711d393Sloli if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) { 55985711d393Sloli int intval; 55995711d393Sloli zprop_source_t src; 56005711d393Sloli char strval[ZPOOL_MAXPROPLEN]; 56015711d393Sloli 56025711d393Sloli intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src); 56035711d393Sloli if (src != ZPROP_SRC_DEFAULT) { 56045711d393Sloli (void) sprintf(strval, "%" PRId32, intval); 56055711d393Sloli verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval, 56065711d393Sloli &props, B_TRUE) == 0); 56075711d393Sloli } 56085711d393Sloli } 56095711d393Sloli 56105711d393Sloli nvroot = make_root_vdev(zhp, props, force, B_FALSE, replacing, B_FALSE, 56117855d95bSToomas Soome boot_type, boot_size, argc, argv); 5612fa9e4066Sahrens if (nvroot == NULL) { 5613fa9e4066Sahrens zpool_close(zhp); 5614fa9e4066Sahrens return (1); 5615fa9e4066Sahrens } 5616fa9e4066Sahrens 561799653d4eSeschrock ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); 561899653d4eSeschrock 561999653d4eSeschrock nvlist_free(nvroot); 562099653d4eSeschrock zpool_close(zhp); 562199653d4eSeschrock 562299653d4eSeschrock return (ret); 5623fa9e4066Sahrens } 5624fa9e4066Sahrens 5625fa9e4066Sahrens /* 5626fa9e4066Sahrens * zpool replace [-f] <pool> <device> <new_device> 5627fa9e4066Sahrens * 5628fa9e4066Sahrens * -f Force attach, even if <new_device> appears to be in use. 5629fa9e4066Sahrens * 5630fa9e4066Sahrens * Replace <device> with <new_device>. 5631fa9e4066Sahrens */ 5632fa9e4066Sahrens /* ARGSUSED */ 5633fa9e4066Sahrens int 5634fa9e4066Sahrens zpool_do_replace(int argc, char **argv) 5635fa9e4066Sahrens { 5636fa9e4066Sahrens return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 5637fa9e4066Sahrens } 5638fa9e4066Sahrens 5639fa9e4066Sahrens /* 56405711d393Sloli * zpool attach [-f] [-o property=value] <pool> <device> <new_device> 5641fa9e4066Sahrens * 5642fa9e4066Sahrens * -f Force attach, even if <new_device> appears to be in use. 56435711d393Sloli * -o Set property=value. 5644fa9e4066Sahrens * 5645fa9e4066Sahrens * Attach <new_device> to the mirror containing <device>. If <device> is not 5646fa9e4066Sahrens * part of a mirror, then <device> will be transformed into a mirror of 5647fa9e4066Sahrens * <device> and <new_device>. In either case, <new_device> will begin life 5648fa9e4066Sahrens * with a DTL of [0, now], and will immediately begin to resilver itself. 5649fa9e4066Sahrens */ 5650fa9e4066Sahrens int 5651fa9e4066Sahrens zpool_do_attach(int argc, char **argv) 5652fa9e4066Sahrens { 5653fa9e4066Sahrens return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 5654fa9e4066Sahrens } 5655fa9e4066Sahrens 5656fa9e4066Sahrens /* 5657fa9e4066Sahrens * zpool detach [-f] <pool> <device> 5658fa9e4066Sahrens * 5659fa9e4066Sahrens * -f Force detach of <device>, even if DTLs argue against it 5660fa9e4066Sahrens * (not supported yet) 5661fa9e4066Sahrens * 5662fa9e4066Sahrens * Detach a device from a mirror. The operation will be refused if <device> 5663fa9e4066Sahrens * is the last device in the mirror, or if the DTLs indicate that this device 5664fa9e4066Sahrens * has the only valid copy of some data. 5665fa9e4066Sahrens */ 5666fa9e4066Sahrens /* ARGSUSED */ 5667fa9e4066Sahrens int 5668fa9e4066Sahrens zpool_do_detach(int argc, char **argv) 5669fa9e4066Sahrens { 5670fa9e4066Sahrens int c; 5671fa9e4066Sahrens char *poolname, *path; 5672fa9e4066Sahrens zpool_handle_t *zhp; 567399653d4eSeschrock int ret; 5674fa9e4066Sahrens 5675fa9e4066Sahrens /* check options */ 5676fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) { 5677fa9e4066Sahrens switch (c) { 5678fa9e4066Sahrens case 'f': 5679fa9e4066Sahrens case '?': 5680fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5681fa9e4066Sahrens optopt); 568299653d4eSeschrock usage(B_FALSE); 5683fa9e4066Sahrens } 5684fa9e4066Sahrens } 5685fa9e4066Sahrens 5686fa9e4066Sahrens argc -= optind; 5687fa9e4066Sahrens argv += optind; 5688fa9e4066Sahrens 5689fa9e4066Sahrens /* get pool name and check number of arguments */ 5690fa9e4066Sahrens if (argc < 1) { 5691fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 569299653d4eSeschrock usage(B_FALSE); 5693fa9e4066Sahrens } 5694fa9e4066Sahrens 5695fa9e4066Sahrens if (argc < 2) { 5696fa9e4066Sahrens (void) fprintf(stderr, 5697fa9e4066Sahrens gettext("missing <device> specification\n")); 569899653d4eSeschrock usage(B_FALSE); 5699fa9e4066Sahrens } 5700fa9e4066Sahrens 5701fa9e4066Sahrens poolname = argv[0]; 5702fa9e4066Sahrens path = argv[1]; 5703fa9e4066Sahrens 570499653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 5705fa9e4066Sahrens return (1); 5706fa9e4066Sahrens 570799653d4eSeschrock ret = zpool_vdev_detach(zhp, path); 570899653d4eSeschrock 570999653d4eSeschrock zpool_close(zhp); 571099653d4eSeschrock 571199653d4eSeschrock return (ret); 5712fa9e4066Sahrens } 5713fa9e4066Sahrens 57141195e687SMark J Musante /* 5715663207adSDon Brady * zpool split [-gLnP] [-o prop=val] ... 57161195e687SMark J Musante * [-o mntopt] ... 57171195e687SMark J Musante * [-R altroot] <pool> <newpool> [<device> ...] 57181195e687SMark J Musante * 5719663207adSDon Brady * -g Display guid for individual vdev name. 5720663207adSDon Brady * -L Follow links when resolving vdev path name. 57211195e687SMark J Musante * -n Do not split the pool, but display the resulting layout if 57221195e687SMark J Musante * it were to be split. 57231195e687SMark J Musante * -o Set property=value, or set mount options. 5724663207adSDon Brady * -P Display full path for vdev name. 57251195e687SMark J Musante * -R Mount the split-off pool under an alternate root. 5726eb633035STom Caputi * -l Load encryption keys while importing. 57271195e687SMark J Musante * 57281195e687SMark J Musante * Splits the named pool and gives it the new pool name. Devices to be split 57291195e687SMark J Musante * off may be listed, provided that no more than one device is specified 57301195e687SMark J Musante * per top-level vdev mirror. The newly split pool is left in an exported 57311195e687SMark J Musante * state unless -R is specified. 57321195e687SMark J Musante * 57331195e687SMark J Musante * Restrictions: the top-level of the pool pool must only be made up of 57341195e687SMark J Musante * mirrors; all devices in the pool must be healthy; no device may be 57351195e687SMark J Musante * undergoing a resilvering operation. 57361195e687SMark J Musante */ 57371195e687SMark J Musante int 57381195e687SMark J Musante zpool_do_split(int argc, char **argv) 57391195e687SMark J Musante { 57401195e687SMark J Musante char *srcpool, *newpool, *propval; 57411195e687SMark J Musante char *mntopts = NULL; 57421195e687SMark J Musante splitflags_t flags; 57431195e687SMark J Musante int c, ret = 0; 5744eb633035STom Caputi boolean_t loadkeys = B_FALSE; 57451195e687SMark J Musante zpool_handle_t *zhp; 57461195e687SMark J Musante nvlist_t *config, *props = NULL; 57471195e687SMark J Musante 57481195e687SMark J Musante flags.dryrun = B_FALSE; 57491195e687SMark J Musante flags.import = B_FALSE; 5750663207adSDon Brady flags.name_flags = 0; 57511195e687SMark J Musante 57521195e687SMark J Musante /* check options */ 5753eb633035STom Caputi while ((c = getopt(argc, argv, ":gLR:lno:P")) != -1) { 57541195e687SMark J Musante switch (c) { 5755663207adSDon Brady case 'g': 5756663207adSDon Brady flags.name_flags |= VDEV_NAME_GUID; 5757663207adSDon Brady break; 5758663207adSDon Brady case 'L': 5759663207adSDon Brady flags.name_flags |= VDEV_NAME_FOLLOW_LINKS; 5760663207adSDon Brady break; 57611195e687SMark J Musante case 'R': 57621195e687SMark J Musante flags.import = B_TRUE; 57631195e687SMark J Musante if (add_prop_list( 57641195e687SMark J Musante zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg, 57651195e687SMark J Musante &props, B_TRUE) != 0) { 5766aab83bb8SJosef 'Jeff' Sipek nvlist_free(props); 57671195e687SMark J Musante usage(B_FALSE); 57681195e687SMark J Musante } 57691195e687SMark J Musante break; 5770eb633035STom Caputi case 'l': 5771eb633035STom Caputi loadkeys = B_TRUE; 5772eb633035STom Caputi break; 57731195e687SMark J Musante case 'n': 57741195e687SMark J Musante flags.dryrun = B_TRUE; 57751195e687SMark J Musante break; 57761195e687SMark J Musante case 'o': 57771195e687SMark J Musante if ((propval = strchr(optarg, '=')) != NULL) { 57781195e687SMark J Musante *propval = '\0'; 57791195e687SMark J Musante propval++; 57801195e687SMark J Musante if (add_prop_list(optarg, propval, 57811195e687SMark J Musante &props, B_TRUE) != 0) { 5782aab83bb8SJosef 'Jeff' Sipek nvlist_free(props); 57831195e687SMark J Musante usage(B_FALSE); 57841195e687SMark J Musante } 57851195e687SMark J Musante } else { 57861195e687SMark J Musante mntopts = optarg; 57871195e687SMark J Musante } 57881195e687SMark J Musante break; 5789663207adSDon Brady case 'P': 5790663207adSDon Brady flags.name_flags |= VDEV_NAME_PATH; 5791663207adSDon Brady break; 57921195e687SMark J Musante case ':': 57931195e687SMark J Musante (void) fprintf(stderr, gettext("missing argument for " 57941195e687SMark J Musante "'%c' option\n"), optopt); 57951195e687SMark J Musante usage(B_FALSE); 57961195e687SMark J Musante break; 57971195e687SMark J Musante case '?': 57981195e687SMark J Musante (void) fprintf(stderr, gettext("invalid option '%c'\n"), 57991195e687SMark J Musante optopt); 58001195e687SMark J Musante usage(B_FALSE); 58011195e687SMark J Musante break; 58021195e687SMark J Musante } 58031195e687SMark J Musante } 58041195e687SMark J Musante 58051195e687SMark J Musante if (!flags.import && mntopts != NULL) { 58061195e687SMark J Musante (void) fprintf(stderr, gettext("setting mntopts is only " 58071195e687SMark J Musante "valid when importing the pool\n")); 58081195e687SMark J Musante usage(B_FALSE); 58091195e687SMark J Musante } 58101195e687SMark J Musante 5811eb633035STom Caputi if (!flags.import && loadkeys) { 5812eb633035STom Caputi (void) fprintf(stderr, gettext("loading keys is only " 5813eb633035STom Caputi "valid when importing the pool\n")); 5814eb633035STom Caputi usage(B_FALSE); 5815eb633035STom Caputi } 5816eb633035STom Caputi 58171195e687SMark J Musante argc -= optind; 58181195e687SMark J Musante argv += optind; 58191195e687SMark J Musante 58201195e687SMark J Musante if (argc < 1) { 58211195e687SMark J Musante (void) fprintf(stderr, gettext("Missing pool name\n")); 58221195e687SMark J Musante usage(B_FALSE); 58231195e687SMark J Musante } 58241195e687SMark J Musante if (argc < 2) { 58251195e687SMark J Musante (void) fprintf(stderr, gettext("Missing new pool name\n")); 58261195e687SMark J Musante usage(B_FALSE); 58271195e687SMark J Musante } 58281195e687SMark J Musante 58291195e687SMark J Musante srcpool = argv[0]; 58301195e687SMark J Musante newpool = argv[1]; 58311195e687SMark J Musante 58321195e687SMark J Musante argc -= 2; 58331195e687SMark J Musante argv += 2; 58341195e687SMark J Musante 58351195e687SMark J Musante if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) 58361195e687SMark J Musante return (1); 58371195e687SMark J Musante 58381195e687SMark J Musante config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv); 58391195e687SMark J Musante if (config == NULL) { 58401195e687SMark J Musante ret = 1; 58411195e687SMark J Musante } else { 58421195e687SMark J Musante if (flags.dryrun) { 58431195e687SMark J Musante (void) printf(gettext("would create '%s' with the " 58441195e687SMark J Musante "following layout:\n\n"), newpool); 5845663207adSDon Brady print_vdev_tree(NULL, newpool, config, 0, "", 5846663207adSDon Brady flags.name_flags); 58471195e687SMark J Musante } 58481195e687SMark J Musante nvlist_free(config); 58491195e687SMark J Musante } 58501195e687SMark J Musante 58511195e687SMark J Musante zpool_close(zhp); 58521195e687SMark J Musante 58531195e687SMark J Musante if (ret != 0 || flags.dryrun || !flags.import) 58541195e687SMark J Musante return (ret); 58551195e687SMark J Musante 58561195e687SMark J Musante /* 58571195e687SMark J Musante * The split was successful. Now we need to open the new 58581195e687SMark J Musante * pool and import it. 58591195e687SMark J Musante */ 58601195e687SMark J Musante if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) 58611195e687SMark J Musante return (1); 5862eb633035STom Caputi 5863eb633035STom Caputi if (loadkeys) { 5864eb633035STom Caputi ret = zfs_crypto_attempt_load_keys(g_zfs, newpool); 5865eb633035STom Caputi if (ret != 0) 5866eb633035STom Caputi ret = 1; 5867eb633035STom Caputi } 5868eb633035STom Caputi 58691195e687SMark J Musante if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 58701195e687SMark J Musante zpool_enable_datasets(zhp, mntopts, 0) != 0) { 58711195e687SMark J Musante ret = 1; 5872fe7cd8aaSCyril Plisko (void) fprintf(stderr, gettext("Split was successful, but " 58731195e687SMark J Musante "the datasets could not all be mounted\n")); 58741195e687SMark J Musante (void) fprintf(stderr, gettext("Try doing '%s' with a " 58751195e687SMark J Musante "different altroot\n"), "zpool import"); 58761195e687SMark J Musante } 58771195e687SMark J Musante zpool_close(zhp); 58781195e687SMark J Musante 58791195e687SMark J Musante return (ret); 58801195e687SMark J Musante } 58811195e687SMark J Musante 58821195e687SMark J Musante 58831195e687SMark J Musante 5884fa9e4066Sahrens /* 5885441d80aaSlling * zpool online <pool> <device> ... 5886fa9e4066Sahrens */ 5887fa9e4066Sahrens int 5888fa9e4066Sahrens zpool_do_online(int argc, char **argv) 5889fa9e4066Sahrens { 5890fa9e4066Sahrens int c, i; 5891fa9e4066Sahrens char *poolname; 5892fa9e4066Sahrens zpool_handle_t *zhp; 5893fa9e4066Sahrens int ret = 0; 58943d7072f8Seschrock vdev_state_t newstate; 5895573ca77eSGeorge Wilson int flags = 0; 5896fa9e4066Sahrens 5897fa9e4066Sahrens /* check options */ 5898573ca77eSGeorge Wilson while ((c = getopt(argc, argv, "et")) != -1) { 5899fa9e4066Sahrens switch (c) { 5900573ca77eSGeorge Wilson case 'e': 5901573ca77eSGeorge Wilson flags |= ZFS_ONLINE_EXPAND; 5902573ca77eSGeorge Wilson break; 5903fa9e4066Sahrens case 't': 5904fa9e4066Sahrens case '?': 5905fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5906fa9e4066Sahrens optopt); 590799653d4eSeschrock usage(B_FALSE); 5908fa9e4066Sahrens } 5909fa9e4066Sahrens } 5910fa9e4066Sahrens 5911fa9e4066Sahrens argc -= optind; 5912fa9e4066Sahrens argv += optind; 5913fa9e4066Sahrens 5914fa9e4066Sahrens /* get pool name and check number of arguments */ 5915fa9e4066Sahrens if (argc < 1) { 5916fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name\n")); 591799653d4eSeschrock usage(B_FALSE); 5918fa9e4066Sahrens } 5919fa9e4066Sahrens if (argc < 2) { 5920fa9e4066Sahrens (void) fprintf(stderr, gettext("missing device name\n")); 592199653d4eSeschrock usage(B_FALSE); 5922fa9e4066Sahrens } 5923fa9e4066Sahrens 5924fa9e4066Sahrens poolname = argv[0]; 5925fa9e4066Sahrens 592699653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 5927fa9e4066Sahrens return (1); 5928fa9e4066Sahrens 59293d7072f8Seschrock for (i = 1; i < argc; i++) { 5930573ca77eSGeorge Wilson if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) { 59313d7072f8Seschrock if (newstate != VDEV_STATE_HEALTHY) { 59323d7072f8Seschrock (void) printf(gettext("warning: device '%s' " 59333d7072f8Seschrock "onlined, but remains in faulted state\n"), 59343d7072f8Seschrock argv[i]); 59353d7072f8Seschrock if (newstate == VDEV_STATE_FAULTED) 59363d7072f8Seschrock (void) printf(gettext("use 'zpool " 59373d7072f8Seschrock "clear' to restore a faulted " 59383d7072f8Seschrock "device\n")); 59393d7072f8Seschrock else 59403d7072f8Seschrock (void) printf(gettext("use 'zpool " 59413d7072f8Seschrock "replace' to replace devices " 59423d7072f8Seschrock "that are no longer present\n")); 59433d7072f8Seschrock } 59443d7072f8Seschrock } else { 5945fa9e4066Sahrens ret = 1; 59463d7072f8Seschrock } 59473d7072f8Seschrock } 5948fa9e4066Sahrens 594999653d4eSeschrock zpool_close(zhp); 595099653d4eSeschrock 5951fa9e4066Sahrens return (ret); 5952fa9e4066Sahrens } 5953fa9e4066Sahrens 5954fa9e4066Sahrens /* 5955441d80aaSlling * zpool offline [-ft] <pool> <device> ... 5956fa9e4066Sahrens * 5957fa9e4066Sahrens * -f Force the device into the offline state, even if doing 5958fa9e4066Sahrens * so would appear to compromise pool availability. 5959fa9e4066Sahrens * (not supported yet) 5960fa9e4066Sahrens * 5961fa9e4066Sahrens * -t Only take the device off-line temporarily. The offline 5962fa9e4066Sahrens * state will not be persistent across reboots. 5963fa9e4066Sahrens */ 5964fa9e4066Sahrens /* ARGSUSED */ 5965fa9e4066Sahrens int 5966fa9e4066Sahrens zpool_do_offline(int argc, char **argv) 5967fa9e4066Sahrens { 5968fa9e4066Sahrens int c, i; 5969fa9e4066Sahrens char *poolname; 5970fa9e4066Sahrens zpool_handle_t *zhp; 597199653d4eSeschrock int ret = 0; 597299653d4eSeschrock boolean_t istmp = B_FALSE; 5973fa9e4066Sahrens 5974fa9e4066Sahrens /* check options */ 5975fa9e4066Sahrens while ((c = getopt(argc, argv, "ft")) != -1) { 5976fa9e4066Sahrens switch (c) { 5977fa9e4066Sahrens case 't': 597899653d4eSeschrock istmp = B_TRUE; 5979441d80aaSlling break; 5980441d80aaSlling case 'f': 5981fa9e4066Sahrens case '?': 5982fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5983fa9e4066Sahrens optopt); 598499653d4eSeschrock usage(B_FALSE); 5985fa9e4066Sahrens } 5986fa9e4066Sahrens } 5987fa9e4066Sahrens 5988fa9e4066Sahrens argc -= optind; 5989fa9e4066Sahrens argv += optind; 5990fa9e4066Sahrens 5991fa9e4066Sahrens /* get pool name and check number of arguments */ 5992fa9e4066Sahrens if (argc < 1) { 5993fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name\n")); 599499653d4eSeschrock usage(B_FALSE); 5995fa9e4066Sahrens } 5996fa9e4066Sahrens if (argc < 2) { 5997fa9e4066Sahrens (void) fprintf(stderr, gettext("missing device name\n")); 599899653d4eSeschrock usage(B_FALSE); 5999fa9e4066Sahrens } 6000fa9e4066Sahrens 6001fa9e4066Sahrens poolname = argv[0]; 6002fa9e4066Sahrens 600399653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 6004fa9e4066Sahrens return (1); 6005fa9e4066Sahrens 60063d7072f8Seschrock for (i = 1; i < argc; i++) { 60073d7072f8Seschrock if (zpool_vdev_offline(zhp, argv[i], istmp) != 0) 6008fa9e4066Sahrens ret = 1; 60093d7072f8Seschrock } 6010fa9e4066Sahrens 601199653d4eSeschrock zpool_close(zhp); 601299653d4eSeschrock 6013fa9e4066Sahrens return (ret); 6014fa9e4066Sahrens } 6015fa9e4066Sahrens 6016ea8dc4b6Seschrock /* 6017ea8dc4b6Seschrock * zpool clear <pool> [device] 6018ea8dc4b6Seschrock * 6019ea8dc4b6Seschrock * Clear all errors associated with a pool or a particular device. 6020ea8dc4b6Seschrock */ 6021ea8dc4b6Seschrock int 6022ea8dc4b6Seschrock zpool_do_clear(int argc, char **argv) 6023ea8dc4b6Seschrock { 6024468c413aSTim Haley int c; 6025ea8dc4b6Seschrock int ret = 0; 6026468c413aSTim Haley boolean_t dryrun = B_FALSE; 6027468c413aSTim Haley boolean_t do_rewind = B_FALSE; 6028468c413aSTim Haley boolean_t xtreme_rewind = B_FALSE; 6029468c413aSTim Haley uint32_t rewind_policy = ZPOOL_NO_REWIND; 6030468c413aSTim Haley nvlist_t *policy = NULL; 6031ea8dc4b6Seschrock zpool_handle_t *zhp; 6032ea8dc4b6Seschrock char *pool, *device; 6033ea8dc4b6Seschrock 6034468c413aSTim Haley /* check options */ 6035468c413aSTim Haley while ((c = getopt(argc, argv, "FnX")) != -1) { 6036468c413aSTim Haley switch (c) { 6037468c413aSTim Haley case 'F': 6038468c413aSTim Haley do_rewind = B_TRUE; 6039468c413aSTim Haley break; 6040468c413aSTim Haley case 'n': 6041468c413aSTim Haley dryrun = B_TRUE; 6042468c413aSTim Haley break; 6043468c413aSTim Haley case 'X': 6044468c413aSTim Haley xtreme_rewind = B_TRUE; 6045468c413aSTim Haley break; 6046468c413aSTim Haley case '?': 6047468c413aSTim Haley (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6048468c413aSTim Haley optopt); 6049468c413aSTim Haley usage(B_FALSE); 6050468c413aSTim Haley } 6051468c413aSTim Haley } 6052468c413aSTim Haley 6053468c413aSTim Haley argc -= optind; 6054468c413aSTim Haley argv += optind; 6055468c413aSTim Haley 6056468c413aSTim Haley if (argc < 1) { 6057ea8dc4b6Seschrock (void) fprintf(stderr, gettext("missing pool name\n")); 605899653d4eSeschrock usage(B_FALSE); 6059ea8dc4b6Seschrock } 6060ea8dc4b6Seschrock 6061468c413aSTim Haley if (argc > 2) { 6062ea8dc4b6Seschrock (void) fprintf(stderr, gettext("too many arguments\n")); 606399653d4eSeschrock usage(B_FALSE); 6064ea8dc4b6Seschrock } 6065ea8dc4b6Seschrock 6066468c413aSTim Haley if ((dryrun || xtreme_rewind) && !do_rewind) { 6067468c413aSTim Haley (void) fprintf(stderr, 6068468c413aSTim Haley gettext("-n or -X only meaningful with -F\n")); 6069468c413aSTim Haley usage(B_FALSE); 6070468c413aSTim Haley } 6071468c413aSTim Haley if (dryrun) 6072468c413aSTim Haley rewind_policy = ZPOOL_TRY_REWIND; 6073468c413aSTim Haley else if (do_rewind) 6074468c413aSTim Haley rewind_policy = ZPOOL_DO_REWIND; 6075468c413aSTim Haley if (xtreme_rewind) 6076468c413aSTim Haley rewind_policy |= ZPOOL_EXTREME_REWIND; 6077468c413aSTim Haley 6078468c413aSTim Haley /* In future, further rewind policy choices can be passed along here */ 6079468c413aSTim Haley if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 60805dafeea3SPavel Zakharov nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, 60815dafeea3SPavel Zakharov rewind_policy) != 0) { 6082468c413aSTim Haley return (1); 60835dafeea3SPavel Zakharov } 6084468c413aSTim Haley 6085468c413aSTim Haley pool = argv[0]; 6086468c413aSTim Haley device = argc == 2 ? argv[1] : NULL; 6087ea8dc4b6Seschrock 6088468c413aSTim Haley if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 6089468c413aSTim Haley nvlist_free(policy); 6090ea8dc4b6Seschrock return (1); 6091468c413aSTim Haley } 6092ea8dc4b6Seschrock 6093468c413aSTim Haley if (zpool_clear(zhp, device, policy) != 0) 6094ea8dc4b6Seschrock ret = 1; 6095ea8dc4b6Seschrock 6096ea8dc4b6Seschrock zpool_close(zhp); 6097ea8dc4b6Seschrock 6098468c413aSTim Haley nvlist_free(policy); 6099468c413aSTim Haley 6100ea8dc4b6Seschrock return (ret); 6101ea8dc4b6Seschrock } 6102ea8dc4b6Seschrock 6103e9103aaeSGarrett D'Amore /* 6104e9103aaeSGarrett D'Amore * zpool reguid <pool> 6105e9103aaeSGarrett D'Amore */ 6106e9103aaeSGarrett D'Amore int 6107e9103aaeSGarrett D'Amore zpool_do_reguid(int argc, char **argv) 6108e9103aaeSGarrett D'Amore { 6109e9103aaeSGarrett D'Amore int c; 6110e9103aaeSGarrett D'Amore char *poolname; 6111e9103aaeSGarrett D'Amore zpool_handle_t *zhp; 6112e9103aaeSGarrett D'Amore int ret = 0; 6113e9103aaeSGarrett D'Amore 6114e9103aaeSGarrett D'Amore /* check options */ 6115e9103aaeSGarrett D'Amore while ((c = getopt(argc, argv, "")) != -1) { 6116e9103aaeSGarrett D'Amore switch (c) { 6117e9103aaeSGarrett D'Amore case '?': 6118e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6119e9103aaeSGarrett D'Amore optopt); 6120e9103aaeSGarrett D'Amore usage(B_FALSE); 6121e9103aaeSGarrett D'Amore } 6122e9103aaeSGarrett D'Amore } 6123e9103aaeSGarrett D'Amore 6124e9103aaeSGarrett D'Amore argc -= optind; 6125e9103aaeSGarrett D'Amore argv += optind; 6126e9103aaeSGarrett D'Amore 6127e9103aaeSGarrett D'Amore /* get pool name and check number of arguments */ 6128e9103aaeSGarrett D'Amore if (argc < 1) { 6129e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("missing pool name\n")); 6130e9103aaeSGarrett D'Amore usage(B_FALSE); 6131e9103aaeSGarrett D'Amore } 6132e9103aaeSGarrett D'Amore 6133e9103aaeSGarrett D'Amore if (argc > 1) { 6134e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("too many arguments\n")); 6135e9103aaeSGarrett D'Amore usage(B_FALSE); 6136e9103aaeSGarrett D'Amore } 6137e9103aaeSGarrett D'Amore 6138e9103aaeSGarrett D'Amore poolname = argv[0]; 6139e9103aaeSGarrett D'Amore if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 6140e9103aaeSGarrett D'Amore return (1); 6141e9103aaeSGarrett D'Amore 6142e9103aaeSGarrett D'Amore ret = zpool_reguid(zhp); 6143e9103aaeSGarrett D'Amore 6144e9103aaeSGarrett D'Amore zpool_close(zhp); 6145e9103aaeSGarrett D'Amore return (ret); 6146e9103aaeSGarrett D'Amore } 6147e9103aaeSGarrett D'Amore 6148e9103aaeSGarrett D'Amore 61494263d13fSGeorge Wilson /* 61504263d13fSGeorge Wilson * zpool reopen <pool> 61514263d13fSGeorge Wilson * 61524263d13fSGeorge Wilson * Reopen the pool so that the kernel can update the sizes of all vdevs. 61534263d13fSGeorge Wilson */ 61544263d13fSGeorge Wilson int 61554263d13fSGeorge Wilson zpool_do_reopen(int argc, char **argv) 61564263d13fSGeorge Wilson { 615731d7e8faSGeorge Wilson int c; 61584263d13fSGeorge Wilson int ret = 0; 61594263d13fSGeorge Wilson zpool_handle_t *zhp; 61604263d13fSGeorge Wilson char *pool; 61614263d13fSGeorge Wilson 616231d7e8faSGeorge Wilson /* check options */ 616331d7e8faSGeorge Wilson while ((c = getopt(argc, argv, "")) != -1) { 616431d7e8faSGeorge Wilson switch (c) { 616531d7e8faSGeorge Wilson case '?': 616631d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("invalid option '%c'\n"), 616731d7e8faSGeorge Wilson optopt); 616831d7e8faSGeorge Wilson usage(B_FALSE); 616931d7e8faSGeorge Wilson } 617031d7e8faSGeorge Wilson } 617131d7e8faSGeorge Wilson 61724263d13fSGeorge Wilson argc--; 61734263d13fSGeorge Wilson argv++; 61744263d13fSGeorge Wilson 617531d7e8faSGeorge Wilson if (argc < 1) { 617631d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("missing pool name\n")); 617731d7e8faSGeorge Wilson usage(B_FALSE); 617831d7e8faSGeorge Wilson } 617931d7e8faSGeorge Wilson 618031d7e8faSGeorge Wilson if (argc > 1) { 618131d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("too many arguments\n")); 618231d7e8faSGeorge Wilson usage(B_FALSE); 618331d7e8faSGeorge Wilson } 61844263d13fSGeorge Wilson 61854263d13fSGeorge Wilson pool = argv[0]; 61864263d13fSGeorge Wilson if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) 61874263d13fSGeorge Wilson return (1); 61884263d13fSGeorge Wilson 61894263d13fSGeorge Wilson ret = zpool_reopen(zhp); 61904263d13fSGeorge Wilson zpool_close(zhp); 61914263d13fSGeorge Wilson return (ret); 61924263d13fSGeorge Wilson } 61934263d13fSGeorge Wilson 6194fa9e4066Sahrens typedef struct scrub_cbdata { 6195fa9e4066Sahrens int cb_type; 619606eeb2adSek int cb_argc; 619706eeb2adSek char **cb_argv; 61981702cce7SAlek Pinchuk pool_scrub_cmd_t cb_scrub_cmd; 6199fa9e4066Sahrens } scrub_cbdata_t; 6200fa9e4066Sahrens 620186714001SSerapheim Dimitropoulos static boolean_t 620286714001SSerapheim Dimitropoulos zpool_has_checkpoint(zpool_handle_t *zhp) 620386714001SSerapheim Dimitropoulos { 620486714001SSerapheim Dimitropoulos nvlist_t *config, *nvroot; 620586714001SSerapheim Dimitropoulos 620686714001SSerapheim Dimitropoulos config = zpool_get_config(zhp, NULL); 620786714001SSerapheim Dimitropoulos 620886714001SSerapheim Dimitropoulos if (config != NULL) { 620986714001SSerapheim Dimitropoulos pool_checkpoint_stat_t *pcs = NULL; 621086714001SSerapheim Dimitropoulos uint_t c; 621186714001SSerapheim Dimitropoulos 621286714001SSerapheim Dimitropoulos nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 621386714001SSerapheim Dimitropoulos (void) nvlist_lookup_uint64_array(nvroot, 621486714001SSerapheim Dimitropoulos ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 621586714001SSerapheim Dimitropoulos 621686714001SSerapheim Dimitropoulos if (pcs == NULL || pcs->pcs_state == CS_NONE) 621786714001SSerapheim Dimitropoulos return (B_FALSE); 621886714001SSerapheim Dimitropoulos 621986714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS || 622086714001SSerapheim Dimitropoulos pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 622186714001SSerapheim Dimitropoulos return (B_TRUE); 622286714001SSerapheim Dimitropoulos } 622386714001SSerapheim Dimitropoulos 622486714001SSerapheim Dimitropoulos return (B_FALSE); 622586714001SSerapheim Dimitropoulos } 622686714001SSerapheim Dimitropoulos 6227fa9e4066Sahrens int 6228fa9e4066Sahrens scrub_callback(zpool_handle_t *zhp, void *data) 6229fa9e4066Sahrens { 6230fa9e4066Sahrens scrub_cbdata_t *cb = data; 623106eeb2adSek int err; 6232fa9e4066Sahrens 6233ea8dc4b6Seschrock /* 6234ea8dc4b6Seschrock * Ignore faulted pools. 6235ea8dc4b6Seschrock */ 6236ea8dc4b6Seschrock if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 6237e4c795beSTom Caputi (void) fprintf(stderr, gettext("cannot scan '%s': pool is " 6238ea8dc4b6Seschrock "currently unavailable\n"), zpool_get_name(zhp)); 6239ea8dc4b6Seschrock return (1); 6240ea8dc4b6Seschrock } 6241ea8dc4b6Seschrock 62421702cce7SAlek Pinchuk err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd); 624306eeb2adSek 624486714001SSerapheim Dimitropoulos if (err == 0 && zpool_has_checkpoint(zhp) && 624586714001SSerapheim Dimitropoulos cb->cb_type == POOL_SCAN_SCRUB) { 624686714001SSerapheim Dimitropoulos (void) printf(gettext("warning: will not scrub state that " 624786714001SSerapheim Dimitropoulos "belongs to the checkpoint of pool '%s'\n"), 624886714001SSerapheim Dimitropoulos zpool_get_name(zhp)); 624986714001SSerapheim Dimitropoulos } 625086714001SSerapheim Dimitropoulos 625106eeb2adSek return (err != 0); 6252fa9e4066Sahrens } 6253fa9e4066Sahrens 6254fa9e4066Sahrens /* 62551702cce7SAlek Pinchuk * zpool scrub [-s | -p] <pool> ... 6256fa9e4066Sahrens * 6257fa9e4066Sahrens * -s Stop. Stops any in-progress scrub. 62581702cce7SAlek Pinchuk * -p Pause. Pause in-progress scrub. 6259fa9e4066Sahrens */ 6260fa9e4066Sahrens int 6261fa9e4066Sahrens zpool_do_scrub(int argc, char **argv) 6262fa9e4066Sahrens { 6263fa9e4066Sahrens int c; 6264fa9e4066Sahrens scrub_cbdata_t cb; 6265fa9e4066Sahrens 62663f9d6ad7SLin Ling cb.cb_type = POOL_SCAN_SCRUB; 62671702cce7SAlek Pinchuk cb.cb_scrub_cmd = POOL_SCRUB_NORMAL; 6268fa9e4066Sahrens 6269fa9e4066Sahrens /* check options */ 62701702cce7SAlek Pinchuk while ((c = getopt(argc, argv, "sp")) != -1) { 6271fa9e4066Sahrens switch (c) { 6272fa9e4066Sahrens case 's': 62733f9d6ad7SLin Ling cb.cb_type = POOL_SCAN_NONE; 6274fa9e4066Sahrens break; 62751702cce7SAlek Pinchuk case 'p': 62761702cce7SAlek Pinchuk cb.cb_scrub_cmd = POOL_SCRUB_PAUSE; 62771702cce7SAlek Pinchuk break; 6278fa9e4066Sahrens case '?': 6279fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6280fa9e4066Sahrens optopt); 628199653d4eSeschrock usage(B_FALSE); 6282fa9e4066Sahrens } 6283fa9e4066Sahrens } 6284fa9e4066Sahrens 62851702cce7SAlek Pinchuk if (cb.cb_type == POOL_SCAN_NONE && 62861702cce7SAlek Pinchuk cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) { 62871702cce7SAlek Pinchuk (void) fprintf(stderr, gettext("invalid option combination: " 62881702cce7SAlek Pinchuk "-s and -p are mutually exclusive\n")); 62891702cce7SAlek Pinchuk usage(B_FALSE); 62901702cce7SAlek Pinchuk } 62911702cce7SAlek Pinchuk 629206eeb2adSek cb.cb_argc = argc; 629306eeb2adSek cb.cb_argv = argv; 6294fa9e4066Sahrens argc -= optind; 6295fa9e4066Sahrens argv += optind; 6296fa9e4066Sahrens 6297e4c795beSTom Caputi if (argc < 1) { 6298e4c795beSTom Caputi (void) fprintf(stderr, gettext("missing pool name argument\n")); 6299e4c795beSTom Caputi usage(B_FALSE); 6300e4c795beSTom Caputi } 6301e4c795beSTom Caputi 6302e4c795beSTom Caputi return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 6303e4c795beSTom Caputi } 6304e4c795beSTom Caputi 6305e4c795beSTom Caputi /* 6306e4c795beSTom Caputi * zpool resilver <pool> ... 6307e4c795beSTom Caputi * 6308e4c795beSTom Caputi * Restarts any in-progress resilver 6309e4c795beSTom Caputi */ 6310e4c795beSTom Caputi int 6311e4c795beSTom Caputi zpool_do_resilver(int argc, char **argv) 6312e4c795beSTom Caputi { 6313e4c795beSTom Caputi int c; 6314e4c795beSTom Caputi scrub_cbdata_t cb; 6315e4c795beSTom Caputi 6316e4c795beSTom Caputi cb.cb_type = POOL_SCAN_RESILVER; 6317e4c795beSTom Caputi cb.cb_scrub_cmd = POOL_SCRUB_NORMAL; 6318e4c795beSTom Caputi cb.cb_argc = argc; 6319e4c795beSTom Caputi cb.cb_argv = argv; 6320e4c795beSTom Caputi 6321e4c795beSTom Caputi /* check options */ 6322e4c795beSTom Caputi while ((c = getopt(argc, argv, "")) != -1) { 6323e4c795beSTom Caputi switch (c) { 6324e4c795beSTom Caputi case '?': 6325e4c795beSTom Caputi (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6326e4c795beSTom Caputi optopt); 6327e4c795beSTom Caputi usage(B_FALSE); 6328e4c795beSTom Caputi } 6329e4c795beSTom Caputi } 6330e4c795beSTom Caputi 6331e4c795beSTom Caputi argc -= optind; 6332e4c795beSTom Caputi argv += optind; 6333e4c795beSTom Caputi 6334fa9e4066Sahrens if (argc < 1) { 6335fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 633699653d4eSeschrock usage(B_FALSE); 6337fa9e4066Sahrens } 6338fa9e4066Sahrens 6339b1b8ab34Slling return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 6340fa9e4066Sahrens } 6341fa9e4066Sahrens 6342084fd14fSBrian Behlendorf /* 6343084fd14fSBrian Behlendorf * zpool trim [-d] [-r <rate>] [-c | -s] <pool> [<device> ...] 6344084fd14fSBrian Behlendorf * 6345084fd14fSBrian Behlendorf * -c Cancel. Ends any in-progress trim. 6346084fd14fSBrian Behlendorf * -d Secure trim. Requires kernel and device support. 6347084fd14fSBrian Behlendorf * -r <rate> Sets the TRIM rate in bytes (per second). Supports 6348084fd14fSBrian Behlendorf * adding a multiplier suffix such as 'k' or 'm'. 6349084fd14fSBrian Behlendorf * -s Suspend. TRIM can then be restarted with no flags. 6350084fd14fSBrian Behlendorf */ 6351084fd14fSBrian Behlendorf int 6352084fd14fSBrian Behlendorf zpool_do_trim(int argc, char **argv) 6353094e47e9SGeorge Wilson { 6354084fd14fSBrian Behlendorf struct option long_options[] = { 6355084fd14fSBrian Behlendorf {"cancel", no_argument, NULL, 'c'}, 6356084fd14fSBrian Behlendorf {"secure", no_argument, NULL, 'd'}, 6357084fd14fSBrian Behlendorf {"rate", required_argument, NULL, 'r'}, 6358084fd14fSBrian Behlendorf {"suspend", no_argument, NULL, 's'}, 6359084fd14fSBrian Behlendorf {0, 0, 0, 0} 6360084fd14fSBrian Behlendorf }; 6361094e47e9SGeorge Wilson 6362084fd14fSBrian Behlendorf pool_trim_func_t cmd_type = POOL_TRIM_START; 6363084fd14fSBrian Behlendorf uint64_t rate = 0; 6364084fd14fSBrian Behlendorf boolean_t secure = B_FALSE; 6365094e47e9SGeorge Wilson 6366084fd14fSBrian Behlendorf int c; 6367084fd14fSBrian Behlendorf while ((c = getopt_long(argc, argv, "cdr:s", long_options, NULL)) 6368084fd14fSBrian Behlendorf != -1) { 6369084fd14fSBrian Behlendorf switch (c) { 6370084fd14fSBrian Behlendorf case 'c': 6371084fd14fSBrian Behlendorf if (cmd_type != POOL_TRIM_START && 6372084fd14fSBrian Behlendorf cmd_type != POOL_TRIM_CANCEL) { 6373084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("-c cannot be " 6374084fd14fSBrian Behlendorf "combined with other options\n")); 6375084fd14fSBrian Behlendorf usage(B_FALSE); 6376084fd14fSBrian Behlendorf } 6377084fd14fSBrian Behlendorf cmd_type = POOL_TRIM_CANCEL; 6378084fd14fSBrian Behlendorf break; 6379084fd14fSBrian Behlendorf case 'd': 6380084fd14fSBrian Behlendorf if (cmd_type != POOL_TRIM_START) { 6381084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("-d cannot be " 6382084fd14fSBrian Behlendorf "combined with the -c or -s options\n")); 6383084fd14fSBrian Behlendorf usage(B_FALSE); 6384084fd14fSBrian Behlendorf } 6385084fd14fSBrian Behlendorf secure = B_TRUE; 6386084fd14fSBrian Behlendorf break; 6387084fd14fSBrian Behlendorf case 'r': 6388084fd14fSBrian Behlendorf if (cmd_type != POOL_TRIM_START) { 6389084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("-r cannot be " 6390084fd14fSBrian Behlendorf "combined with the -c or -s options\n")); 6391084fd14fSBrian Behlendorf usage(B_FALSE); 6392084fd14fSBrian Behlendorf } 6393084fd14fSBrian Behlendorf if (zfs_nicestrtonum(NULL, optarg, &rate) == -1) { 6394084fd14fSBrian Behlendorf (void) fprintf(stderr, 6395084fd14fSBrian Behlendorf gettext("invalid value for rate\n")); 6396084fd14fSBrian Behlendorf usage(B_FALSE); 6397084fd14fSBrian Behlendorf } 6398084fd14fSBrian Behlendorf break; 6399084fd14fSBrian Behlendorf case 's': 6400084fd14fSBrian Behlendorf if (cmd_type != POOL_TRIM_START && 6401084fd14fSBrian Behlendorf cmd_type != POOL_TRIM_SUSPEND) { 6402084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("-s cannot be " 6403084fd14fSBrian Behlendorf "combined with other options\n")); 6404084fd14fSBrian Behlendorf usage(B_FALSE); 6405084fd14fSBrian Behlendorf } 6406084fd14fSBrian Behlendorf cmd_type = POOL_TRIM_SUSPEND; 6407084fd14fSBrian Behlendorf break; 6408084fd14fSBrian Behlendorf case '?': 6409084fd14fSBrian Behlendorf if (optopt != 0) { 6410084fd14fSBrian Behlendorf (void) fprintf(stderr, 6411084fd14fSBrian Behlendorf gettext("invalid option '%c'\n"), optopt); 6412084fd14fSBrian Behlendorf } else { 6413084fd14fSBrian Behlendorf (void) fprintf(stderr, 6414084fd14fSBrian Behlendorf gettext("invalid option '%s'\n"), 6415084fd14fSBrian Behlendorf argv[optind - 1]); 6416084fd14fSBrian Behlendorf } 6417084fd14fSBrian Behlendorf usage(B_FALSE); 6418084fd14fSBrian Behlendorf } 6419094e47e9SGeorge Wilson } 6420094e47e9SGeorge Wilson 6421084fd14fSBrian Behlendorf argc -= optind; 6422084fd14fSBrian Behlendorf argv += optind; 6423084fd14fSBrian Behlendorf 6424084fd14fSBrian Behlendorf if (argc < 1) { 6425084fd14fSBrian Behlendorf (void) fprintf(stderr, gettext("missing pool name argument\n")); 6426084fd14fSBrian Behlendorf usage(B_FALSE); 6427084fd14fSBrian Behlendorf return (-1); 6428084fd14fSBrian Behlendorf } 6429084fd14fSBrian Behlendorf 6430084fd14fSBrian Behlendorf char *poolname = argv[0]; 6431084fd14fSBrian Behlendorf zpool_handle_t *zhp = zpool_open(g_zfs, poolname); 6432084fd14fSBrian Behlendorf if (zhp == NULL) 6433084fd14fSBrian Behlendorf return (-1); 6434084fd14fSBrian Behlendorf 6435084fd14fSBrian Behlendorf trimflags_t trim_flags = { 6436084fd14fSBrian Behlendorf .secure = secure, 6437084fd14fSBrian Behlendorf .rate = rate, 6438084fd14fSBrian Behlendorf }; 6439084fd14fSBrian Behlendorf 6440084fd14fSBrian Behlendorf nvlist_t *vdevs = fnvlist_alloc(); 6441084fd14fSBrian Behlendorf if (argc == 1) { 6442084fd14fSBrian Behlendorf /* no individual leaf vdevs specified, so add them all */ 6443084fd14fSBrian Behlendorf nvlist_t *config = zpool_get_config(zhp, NULL); 6444084fd14fSBrian Behlendorf nvlist_t *nvroot = fnvlist_lookup_nvlist(config, 6445084fd14fSBrian Behlendorf ZPOOL_CONFIG_VDEV_TREE); 6446084fd14fSBrian Behlendorf zpool_collect_leaves(zhp, nvroot, vdevs); 6447084fd14fSBrian Behlendorf trim_flags.fullpool = B_TRUE; 6448084fd14fSBrian Behlendorf } else { 6449084fd14fSBrian Behlendorf trim_flags.fullpool = B_FALSE; 6450084fd14fSBrian Behlendorf for (int i = 1; i < argc; i++) { 6451084fd14fSBrian Behlendorf fnvlist_add_boolean(vdevs, argv[i]); 6452084fd14fSBrian Behlendorf } 6453094e47e9SGeorge Wilson } 6454084fd14fSBrian Behlendorf 6455084fd14fSBrian Behlendorf int error = zpool_trim(zhp, cmd_type, vdevs, &trim_flags); 6456084fd14fSBrian Behlendorf 6457084fd14fSBrian Behlendorf fnvlist_free(vdevs); 6458084fd14fSBrian Behlendorf zpool_close(zhp); 6459084fd14fSBrian Behlendorf 6460084fd14fSBrian Behlendorf return (error); 6461094e47e9SGeorge Wilson } 6462094e47e9SGeorge Wilson 6463094e47e9SGeorge Wilson /* 6464084fd14fSBrian Behlendorf * zpool initialize [-c | -s] <pool> [<vdev> ...] 6465094e47e9SGeorge Wilson * Initialize all unused blocks in the specified vdevs, or all vdevs in the pool 6466094e47e9SGeorge Wilson * if none specified. 6467094e47e9SGeorge Wilson * 6468094e47e9SGeorge Wilson * -c Cancel. Ends active initializing. 6469094e47e9SGeorge Wilson * -s Suspend. Initializing can then be restarted with no flags. 6470094e47e9SGeorge Wilson */ 6471094e47e9SGeorge Wilson int 6472094e47e9SGeorge Wilson zpool_do_initialize(int argc, char **argv) 6473094e47e9SGeorge Wilson { 6474094e47e9SGeorge Wilson int c; 6475094e47e9SGeorge Wilson char *poolname; 6476094e47e9SGeorge Wilson zpool_handle_t *zhp; 6477094e47e9SGeorge Wilson nvlist_t *vdevs; 6478094e47e9SGeorge Wilson int err = 0; 6479094e47e9SGeorge Wilson 6480094e47e9SGeorge Wilson struct option long_options[] = { 6481094e47e9SGeorge Wilson {"cancel", no_argument, NULL, 'c'}, 6482094e47e9SGeorge Wilson {"suspend", no_argument, NULL, 's'}, 6483094e47e9SGeorge Wilson {0, 0, 0, 0} 6484094e47e9SGeorge Wilson }; 6485094e47e9SGeorge Wilson 6486084fd14fSBrian Behlendorf pool_initialize_func_t cmd_type = POOL_INITIALIZE_START; 6487094e47e9SGeorge Wilson while ((c = getopt_long(argc, argv, "cs", long_options, NULL)) != -1) { 6488094e47e9SGeorge Wilson switch (c) { 6489094e47e9SGeorge Wilson case 'c': 6490084fd14fSBrian Behlendorf if (cmd_type != POOL_INITIALIZE_START && 6491084fd14fSBrian Behlendorf cmd_type != POOL_INITIALIZE_CANCEL) { 6492094e47e9SGeorge Wilson (void) fprintf(stderr, gettext("-c cannot be " 6493094e47e9SGeorge Wilson "combined with other options\n")); 6494094e47e9SGeorge Wilson usage(B_FALSE); 6495094e47e9SGeorge Wilson } 6496094e47e9SGeorge Wilson cmd_type = POOL_INITIALIZE_CANCEL; 6497094e47e9SGeorge Wilson break; 6498094e47e9SGeorge Wilson case 's': 6499084fd14fSBrian Behlendorf if (cmd_type != POOL_INITIALIZE_START && 6500084fd14fSBrian Behlendorf cmd_type != POOL_INITIALIZE_SUSPEND) { 6501094e47e9SGeorge Wilson (void) fprintf(stderr, gettext("-s cannot be " 6502094e47e9SGeorge Wilson "combined with other options\n")); 6503094e47e9SGeorge Wilson usage(B_FALSE); 6504094e47e9SGeorge Wilson } 6505094e47e9SGeorge Wilson cmd_type = POOL_INITIALIZE_SUSPEND; 6506094e47e9SGeorge Wilson break; 6507094e47e9SGeorge Wilson case '?': 6508094e47e9SGeorge Wilson if (optopt != 0) { 6509094e47e9SGeorge Wilson (void) fprintf(stderr, 6510094e47e9SGeorge Wilson gettext("invalid option '%c'\n"), optopt); 6511094e47e9SGeorge Wilson } else { 6512094e47e9SGeorge Wilson (void) fprintf(stderr, 6513094e47e9SGeorge Wilson gettext("invalid option '%s'\n"), 6514094e47e9SGeorge Wilson argv[optind - 1]); 6515094e47e9SGeorge Wilson } 6516094e47e9SGeorge Wilson usage(B_FALSE); 6517094e47e9SGeorge Wilson } 6518094e47e9SGeorge Wilson } 6519094e47e9SGeorge Wilson 6520094e47e9SGeorge Wilson argc -= optind; 6521094e47e9SGeorge Wilson argv += optind; 6522094e47e9SGeorge Wilson 6523094e47e9SGeorge Wilson if (argc < 1) { 6524094e47e9SGeorge Wilson (void) fprintf(stderr, gettext("missing pool name argument\n")); 6525094e47e9SGeorge Wilson usage(B_FALSE); 6526094e47e9SGeorge Wilson return (-1); 6527094e47e9SGeorge Wilson } 6528094e47e9SGeorge Wilson 6529094e47e9SGeorge Wilson poolname = argv[0]; 6530094e47e9SGeorge Wilson zhp = zpool_open(g_zfs, poolname); 6531094e47e9SGeorge Wilson if (zhp == NULL) 6532094e47e9SGeorge Wilson return (-1); 6533094e47e9SGeorge Wilson 6534094e47e9SGeorge Wilson vdevs = fnvlist_alloc(); 6535094e47e9SGeorge Wilson if (argc == 1) { 6536094e47e9SGeorge Wilson /* no individual leaf vdevs specified, so add them all */ 6537094e47e9SGeorge Wilson nvlist_t *config = zpool_get_config(zhp, NULL); 6538094e47e9SGeorge Wilson nvlist_t *nvroot = fnvlist_lookup_nvlist(config, 6539094e47e9SGeorge Wilson ZPOOL_CONFIG_VDEV_TREE); 6540094e47e9SGeorge Wilson zpool_collect_leaves(zhp, nvroot, vdevs); 6541094e47e9SGeorge Wilson } else { 6542084fd14fSBrian Behlendorf for (int i = 1; i < argc; i++) { 6543094e47e9SGeorge Wilson fnvlist_add_boolean(vdevs, argv[i]); 6544094e47e9SGeorge Wilson } 6545094e47e9SGeorge Wilson } 6546094e47e9SGeorge Wilson 6547094e47e9SGeorge Wilson err = zpool_initialize(zhp, cmd_type, vdevs); 6548094e47e9SGeorge Wilson 6549094e47e9SGeorge Wilson fnvlist_free(vdevs); 6550094e47e9SGeorge Wilson zpool_close(zhp); 6551094e47e9SGeorge Wilson 6552094e47e9SGeorge Wilson return (err); 6553094e47e9SGeorge Wilson } 6554094e47e9SGeorge Wilson 6555fa9e4066Sahrens /* 6556fa9e4066Sahrens * Print out detailed scrub status. 6557fa9e4066Sahrens */ 65585cabbc6bSPrashanth Sreenivasa static void 65593f9d6ad7SLin Ling print_scan_status(pool_scan_stat_t *ps) 6560fa9e4066Sahrens { 65611702cce7SAlek Pinchuk time_t start, end, pause; 6562a3874b8bSToomas Soome uint64_t total_secs_left; 6563a3874b8bSToomas Soome uint64_t elapsed, secs_left, mins_left, hours_left, days_left; 6564a3874b8bSToomas Soome uint64_t pass_scanned, scanned, pass_issued, issued, total; 6565a3874b8bSToomas Soome uint_t scan_rate, issue_rate; 6566fa9e4066Sahrens double fraction_done; 6567a3874b8bSToomas Soome char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7]; 6568a3874b8bSToomas Soome char srate_buf[7], irate_buf[7]; 6569fa9e4066Sahrens 6570ce72e614SYuri Pankov (void) printf(gettext(" scan: ")); 6571fa9e4066Sahrens 65723f9d6ad7SLin Ling /* If there's never been a scan, there's not much to say. */ 65733f9d6ad7SLin Ling if (ps == NULL || ps->pss_func == POOL_SCAN_NONE || 65743f9d6ad7SLin Ling ps->pss_func >= POOL_SCAN_FUNCS) { 6575fa9e4066Sahrens (void) printf(gettext("none requested\n")); 6576fa9e4066Sahrens return; 6577fa9e4066Sahrens } 6578fa9e4066Sahrens 65793f9d6ad7SLin Ling start = ps->pss_start_time; 65803f9d6ad7SLin Ling end = ps->pss_end_time; 65811702cce7SAlek Pinchuk pause = ps->pss_pass_scrub_pause; 6582a3874b8bSToomas Soome 65833f9d6ad7SLin Ling zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf)); 6584fa9e4066Sahrens 65853f9d6ad7SLin Ling assert(ps->pss_func == POOL_SCAN_SCRUB || 65863f9d6ad7SLin Ling ps->pss_func == POOL_SCAN_RESILVER); 6587a3874b8bSToomas Soome 65883f9d6ad7SLin Ling /* 65893f9d6ad7SLin Ling * Scan is finished or canceled. 65903f9d6ad7SLin Ling */ 65913f9d6ad7SLin Ling if (ps->pss_state == DSS_FINISHED) { 6592a3874b8bSToomas Soome total_secs_left = end - start; 6593a3874b8bSToomas Soome days_left = total_secs_left / 60 / 60 / 24; 6594a3874b8bSToomas Soome hours_left = (total_secs_left / 60 / 60) % 24; 6595a3874b8bSToomas Soome mins_left = (total_secs_left / 60) % 60; 6596a3874b8bSToomas Soome secs_left = (total_secs_left % 60); 65973f9d6ad7SLin Ling 65983f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) { 6599a3874b8bSToomas Soome (void) printf(gettext("scrub repaired %s " 6600a3874b8bSToomas Soome "in %llu days %02llu:%02llu:%02llu " 6601a3874b8bSToomas Soome "with %llu errors on %s"), processed_buf, 6602a3874b8bSToomas Soome (u_longlong_t)days_left, (u_longlong_t)hours_left, 6603a3874b8bSToomas Soome (u_longlong_t)mins_left, (u_longlong_t)secs_left, 6604a3874b8bSToomas Soome (u_longlong_t)ps->pss_errors, ctime(&end)); 66053f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) { 6606a3874b8bSToomas Soome (void) printf(gettext("resilvered %s " 6607a3874b8bSToomas Soome "in %llu days %02llu:%02llu:%02llu " 6608a3874b8bSToomas Soome "with %llu errors on %s"), processed_buf, 6609a3874b8bSToomas Soome (u_longlong_t)days_left, (u_longlong_t)hours_left, 6610a3874b8bSToomas Soome (u_longlong_t)mins_left, (u_longlong_t)secs_left, 6611a3874b8bSToomas Soome (u_longlong_t)ps->pss_errors, ctime(&end)); 66123f9d6ad7SLin Ling } 66133f9d6ad7SLin Ling return; 66143f9d6ad7SLin Ling } else if (ps->pss_state == DSS_CANCELED) { 66153f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) { 66163f9d6ad7SLin Ling (void) printf(gettext("scrub canceled on %s"), 66173f9d6ad7SLin Ling ctime(&end)); 66183f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) { 66193f9d6ad7SLin Ling (void) printf(gettext("resilver canceled on %s"), 66203f9d6ad7SLin Ling ctime(&end)); 66213f9d6ad7SLin Ling } 6622fa9e4066Sahrens return; 6623fa9e4066Sahrens } 6624fa9e4066Sahrens 66253f9d6ad7SLin Ling assert(ps->pss_state == DSS_SCANNING); 66263f9d6ad7SLin Ling 6627a3874b8bSToomas Soome /* Scan is in progress. Resilvers can't be paused. */ 66283f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) { 66291702cce7SAlek Pinchuk if (pause == 0) { 66301702cce7SAlek Pinchuk (void) printf(gettext("scrub in progress since %s"), 66311702cce7SAlek Pinchuk ctime(&start)); 66321702cce7SAlek Pinchuk } else { 6633a3874b8bSToomas Soome (void) printf(gettext("scrub paused since %s"), 6634a3874b8bSToomas Soome ctime(&pause)); 6635a3874b8bSToomas Soome (void) printf(gettext("\tscrub started on %s"), 66361702cce7SAlek Pinchuk ctime(&start)); 66371702cce7SAlek Pinchuk } 66383f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) { 66393f9d6ad7SLin Ling (void) printf(gettext("resilver in progress since %s"), 66403f9d6ad7SLin Ling ctime(&start)); 66413f9d6ad7SLin Ling } 6642fa9e4066Sahrens 6643a3874b8bSToomas Soome scanned = ps->pss_examined; 6644a3874b8bSToomas Soome pass_scanned = ps->pss_pass_exam; 6645a3874b8bSToomas Soome issued = ps->pss_issued; 6646a3874b8bSToomas Soome pass_issued = ps->pss_pass_issued; 66473f9d6ad7SLin Ling total = ps->pss_to_examine; 66483f9d6ad7SLin Ling 6649a3874b8bSToomas Soome /* we are only done with a block once we have issued the IO for it */ 6650a3874b8bSToomas Soome fraction_done = (double)issued / total; 6651a3874b8bSToomas Soome 6652a3874b8bSToomas Soome /* elapsed time for this pass, rounding up to 1 if it's 0 */ 66533f9d6ad7SLin Ling elapsed = time(NULL) - ps->pss_pass_start; 66541702cce7SAlek Pinchuk elapsed -= ps->pss_pass_scrub_spent_paused; 6655a3874b8bSToomas Soome elapsed = (elapsed != 0) ? elapsed : 1; 6656a3874b8bSToomas Soome 6657a3874b8bSToomas Soome scan_rate = pass_scanned / elapsed; 6658a3874b8bSToomas Soome issue_rate = pass_issued / elapsed; 66593db6627cSTom Caputi total_secs_left = (issue_rate != 0 && total >= issued) ? 6660a3874b8bSToomas Soome ((total - issued) / issue_rate) : UINT64_MAX; 6661a3874b8bSToomas Soome 6662a3874b8bSToomas Soome days_left = total_secs_left / 60 / 60 / 24; 6663a3874b8bSToomas Soome hours_left = (total_secs_left / 60 / 60) % 24; 6664a3874b8bSToomas Soome mins_left = (total_secs_left / 60) % 60; 6665a3874b8bSToomas Soome secs_left = (total_secs_left % 60); 6666a3874b8bSToomas Soome 6667a3874b8bSToomas Soome /* format all of the numbers we will be reporting */ 6668a3874b8bSToomas Soome zfs_nicenum(scanned, scanned_buf, sizeof (scanned_buf)); 6669a3874b8bSToomas Soome zfs_nicenum(issued, issued_buf, sizeof (issued_buf)); 66703f9d6ad7SLin Ling zfs_nicenum(total, total_buf, sizeof (total_buf)); 6671a3874b8bSToomas Soome zfs_nicenum(scan_rate, srate_buf, sizeof (srate_buf)); 6672a3874b8bSToomas Soome zfs_nicenum(issue_rate, irate_buf, sizeof (irate_buf)); 66733f9d6ad7SLin Ling 6674a3874b8bSToomas Soome /* do not print estimated time if we have a paused scrub */ 66751702cce7SAlek Pinchuk if (pause == 0) { 6676a3874b8bSToomas Soome (void) printf(gettext("\t%s scanned at %s/s, " 6677a3874b8bSToomas Soome "%s issued at %s/s, %s total\n"), 6678a3874b8bSToomas Soome scanned_buf, srate_buf, issued_buf, irate_buf, total_buf); 667973d314ceSLin Ling } else { 6680a3874b8bSToomas Soome (void) printf(gettext("\t%s scanned, %s issued, %s total\n"), 6681a3874b8bSToomas Soome scanned_buf, issued_buf, total_buf); 668273d314ceSLin Ling } 66833f9d6ad7SLin Ling 66843f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_RESILVER) { 6685a3874b8bSToomas Soome (void) printf(gettext("\t%s resilvered, %.2f%% done"), 66863f9d6ad7SLin Ling processed_buf, 100 * fraction_done); 66873f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_SCRUB) { 6688a3874b8bSToomas Soome (void) printf(gettext("\t%s repaired, %.2f%% done"), 66893f9d6ad7SLin Ling processed_buf, 100 * fraction_done); 66903f9d6ad7SLin Ling } 6691a3874b8bSToomas Soome 6692a3874b8bSToomas Soome if (pause == 0) { 66933db6627cSTom Caputi if (total_secs_left != UINT64_MAX && 66943db6627cSTom Caputi issue_rate >= 10 * 1024 * 1024) { 6695a3874b8bSToomas Soome (void) printf(gettext(", %llu days " 6696a3874b8bSToomas Soome "%02llu:%02llu:%02llu to go\n"), 6697a3874b8bSToomas Soome (u_longlong_t)days_left, (u_longlong_t)hours_left, 6698a3874b8bSToomas Soome (u_longlong_t)mins_left, (u_longlong_t)secs_left); 6699a3874b8bSToomas Soome } else { 6700a3874b8bSToomas Soome (void) printf(gettext(", no estimated " 6701a3874b8bSToomas Soome "completion time\n")); 6702a3874b8bSToomas Soome } 6703a3874b8bSToomas Soome } else { 6704a3874b8bSToomas Soome (void) printf(gettext("\n")); 6705a3874b8bSToomas Soome } 6706fa9e4066Sahrens } 6707fa9e4066Sahrens 670886714001SSerapheim Dimitropoulos /* 670986714001SSerapheim Dimitropoulos * As we don't scrub checkpointed blocks, we want to warn the 671086714001SSerapheim Dimitropoulos * user that we skipped scanning some blocks if a checkpoint exists 671186714001SSerapheim Dimitropoulos * or existed at any time during the scan. 671286714001SSerapheim Dimitropoulos */ 671386714001SSerapheim Dimitropoulos static void 671486714001SSerapheim Dimitropoulos print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs) 671586714001SSerapheim Dimitropoulos { 671686714001SSerapheim Dimitropoulos if (ps == NULL || pcs == NULL) 671786714001SSerapheim Dimitropoulos return; 671886714001SSerapheim Dimitropoulos 671986714001SSerapheim Dimitropoulos if (pcs->pcs_state == CS_NONE || 672086714001SSerapheim Dimitropoulos pcs->pcs_state == CS_CHECKPOINT_DISCARDING) 672186714001SSerapheim Dimitropoulos return; 672286714001SSerapheim Dimitropoulos 672386714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS); 672486714001SSerapheim Dimitropoulos 672586714001SSerapheim Dimitropoulos if (ps->pss_state == DSS_NONE) 672686714001SSerapheim Dimitropoulos return; 672786714001SSerapheim Dimitropoulos 672886714001SSerapheim Dimitropoulos if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) && 672986714001SSerapheim Dimitropoulos ps->pss_end_time < pcs->pcs_start_time) 673086714001SSerapheim Dimitropoulos return; 673186714001SSerapheim Dimitropoulos 673286714001SSerapheim Dimitropoulos if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) { 673386714001SSerapheim Dimitropoulos (void) printf(gettext(" scan warning: skipped blocks " 673486714001SSerapheim Dimitropoulos "that are only referenced by the checkpoint.\n")); 673586714001SSerapheim Dimitropoulos } else { 673686714001SSerapheim Dimitropoulos assert(ps->pss_state == DSS_SCANNING); 673786714001SSerapheim Dimitropoulos (void) printf(gettext(" scan warning: skipping blocks " 673886714001SSerapheim Dimitropoulos "that are only referenced by the checkpoint.\n")); 673986714001SSerapheim Dimitropoulos } 674086714001SSerapheim Dimitropoulos } 674186714001SSerapheim Dimitropoulos 67425cabbc6bSPrashanth Sreenivasa /* 67435cabbc6bSPrashanth Sreenivasa * Print out detailed removal status. 67445cabbc6bSPrashanth Sreenivasa */ 67455cabbc6bSPrashanth Sreenivasa static void 67465cabbc6bSPrashanth Sreenivasa print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs) 67475cabbc6bSPrashanth Sreenivasa { 67485cabbc6bSPrashanth Sreenivasa char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7]; 67495cabbc6bSPrashanth Sreenivasa time_t start, end; 67505cabbc6bSPrashanth Sreenivasa nvlist_t *config, *nvroot; 67515cabbc6bSPrashanth Sreenivasa nvlist_t **child; 67525cabbc6bSPrashanth Sreenivasa uint_t children; 67535cabbc6bSPrashanth Sreenivasa char *vdev_name; 67545cabbc6bSPrashanth Sreenivasa 67555cabbc6bSPrashanth Sreenivasa if (prs == NULL || prs->prs_state == DSS_NONE) 67565cabbc6bSPrashanth Sreenivasa return; 67575cabbc6bSPrashanth Sreenivasa 67585cabbc6bSPrashanth Sreenivasa /* 67595cabbc6bSPrashanth Sreenivasa * Determine name of vdev. 67605cabbc6bSPrashanth Sreenivasa */ 67615cabbc6bSPrashanth Sreenivasa config = zpool_get_config(zhp, NULL); 67625cabbc6bSPrashanth Sreenivasa nvroot = fnvlist_lookup_nvlist(config, 67635cabbc6bSPrashanth Sreenivasa ZPOOL_CONFIG_VDEV_TREE); 67645cabbc6bSPrashanth Sreenivasa verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 67655cabbc6bSPrashanth Sreenivasa &child, &children) == 0); 67665cabbc6bSPrashanth Sreenivasa assert(prs->prs_removing_vdev < children); 67675cabbc6bSPrashanth Sreenivasa vdev_name = zpool_vdev_name(g_zfs, zhp, 67685cabbc6bSPrashanth Sreenivasa child[prs->prs_removing_vdev], B_TRUE); 67695cabbc6bSPrashanth Sreenivasa 67705cabbc6bSPrashanth Sreenivasa (void) printf(gettext("remove: ")); 67715cabbc6bSPrashanth Sreenivasa 67725cabbc6bSPrashanth Sreenivasa start = prs->prs_start_time; 67735cabbc6bSPrashanth Sreenivasa end = prs->prs_end_time; 67745cabbc6bSPrashanth Sreenivasa zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf)); 67755cabbc6bSPrashanth Sreenivasa 67765cabbc6bSPrashanth Sreenivasa /* 67775cabbc6bSPrashanth Sreenivasa * Removal is finished or canceled. 67785cabbc6bSPrashanth Sreenivasa */ 67795cabbc6bSPrashanth Sreenivasa if (prs->prs_state == DSS_FINISHED) { 67805cabbc6bSPrashanth Sreenivasa uint64_t minutes_taken = (end - start) / 60; 67815cabbc6bSPrashanth Sreenivasa 67825cabbc6bSPrashanth Sreenivasa (void) printf(gettext("Removal of vdev %llu copied %s " 67835cabbc6bSPrashanth Sreenivasa "in %lluh%um, completed on %s"), 67845cabbc6bSPrashanth Sreenivasa (longlong_t)prs->prs_removing_vdev, 67855cabbc6bSPrashanth Sreenivasa copied_buf, 67865cabbc6bSPrashanth Sreenivasa (u_longlong_t)(minutes_taken / 60), 67875cabbc6bSPrashanth Sreenivasa (uint_t)(minutes_taken % 60), 67885cabbc6bSPrashanth Sreenivasa ctime((time_t *)&end)); 67895cabbc6bSPrashanth Sreenivasa } else if (prs->prs_state == DSS_CANCELED) { 67905cabbc6bSPrashanth Sreenivasa (void) printf(gettext("Removal of %s canceled on %s"), 67915cabbc6bSPrashanth Sreenivasa vdev_name, ctime(&end)); 67925cabbc6bSPrashanth Sreenivasa } else { 67935cabbc6bSPrashanth Sreenivasa uint64_t copied, total, elapsed, mins_left, hours_left; 67945cabbc6bSPrashanth Sreenivasa double fraction_done; 67955cabbc6bSPrashanth Sreenivasa uint_t rate; 67965cabbc6bSPrashanth Sreenivasa 67975cabbc6bSPrashanth Sreenivasa assert(prs->prs_state == DSS_SCANNING); 67985cabbc6bSPrashanth Sreenivasa 67995cabbc6bSPrashanth Sreenivasa /* 68005cabbc6bSPrashanth Sreenivasa * Removal is in progress. 68015cabbc6bSPrashanth Sreenivasa */ 68025cabbc6bSPrashanth Sreenivasa (void) printf(gettext( 68035cabbc6bSPrashanth Sreenivasa "Evacuation of %s in progress since %s"), 68045cabbc6bSPrashanth Sreenivasa vdev_name, ctime(&start)); 68055cabbc6bSPrashanth Sreenivasa 68065cabbc6bSPrashanth Sreenivasa copied = prs->prs_copied > 0 ? prs->prs_copied : 1; 68075cabbc6bSPrashanth Sreenivasa total = prs->prs_to_copy; 68085cabbc6bSPrashanth Sreenivasa fraction_done = (double)copied / total; 68095cabbc6bSPrashanth Sreenivasa 68105cabbc6bSPrashanth Sreenivasa /* elapsed time for this pass */ 68115cabbc6bSPrashanth Sreenivasa elapsed = time(NULL) - prs->prs_start_time; 68125cabbc6bSPrashanth Sreenivasa elapsed = elapsed > 0 ? elapsed : 1; 68135cabbc6bSPrashanth Sreenivasa rate = copied / elapsed; 68145cabbc6bSPrashanth Sreenivasa rate = rate > 0 ? rate : 1; 68155cabbc6bSPrashanth Sreenivasa mins_left = ((total - copied) / rate) / 60; 68165cabbc6bSPrashanth Sreenivasa hours_left = mins_left / 60; 68175cabbc6bSPrashanth Sreenivasa 68185cabbc6bSPrashanth Sreenivasa zfs_nicenum(copied, examined_buf, sizeof (examined_buf)); 68195cabbc6bSPrashanth Sreenivasa zfs_nicenum(total, total_buf, sizeof (total_buf)); 68205cabbc6bSPrashanth Sreenivasa zfs_nicenum(rate, rate_buf, sizeof (rate_buf)); 68215cabbc6bSPrashanth Sreenivasa 68225cabbc6bSPrashanth Sreenivasa /* 68235cabbc6bSPrashanth Sreenivasa * do not print estimated time if hours_left is more than 68245cabbc6bSPrashanth Sreenivasa * 30 days 68255cabbc6bSPrashanth Sreenivasa */ 68265cabbc6bSPrashanth Sreenivasa (void) printf(gettext(" %s copied out of %s at %s/s, " 68275cabbc6bSPrashanth Sreenivasa "%.2f%% done"), 68285cabbc6bSPrashanth Sreenivasa examined_buf, total_buf, rate_buf, 100 * fraction_done); 68295cabbc6bSPrashanth Sreenivasa if (hours_left < (30 * 24)) { 68305cabbc6bSPrashanth Sreenivasa (void) printf(gettext(", %lluh%um to go\n"), 68315cabbc6bSPrashanth Sreenivasa (u_longlong_t)hours_left, (uint_t)(mins_left % 60)); 68325cabbc6bSPrashanth Sreenivasa } else { 68335cabbc6bSPrashanth Sreenivasa (void) printf(gettext( 68345cabbc6bSPrashanth Sreenivasa ", (copy is slow, no estimated time)\n")); 68355cabbc6bSPrashanth Sreenivasa } 68365cabbc6bSPrashanth Sreenivasa } 68375cabbc6bSPrashanth Sreenivasa 68385cabbc6bSPrashanth Sreenivasa if (prs->prs_mapping_memory > 0) { 68395cabbc6bSPrashanth Sreenivasa char mem_buf[7]; 68405cabbc6bSPrashanth Sreenivasa zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf)); 68415cabbc6bSPrashanth Sreenivasa (void) printf(gettext(" %s memory used for " 68425cabbc6bSPrashanth Sreenivasa "removed device mappings\n"), 68435cabbc6bSPrashanth Sreenivasa mem_buf); 68445cabbc6bSPrashanth Sreenivasa } 68455cabbc6bSPrashanth Sreenivasa } 68465cabbc6bSPrashanth Sreenivasa 684786714001SSerapheim Dimitropoulos static void 684886714001SSerapheim Dimitropoulos print_checkpoint_status(pool_checkpoint_stat_t *pcs) 684986714001SSerapheim Dimitropoulos { 685086714001SSerapheim Dimitropoulos time_t start; 685186714001SSerapheim Dimitropoulos char space_buf[7]; 685286714001SSerapheim Dimitropoulos 685386714001SSerapheim Dimitropoulos if (pcs == NULL || pcs->pcs_state == CS_NONE) 685486714001SSerapheim Dimitropoulos return; 685586714001SSerapheim Dimitropoulos 685686714001SSerapheim Dimitropoulos (void) printf(gettext("checkpoint: ")); 685786714001SSerapheim Dimitropoulos 685886714001SSerapheim Dimitropoulos start = pcs->pcs_start_time; 685986714001SSerapheim Dimitropoulos zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf)); 686086714001SSerapheim Dimitropoulos 686186714001SSerapheim Dimitropoulos if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) { 686286714001SSerapheim Dimitropoulos char *date = ctime(&start); 686386714001SSerapheim Dimitropoulos 686486714001SSerapheim Dimitropoulos /* 686586714001SSerapheim Dimitropoulos * ctime() adds a newline at the end of the generated 686686714001SSerapheim Dimitropoulos * string, thus the weird format specifier and the 686786714001SSerapheim Dimitropoulos * strlen() call used to chop it off from the output. 686886714001SSerapheim Dimitropoulos */ 686986714001SSerapheim Dimitropoulos (void) printf(gettext("created %.*s, consumes %s\n"), 687086714001SSerapheim Dimitropoulos strlen(date) - 1, date, space_buf); 687186714001SSerapheim Dimitropoulos return; 687286714001SSerapheim Dimitropoulos } 687386714001SSerapheim Dimitropoulos 687486714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 687586714001SSerapheim Dimitropoulos 687686714001SSerapheim Dimitropoulos (void) printf(gettext("discarding, %s remaining.\n"), 687786714001SSerapheim Dimitropoulos space_buf); 687886714001SSerapheim Dimitropoulos } 687986714001SSerapheim Dimitropoulos 6880ea8dc4b6Seschrock static void 6881ea8dc4b6Seschrock print_error_log(zpool_handle_t *zhp) 6882ea8dc4b6Seschrock { 688375519f38Sek nvlist_t *nverrlist = NULL; 688455434c77Sek nvpair_t *elem; 688555434c77Sek char *pathname; 688655434c77Sek size_t len = MAXPATHLEN * 2; 6887ea8dc4b6Seschrock 688855434c77Sek if (zpool_get_errlog(zhp, &nverrlist) != 0) { 6889ea8dc4b6Seschrock (void) printf("errors: List of errors unavailable " 6890ea8dc4b6Seschrock "(insufficient privileges)\n"); 6891ea8dc4b6Seschrock return; 6892ea8dc4b6Seschrock } 6893ea8dc4b6Seschrock 689455434c77Sek (void) printf("errors: Permanent errors have been " 689555434c77Sek "detected in the following files:\n\n"); 6896ea8dc4b6Seschrock 689755434c77Sek pathname = safe_malloc(len); 689855434c77Sek elem = NULL; 689955434c77Sek while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 690055434c77Sek nvlist_t *nv; 690155434c77Sek uint64_t dsobj, obj; 690255434c77Sek 690355434c77Sek verify(nvpair_value_nvlist(elem, &nv) == 0); 690455434c77Sek verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 690555434c77Sek &dsobj) == 0); 690655434c77Sek verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 690755434c77Sek &obj) == 0); 690855434c77Sek zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 690955434c77Sek (void) printf("%7s %s\n", "", pathname); 691055434c77Sek } 691155434c77Sek free(pathname); 691255434c77Sek nvlist_free(nverrlist); 6913ea8dc4b6Seschrock } 6914ea8dc4b6Seschrock 691599653d4eSeschrock static void 6916663207adSDon Brady print_spares(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **spares, 6917663207adSDon Brady uint_t nspares) 691899653d4eSeschrock { 691999653d4eSeschrock uint_t i; 692099653d4eSeschrock char *name; 692199653d4eSeschrock 692299653d4eSeschrock if (nspares == 0) 692399653d4eSeschrock return; 692499653d4eSeschrock 692599653d4eSeschrock (void) printf(gettext("\tspares\n")); 692699653d4eSeschrock 692799653d4eSeschrock for (i = 0; i < nspares; i++) { 6928663207adSDon Brady name = zpool_vdev_name(g_zfs, zhp, spares[i], 6929663207adSDon Brady cb->cb_name_flags); 6930663207adSDon Brady print_status_config(zhp, cb, name, spares[i], 2, B_TRUE); 693199653d4eSeschrock free(name); 693299653d4eSeschrock } 693399653d4eSeschrock } 693499653d4eSeschrock 6935fa94a07fSbrendan static void 6936663207adSDon Brady print_l2cache(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **l2cache, 6937663207adSDon Brady uint_t nl2cache) 6938fa94a07fSbrendan { 6939fa94a07fSbrendan uint_t i; 6940fa94a07fSbrendan char *name; 6941fa94a07fSbrendan 6942fa94a07fSbrendan if (nl2cache == 0) 6943fa94a07fSbrendan return; 6944fa94a07fSbrendan 6945fa94a07fSbrendan (void) printf(gettext("\tcache\n")); 6946fa94a07fSbrendan 6947fa94a07fSbrendan for (i = 0; i < nl2cache; i++) { 6948663207adSDon Brady name = zpool_vdev_name(g_zfs, zhp, l2cache[i], 6949663207adSDon Brady cb->cb_name_flags); 6950663207adSDon Brady print_status_config(zhp, cb, name, l2cache[i], 2, B_FALSE); 6951aa8cf21aSNeil Perrin free(name); 6952aa8cf21aSNeil Perrin } 6953aa8cf21aSNeil Perrin } 6954aa8cf21aSNeil Perrin 69559eb19f4dSGeorge Wilson static void 69569eb19f4dSGeorge Wilson print_dedup_stats(nvlist_t *config) 69579eb19f4dSGeorge Wilson { 69589eb19f4dSGeorge Wilson ddt_histogram_t *ddh; 69599eb19f4dSGeorge Wilson ddt_stat_t *dds; 69609eb19f4dSGeorge Wilson ddt_object_t *ddo; 69619eb19f4dSGeorge Wilson uint_t c; 69629eb19f4dSGeorge Wilson 69639eb19f4dSGeorge Wilson /* 69649eb19f4dSGeorge Wilson * If the pool was faulted then we may not have been able to 69652384d9f8SGeorge Wilson * obtain the config. Otherwise, if we have anything in the dedup 69669eb19f4dSGeorge Wilson * table continue processing the stats. 69679eb19f4dSGeorge Wilson */ 69689eb19f4dSGeorge Wilson if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS, 6969ce72e614SYuri Pankov (uint64_t **)&ddo, &c) != 0) 69709eb19f4dSGeorge Wilson return; 69719eb19f4dSGeorge Wilson 69729eb19f4dSGeorge Wilson (void) printf("\n"); 6973ce72e614SYuri Pankov (void) printf(gettext(" dedup: ")); 6974ce72e614SYuri Pankov if (ddo->ddo_count == 0) { 6975ce72e614SYuri Pankov (void) printf(gettext("no DDT entries\n")); 6976ce72e614SYuri Pankov return; 6977ce72e614SYuri Pankov } 6978ce72e614SYuri Pankov 69799eb19f4dSGeorge Wilson (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n", 69809eb19f4dSGeorge Wilson (u_longlong_t)ddo->ddo_count, 69819eb19f4dSGeorge Wilson (u_longlong_t)ddo->ddo_dspace, 69829eb19f4dSGeorge Wilson (u_longlong_t)ddo->ddo_mspace); 69839eb19f4dSGeorge Wilson 69849eb19f4dSGeorge Wilson verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS, 69859eb19f4dSGeorge Wilson (uint64_t **)&dds, &c) == 0); 69869eb19f4dSGeorge Wilson verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM, 69879eb19f4dSGeorge Wilson (uint64_t **)&ddh, &c) == 0); 69889eb19f4dSGeorge Wilson zpool_dump_ddt(dds, ddh); 69899eb19f4dSGeorge Wilson } 69909eb19f4dSGeorge Wilson 6991fa9e4066Sahrens /* 6992fa9e4066Sahrens * Display a summary of pool status. Displays a summary such as: 6993fa9e4066Sahrens * 6994fa9e4066Sahrens * pool: tank 6995fa9e4066Sahrens * status: DEGRADED 6996fa9e4066Sahrens * reason: One or more devices ... 6997654b400cSJoshua M. Clulow * see: http://illumos.org/msg/ZFS-xxxx-01 6998fa9e4066Sahrens * config: 6999fa9e4066Sahrens * mirror DEGRADED 7000fa9e4066Sahrens * c1t0d0 OK 7001ea8dc4b6Seschrock * c2t0d0 UNAVAIL 7002fa9e4066Sahrens * 7003fa9e4066Sahrens * When given the '-v' option, we print out the complete config. If the '-e' 7004fa9e4066Sahrens * option is specified, then we print out error rate information as well. 7005fa9e4066Sahrens */ 7006fa9e4066Sahrens int 7007fa9e4066Sahrens status_callback(zpool_handle_t *zhp, void *data) 7008fa9e4066Sahrens { 7009fa9e4066Sahrens status_cbdata_t *cbp = data; 7010fa9e4066Sahrens nvlist_t *config, *nvroot; 7011fa9e4066Sahrens char *msgid; 7012fa9e4066Sahrens int reason; 7013eb633035STom Caputi zpool_errata_t errata; 701446657f8dSmmusante const char *health; 701546657f8dSmmusante uint_t c; 701646657f8dSmmusante vdev_stat_t *vs; 7017fa9e4066Sahrens 7018088e9d47Seschrock config = zpool_get_config(zhp, NULL); 7019eb633035STom Caputi reason = zpool_get_status(zhp, &msgid, &errata); 7020fa9e4066Sahrens 7021fa9e4066Sahrens cbp->cb_count++; 7022fa9e4066Sahrens 7023fa9e4066Sahrens /* 7024fa9e4066Sahrens * If we were given 'zpool status -x', only report those pools with 7025fa9e4066Sahrens * problems. 7026fa9e4066Sahrens */ 7027b3a6f804STim Connors if (cbp->cb_explain && 7028b3a6f804STim Connors (reason == ZPOOL_STATUS_OK || 7029b3a6f804STim Connors reason == ZPOOL_STATUS_VERSION_OLDER || 7030b3a6f804STim Connors reason == ZPOOL_STATUS_FEAT_DISABLED)) { 7031e9dbad6fSeschrock if (!cbp->cb_allpools) { 7032e9dbad6fSeschrock (void) printf(gettext("pool '%s' is healthy\n"), 7033e9dbad6fSeschrock zpool_get_name(zhp)); 7034e9dbad6fSeschrock if (cbp->cb_first) 7035e9dbad6fSeschrock cbp->cb_first = B_FALSE; 7036e9dbad6fSeschrock } 7037fa9e4066Sahrens return (0); 7038e9dbad6fSeschrock } 7039fa9e4066Sahrens 7040fa9e4066Sahrens if (cbp->cb_first) 704199653d4eSeschrock cbp->cb_first = B_FALSE; 7042fa9e4066Sahrens else 7043fa9e4066Sahrens (void) printf("\n"); 7044fa9e4066Sahrens 70455cabbc6bSPrashanth Sreenivasa nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 70463f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 704746657f8dSmmusante (uint64_t **)&vs, &c) == 0); 7048990b4856Slling health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 7049fa9e4066Sahrens 7050fa9e4066Sahrens (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 7051fa9e4066Sahrens (void) printf(gettext(" state: %s\n"), health); 7052fa9e4066Sahrens 7053fa9e4066Sahrens switch (reason) { 7054fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_R: 7055fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 7056fa9e4066Sahrens "be opened. Sufficient replicas exist for\n\tthe pool to " 7057fa9e4066Sahrens "continue functioning in a degraded state.\n")); 7058fa9e4066Sahrens (void) printf(gettext("action: Attach the missing device and " 7059fa9e4066Sahrens "online it using 'zpool online'.\n")); 7060fa9e4066Sahrens break; 7061fa9e4066Sahrens 7062fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_NR: 7063fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 7064fa9e4066Sahrens "be opened. There are insufficient\n\treplicas for the " 7065fa9e4066Sahrens "pool to continue functioning.\n")); 7066fa9e4066Sahrens (void) printf(gettext("action: Attach the missing device and " 7067fa9e4066Sahrens "online it using 'zpool online'.\n")); 7068fa9e4066Sahrens break; 7069fa9e4066Sahrens 7070fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_R: 7071fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 7072fa9e4066Sahrens "be used because the label is missing or\n\tinvalid. " 7073fa9e4066Sahrens "Sufficient replicas exist for the pool to continue\n\t" 7074fa9e4066Sahrens "functioning in a degraded state.\n")); 7075fa9e4066Sahrens (void) printf(gettext("action: Replace the device using " 7076fa9e4066Sahrens "'zpool replace'.\n")); 7077fa9e4066Sahrens break; 7078fa9e4066Sahrens 7079fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_NR: 7080fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 7081b1b8ab34Slling "be used because the label is missing \n\tor invalid. " 7082fa9e4066Sahrens "There are insufficient replicas for the pool to " 7083fa9e4066Sahrens "continue\n\tfunctioning.\n")); 7084468c413aSTim Haley zpool_explain_recover(zpool_get_handle(zhp), 7085468c413aSTim Haley zpool_get_name(zhp), reason, config); 7086fa9e4066Sahrens break; 7087fa9e4066Sahrens 7088fa9e4066Sahrens case ZPOOL_STATUS_FAILING_DEV: 7089fa9e4066Sahrens (void) printf(gettext("status: One or more devices has " 7090fa9e4066Sahrens "experienced an unrecoverable error. An\n\tattempt was " 7091fa9e4066Sahrens "made to correct the error. Applications are " 7092fa9e4066Sahrens "unaffected.\n")); 7093fa9e4066Sahrens (void) printf(gettext("action: Determine if the device needs " 7094fa9e4066Sahrens "to be replaced, and clear the errors\n\tusing " 7095ea8dc4b6Seschrock "'zpool clear' or replace the device with 'zpool " 7096fa9e4066Sahrens "replace'.\n")); 7097fa9e4066Sahrens break; 7098fa9e4066Sahrens 7099fa9e4066Sahrens case ZPOOL_STATUS_OFFLINE_DEV: 7100fa9e4066Sahrens (void) printf(gettext("status: One or more devices has " 7101d7d4af51Smmusante "been taken offline by the administrator.\n\tSufficient " 7102fa9e4066Sahrens "replicas exist for the pool to continue functioning in " 7103fa9e4066Sahrens "a\n\tdegraded state.\n")); 7104fa9e4066Sahrens (void) printf(gettext("action: Online the device using " 7105fa9e4066Sahrens "'zpool online' or replace the device with\n\t'zpool " 7106fa9e4066Sahrens "replace'.\n")); 7107fa9e4066Sahrens break; 7108fa9e4066Sahrens 7109c25309d4SGeorge Wilson case ZPOOL_STATUS_REMOVED_DEV: 7110c25309d4SGeorge Wilson (void) printf(gettext("status: One or more devices has " 7111c25309d4SGeorge Wilson "been removed by the administrator.\n\tSufficient " 7112c25309d4SGeorge Wilson "replicas exist for the pool to continue functioning in " 7113c25309d4SGeorge Wilson "a\n\tdegraded state.\n")); 7114c25309d4SGeorge Wilson (void) printf(gettext("action: Online the device using " 7115c25309d4SGeorge Wilson "'zpool online' or replace the device with\n\t'zpool " 7116c25309d4SGeorge Wilson "replace'.\n")); 7117c25309d4SGeorge Wilson break; 7118c25309d4SGeorge Wilson 7119fa9e4066Sahrens case ZPOOL_STATUS_RESILVERING: 7120fa9e4066Sahrens (void) printf(gettext("status: One or more devices is " 7121fa9e4066Sahrens "currently being resilvered. The pool will\n\tcontinue " 7122fa9e4066Sahrens "to function, possibly in a degraded state.\n")); 7123fa9e4066Sahrens (void) printf(gettext("action: Wait for the resilver to " 7124fa9e4066Sahrens "complete.\n")); 7125fa9e4066Sahrens break; 7126fa9e4066Sahrens 7127ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_DATA: 7128ea8dc4b6Seschrock (void) printf(gettext("status: One or more devices has " 7129ea8dc4b6Seschrock "experienced an error resulting in data\n\tcorruption. " 7130ea8dc4b6Seschrock "Applications may be affected.\n")); 7131ea8dc4b6Seschrock (void) printf(gettext("action: Restore the file in question " 7132ea8dc4b6Seschrock "if possible. Otherwise restore the\n\tentire pool from " 7133ea8dc4b6Seschrock "backup.\n")); 7134ea8dc4b6Seschrock break; 7135ea8dc4b6Seschrock 7136ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_POOL: 7137ea8dc4b6Seschrock (void) printf(gettext("status: The pool metadata is corrupted " 7138ea8dc4b6Seschrock "and the pool cannot be opened.\n")); 7139468c413aSTim Haley zpool_explain_recover(zpool_get_handle(zhp), 7140468c413aSTim Haley zpool_get_name(zhp), reason, config); 7141ea8dc4b6Seschrock break; 7142ea8dc4b6Seschrock 7143eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_OLDER: 714457221772SChristopher Siden (void) printf(gettext("status: The pool is formatted using a " 714557221772SChristopher Siden "legacy on-disk format. The pool can\n\tstill be used, " 714657221772SChristopher Siden "but some features are unavailable.\n")); 7147eaca9bbdSeschrock (void) printf(gettext("action: Upgrade the pool using 'zpool " 7148eaca9bbdSeschrock "upgrade'. Once this is done, the\n\tpool will no longer " 714957221772SChristopher Siden "be accessible on software that does not support feature\n" 715057221772SChristopher Siden "\tflags.\n")); 7151eaca9bbdSeschrock break; 7152eaca9bbdSeschrock 7153eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 7154eaca9bbdSeschrock (void) printf(gettext("status: The pool has been upgraded to a " 7155eaca9bbdSeschrock "newer, incompatible on-disk version.\n\tThe pool cannot " 7156eaca9bbdSeschrock "be accessed on this system.\n")); 7157eaca9bbdSeschrock (void) printf(gettext("action: Access the pool from a system " 7158eaca9bbdSeschrock "running more recent software, or\n\trestore the pool from " 7159eaca9bbdSeschrock "backup.\n")); 7160eaca9bbdSeschrock break; 7161eaca9bbdSeschrock 716257221772SChristopher Siden case ZPOOL_STATUS_FEAT_DISABLED: 716357221772SChristopher Siden (void) printf(gettext("status: Some supported features are not " 716457221772SChristopher Siden "enabled on the pool. The pool can\n\tstill be used, but " 716557221772SChristopher Siden "some features are unavailable.\n")); 716657221772SChristopher Siden (void) printf(gettext("action: Enable all features using " 716757221772SChristopher Siden "'zpool upgrade'. Once this is done,\n\tthe pool may no " 716857221772SChristopher Siden "longer be accessible by software that does not support\n\t" 716957221772SChristopher Siden "the features. See zpool-features(5) for details.\n")); 717057221772SChristopher Siden break; 717157221772SChristopher Siden 7172ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ: 7173ad135b5dSChristopher Siden (void) printf(gettext("status: The pool cannot be accessed on " 7174ad135b5dSChristopher Siden "this system because it uses the\n\tfollowing feature(s) " 7175ad135b5dSChristopher Siden "not supported on this system:\n")); 7176ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 7177ad135b5dSChristopher Siden (void) printf("\n"); 7178ad135b5dSChristopher Siden (void) printf(gettext("action: Access the pool from a system " 7179ad135b5dSChristopher Siden "that supports the required feature(s),\n\tor restore the " 7180ad135b5dSChristopher Siden "pool from backup.\n")); 7181ad135b5dSChristopher Siden break; 7182ad135b5dSChristopher Siden 7183ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 7184ad135b5dSChristopher Siden (void) printf(gettext("status: The pool can only be accessed " 7185ad135b5dSChristopher Siden "in read-only mode on this system. It\n\tcannot be " 7186ad135b5dSChristopher Siden "accessed in read-write mode because it uses the " 7187ad135b5dSChristopher Siden "following\n\tfeature(s) not supported on this system:\n")); 7188ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 7189ad135b5dSChristopher Siden (void) printf("\n"); 7190ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be accessed in " 7191ad135b5dSChristopher Siden "read-write mode. Import the pool with\n" 7192ad135b5dSChristopher Siden "\t\"-o readonly=on\", access the pool from a system that " 7193ad135b5dSChristopher Siden "supports the\n\trequired feature(s), or restore the " 7194ad135b5dSChristopher Siden "pool from backup.\n")); 7195ad135b5dSChristopher Siden break; 7196ad135b5dSChristopher Siden 71973d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_R: 71983d7072f8Seschrock (void) printf(gettext("status: One or more devices are " 71993d7072f8Seschrock "faulted in response to persistent errors.\n\tSufficient " 72003d7072f8Seschrock "replicas exist for the pool to continue functioning " 72013d7072f8Seschrock "in a\n\tdegraded state.\n")); 72023d7072f8Seschrock (void) printf(gettext("action: Replace the faulted device, " 72033d7072f8Seschrock "or use 'zpool clear' to mark the device\n\trepaired.\n")); 72043d7072f8Seschrock break; 72053d7072f8Seschrock 72063d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_NR: 72073d7072f8Seschrock (void) printf(gettext("status: One or more devices are " 72083d7072f8Seschrock "faulted in response to persistent errors. There are " 72093d7072f8Seschrock "insufficient replicas for the pool to\n\tcontinue " 72103d7072f8Seschrock "functioning.\n")); 72113d7072f8Seschrock (void) printf(gettext("action: Destroy and re-create the pool " 72123d7072f8Seschrock "from a backup source. Manually marking the device\n" 72133d7072f8Seschrock "\trepaired using 'zpool clear' may allow some data " 72143d7072f8Seschrock "to be recovered.\n")); 72153d7072f8Seschrock break; 72163d7072f8Seschrock 7217e0f1c0afSOlaf Faaland case ZPOOL_STATUS_IO_FAILURE_MMP: 7218e0f1c0afSOlaf Faaland (void) printf(gettext("status: The pool is suspended because " 7219e0f1c0afSOlaf Faaland "multihost writes failed or were delayed;\n\tanother " 7220e0f1c0afSOlaf Faaland "system could import the pool undetected.\n")); 7221e0f1c0afSOlaf Faaland (void) printf(gettext("action: Make sure the pool's devices " 7222e0f1c0afSOlaf Faaland "are connected, then reboot your system and\n\timport the " 7223e0f1c0afSOlaf Faaland "pool.\n")); 7224e0f1c0afSOlaf Faaland break; 7225e0f1c0afSOlaf Faaland 722632b87932Sek case ZPOOL_STATUS_IO_FAILURE_WAIT: 722732b87932Sek case ZPOOL_STATUS_IO_FAILURE_CONTINUE: 722832b87932Sek (void) printf(gettext("status: One or more devices are " 72298a79c1b5Sek "faulted in response to IO failures.\n")); 723032b87932Sek (void) printf(gettext("action: Make sure the affected devices " 723132b87932Sek "are connected, then run 'zpool clear'.\n")); 723232b87932Sek break; 723332b87932Sek 7234b87f3af3Sperrin case ZPOOL_STATUS_BAD_LOG: 7235b87f3af3Sperrin (void) printf(gettext("status: An intent log record " 7236b87f3af3Sperrin "could not be read.\n" 7237b87f3af3Sperrin "\tWaiting for adminstrator intervention to fix the " 7238b87f3af3Sperrin "faulted pool.\n")); 7239b87f3af3Sperrin (void) printf(gettext("action: Either restore the affected " 7240b87f3af3Sperrin "device(s) and run 'zpool online',\n" 7241b87f3af3Sperrin "\tor ignore the intent log records by running " 7242b87f3af3Sperrin "'zpool clear'.\n")); 7243b87f3af3Sperrin break; 7244b87f3af3Sperrin 7245eb633035STom Caputi case ZPOOL_STATUS_ERRATA: 7246eb633035STom Caputi (void) printf(gettext("status: Errata #%d detected.\n"), 7247eb633035STom Caputi errata); 7248eb633035STom Caputi 7249eb633035STom Caputi switch (errata) { 7250eb633035STom Caputi case ZPOOL_ERRATA_NONE: 7251eb633035STom Caputi break; 7252eb633035STom Caputi 7253eb633035STom Caputi case ZPOOL_ERRATA_ZOL_2094_SCRUB: 7254eb633035STom Caputi (void) printf(gettext("action: To correct the issue " 7255eb633035STom Caputi "run 'zpool scrub'.\n")); 7256eb633035STom Caputi break; 7257eb633035STom Caputi 7258eb633035STom Caputi case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION: 7259eb633035STom Caputi (void) printf(gettext("\tExisting encrypted datasets " 7260eb633035STom Caputi "contain an on-disk incompatibility\n\twhich " 7261eb633035STom Caputi "needs to be corrected.\n")); 7262eb633035STom Caputi (void) printf(gettext("action: To correct the issue " 7263eb633035STom Caputi "backup existing encrypted datasets to new\n\t" 7264eb633035STom Caputi "encrypted datasets and destroy the old ones. " 7265eb633035STom Caputi "'zfs mount -o ro' can\n\tbe used to temporarily " 7266eb633035STom Caputi "mount existing encrypted datasets readonly.\n")); 7267eb633035STom Caputi break; 7268eb633035STom Caputi 7269eb633035STom Caputi case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION: 7270eb633035STom Caputi (void) printf(gettext("\tExisting encrypted datasets " 7271eb633035STom Caputi "contain an on-disk incompatibility\n\twhich " 7272eb633035STom Caputi "needs to be corrected.\n")); 7273eb633035STom Caputi (void) printf(gettext("action: To correct the issue " 7274eb633035STom Caputi "enable the bookmark_v2 feature and " 7275eb633035STom Caputi "backup\n\tany existing encrypted datasets to " 7276eb633035STom Caputi "new encrypted datasets and\n\tdestroy the old " 7277eb633035STom Caputi "ones. If this pool does not contain any\n\t" 7278eb633035STom Caputi "encrypted datasets, simply enable the " 7279eb633035STom Caputi "bookmark_v2 feature\n")); 7280eb633035STom Caputi break; 7281eb633035STom Caputi 7282eb633035STom Caputi default: 7283eb633035STom Caputi /* 7284eb633035STom Caputi * All errata which allow the pool to be imported 7285eb633035STom Caputi * must contain an action message. 7286eb633035STom Caputi */ 7287eb633035STom Caputi assert(0); 7288eb633035STom Caputi } 7289eb633035STom Caputi break; 7290eb633035STom Caputi 7291fa9e4066Sahrens default: 7292fa9e4066Sahrens /* 7293fa9e4066Sahrens * The remaining errors can't actually be generated, yet. 7294fa9e4066Sahrens */ 7295fa9e4066Sahrens assert(reason == ZPOOL_STATUS_OK); 7296fa9e4066Sahrens } 7297fa9e4066Sahrens 7298fa9e4066Sahrens if (msgid != NULL) 7299654b400cSJoshua M. Clulow (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 7300fa9e4066Sahrens msgid); 7301fa9e4066Sahrens 7302fa9e4066Sahrens if (config != NULL) { 7303ea8dc4b6Seschrock uint64_t nerr; 7304fa94a07fSbrendan nvlist_t **spares, **l2cache; 7305fa94a07fSbrendan uint_t nspares, nl2cache; 730686714001SSerapheim Dimitropoulos pool_checkpoint_stat_t *pcs = NULL; 73073f9d6ad7SLin Ling pool_scan_stat_t *ps = NULL; 73085cabbc6bSPrashanth Sreenivasa pool_removal_stat_t *prs = NULL; 7309fa9e4066Sahrens 731086714001SSerapheim Dimitropoulos (void) nvlist_lookup_uint64_array(nvroot, 731186714001SSerapheim Dimitropoulos ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 73123f9d6ad7SLin Ling (void) nvlist_lookup_uint64_array(nvroot, 73133f9d6ad7SLin Ling ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c); 73145cabbc6bSPrashanth Sreenivasa (void) nvlist_lookup_uint64_array(nvroot, 73155cabbc6bSPrashanth Sreenivasa ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c); 731686714001SSerapheim Dimitropoulos 731786714001SSerapheim Dimitropoulos print_scan_status(ps); 731886714001SSerapheim Dimitropoulos print_checkpoint_scan_warning(ps, pcs); 73195cabbc6bSPrashanth Sreenivasa print_removal_status(zhp, prs); 732086714001SSerapheim Dimitropoulos print_checkpoint_status(pcs); 73215cabbc6bSPrashanth Sreenivasa 7322663207adSDon Brady cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0, 7323663207adSDon Brady cbp->cb_name_flags); 7324663207adSDon Brady if (cbp->cb_namewidth < 10) 7325663207adSDon Brady cbp->cb_namewidth = 10; 7326fa9e4066Sahrens 7327fa9e4066Sahrens (void) printf(gettext("config:\n\n")); 7328663207adSDon Brady (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), 7329663207adSDon Brady cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE", 7330663207adSDon Brady "CKSUM"); 7331663207adSDon Brady 7332dd50e0ccSTony Hutter if (cbp->cb_print_slow_ios) 7333dd50e0ccSTony Hutter (void) printf(" %5s", gettext("SLOW")); 7334dd50e0ccSTony Hutter 7335663207adSDon Brady print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0, 7336663207adSDon Brady B_FALSE); 7337663207adSDon Brady 7338663207adSDon Brady print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_DEDUP); 7339663207adSDon Brady print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_SPECIAL); 7340663207adSDon Brady print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_CLASS_LOGS); 734199653d4eSeschrock 7342fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 7343fa94a07fSbrendan &l2cache, &nl2cache) == 0) 7344663207adSDon Brady print_l2cache(zhp, cbp, l2cache, nl2cache); 7345fa94a07fSbrendan 734699653d4eSeschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 734799653d4eSeschrock &spares, &nspares) == 0) 7348663207adSDon Brady print_spares(zhp, cbp, spares, nspares); 7349ea8dc4b6Seschrock 7350ea8dc4b6Seschrock if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 7351ea8dc4b6Seschrock &nerr) == 0) { 735255434c77Sek nvlist_t *nverrlist = NULL; 735355434c77Sek 7354ea8dc4b6Seschrock /* 7355ea8dc4b6Seschrock * If the approximate error count is small, get a 7356ea8dc4b6Seschrock * precise count by fetching the entire log and 7357ea8dc4b6Seschrock * uniquifying the results. 7358ea8dc4b6Seschrock */ 735975519f38Sek if (nerr > 0 && nerr < 100 && !cbp->cb_verbose && 736055434c77Sek zpool_get_errlog(zhp, &nverrlist) == 0) { 736155434c77Sek nvpair_t *elem; 736255434c77Sek 736355434c77Sek elem = NULL; 736455434c77Sek nerr = 0; 736555434c77Sek while ((elem = nvlist_next_nvpair(nverrlist, 736655434c77Sek elem)) != NULL) { 736755434c77Sek nerr++; 736855434c77Sek } 736955434c77Sek } 737055434c77Sek nvlist_free(nverrlist); 7371ea8dc4b6Seschrock 7372ea8dc4b6Seschrock (void) printf("\n"); 737399653d4eSeschrock 7374ea8dc4b6Seschrock if (nerr == 0) 7375ea8dc4b6Seschrock (void) printf(gettext("errors: No known data " 7376ea8dc4b6Seschrock "errors\n")); 7377ea8dc4b6Seschrock else if (!cbp->cb_verbose) 7378e9dbad6fSeschrock (void) printf(gettext("errors: %llu data " 73795ad82045Snd "errors, use '-v' for a list\n"), 73805ad82045Snd (u_longlong_t)nerr); 7381ea8dc4b6Seschrock else 7382ea8dc4b6Seschrock print_error_log(zhp); 7383ea8dc4b6Seschrock } 73849eb19f4dSGeorge Wilson 73859eb19f4dSGeorge Wilson if (cbp->cb_dedup_stats) 73869eb19f4dSGeorge Wilson print_dedup_stats(config); 7387fa9e4066Sahrens } else { 7388fa9e4066Sahrens (void) printf(gettext("config: The configuration cannot be " 7389fa9e4066Sahrens "determined.\n")); 7390fa9e4066Sahrens } 7391fa9e4066Sahrens 7392fa9e4066Sahrens return (0); 7393fa9e4066Sahrens } 7394fa9e4066Sahrens 7395fa9e4066Sahrens /* 7396dd50e0ccSTony Hutter * zpool status [-igLpPstvx] [-T d|u] [pool] ... [interval [count]] 7397fa9e4066Sahrens * 7398084fd14fSBrian Behlendorf * -i Display vdev initialization status. 7399663207adSDon Brady * -g Display guid for individual vdev name. 7400663207adSDon Brady * -L Follow links when resolving vdev path name. 7401dd50e0ccSTony Hutter * -p Display values in parsable (exact) format. 7402663207adSDon Brady * -P Display full path for vdev name. 7403dd50e0ccSTony Hutter * -s Display slow IOs column. 7404fa9e4066Sahrens * -v Display complete error logs 7405fa9e4066Sahrens * -x Display only pools with potential problems 74069eb19f4dSGeorge Wilson * -D Display dedup status (undocumented) 7407084fd14fSBrian Behlendorf * -t Display vdev TRIM status. 74083f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format 7409fa9e4066Sahrens * 7410fa9e4066Sahrens * Describes the health status of all pools or some subset. 7411fa9e4066Sahrens */ 7412fa9e4066Sahrens int 7413fa9e4066Sahrens zpool_do_status(int argc, char **argv) 7414fa9e4066Sahrens { 7415fa9e4066Sahrens int c; 7416fa9e4066Sahrens int ret; 7417dd50e0ccSTony Hutter float interval = 0; 7418dd50e0ccSTony Hutter unsigned long count = 0; 7419fa9e4066Sahrens status_cbdata_t cb = { 0 }; 7420fa9e4066Sahrens 7421fa9e4066Sahrens /* check options */ 7422dd50e0ccSTony Hutter while ((c = getopt(argc, argv, "igLpPsvxDtT:")) != -1) { 7423fa9e4066Sahrens switch (c) { 7424084fd14fSBrian Behlendorf case 'i': 7425084fd14fSBrian Behlendorf cb.cb_print_vdev_init = B_TRUE; 7426084fd14fSBrian Behlendorf break; 7427663207adSDon Brady case 'g': 7428663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_GUID; 7429663207adSDon Brady break; 7430663207adSDon Brady case 'L': 7431663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS; 7432663207adSDon Brady break; 7433dd50e0ccSTony Hutter case 'p': 7434dd50e0ccSTony Hutter cb.cb_literal = B_TRUE; 7435dd50e0ccSTony Hutter break; 7436663207adSDon Brady case 'P': 7437663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_PATH; 7438663207adSDon Brady break; 7439dd50e0ccSTony Hutter case 's': 7440dd50e0ccSTony Hutter cb.cb_print_slow_ios = B_TRUE; 7441dd50e0ccSTony Hutter break; 7442fa9e4066Sahrens case 'v': 744399653d4eSeschrock cb.cb_verbose = B_TRUE; 7444fa9e4066Sahrens break; 7445fa9e4066Sahrens case 'x': 744699653d4eSeschrock cb.cb_explain = B_TRUE; 7447fa9e4066Sahrens break; 74489eb19f4dSGeorge Wilson case 'D': 74499eb19f4dSGeorge Wilson cb.cb_dedup_stats = B_TRUE; 74509eb19f4dSGeorge Wilson break; 7451084fd14fSBrian Behlendorf case 't': 7452084fd14fSBrian Behlendorf cb.cb_print_vdev_trim = B_TRUE; 7453084fd14fSBrian Behlendorf break; 74543f9d6ad7SLin Ling case 'T': 74553f9d6ad7SLin Ling get_timestamp_arg(*optarg); 74563f9d6ad7SLin Ling break; 7457fa9e4066Sahrens case '?': 7458fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 7459fa9e4066Sahrens optopt); 746099653d4eSeschrock usage(B_FALSE); 7461fa9e4066Sahrens } 7462fa9e4066Sahrens } 7463fa9e4066Sahrens 7464fa9e4066Sahrens argc -= optind; 7465fa9e4066Sahrens argv += optind; 7466fa9e4066Sahrens 74673f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count); 7468fa9e4066Sahrens 7469e9dbad6fSeschrock if (argc == 0) 7470e9dbad6fSeschrock cb.cb_allpools = B_TRUE; 7471e9dbad6fSeschrock 74723f9d6ad7SLin Ling cb.cb_first = B_TRUE; 7473663207adSDon Brady cb.cb_print_status = B_TRUE; 7474fa9e4066Sahrens 74753f9d6ad7SLin Ling for (;;) { 74763f9d6ad7SLin Ling if (timestamp_fmt != NODATE) 74773f9d6ad7SLin Ling print_timestamp(timestamp_fmt); 7478fa9e4066Sahrens 74793f9d6ad7SLin Ling ret = for_each_pool(argc, argv, B_TRUE, NULL, 74803f9d6ad7SLin Ling status_callback, &cb); 74813f9d6ad7SLin Ling 74823f9d6ad7SLin Ling if (argc == 0 && cb.cb_count == 0) 74833f9d6ad7SLin Ling (void) printf(gettext("no pools available\n")); 74843f9d6ad7SLin Ling else if (cb.cb_explain && cb.cb_first && cb.cb_allpools) 74853f9d6ad7SLin Ling (void) printf(gettext("all pools are healthy\n")); 74863f9d6ad7SLin Ling 74873f9d6ad7SLin Ling if (ret != 0) 74883f9d6ad7SLin Ling return (ret); 74893f9d6ad7SLin Ling 74903f9d6ad7SLin Ling if (interval == 0) 74913f9d6ad7SLin Ling break; 74923f9d6ad7SLin Ling 74933f9d6ad7SLin Ling if (count != 0 && --count == 0) 74943f9d6ad7SLin Ling break; 74953f9d6ad7SLin Ling 7496dd50e0ccSTony Hutter (void) fsleep(interval); 74973f9d6ad7SLin Ling } 74983f9d6ad7SLin Ling 74993f9d6ad7SLin Ling return (0); 7500fa9e4066Sahrens } 7501fa9e4066Sahrens 7502eaca9bbdSeschrock typedef struct upgrade_cbdata { 7503eaca9bbdSeschrock int cb_first; 750406eeb2adSek int cb_argc; 7505990b4856Slling uint64_t cb_version; 750606eeb2adSek char **cb_argv; 7507eaca9bbdSeschrock } upgrade_cbdata_t; 7508eaca9bbdSeschrock 750957221772SChristopher Siden static int 751057221772SChristopher Siden upgrade_version(zpool_handle_t *zhp, uint64_t version) 751157221772SChristopher Siden { 751257221772SChristopher Siden int ret; 751357221772SChristopher Siden nvlist_t *config; 751457221772SChristopher Siden uint64_t oldversion; 751557221772SChristopher Siden 751657221772SChristopher Siden config = zpool_get_config(zhp, NULL); 751757221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 751857221772SChristopher Siden &oldversion) == 0); 751957221772SChristopher Siden 752057221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(oldversion)); 752157221772SChristopher Siden assert(oldversion < version); 752257221772SChristopher Siden 752357221772SChristopher Siden ret = zpool_upgrade(zhp, version); 752457221772SChristopher Siden if (ret != 0) 752557221772SChristopher Siden return (ret); 752657221772SChristopher Siden 752757221772SChristopher Siden if (version >= SPA_VERSION_FEATURES) { 752857221772SChristopher Siden (void) printf(gettext("Successfully upgraded " 752957221772SChristopher Siden "'%s' from version %llu to feature flags.\n"), 753057221772SChristopher Siden zpool_get_name(zhp), oldversion); 753157221772SChristopher Siden } else { 753257221772SChristopher Siden (void) printf(gettext("Successfully upgraded " 753357221772SChristopher Siden "'%s' from version %llu to version %llu.\n"), 753457221772SChristopher Siden zpool_get_name(zhp), oldversion, version); 753557221772SChristopher Siden } 753657221772SChristopher Siden 753757221772SChristopher Siden return (0); 753857221772SChristopher Siden } 753957221772SChristopher Siden 754057221772SChristopher Siden static int 754157221772SChristopher Siden upgrade_enable_all(zpool_handle_t *zhp, int *countp) 754257221772SChristopher Siden { 754357221772SChristopher Siden int i, ret, count; 754457221772SChristopher Siden boolean_t firstff = B_TRUE; 754557221772SChristopher Siden nvlist_t *enabled = zpool_get_features(zhp); 754657221772SChristopher Siden 754757221772SChristopher Siden count = 0; 754857221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 754957221772SChristopher Siden const char *fname = spa_feature_table[i].fi_uname; 755057221772SChristopher Siden const char *fguid = spa_feature_table[i].fi_guid; 755157221772SChristopher Siden if (!nvlist_exists(enabled, fguid)) { 755257221772SChristopher Siden char *propname; 755357221772SChristopher Siden verify(-1 != asprintf(&propname, "feature@%s", fname)); 755457221772SChristopher Siden ret = zpool_set_prop(zhp, propname, 755557221772SChristopher Siden ZFS_FEATURE_ENABLED); 755657221772SChristopher Siden if (ret != 0) { 755757221772SChristopher Siden free(propname); 755857221772SChristopher Siden return (ret); 755957221772SChristopher Siden } 756057221772SChristopher Siden count++; 756157221772SChristopher Siden 756257221772SChristopher Siden if (firstff) { 756357221772SChristopher Siden (void) printf(gettext("Enabled the " 756457221772SChristopher Siden "following features on '%s':\n"), 756557221772SChristopher Siden zpool_get_name(zhp)); 756657221772SChristopher Siden firstff = B_FALSE; 756757221772SChristopher Siden } 756857221772SChristopher Siden (void) printf(gettext(" %s\n"), fname); 756957221772SChristopher Siden free(propname); 757057221772SChristopher Siden } 757157221772SChristopher Siden } 757257221772SChristopher Siden 757357221772SChristopher Siden if (countp != NULL) 757457221772SChristopher Siden *countp = count; 757557221772SChristopher Siden return (0); 757657221772SChristopher Siden } 757757221772SChristopher Siden 7578eaca9bbdSeschrock static int 7579eaca9bbdSeschrock upgrade_cb(zpool_handle_t *zhp, void *arg) 7580eaca9bbdSeschrock { 7581eaca9bbdSeschrock upgrade_cbdata_t *cbp = arg; 7582eaca9bbdSeschrock nvlist_t *config; 7583eaca9bbdSeschrock uint64_t version; 758457221772SChristopher Siden boolean_t printnl = B_FALSE; 758557221772SChristopher Siden int ret; 7586eaca9bbdSeschrock 7587eaca9bbdSeschrock config = zpool_get_config(zhp, NULL); 7588eaca9bbdSeschrock verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 7589eaca9bbdSeschrock &version) == 0); 7590eaca9bbdSeschrock 759157221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(version)); 7592eaca9bbdSeschrock 759357221772SChristopher Siden if (version < cbp->cb_version) { 759457221772SChristopher Siden cbp->cb_first = B_FALSE; 759557221772SChristopher Siden ret = upgrade_version(zhp, cbp->cb_version); 759657221772SChristopher Siden if (ret != 0) 759757221772SChristopher Siden return (ret); 759857221772SChristopher Siden printnl = B_TRUE; 759957221772SChristopher Siden 760057221772SChristopher Siden /* 760157221772SChristopher Siden * If they did "zpool upgrade -a", then we could 760257221772SChristopher Siden * be doing ioctls to different pools. We need 760357221772SChristopher Siden * to log this history once to each pool, and bypass 760457221772SChristopher Siden * the normal history logging that happens in main(). 760557221772SChristopher Siden */ 760657221772SChristopher Siden (void) zpool_log_history(g_zfs, history_str); 760757221772SChristopher Siden log_history = B_FALSE; 760857221772SChristopher Siden } 760957221772SChristopher Siden 761057221772SChristopher Siden if (cbp->cb_version >= SPA_VERSION_FEATURES) { 761157221772SChristopher Siden int count; 761257221772SChristopher Siden ret = upgrade_enable_all(zhp, &count); 761357221772SChristopher Siden if (ret != 0) 761457221772SChristopher Siden return (ret); 761557221772SChristopher Siden 761657221772SChristopher Siden if (count > 0) { 761799653d4eSeschrock cbp->cb_first = B_FALSE; 761857221772SChristopher Siden printnl = B_TRUE; 7619eaca9bbdSeschrock } 762057221772SChristopher Siden } 7621eaca9bbdSeschrock 762257221772SChristopher Siden if (printnl) { 762357221772SChristopher Siden (void) printf(gettext("\n")); 762457221772SChristopher Siden } 762557221772SChristopher Siden 762657221772SChristopher Siden return (0); 762757221772SChristopher Siden } 762857221772SChristopher Siden 762957221772SChristopher Siden static int 763057221772SChristopher Siden upgrade_list_older_cb(zpool_handle_t *zhp, void *arg) 763157221772SChristopher Siden { 763257221772SChristopher Siden upgrade_cbdata_t *cbp = arg; 763357221772SChristopher Siden nvlist_t *config; 763457221772SChristopher Siden uint64_t version; 763557221772SChristopher Siden 763657221772SChristopher Siden config = zpool_get_config(zhp, NULL); 763757221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 763857221772SChristopher Siden &version) == 0); 763957221772SChristopher Siden 764057221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(version)); 764157221772SChristopher Siden 764257221772SChristopher Siden if (version < SPA_VERSION_FEATURES) { 7643eaca9bbdSeschrock if (cbp->cb_first) { 7644eaca9bbdSeschrock (void) printf(gettext("The following pools are " 764557221772SChristopher Siden "formatted with legacy version numbers and can\n" 764657221772SChristopher Siden "be upgraded to use feature flags. After " 764757221772SChristopher Siden "being upgraded, these pools\nwill no " 764857221772SChristopher Siden "longer be accessible by software that does not " 764957221772SChristopher Siden "support feature\nflags.\n\n")); 7650eaca9bbdSeschrock (void) printf(gettext("VER POOL\n")); 7651eaca9bbdSeschrock (void) printf(gettext("--- ------------\n")); 765299653d4eSeschrock cbp->cb_first = B_FALSE; 7653eaca9bbdSeschrock } 7654eaca9bbdSeschrock 76555ad82045Snd (void) printf("%2llu %s\n", (u_longlong_t)version, 7656eaca9bbdSeschrock zpool_get_name(zhp)); 7657eaca9bbdSeschrock } 7658eaca9bbdSeschrock 765957221772SChristopher Siden return (0); 766057221772SChristopher Siden } 766157221772SChristopher Siden 766257221772SChristopher Siden static int 766357221772SChristopher Siden upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg) 766457221772SChristopher Siden { 766557221772SChristopher Siden upgrade_cbdata_t *cbp = arg; 766657221772SChristopher Siden nvlist_t *config; 766757221772SChristopher Siden uint64_t version; 766857221772SChristopher Siden 766957221772SChristopher Siden config = zpool_get_config(zhp, NULL); 767057221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 767157221772SChristopher Siden &version) == 0); 767257221772SChristopher Siden 767357221772SChristopher Siden if (version >= SPA_VERSION_FEATURES) { 767457221772SChristopher Siden int i; 767557221772SChristopher Siden boolean_t poolfirst = B_TRUE; 767657221772SChristopher Siden nvlist_t *enabled = zpool_get_features(zhp); 767757221772SChristopher Siden 767857221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 767957221772SChristopher Siden const char *fguid = spa_feature_table[i].fi_guid; 768057221772SChristopher Siden const char *fname = spa_feature_table[i].fi_uname; 768157221772SChristopher Siden if (!nvlist_exists(enabled, fguid)) { 768257221772SChristopher Siden if (cbp->cb_first) { 768357221772SChristopher Siden (void) printf(gettext("\nSome " 768457221772SChristopher Siden "supported features are not " 768557221772SChristopher Siden "enabled on the following pools. " 768657221772SChristopher Siden "Once a\nfeature is enabled the " 768757221772SChristopher Siden "pool may become incompatible with " 768857221772SChristopher Siden "software\nthat does not support " 768957221772SChristopher Siden "the feature. See " 769057221772SChristopher Siden "zpool-features(5) for " 769157221772SChristopher Siden "details.\n\n")); 769257221772SChristopher Siden (void) printf(gettext("POOL " 769357221772SChristopher Siden "FEATURE\n")); 769457221772SChristopher Siden (void) printf(gettext("------" 769557221772SChristopher Siden "---------\n")); 769657221772SChristopher Siden cbp->cb_first = B_FALSE; 769757221772SChristopher Siden } 769857221772SChristopher Siden 769957221772SChristopher Siden if (poolfirst) { 770057221772SChristopher Siden (void) printf(gettext("%s\n"), 770157221772SChristopher Siden zpool_get_name(zhp)); 770257221772SChristopher Siden poolfirst = B_FALSE; 770357221772SChristopher Siden } 770457221772SChristopher Siden 770557221772SChristopher Siden (void) printf(gettext(" %s\n"), fname); 770657221772SChristopher Siden } 770757221772SChristopher Siden } 770857221772SChristopher Siden } 770957221772SChristopher Siden 771057221772SChristopher Siden return (0); 7711eaca9bbdSeschrock } 7712eaca9bbdSeschrock 7713eaca9bbdSeschrock /* ARGSUSED */ 7714eaca9bbdSeschrock static int 771506eeb2adSek upgrade_one(zpool_handle_t *zhp, void *data) 7716eaca9bbdSeschrock { 771757221772SChristopher Siden boolean_t printnl = B_FALSE; 7718990b4856Slling upgrade_cbdata_t *cbp = data; 7719990b4856Slling uint64_t cur_version; 7720eaca9bbdSeschrock int ret; 7721eaca9bbdSeschrock 77228654d025Sperrin if (strcmp("log", zpool_get_name(zhp)) == 0) { 77238654d025Sperrin (void) printf(gettext("'log' is now a reserved word\n" 77248654d025Sperrin "Pool 'log' must be renamed using export and import" 77258654d025Sperrin " to upgrade.\n")); 77268654d025Sperrin return (1); 77278654d025Sperrin } 7728990b4856Slling 7729990b4856Slling cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 7730e6c728e1Sbrendan if (cur_version > cbp->cb_version) { 7731eaca9bbdSeschrock (void) printf(gettext("Pool '%s' is already formatted " 773257221772SChristopher Siden "using more current version '%llu'.\n\n"), 7733e6c728e1Sbrendan zpool_get_name(zhp), cur_version); 7734e6c728e1Sbrendan return (0); 7735e6c728e1Sbrendan } 773657221772SChristopher Siden 773757221772SChristopher Siden if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) { 7738e6c728e1Sbrendan (void) printf(gettext("Pool '%s' is already formatted " 773957221772SChristopher Siden "using version %llu.\n\n"), zpool_get_name(zhp), 774057221772SChristopher Siden cbp->cb_version); 7741eaca9bbdSeschrock return (0); 7742eaca9bbdSeschrock } 7743eaca9bbdSeschrock 774457221772SChristopher Siden if (cur_version != cbp->cb_version) { 774557221772SChristopher Siden printnl = B_TRUE; 774657221772SChristopher Siden ret = upgrade_version(zhp, cbp->cb_version); 774757221772SChristopher Siden if (ret != 0) 774857221772SChristopher Siden return (ret); 774957221772SChristopher Siden } 775006eeb2adSek 775157221772SChristopher Siden if (cbp->cb_version >= SPA_VERSION_FEATURES) { 775257221772SChristopher Siden int count = 0; 775357221772SChristopher Siden ret = upgrade_enable_all(zhp, &count); 775457221772SChristopher Siden if (ret != 0) 775557221772SChristopher Siden return (ret); 775657221772SChristopher Siden 775757221772SChristopher Siden if (count != 0) { 775857221772SChristopher Siden printnl = B_TRUE; 775957221772SChristopher Siden } else if (cur_version == SPA_VERSION) { 776057221772SChristopher Siden (void) printf(gettext("Pool '%s' already has all " 776157221772SChristopher Siden "supported features enabled.\n"), 776257221772SChristopher Siden zpool_get_name(zhp)); 776357221772SChristopher Siden } 776457221772SChristopher Siden } 776557221772SChristopher Siden 776657221772SChristopher Siden if (printnl) { 776757221772SChristopher Siden (void) printf(gettext("\n")); 776806eeb2adSek } 7769eaca9bbdSeschrock 777057221772SChristopher Siden return (0); 7771eaca9bbdSeschrock } 7772eaca9bbdSeschrock 7773eaca9bbdSeschrock /* 7774eaca9bbdSeschrock * zpool upgrade 7775eaca9bbdSeschrock * zpool upgrade -v 7776990b4856Slling * zpool upgrade [-V version] <-a | pool ...> 7777eaca9bbdSeschrock * 7778eaca9bbdSeschrock * With no arguments, display downrev'd ZFS pool available for upgrade. 7779eaca9bbdSeschrock * Individual pools can be upgraded by specifying the pool, and '-a' will 7780eaca9bbdSeschrock * upgrade all pools. 7781eaca9bbdSeschrock */ 7782eaca9bbdSeschrock int 7783eaca9bbdSeschrock zpool_do_upgrade(int argc, char **argv) 7784eaca9bbdSeschrock { 7785eaca9bbdSeschrock int c; 7786eaca9bbdSeschrock upgrade_cbdata_t cb = { 0 }; 7787eaca9bbdSeschrock int ret = 0; 7788eaca9bbdSeschrock boolean_t showversions = B_FALSE; 778957221772SChristopher Siden boolean_t upgradeall = B_FALSE; 7790990b4856Slling char *end; 7791990b4856Slling 7792eaca9bbdSeschrock 7793eaca9bbdSeschrock /* check options */ 7794478ed9adSEric Taylor while ((c = getopt(argc, argv, ":avV:")) != -1) { 7795eaca9bbdSeschrock switch (c) { 7796eaca9bbdSeschrock case 'a': 779757221772SChristopher Siden upgradeall = B_TRUE; 7798eaca9bbdSeschrock break; 7799eaca9bbdSeschrock case 'v': 7800eaca9bbdSeschrock showversions = B_TRUE; 7801eaca9bbdSeschrock break; 7802990b4856Slling case 'V': 7803990b4856Slling cb.cb_version = strtoll(optarg, &end, 10); 7804ad135b5dSChristopher Siden if (*end != '\0' || 7805ad135b5dSChristopher Siden !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) { 7806990b4856Slling (void) fprintf(stderr, 7807990b4856Slling gettext("invalid version '%s'\n"), optarg); 7808990b4856Slling usage(B_FALSE); 7809990b4856Slling } 7810990b4856Slling break; 7811478ed9adSEric Taylor case ':': 7812478ed9adSEric Taylor (void) fprintf(stderr, gettext("missing argument for " 7813478ed9adSEric Taylor "'%c' option\n"), optopt); 7814478ed9adSEric Taylor usage(B_FALSE); 7815478ed9adSEric Taylor break; 7816eaca9bbdSeschrock case '?': 7817eaca9bbdSeschrock (void) fprintf(stderr, gettext("invalid option '%c'\n"), 7818eaca9bbdSeschrock optopt); 781999653d4eSeschrock usage(B_FALSE); 7820eaca9bbdSeschrock } 7821eaca9bbdSeschrock } 7822eaca9bbdSeschrock 782306eeb2adSek cb.cb_argc = argc; 782406eeb2adSek cb.cb_argv = argv; 7825eaca9bbdSeschrock argc -= optind; 7826eaca9bbdSeschrock argv += optind; 7827eaca9bbdSeschrock 7828351420b3Slling if (cb.cb_version == 0) { 7829351420b3Slling cb.cb_version = SPA_VERSION; 783057221772SChristopher Siden } else if (!upgradeall && argc == 0) { 7831351420b3Slling (void) fprintf(stderr, gettext("-V option is " 7832351420b3Slling "incompatible with other arguments\n")); 7833351420b3Slling usage(B_FALSE); 7834351420b3Slling } 7835351420b3Slling 7836eaca9bbdSeschrock if (showversions) { 783757221772SChristopher Siden if (upgradeall || argc != 0) { 7838eaca9bbdSeschrock (void) fprintf(stderr, gettext("-v option is " 7839eaca9bbdSeschrock "incompatible with other arguments\n")); 784099653d4eSeschrock usage(B_FALSE); 7841eaca9bbdSeschrock } 784257221772SChristopher Siden } else if (upgradeall) { 7843eaca9bbdSeschrock if (argc != 0) { 7844351420b3Slling (void) fprintf(stderr, gettext("-a option should not " 7845351420b3Slling "be used along with a pool name\n")); 784699653d4eSeschrock usage(B_FALSE); 7847eaca9bbdSeschrock } 7848eaca9bbdSeschrock } 7849eaca9bbdSeschrock 7850ad135b5dSChristopher Siden (void) printf(gettext("This system supports ZFS pool feature " 7851ad135b5dSChristopher Siden "flags.\n\n")); 7852eaca9bbdSeschrock if (showversions) { 785357221772SChristopher Siden int i; 785457221772SChristopher Siden 785557221772SChristopher Siden (void) printf(gettext("The following features are " 785657221772SChristopher Siden "supported:\n\n")); 785757221772SChristopher Siden (void) printf(gettext("FEAT DESCRIPTION\n")); 785857221772SChristopher Siden (void) printf("----------------------------------------------" 785957221772SChristopher Siden "---------------\n"); 786057221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 786157221772SChristopher Siden zfeature_info_t *fi = &spa_feature_table[i]; 7862ca0cc391SMatthew Ahrens const char *ro = 7863ca0cc391SMatthew Ahrens (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 786457221772SChristopher Siden " (read-only compatible)" : ""; 786557221772SChristopher Siden 786657221772SChristopher Siden (void) printf("%-37s%s\n", fi->fi_uname, ro); 786757221772SChristopher Siden (void) printf(" %s\n", fi->fi_desc); 786857221772SChristopher Siden } 786957221772SChristopher Siden (void) printf("\n"); 787057221772SChristopher Siden 787157221772SChristopher Siden (void) printf(gettext("The following legacy versions are also " 7872d7d4af51Smmusante "supported:\n\n")); 7873eaca9bbdSeschrock (void) printf(gettext("VER DESCRIPTION\n")); 7874eaca9bbdSeschrock (void) printf("--- -----------------------------------------" 7875eaca9bbdSeschrock "---------------\n"); 787699653d4eSeschrock (void) printf(gettext(" 1 Initial ZFS version\n")); 787744cd46caSbillm (void) printf(gettext(" 2 Ditto blocks " 787844cd46caSbillm "(replicated metadata)\n")); 787999653d4eSeschrock (void) printf(gettext(" 3 Hot spares and double parity " 788099653d4eSeschrock "RAID-Z\n")); 7881d7306b64Sek (void) printf(gettext(" 4 zpool history\n")); 7882c9431fa1Sahl (void) printf(gettext(" 5 Compression using the gzip " 7883c9431fa1Sahl "algorithm\n")); 7884990b4856Slling (void) printf(gettext(" 6 bootfs pool property\n")); 78858654d025Sperrin (void) printf(gettext(" 7 Separate intent log devices\n")); 7886ecd6cf80Smarks (void) printf(gettext(" 8 Delegated administration\n")); 78878eed72d4Sck (void) printf(gettext(" 9 refquota and refreservation " 7888a9799022Sck "properties\n")); 7889fa94a07fSbrendan (void) printf(gettext(" 10 Cache devices\n")); 7890088f3894Sahrens (void) printf(gettext(" 11 Improved scrub performance\n")); 7891bb0ade09Sahrens (void) printf(gettext(" 12 Snapshot properties\n")); 789274e7dc98SMatthew Ahrens (void) printf(gettext(" 13 snapused property\n")); 789314843421SMatthew Ahrens (void) printf(gettext(" 14 passthrough-x aclinherit\n")); 789414843421SMatthew Ahrens (void) printf(gettext(" 15 user/group space accounting\n")); 7895478ed9adSEric Taylor (void) printf(gettext(" 16 stmf property support\n")); 78967aeab329SAdam Leventhal (void) printf(gettext(" 17 Triple-parity RAID-Z\n")); 7897b24ab676SJeff Bonwick (void) printf(gettext(" 18 Snapshot user holds\n")); 789888ecc943SGeorge Wilson (void) printf(gettext(" 19 Log device removal\n")); 7899b24ab676SJeff Bonwick (void) printf(gettext(" 20 Compression using zle " 7900b24ab676SJeff Bonwick "(zero-length encoding)\n")); 7901b24ab676SJeff Bonwick (void) printf(gettext(" 21 Deduplication\n")); 790292241e0bSTom Erickson (void) printf(gettext(" 22 Received properties\n")); 79036e1f5caaSNeil Perrin (void) printf(gettext(" 23 Slim ZIL\n")); 79040a586ceaSMark Shellenbaum (void) printf(gettext(" 24 System attributes\n")); 79053f9d6ad7SLin Ling (void) printf(gettext(" 25 Improved scrub stats\n")); 7906cde58dbcSMatthew Ahrens (void) printf(gettext(" 26 Improved snapshot deletion " 7907cde58dbcSMatthew Ahrens "performance\n")); 79086e0cbcaaSMatthew Ahrens (void) printf(gettext(" 27 Improved snapshot creation " 79096e0cbcaaSMatthew Ahrens "performance\n")); 7910cb04b873SMark J Musante (void) printf(gettext(" 28 Multiple vdev replacements\n")); 7911b24ab676SJeff Bonwick (void) printf(gettext("\nFor more information on a particular " 79129a8685acSstephanie scheffler "version, including supported releases,\n")); 79139a8685acSstephanie scheffler (void) printf(gettext("see the ZFS Administration Guide.\n\n")); 791457221772SChristopher Siden } else if (argc == 0 && upgradeall) { 791557221772SChristopher Siden cb.cb_first = B_TRUE; 791699653d4eSeschrock ret = zpool_iter(g_zfs, upgrade_cb, &cb); 791757221772SChristopher Siden if (ret == 0 && cb.cb_first) { 791857221772SChristopher Siden if (cb.cb_version == SPA_VERSION) { 791957221772SChristopher Siden (void) printf(gettext("All pools are already " 792057221772SChristopher Siden "formatted using feature flags.\n\n")); 792157221772SChristopher Siden (void) printf(gettext("Every feature flags " 792257221772SChristopher Siden "pool already has all supported features " 792357221772SChristopher Siden "enabled.\n")); 792457221772SChristopher Siden } else { 792557221772SChristopher Siden (void) printf(gettext("All pools are already " 792657221772SChristopher Siden "formatted with version %llu or higher.\n"), 792757221772SChristopher Siden cb.cb_version); 7928eaca9bbdSeschrock } 7929eaca9bbdSeschrock } 793057221772SChristopher Siden } else if (argc == 0) { 793157221772SChristopher Siden cb.cb_first = B_TRUE; 793257221772SChristopher Siden ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb); 793357221772SChristopher Siden assert(ret == 0); 7934eaca9bbdSeschrock 793557221772SChristopher Siden if (cb.cb_first) { 793657221772SChristopher Siden (void) printf(gettext("All pools are formatted " 793757221772SChristopher Siden "using feature flags.\n\n")); 793857221772SChristopher Siden } else { 793957221772SChristopher Siden (void) printf(gettext("\nUse 'zpool upgrade -v' " 794057221772SChristopher Siden "for a list of available legacy versions.\n")); 794157221772SChristopher Siden } 794257221772SChristopher Siden 794357221772SChristopher Siden cb.cb_first = B_TRUE; 794457221772SChristopher Siden ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb); 794557221772SChristopher Siden assert(ret == 0); 794657221772SChristopher Siden 794757221772SChristopher Siden if (cb.cb_first) { 794857221772SChristopher Siden (void) printf(gettext("Every feature flags pool has " 794957221772SChristopher Siden "all supported features enabled.\n")); 795057221772SChristopher Siden } else { 795157221772SChristopher Siden (void) printf(gettext("\n")); 7952eaca9bbdSeschrock } 7953eaca9bbdSeschrock } else { 7954b1b8ab34Slling ret = for_each_pool(argc, argv, B_FALSE, NULL, 7955b1b8ab34Slling upgrade_one, &cb); 795606eeb2adSek } 795706eeb2adSek 795806eeb2adSek return (ret); 795906eeb2adSek } 796006eeb2adSek 7961ecd6cf80Smarks typedef struct hist_cbdata { 7962ecd6cf80Smarks boolean_t first; 79634445fffbSMatthew Ahrens boolean_t longfmt; 79644445fffbSMatthew Ahrens boolean_t internal; 7965ecd6cf80Smarks } hist_cbdata_t; 7966ecd6cf80Smarks 7967a52121eaSChunwei Chen static void 7968a52121eaSChunwei Chen print_history_records(nvlist_t *nvhis, hist_cbdata_t *cb) 796906eeb2adSek { 797006eeb2adSek nvlist_t **records; 797106eeb2adSek uint_t numrecords; 7972a52121eaSChunwei Chen int i; 797306eeb2adSek 797406eeb2adSek verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, 797506eeb2adSek &records, &numrecords) == 0); 797606eeb2adSek for (i = 0; i < numrecords; i++) { 79774445fffbSMatthew Ahrens nvlist_t *rec = records[i]; 79784445fffbSMatthew Ahrens char tbuf[30] = ""; 7979ecd6cf80Smarks 79804445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_TIME)) { 79814445fffbSMatthew Ahrens time_t tsec; 79824445fffbSMatthew Ahrens struct tm t; 79834445fffbSMatthew Ahrens 79844445fffbSMatthew Ahrens tsec = fnvlist_lookup_uint64(records[i], 79854445fffbSMatthew Ahrens ZPOOL_HIST_TIME); 79864445fffbSMatthew Ahrens (void) localtime_r(&tsec, &t); 79874445fffbSMatthew Ahrens (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 79884445fffbSMatthew Ahrens } 7989ecd6cf80Smarks 79904445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_CMD)) { 79914445fffbSMatthew Ahrens (void) printf("%s %s", tbuf, 79924445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_CMD)); 79934445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) { 79944445fffbSMatthew Ahrens int ievent = 79954445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT); 79964445fffbSMatthew Ahrens if (!cb->internal) 79974445fffbSMatthew Ahrens continue; 79984445fffbSMatthew Ahrens if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) { 79994445fffbSMatthew Ahrens (void) printf("%s unrecognized record:\n", 80004445fffbSMatthew Ahrens tbuf); 80014445fffbSMatthew Ahrens dump_nvlist(rec, 4); 80024445fffbSMatthew Ahrens continue; 80034445fffbSMatthew Ahrens } 80044445fffbSMatthew Ahrens (void) printf("%s [internal %s txg:%lld] %s", tbuf, 80054445fffbSMatthew Ahrens zfs_history_event_names[ievent], 80064445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 80074445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR)); 80084445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) { 80094445fffbSMatthew Ahrens if (!cb->internal) 8010ecd6cf80Smarks continue; 80114445fffbSMatthew Ahrens (void) printf("%s [txg:%lld] %s", tbuf, 80124445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 80134445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME)); 80144445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) { 80154445fffbSMatthew Ahrens (void) printf(" %s (%llu)", 80164445fffbSMatthew Ahrens fnvlist_lookup_string(rec, 80174445fffbSMatthew Ahrens ZPOOL_HIST_DSNAME), 80184445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, 80194445fffbSMatthew Ahrens ZPOOL_HIST_DSID)); 80204445fffbSMatthew Ahrens } 80214445fffbSMatthew Ahrens (void) printf(" %s", fnvlist_lookup_string(rec, 80224445fffbSMatthew Ahrens ZPOOL_HIST_INT_STR)); 80234445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) { 80244445fffbSMatthew Ahrens if (!cb->internal) 80254445fffbSMatthew Ahrens continue; 80264445fffbSMatthew Ahrens (void) printf("%s ioctl %s\n", tbuf, 80274445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL)); 80284445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) { 80294445fffbSMatthew Ahrens (void) printf(" input:\n"); 80304445fffbSMatthew Ahrens dump_nvlist(fnvlist_lookup_nvlist(rec, 80314445fffbSMatthew Ahrens ZPOOL_HIST_INPUT_NVL), 8); 80324445fffbSMatthew Ahrens } 80334445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) { 80344445fffbSMatthew Ahrens (void) printf(" output:\n"); 80354445fffbSMatthew Ahrens dump_nvlist(fnvlist_lookup_nvlist(rec, 80364445fffbSMatthew Ahrens ZPOOL_HIST_OUTPUT_NVL), 8); 80374445fffbSMatthew Ahrens } 8038dfc11533SChris Williamson if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) { 8039dfc11533SChris Williamson (void) printf(" errno: %lld\n", 8040dfc11533SChris Williamson fnvlist_lookup_int64(rec, 8041dfc11533SChris Williamson ZPOOL_HIST_ERRNO)); 8042dfc11533SChris Williamson } 80434445fffbSMatthew Ahrens } else { 80444445fffbSMatthew Ahrens if (!cb->internal) 8045ecd6cf80Smarks continue; 80464445fffbSMatthew Ahrens (void) printf("%s unrecognized record:\n", tbuf); 80474445fffbSMatthew Ahrens dump_nvlist(rec, 4); 804806eeb2adSek } 8049ecd6cf80Smarks 8050ecd6cf80Smarks if (!cb->longfmt) { 8051ecd6cf80Smarks (void) printf("\n"); 8052ecd6cf80Smarks continue; 8053ecd6cf80Smarks } 8054ecd6cf80Smarks (void) printf(" ["); 80554445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_WHO)) { 80564445fffbSMatthew Ahrens uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO); 80574445fffbSMatthew Ahrens struct passwd *pwd = getpwuid(who); 80584445fffbSMatthew Ahrens (void) printf("user %d ", (int)who); 80594445fffbSMatthew Ahrens if (pwd != NULL) 80604445fffbSMatthew Ahrens (void) printf("(%s) ", pwd->pw_name); 8061ecd6cf80Smarks } 80624445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_HOST)) { 80634445fffbSMatthew Ahrens (void) printf("on %s", 80644445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_HOST)); 8065ecd6cf80Smarks } 80664445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) { 80674445fffbSMatthew Ahrens (void) printf(":%s", 80684445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE)); 8069ecd6cf80Smarks } 8070ecd6cf80Smarks (void) printf("]"); 8071ecd6cf80Smarks (void) printf("\n"); 807206eeb2adSek } 8073a52121eaSChunwei Chen } 8074a52121eaSChunwei Chen 8075a52121eaSChunwei Chen /* 8076a52121eaSChunwei Chen * Print out the command history for a specific pool. 8077a52121eaSChunwei Chen */ 8078a52121eaSChunwei Chen static int 8079a52121eaSChunwei Chen get_history_one(zpool_handle_t *zhp, void *data) 8080a52121eaSChunwei Chen { 8081a52121eaSChunwei Chen nvlist_t *nvhis; 8082a52121eaSChunwei Chen int ret; 8083a52121eaSChunwei Chen hist_cbdata_t *cb = (hist_cbdata_t *)data; 8084a52121eaSChunwei Chen uint64_t off = 0; 8085a52121eaSChunwei Chen boolean_t eof = B_FALSE; 8086a52121eaSChunwei Chen 8087a52121eaSChunwei Chen cb->first = B_FALSE; 8088a52121eaSChunwei Chen 8089a52121eaSChunwei Chen (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); 8090a52121eaSChunwei Chen 8091a52121eaSChunwei Chen while (!eof) { 8092a52121eaSChunwei Chen if ((ret = zpool_get_history(zhp, &nvhis, &off, &eof)) != 0) 8093a52121eaSChunwei Chen return (ret); 8094a52121eaSChunwei Chen 8095a52121eaSChunwei Chen print_history_records(nvhis, cb); 8096a52121eaSChunwei Chen nvlist_free(nvhis); 8097a52121eaSChunwei Chen } 809806eeb2adSek (void) printf("\n"); 809906eeb2adSek 810006eeb2adSek return (ret); 810106eeb2adSek } 810206eeb2adSek 810306eeb2adSek /* 810406eeb2adSek * zpool history <pool> 810506eeb2adSek * 810606eeb2adSek * Displays the history of commands that modified pools. 810706eeb2adSek */ 810806eeb2adSek int 810906eeb2adSek zpool_do_history(int argc, char **argv) 811006eeb2adSek { 8111ecd6cf80Smarks hist_cbdata_t cbdata = { 0 }; 811206eeb2adSek int ret; 8113ecd6cf80Smarks int c; 811406eeb2adSek 8115ecd6cf80Smarks cbdata.first = B_TRUE; 8116ecd6cf80Smarks /* check options */ 8117ecd6cf80Smarks while ((c = getopt(argc, argv, "li")) != -1) { 8118ecd6cf80Smarks switch (c) { 8119ecd6cf80Smarks case 'l': 81204445fffbSMatthew Ahrens cbdata.longfmt = B_TRUE; 8121ecd6cf80Smarks break; 8122ecd6cf80Smarks case 'i': 81234445fffbSMatthew Ahrens cbdata.internal = B_TRUE; 8124ecd6cf80Smarks break; 8125ecd6cf80Smarks case '?': 8126ecd6cf80Smarks (void) fprintf(stderr, gettext("invalid option '%c'\n"), 8127ecd6cf80Smarks optopt); 8128ecd6cf80Smarks usage(B_FALSE); 8129ecd6cf80Smarks } 8130ecd6cf80Smarks } 813106eeb2adSek argc -= optind; 813206eeb2adSek argv += optind; 813306eeb2adSek 8134b1b8ab34Slling ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one, 8135ecd6cf80Smarks &cbdata); 813606eeb2adSek 8137ecd6cf80Smarks if (argc == 0 && cbdata.first == B_TRUE) { 813806eeb2adSek (void) printf(gettext("no pools available\n")); 813906eeb2adSek return (0); 8140eaca9bbdSeschrock } 8141eaca9bbdSeschrock 8142eaca9bbdSeschrock return (ret); 8143eaca9bbdSeschrock } 8144eaca9bbdSeschrock 8145b1b8ab34Slling static int 8146b1b8ab34Slling get_callback(zpool_handle_t *zhp, void *data) 8147b1b8ab34Slling { 8148990b4856Slling zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; 8149b1b8ab34Slling char value[MAXNAMELEN]; 8150990b4856Slling zprop_source_t srctype; 8151990b4856Slling zprop_list_t *pl; 8152b1b8ab34Slling 8153b1b8ab34Slling for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 8154b1b8ab34Slling 8155b1b8ab34Slling /* 8156990b4856Slling * Skip the special fake placeholder. This will also skip 8157990b4856Slling * over the name property when 'all' is specified. 8158b1b8ab34Slling */ 8159990b4856Slling if (pl->pl_prop == ZPOOL_PROP_NAME && 8160b1b8ab34Slling pl == cbp->cb_proplist) 8161b1b8ab34Slling continue; 8162b1b8ab34Slling 8163ad135b5dSChristopher Siden if (pl->pl_prop == ZPROP_INVAL && 8164ad135b5dSChristopher Siden (zpool_prop_feature(pl->pl_user_prop) || 8165ad135b5dSChristopher Siden zpool_prop_unsupported(pl->pl_user_prop))) { 8166ad135b5dSChristopher Siden srctype = ZPROP_SRC_LOCAL; 8167b1b8ab34Slling 8168ad135b5dSChristopher Siden if (zpool_prop_get_feature(zhp, pl->pl_user_prop, 8169ad135b5dSChristopher Siden value, sizeof (value)) == 0) { 8170ad135b5dSChristopher Siden zprop_print_one_property(zpool_get_name(zhp), 8171ad135b5dSChristopher Siden cbp, pl->pl_user_prop, value, srctype, 8172ad135b5dSChristopher Siden NULL, NULL); 8173ad135b5dSChristopher Siden } 8174ad135b5dSChristopher Siden } else { 8175ad135b5dSChristopher Siden if (zpool_get_prop(zhp, pl->pl_prop, value, 8176c58b3526SAdam Stevko sizeof (value), &srctype, cbp->cb_literal) != 0) 8177ad135b5dSChristopher Siden continue; 8178ad135b5dSChristopher Siden 8179ad135b5dSChristopher Siden zprop_print_one_property(zpool_get_name(zhp), cbp, 8180ad135b5dSChristopher Siden zpool_prop_to_name(pl->pl_prop), value, srctype, 8181ad135b5dSChristopher Siden NULL, NULL); 8182ad135b5dSChristopher Siden } 8183b1b8ab34Slling } 8184b1b8ab34Slling return (0); 8185b1b8ab34Slling } 8186b1b8ab34Slling 8187c58b3526SAdam Stevko /* 8188c58b3526SAdam Stevko * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ... 8189c58b3526SAdam Stevko * 8190c58b3526SAdam Stevko * -H Scripted mode. Don't display headers, and separate properties 8191c58b3526SAdam Stevko * by a single tab. 8192c58b3526SAdam Stevko * -o List of columns to display. Defaults to 8193c58b3526SAdam Stevko * "name,property,value,source". 819404e56356SAndriy Gapon * -p Diplay values in parsable (exact) format. 8195c58b3526SAdam Stevko * 8196c58b3526SAdam Stevko * Get properties of pools in the system. Output space statistics 8197c58b3526SAdam Stevko * for each one as well as other attributes. 8198c58b3526SAdam Stevko */ 8199b1b8ab34Slling int 8200b1b8ab34Slling zpool_do_get(int argc, char **argv) 8201b1b8ab34Slling { 8202990b4856Slling zprop_get_cbdata_t cb = { 0 }; 8203990b4856Slling zprop_list_t fake_name = { 0 }; 8204b1b8ab34Slling int ret; 8205c58b3526SAdam Stevko int c, i; 8206c58b3526SAdam Stevko char *value; 8207b1b8ab34Slling 8208b1b8ab34Slling cb.cb_first = B_TRUE; 8209c58b3526SAdam Stevko 8210c58b3526SAdam Stevko /* 8211c58b3526SAdam Stevko * Set up default columns and sources. 8212c58b3526SAdam Stevko */ 8213990b4856Slling cb.cb_sources = ZPROP_SRC_ALL; 8214b1b8ab34Slling cb.cb_columns[0] = GET_COL_NAME; 8215b1b8ab34Slling cb.cb_columns[1] = GET_COL_PROPERTY; 8216b1b8ab34Slling cb.cb_columns[2] = GET_COL_VALUE; 8217b1b8ab34Slling cb.cb_columns[3] = GET_COL_SOURCE; 8218990b4856Slling cb.cb_type = ZFS_TYPE_POOL; 8219b1b8ab34Slling 8220c58b3526SAdam Stevko /* check options */ 8221c58b3526SAdam Stevko while ((c = getopt(argc, argv, ":Hpo:")) != -1) { 8222c58b3526SAdam Stevko switch (c) { 8223c58b3526SAdam Stevko case 'p': 8224c58b3526SAdam Stevko cb.cb_literal = B_TRUE; 8225c58b3526SAdam Stevko break; 8226c58b3526SAdam Stevko case 'H': 8227c58b3526SAdam Stevko cb.cb_scripted = B_TRUE; 8228c58b3526SAdam Stevko break; 8229c58b3526SAdam Stevko case 'o': 8230c58b3526SAdam Stevko bzero(&cb.cb_columns, sizeof (cb.cb_columns)); 8231c58b3526SAdam Stevko i = 0; 8232c58b3526SAdam Stevko while (*optarg != '\0') { 8233c58b3526SAdam Stevko static char *col_subopts[] = 8234c58b3526SAdam Stevko { "name", "property", "value", "source", 8235c58b3526SAdam Stevko "all", NULL }; 8236c58b3526SAdam Stevko 8237c58b3526SAdam Stevko if (i == ZFS_GET_NCOLS) { 8238c58b3526SAdam Stevko (void) fprintf(stderr, gettext("too " 8239c58b3526SAdam Stevko "many fields given to -o " 8240c58b3526SAdam Stevko "option\n")); 8241c58b3526SAdam Stevko usage(B_FALSE); 8242c58b3526SAdam Stevko } 8243c58b3526SAdam Stevko 8244c58b3526SAdam Stevko switch (getsubopt(&optarg, col_subopts, 8245c58b3526SAdam Stevko &value)) { 8246c58b3526SAdam Stevko case 0: 8247c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_NAME; 8248c58b3526SAdam Stevko break; 8249c58b3526SAdam Stevko case 1: 8250c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_PROPERTY; 8251c58b3526SAdam Stevko break; 8252c58b3526SAdam Stevko case 2: 8253c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_VALUE; 8254c58b3526SAdam Stevko break; 8255c58b3526SAdam Stevko case 3: 8256c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_SOURCE; 8257c58b3526SAdam Stevko break; 8258c58b3526SAdam Stevko case 4: 8259c58b3526SAdam Stevko if (i > 0) { 8260c58b3526SAdam Stevko (void) fprintf(stderr, 8261c58b3526SAdam Stevko gettext("\"all\" conflicts " 8262c58b3526SAdam Stevko "with specific fields " 8263c58b3526SAdam Stevko "given to -o option\n")); 8264c58b3526SAdam Stevko usage(B_FALSE); 8265c58b3526SAdam Stevko } 8266c58b3526SAdam Stevko cb.cb_columns[0] = GET_COL_NAME; 8267c58b3526SAdam Stevko cb.cb_columns[1] = GET_COL_PROPERTY; 8268c58b3526SAdam Stevko cb.cb_columns[2] = GET_COL_VALUE; 8269c58b3526SAdam Stevko cb.cb_columns[3] = GET_COL_SOURCE; 8270c58b3526SAdam Stevko i = ZFS_GET_NCOLS; 8271c58b3526SAdam Stevko break; 8272c58b3526SAdam Stevko default: 8273c58b3526SAdam Stevko (void) fprintf(stderr, 8274c58b3526SAdam Stevko gettext("invalid column name " 8275c58b3526SAdam Stevko "'%s'\n"), value); 8276c58b3526SAdam Stevko usage(B_FALSE); 8277c58b3526SAdam Stevko } 8278c58b3526SAdam Stevko } 8279c58b3526SAdam Stevko break; 8280c58b3526SAdam Stevko case '?': 8281c58b3526SAdam Stevko (void) fprintf(stderr, gettext("invalid option '%c'\n"), 8282c58b3526SAdam Stevko optopt); 8283c58b3526SAdam Stevko usage(B_FALSE); 8284c58b3526SAdam Stevko } 8285c58b3526SAdam Stevko } 8286c58b3526SAdam Stevko 8287c58b3526SAdam Stevko argc -= optind; 8288c58b3526SAdam Stevko argv += optind; 8289c58b3526SAdam Stevko 8290c58b3526SAdam Stevko if (argc < 1) { 8291c58b3526SAdam Stevko (void) fprintf(stderr, gettext("missing property " 8292c58b3526SAdam Stevko "argument\n")); 8293c58b3526SAdam Stevko usage(B_FALSE); 8294c58b3526SAdam Stevko } 8295c58b3526SAdam Stevko 8296c58b3526SAdam Stevko if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist, 8297990b4856Slling ZFS_TYPE_POOL) != 0) 8298b1b8ab34Slling usage(B_FALSE); 8299b1b8ab34Slling 8300c58b3526SAdam Stevko argc--; 8301c58b3526SAdam Stevko argv++; 8302c58b3526SAdam Stevko 8303b1b8ab34Slling if (cb.cb_proplist != NULL) { 8304990b4856Slling fake_name.pl_prop = ZPOOL_PROP_NAME; 8305b1b8ab34Slling fake_name.pl_width = strlen(gettext("NAME")); 8306b1b8ab34Slling fake_name.pl_next = cb.cb_proplist; 8307b1b8ab34Slling cb.cb_proplist = &fake_name; 8308b1b8ab34Slling } 8309b1b8ab34Slling 8310c58b3526SAdam Stevko ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, 8311b1b8ab34Slling get_callback, &cb); 8312b1b8ab34Slling 8313b1b8ab34Slling if (cb.cb_proplist == &fake_name) 8314990b4856Slling zprop_free_list(fake_name.pl_next); 8315b1b8ab34Slling else 8316990b4856Slling zprop_free_list(cb.cb_proplist); 8317b1b8ab34Slling 8318b1b8ab34Slling return (ret); 8319b1b8ab34Slling } 8320b1b8ab34Slling 8321b1b8ab34Slling typedef struct set_cbdata { 8322b1b8ab34Slling char *cb_propname; 8323b1b8ab34Slling char *cb_value; 8324b1b8ab34Slling boolean_t cb_any_successful; 8325b1b8ab34Slling } set_cbdata_t; 8326b1b8ab34Slling 8327b1b8ab34Slling int 8328b1b8ab34Slling set_callback(zpool_handle_t *zhp, void *data) 8329b1b8ab34Slling { 8330b1b8ab34Slling int error; 8331b1b8ab34Slling set_cbdata_t *cb = (set_cbdata_t *)data; 8332b1b8ab34Slling 8333b1b8ab34Slling error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value); 8334b1b8ab34Slling 8335b1b8ab34Slling if (!error) 8336b1b8ab34Slling cb->cb_any_successful = B_TRUE; 8337b1b8ab34Slling 8338b1b8ab34Slling return (error); 8339b1b8ab34Slling } 8340b1b8ab34Slling 8341b1b8ab34Slling int 8342b1b8ab34Slling zpool_do_set(int argc, char **argv) 8343b1b8ab34Slling { 8344b1b8ab34Slling set_cbdata_t cb = { 0 }; 8345b1b8ab34Slling int error; 8346b1b8ab34Slling 8347b1b8ab34Slling if (argc > 1 && argv[1][0] == '-') { 8348b1b8ab34Slling (void) fprintf(stderr, gettext("invalid option '%c'\n"), 8349b1b8ab34Slling argv[1][1]); 8350b1b8ab34Slling usage(B_FALSE); 8351b1b8ab34Slling } 8352b1b8ab34Slling 8353b1b8ab34Slling if (argc < 2) { 8354b1b8ab34Slling (void) fprintf(stderr, gettext("missing property=value " 8355b1b8ab34Slling "argument\n")); 8356b1b8ab34Slling usage(B_FALSE); 8357b1b8ab34Slling } 8358b1b8ab34Slling 8359b1b8ab34Slling if (argc < 3) { 8360b1b8ab34Slling (void) fprintf(stderr, gettext("missing pool name\n")); 8361b1b8ab34Slling usage(B_FALSE); 8362b1b8ab34Slling } 8363b1b8ab34Slling 8364b1b8ab34Slling if (argc > 3) { 8365b1b8ab34Slling (void) fprintf(stderr, gettext("too many pool names\n")); 8366b1b8ab34Slling usage(B_FALSE); 8367b1b8ab34Slling } 8368b1b8ab34Slling 8369b1b8ab34Slling cb.cb_propname = argv[1]; 8370b1b8ab34Slling cb.cb_value = strchr(cb.cb_propname, '='); 8371b1b8ab34Slling if (cb.cb_value == NULL) { 8372b1b8ab34Slling (void) fprintf(stderr, gettext("missing value in " 8373b1b8ab34Slling "property=value argument\n")); 8374b1b8ab34Slling usage(B_FALSE); 8375b1b8ab34Slling } 8376b1b8ab34Slling 8377b1b8ab34Slling *(cb.cb_value) = '\0'; 8378b1b8ab34Slling cb.cb_value++; 8379b1b8ab34Slling 8380b1b8ab34Slling error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, 8381b1b8ab34Slling set_callback, &cb); 8382b1b8ab34Slling 8383b1b8ab34Slling return (error); 8384b1b8ab34Slling } 8385b1b8ab34Slling 8386b1b8ab34Slling static int 8387b1b8ab34Slling find_command_idx(char *command, int *idx) 8388b1b8ab34Slling { 8389b1b8ab34Slling int i; 8390b1b8ab34Slling 8391b1b8ab34Slling for (i = 0; i < NCOMMAND; i++) { 8392b1b8ab34Slling if (command_table[i].name == NULL) 8393b1b8ab34Slling continue; 8394b1b8ab34Slling 8395b1b8ab34Slling if (strcmp(command, command_table[i].name) == 0) { 8396b1b8ab34Slling *idx = i; 8397b1b8ab34Slling return (0); 8398b1b8ab34Slling } 8399b1b8ab34Slling } 8400b1b8ab34Slling return (1); 8401b1b8ab34Slling } 8402b1b8ab34Slling 8403fa9e4066Sahrens int 8404fa9e4066Sahrens main(int argc, char **argv) 8405fa9e4066Sahrens { 8406b327cd3fSIgor Kozhukhov int ret = 0; 8407fa9e4066Sahrens int i; 8408fa9e4066Sahrens char *cmdname; 8409fa9e4066Sahrens 8410fa9e4066Sahrens (void) setlocale(LC_ALL, ""); 8411fa9e4066Sahrens (void) textdomain(TEXT_DOMAIN); 8412fa9e4066Sahrens 841399653d4eSeschrock if ((g_zfs = libzfs_init()) == NULL) { 841499653d4eSeschrock (void) fprintf(stderr, gettext("internal error: failed to " 8415203a47d8Snd "initialize ZFS library\n")); 841699653d4eSeschrock return (1); 841799653d4eSeschrock } 841899653d4eSeschrock 841999653d4eSeschrock libzfs_print_on_error(g_zfs, B_TRUE); 842099653d4eSeschrock 8421fa9e4066Sahrens opterr = 0; 8422fa9e4066Sahrens 8423fa9e4066Sahrens /* 8424fa9e4066Sahrens * Make sure the user has specified some command. 8425fa9e4066Sahrens */ 8426fa9e4066Sahrens if (argc < 2) { 8427fa9e4066Sahrens (void) fprintf(stderr, gettext("missing command\n")); 842899653d4eSeschrock usage(B_FALSE); 8429fa9e4066Sahrens } 8430fa9e4066Sahrens 8431fa9e4066Sahrens cmdname = argv[1]; 8432fa9e4066Sahrens 8433fa9e4066Sahrens /* 8434fa9e4066Sahrens * Special case '-?' 8435fa9e4066Sahrens */ 8436fa9e4066Sahrens if (strcmp(cmdname, "-?") == 0) 843799653d4eSeschrock usage(B_TRUE); 8438fa9e4066Sahrens 84394445fffbSMatthew Ahrens zfs_save_arguments(argc, argv, history_str, sizeof (history_str)); 84402a6b87f0Sek 8441fa9e4066Sahrens /* 8442fa9e4066Sahrens * Run the appropriate command. 8443fa9e4066Sahrens */ 8444b1b8ab34Slling if (find_command_idx(cmdname, &i) == 0) { 8445b1b8ab34Slling current_command = &command_table[i]; 8446b1b8ab34Slling ret = command_table[i].func(argc - 1, argv + 1); 844791ebeef5Sahrens } else if (strchr(cmdname, '=')) { 844891ebeef5Sahrens verify(find_command_idx("set", &i) == 0); 844991ebeef5Sahrens current_command = &command_table[i]; 845091ebeef5Sahrens ret = command_table[i].func(argc, argv); 845191ebeef5Sahrens } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 845291ebeef5Sahrens /* 845391ebeef5Sahrens * 'freeze' is a vile debugging abomination, so we treat 845491ebeef5Sahrens * it as such. 845591ebeef5Sahrens */ 8456ea8dc4b6Seschrock char buf[16384]; 8457ea8dc4b6Seschrock int fd = open(ZFS_DEV, O_RDWR); 8458fa9e4066Sahrens (void) strcpy((void *)buf, argv[2]); 8459fa9e4066Sahrens return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf)); 846091ebeef5Sahrens } else { 8461fa9e4066Sahrens (void) fprintf(stderr, gettext("unrecognized " 8462fa9e4066Sahrens "command '%s'\n"), cmdname); 846399653d4eSeschrock usage(B_FALSE); 8464fa9e4066Sahrens } 8465fa9e4066Sahrens 84664445fffbSMatthew Ahrens if (ret == 0 && log_history) 84674445fffbSMatthew Ahrens (void) zpool_log_history(g_zfs, history_str); 84684445fffbSMatthew Ahrens 846999653d4eSeschrock libzfs_fini(g_zfs); 847099653d4eSeschrock 8471fa9e4066Sahrens /* 8472fa9e4066Sahrens * The 'ZFS_ABORT' environment variable causes us to dump core on exit 8473fa9e4066Sahrens * for the purposes of running ::findleaks. 8474fa9e4066Sahrens */ 8475fa9e4066Sahrens if (getenv("ZFS_ABORT") != NULL) { 8476fa9e4066Sahrens (void) printf("dumping core by request\n"); 8477fa9e4066Sahrens abort(); 8478fa9e4066Sahrens } 8479fa9e4066Sahrens 8480fa9e4066Sahrens return (ret); 8481fa9e4066Sahrens } 8482