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. 3195fa23b1SJerry Jelinek * Copyright 2019 Joyent, Inc. 32*5711d393Sloli * Copyright (c) 2012 by Cyril Plisko. All rights reserved. 33fa9e4066Sahrens */ 34fa9e4066Sahrens 35fa9e4066Sahrens #include <assert.h> 36fa9e4066Sahrens #include <ctype.h> 37fa9e4066Sahrens #include <dirent.h> 38fa9e4066Sahrens #include <errno.h> 39fa9e4066Sahrens #include <fcntl.h> 4086714001SSerapheim Dimitropoulos #include <getopt.h> 41fa9e4066Sahrens #include <libgen.h> 42fa9e4066Sahrens #include <libintl.h> 43fa9e4066Sahrens #include <libuutil.h> 44fa9e4066Sahrens #include <locale.h> 45fa9e4066Sahrens #include <stdio.h> 46fa9e4066Sahrens #include <stdlib.h> 47fa9e4066Sahrens #include <string.h> 48fa9e4066Sahrens #include <strings.h> 49fa9e4066Sahrens #include <unistd.h> 50fa9e4066Sahrens #include <priv.h> 51ecd6cf80Smarks #include <pwd.h> 52ecd6cf80Smarks #include <zone.h> 534263d13fSGeorge Wilson #include <zfs_prop.h> 54b1b8ab34Slling #include <sys/fs/zfs.h> 55fa9e4066Sahrens #include <sys/stat.h> 56e0f1c0afSOlaf Faaland #include <sys/debug.h> 57fa9e4066Sahrens 58fa9e4066Sahrens #include <libzfs.h> 59fa9e4066Sahrens 60fa9e4066Sahrens #include "zpool_util.h" 61b7b97454Sperrin #include "zfs_comutil.h" 62ad135b5dSChristopher Siden #include "zfeature_common.h" 63fa9e4066Sahrens 6426fd7700SKrishnendu Sadhukhan - Sun Microsystems #include "statcommon.h" 6526fd7700SKrishnendu Sadhukhan - Sun Microsystems 66fa9e4066Sahrens static int zpool_do_create(int, char **); 67fa9e4066Sahrens static int zpool_do_destroy(int, char **); 68fa9e4066Sahrens 69fa9e4066Sahrens static int zpool_do_add(int, char **); 7099653d4eSeschrock static int zpool_do_remove(int, char **); 716401734dSWill Andrews static int zpool_do_labelclear(int, char **); 72fa9e4066Sahrens 7386714001SSerapheim Dimitropoulos static int zpool_do_checkpoint(int, char **); 7486714001SSerapheim Dimitropoulos 75fa9e4066Sahrens static int zpool_do_list(int, char **); 76fa9e4066Sahrens static int zpool_do_iostat(int, char **); 77fa9e4066Sahrens static int zpool_do_status(int, char **); 78fa9e4066Sahrens 79fa9e4066Sahrens static int zpool_do_online(int, char **); 80fa9e4066Sahrens static int zpool_do_offline(int, char **); 81ea8dc4b6Seschrock static int zpool_do_clear(int, char **); 824263d13fSGeorge Wilson static int zpool_do_reopen(int, char **); 83fa9e4066Sahrens 84e9103aaeSGarrett D'Amore static int zpool_do_reguid(int, char **); 85e9103aaeSGarrett D'Amore 86fa9e4066Sahrens static int zpool_do_attach(int, char **); 87fa9e4066Sahrens static int zpool_do_detach(int, char **); 88fa9e4066Sahrens static int zpool_do_replace(int, char **); 891195e687SMark J Musante static int zpool_do_split(int, char **); 90fa9e4066Sahrens 91094e47e9SGeorge Wilson static int zpool_do_initialize(int, char **); 92fa9e4066Sahrens static int zpool_do_scrub(int, char **); 93e4c795beSTom Caputi static int zpool_do_resilver(int, char **); 94fa9e4066Sahrens 95fa9e4066Sahrens static int zpool_do_import(int, char **); 96fa9e4066Sahrens static int zpool_do_export(int, char **); 97fa9e4066Sahrens 98eaca9bbdSeschrock static int zpool_do_upgrade(int, char **); 99eaca9bbdSeschrock 10006eeb2adSek static int zpool_do_history(int, char **); 10106eeb2adSek 102b1b8ab34Slling static int zpool_do_get(int, char **); 103b1b8ab34Slling static int zpool_do_set(int, char **); 104b1b8ab34Slling 1059c2acf00SAlek Pinchuk static int zpool_do_sync(int, char **); 1069c2acf00SAlek Pinchuk 107fa9e4066Sahrens /* 108fa9e4066Sahrens * These libumem hooks provide a reasonable set of defaults for the allocator's 109fa9e4066Sahrens * debugging facilities. 110fa9e4066Sahrens */ 11129ab75c9Srm 11229ab75c9Srm #ifdef DEBUG 113fa9e4066Sahrens const char * 11499653d4eSeschrock _umem_debug_init(void) 115fa9e4066Sahrens { 116fa9e4066Sahrens return ("default,verbose"); /* $UMEM_DEBUG setting */ 117fa9e4066Sahrens } 118fa9e4066Sahrens 119fa9e4066Sahrens const char * 120fa9e4066Sahrens _umem_logging_init(void) 121fa9e4066Sahrens { 122fa9e4066Sahrens return ("fail,contents"); /* $UMEM_LOGGING setting */ 123fa9e4066Sahrens } 12429ab75c9Srm #endif 125fa9e4066Sahrens 12665cd9f28Seschrock typedef enum { 12765cd9f28Seschrock HELP_ADD, 12865cd9f28Seschrock HELP_ATTACH, 129ea8dc4b6Seschrock HELP_CLEAR, 13065cd9f28Seschrock HELP_CREATE, 13186714001SSerapheim Dimitropoulos HELP_CHECKPOINT, 13265cd9f28Seschrock HELP_DESTROY, 13365cd9f28Seschrock HELP_DETACH, 13465cd9f28Seschrock HELP_EXPORT, 13506eeb2adSek HELP_HISTORY, 13665cd9f28Seschrock HELP_IMPORT, 13765cd9f28Seschrock HELP_IOSTAT, 1386401734dSWill Andrews HELP_LABELCLEAR, 13965cd9f28Seschrock HELP_LIST, 14065cd9f28Seschrock HELP_OFFLINE, 14165cd9f28Seschrock HELP_ONLINE, 14265cd9f28Seschrock HELP_REPLACE, 14399653d4eSeschrock HELP_REMOVE, 144094e47e9SGeorge Wilson HELP_INITIALIZE, 14565cd9f28Seschrock HELP_SCRUB, 146e4c795beSTom Caputi HELP_RESILVER, 147eaca9bbdSeschrock HELP_STATUS, 148b1b8ab34Slling HELP_UPGRADE, 149b1b8ab34Slling HELP_GET, 1501195e687SMark J Musante HELP_SET, 151e9103aaeSGarrett D'Amore HELP_SPLIT, 1529c2acf00SAlek Pinchuk HELP_SYNC, 1534263d13fSGeorge Wilson HELP_REGUID, 1544263d13fSGeorge Wilson HELP_REOPEN 15565cd9f28Seschrock } zpool_help_t; 15665cd9f28Seschrock 15765cd9f28Seschrock 158fa9e4066Sahrens typedef struct zpool_command { 159fa9e4066Sahrens const char *name; 160fa9e4066Sahrens int (*func)(int, char **); 16165cd9f28Seschrock zpool_help_t usage; 162fa9e4066Sahrens } zpool_command_t; 163fa9e4066Sahrens 164fa9e4066Sahrens /* 165fa9e4066Sahrens * Master command table. Each ZFS command has a name, associated function, and 166ea8dc4b6Seschrock * usage message. The usage messages need to be internationalized, so we have 167ea8dc4b6Seschrock * to have a function to return the usage message based on a command index. 16865cd9f28Seschrock * 16965cd9f28Seschrock * These commands are organized according to how they are displayed in the usage 17065cd9f28Seschrock * message. An empty command (one with a NULL name) indicates an empty line in 17165cd9f28Seschrock * the generic usage message. 172fa9e4066Sahrens */ 173fa9e4066Sahrens static zpool_command_t command_table[] = { 17465cd9f28Seschrock { "create", zpool_do_create, HELP_CREATE }, 17565cd9f28Seschrock { "destroy", zpool_do_destroy, HELP_DESTROY }, 176fa9e4066Sahrens { NULL }, 17765cd9f28Seschrock { "add", zpool_do_add, HELP_ADD }, 17899653d4eSeschrock { "remove", zpool_do_remove, HELP_REMOVE }, 179fa9e4066Sahrens { NULL }, 1806401734dSWill Andrews { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR }, 1816401734dSWill Andrews { NULL }, 18286714001SSerapheim Dimitropoulos { "checkpoint", zpool_do_checkpoint, HELP_CHECKPOINT }, 18386714001SSerapheim Dimitropoulos { NULL }, 18465cd9f28Seschrock { "list", zpool_do_list, HELP_LIST }, 18565cd9f28Seschrock { "iostat", zpool_do_iostat, HELP_IOSTAT }, 18665cd9f28Seschrock { "status", zpool_do_status, HELP_STATUS }, 187fa9e4066Sahrens { NULL }, 18865cd9f28Seschrock { "online", zpool_do_online, HELP_ONLINE }, 18965cd9f28Seschrock { "offline", zpool_do_offline, HELP_OFFLINE }, 190ea8dc4b6Seschrock { "clear", zpool_do_clear, HELP_CLEAR }, 1914263d13fSGeorge Wilson { "reopen", zpool_do_reopen, HELP_REOPEN }, 192fa9e4066Sahrens { NULL }, 19365cd9f28Seschrock { "attach", zpool_do_attach, HELP_ATTACH }, 19465cd9f28Seschrock { "detach", zpool_do_detach, HELP_DETACH }, 19565cd9f28Seschrock { "replace", zpool_do_replace, HELP_REPLACE }, 1961195e687SMark J Musante { "split", zpool_do_split, HELP_SPLIT }, 197fa9e4066Sahrens { NULL }, 198094e47e9SGeorge Wilson { "initialize", zpool_do_initialize, HELP_INITIALIZE }, 199e4c795beSTom Caputi { "resilver", zpool_do_resilver, HELP_RESILVER }, 20065cd9f28Seschrock { "scrub", zpool_do_scrub, HELP_SCRUB }, 201fa9e4066Sahrens { NULL }, 20265cd9f28Seschrock { "import", zpool_do_import, HELP_IMPORT }, 20365cd9f28Seschrock { "export", zpool_do_export, HELP_EXPORT }, 20406eeb2adSek { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, 205e9103aaeSGarrett D'Amore { "reguid", zpool_do_reguid, HELP_REGUID }, 20606eeb2adSek { NULL }, 207b1b8ab34Slling { "history", zpool_do_history, HELP_HISTORY }, 208b1b8ab34Slling { "get", zpool_do_get, HELP_GET }, 209b1b8ab34Slling { "set", zpool_do_set, HELP_SET }, 2109c2acf00SAlek Pinchuk { "sync", zpool_do_sync, HELP_SYNC }, 211fa9e4066Sahrens }; 212fa9e4066Sahrens 213fa9e4066Sahrens #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 214fa9e4066Sahrens 215663207adSDon Brady #define VDEV_ALLOC_CLASS_LOGS "logs" 216663207adSDon Brady 2174445fffbSMatthew Ahrens static zpool_command_t *current_command; 2182a6b87f0Sek static char history_str[HIS_MAX_RECORD_LEN]; 2194445fffbSMatthew Ahrens static boolean_t log_history = B_TRUE; 22026fd7700SKrishnendu Sadhukhan - Sun Microsystems static uint_t timestamp_fmt = NODATE; 22126fd7700SKrishnendu Sadhukhan - Sun Microsystems 22265cd9f28Seschrock static const char * 2239a686fbcSPaul Dagnelie get_usage(zpool_help_t idx) 2249a686fbcSPaul Dagnelie { 22565cd9f28Seschrock switch (idx) { 22665cd9f28Seschrock case HELP_ADD: 227*5711d393Sloli return (gettext("\tadd [-fgLnP] [-o property=value] " 228*5711d393Sloli "<pool> <vdev> ...\n")); 22965cd9f28Seschrock case HELP_ATTACH: 230*5711d393Sloli return (gettext("\tattach [-f] [-o property=value] " 231*5711d393Sloli "<pool> <device> <new-device>\n")); 232ea8dc4b6Seschrock case HELP_CLEAR: 233468c413aSTim Haley return (gettext("\tclear [-nF] <pool> [device]\n")); 23465cd9f28Seschrock case HELP_CREATE: 2357855d95bSToomas Soome return (gettext("\tcreate [-fnd] [-B] " 2367855d95bSToomas Soome "[-o property=value] ... \n" 23704e56356SAndriy Gapon "\t [-O file-system-property=value] ...\n" 23804e56356SAndriy Gapon "\t [-m mountpoint] [-R root] [-t tempname] " 23904e56356SAndriy Gapon "<pool> <vdev> ...\n")); 24086714001SSerapheim Dimitropoulos case HELP_CHECKPOINT: 24186714001SSerapheim Dimitropoulos return (gettext("\tcheckpoint [--discard] <pool> ...\n")); 24265cd9f28Seschrock case HELP_DESTROY: 24365cd9f28Seschrock return (gettext("\tdestroy [-f] <pool>\n")); 24465cd9f28Seschrock case HELP_DETACH: 24565cd9f28Seschrock return (gettext("\tdetach <pool> <device>\n")); 24665cd9f28Seschrock case HELP_EXPORT: 24765cd9f28Seschrock return (gettext("\texport [-f] <pool> ...\n")); 24806eeb2adSek case HELP_HISTORY: 249ecd6cf80Smarks return (gettext("\thistory [-il] [<pool>] ...\n")); 25065cd9f28Seschrock case HELP_IMPORT: 2514c58d714Sdarrenm return (gettext("\timport [-d dir] [-D]\n" 252eb633035STom Caputi "\timport [-d dir | -c cachefile] [-F [-n]] [-l] " 253eb633035STom Caputi "<pool | id>\n" 2542f8aaab3Seschrock "\timport [-o mntopts] [-o property=value] ... \n" 255eb633035STom Caputi "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] " 256f9af39baSGeorge Wilson "[-R root] [-F [-n]] -a\n" 2572f8aaab3Seschrock "\timport [-o mntopts] [-o property=value] ... \n" 258eb633035STom Caputi "\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] " 25904e56356SAndriy Gapon "[-R root] [-F [-n]] [-t]\n" 26086714001SSerapheim Dimitropoulos "\t [--rewind-to-checkpoint] <pool | id> [newpool]\n")); 26165cd9f28Seschrock case HELP_IOSTAT: 262663207adSDon Brady return (gettext("\tiostat [-gLPv] [-T d|u] [pool] ... " 263663207adSDon Brady "[interval [count]]\n")); 2646401734dSWill Andrews case HELP_LABELCLEAR: 2656401734dSWill Andrews return (gettext("\tlabelclear [-f] <vdev>\n")); 26665cd9f28Seschrock case HELP_LIST: 267663207adSDon Brady return (gettext("\tlist [-gHLpPv] [-o property[,...]] " 2683f9d6ad7SLin Ling "[-T d|u] [pool] ... [interval [count]]\n")); 26965cd9f28Seschrock case HELP_OFFLINE: 270441d80aaSlling return (gettext("\toffline [-t] <pool> <device> ...\n")); 27165cd9f28Seschrock case HELP_ONLINE: 272441d80aaSlling return (gettext("\tonline <pool> <device> ...\n")); 27365cd9f28Seschrock case HELP_REPLACE: 27465cd9f28Seschrock return (gettext("\treplace [-f] <pool> <device> " 275e45ce728Sahrens "[new-device]\n")); 27699653d4eSeschrock case HELP_REMOVE: 2775cabbc6bSPrashanth Sreenivasa return (gettext("\tremove [-nps] <pool> <device> ...\n")); 2784263d13fSGeorge Wilson case HELP_REOPEN: 27931d7e8faSGeorge Wilson return (gettext("\treopen <pool>\n")); 280094e47e9SGeorge Wilson case HELP_INITIALIZE: 281094e47e9SGeorge Wilson return (gettext("\tinitialize [-cs] <pool> [<device> ...]\n")); 28265cd9f28Seschrock case HELP_SCRUB: 2831702cce7SAlek Pinchuk return (gettext("\tscrub [-s | -p] <pool> ...\n")); 284e4c795beSTom Caputi case HELP_RESILVER: 285e4c795beSTom Caputi return (gettext("\tresilver <pool> ...\n")); 28665cd9f28Seschrock case HELP_STATUS: 287663207adSDon Brady return (gettext("\tstatus [-DgLPvx] [-T d|u] [pool] ... " 288663207adSDon Brady "[interval [count]]\n")); 289eaca9bbdSeschrock case HELP_UPGRADE: 290eaca9bbdSeschrock return (gettext("\tupgrade\n" 291eaca9bbdSeschrock "\tupgrade -v\n" 292990b4856Slling "\tupgrade [-V version] <-a | pool ...>\n")); 293b1b8ab34Slling case HELP_GET: 294c58b3526SAdam Stevko return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] " 295c58b3526SAdam Stevko "<\"all\" | property[,...]> <pool> ...\n")); 296b1b8ab34Slling case HELP_SET: 297b1b8ab34Slling return (gettext("\tset <property=value> <pool> \n")); 2981195e687SMark J Musante case HELP_SPLIT: 299eb633035STom Caputi return (gettext("\tsplit [-gLlnP] [-R altroot] [-o mntopts]\n" 3001195e687SMark J Musante "\t [-o property=value] <pool> <newpool> " 3011195e687SMark J Musante "[<device> ...]\n")); 302e9103aaeSGarrett D'Amore case HELP_REGUID: 303e9103aaeSGarrett D'Amore return (gettext("\treguid <pool>\n")); 3049c2acf00SAlek Pinchuk case HELP_SYNC: 3059c2acf00SAlek Pinchuk return (gettext("\tsync [pool] ...\n")); 30665cd9f28Seschrock } 30765cd9f28Seschrock 30865cd9f28Seschrock abort(); 30965cd9f28Seschrock /* NOTREACHED */ 31065cd9f28Seschrock } 31165cd9f28Seschrock 312fa9e4066Sahrens 313b1b8ab34Slling /* 314b1b8ab34Slling * Callback routine that will print out a pool property value. 315b1b8ab34Slling */ 316990b4856Slling static int 317990b4856Slling print_prop_cb(int prop, void *cb) 318b1b8ab34Slling { 319b1b8ab34Slling FILE *fp = cb; 320b1b8ab34Slling 321663207adSDon Brady (void) fprintf(fp, "\t%-19s ", zpool_prop_to_name(prop)); 322b1b8ab34Slling 323990b4856Slling if (zpool_prop_readonly(prop)) 324990b4856Slling (void) fprintf(fp, " NO "); 325990b4856Slling else 326b24ab676SJeff Bonwick (void) fprintf(fp, " YES "); 327990b4856Slling 328b1b8ab34Slling if (zpool_prop_values(prop) == NULL) 329b1b8ab34Slling (void) fprintf(fp, "-\n"); 330b1b8ab34Slling else 331b1b8ab34Slling (void) fprintf(fp, "%s\n", zpool_prop_values(prop)); 332b1b8ab34Slling 333990b4856Slling return (ZPROP_CONT); 334b1b8ab34Slling } 335b1b8ab34Slling 336fa9e4066Sahrens /* 337fa9e4066Sahrens * Display usage message. If we're inside a command, display only the usage for 338fa9e4066Sahrens * that command. Otherwise, iterate over the entire command table and display 339fa9e4066Sahrens * a complete usage message. 340fa9e4066Sahrens */ 341fa9e4066Sahrens void 34299653d4eSeschrock usage(boolean_t requested) 343fa9e4066Sahrens { 344fa9e4066Sahrens FILE *fp = requested ? stdout : stderr; 345fa9e4066Sahrens 346fa9e4066Sahrens if (current_command == NULL) { 347fa9e4066Sahrens int i; 348fa9e4066Sahrens 349fa9e4066Sahrens (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 350fa9e4066Sahrens (void) fprintf(fp, 351fa9e4066Sahrens gettext("where 'command' is one of the following:\n\n")); 352fa9e4066Sahrens 353fa9e4066Sahrens for (i = 0; i < NCOMMAND; i++) { 354fa9e4066Sahrens if (command_table[i].name == NULL) 355fa9e4066Sahrens (void) fprintf(fp, "\n"); 356fa9e4066Sahrens else 357fa9e4066Sahrens (void) fprintf(fp, "%s", 35865cd9f28Seschrock get_usage(command_table[i].usage)); 359fa9e4066Sahrens } 360fa9e4066Sahrens } else { 361fa9e4066Sahrens (void) fprintf(fp, gettext("usage:\n")); 36265cd9f28Seschrock (void) fprintf(fp, "%s", get_usage(current_command->usage)); 363fa9e4066Sahrens } 364fa9e4066Sahrens 365b1b8ab34Slling if (current_command != NULL && 366b1b8ab34Slling ((strcmp(current_command->name, "set") == 0) || 367990b4856Slling (strcmp(current_command->name, "get") == 0) || 368990b4856Slling (strcmp(current_command->name, "list") == 0))) { 369b1b8ab34Slling 370b1b8ab34Slling (void) fprintf(fp, 371b1b8ab34Slling gettext("\nthe following properties are supported:\n")); 372b1b8ab34Slling 373663207adSDon Brady (void) fprintf(fp, "\n\t%-19s %s %s\n\n", 374990b4856Slling "PROPERTY", "EDIT", "VALUES"); 375b1b8ab34Slling 376b1b8ab34Slling /* Iterate over all properties */ 377990b4856Slling (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, 378990b4856Slling ZFS_TYPE_POOL); 379ad135b5dSChristopher Siden 380663207adSDon Brady (void) fprintf(fp, "\t%-19s ", "feature@..."); 381ad135b5dSChristopher Siden (void) fprintf(fp, "YES disabled | enabled | active\n"); 382ad135b5dSChristopher Siden 383ad135b5dSChristopher Siden (void) fprintf(fp, gettext("\nThe feature@ properties must be " 384ad135b5dSChristopher Siden "appended with a feature name.\nSee zpool-features(5).\n")); 385b1b8ab34Slling } 386b1b8ab34Slling 387e9dbad6fSeschrock /* 388e9dbad6fSeschrock * See comments at end of main(). 389e9dbad6fSeschrock */ 390e9dbad6fSeschrock if (getenv("ZFS_ABORT") != NULL) { 391e9dbad6fSeschrock (void) printf("dumping core by request\n"); 392e9dbad6fSeschrock abort(); 393e9dbad6fSeschrock } 394e9dbad6fSeschrock 395fa9e4066Sahrens exit(requested ? 0 : 2); 396fa9e4066Sahrens } 397fa9e4066Sahrens 398663207adSDon Brady /* 399663207adSDon Brady * print a pool vdev config for dry runs 400663207adSDon Brady */ 401663207adSDon Brady static void 4028654d025Sperrin print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, 403663207adSDon Brady const char *match, int name_flags) 404fa9e4066Sahrens { 405fa9e4066Sahrens nvlist_t **child; 406fa9e4066Sahrens uint_t c, children; 407afefbcddSeschrock char *vname; 408663207adSDon Brady boolean_t printed = B_FALSE; 409fa9e4066Sahrens 410fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 411663207adSDon Brady &child, &children) != 0) { 412663207adSDon Brady if (name != NULL) 413663207adSDon Brady (void) printf("\t%*s%s\n", indent, "", name); 414fa9e4066Sahrens return; 415663207adSDon Brady } 416fa9e4066Sahrens 417afefbcddSeschrock for (c = 0; c < children; c++) { 4188654d025Sperrin uint64_t is_log = B_FALSE; 419663207adSDon Brady char *class = ""; 4208654d025Sperrin 4218654d025Sperrin (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 4228654d025Sperrin &is_log); 423663207adSDon Brady if (is_log) 424663207adSDon Brady class = VDEV_ALLOC_BIAS_LOG; 425663207adSDon Brady (void) nvlist_lookup_string(child[c], 426663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &class); 427663207adSDon Brady if (strcmp(match, class) != 0) 4288654d025Sperrin continue; 4298654d025Sperrin 430663207adSDon Brady if (!printed && name != NULL) { 431663207adSDon Brady (void) printf("\t%*s%s\n", indent, "", name); 432663207adSDon Brady printed = B_TRUE; 433663207adSDon Brady } 434663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags); 435663207adSDon Brady print_vdev_tree(zhp, vname, child[c], indent + 2, "", 436663207adSDon Brady name_flags); 437afefbcddSeschrock free(vname); 438afefbcddSeschrock } 439fa9e4066Sahrens } 440fa9e4066Sahrens 44157221772SChristopher Siden static boolean_t 44257221772SChristopher Siden prop_list_contains_feature(nvlist_t *proplist) 44357221772SChristopher Siden { 44457221772SChristopher Siden nvpair_t *nvp; 44557221772SChristopher Siden for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp; 44657221772SChristopher Siden nvp = nvlist_next_nvpair(proplist, nvp)) { 44757221772SChristopher Siden if (zpool_prop_feature(nvpair_name(nvp))) 44857221772SChristopher Siden return (B_TRUE); 44957221772SChristopher Siden } 45057221772SChristopher Siden return (B_FALSE); 45157221772SChristopher Siden } 45257221772SChristopher Siden 453990b4856Slling /* 454990b4856Slling * Add a property pair (name, string-value) into a property nvlist. 455990b4856Slling */ 456990b4856Slling static int 4570a48a24eStimh add_prop_list(const char *propname, char *propval, nvlist_t **props, 4580a48a24eStimh boolean_t poolprop) 459990b4856Slling { 460d2aa06e8SAndrew Stormont zpool_prop_t prop = ZPOOL_PROP_INVAL; 4610a48a24eStimh zfs_prop_t fprop; 462990b4856Slling nvlist_t *proplist; 4630a48a24eStimh const char *normnm; 4640a48a24eStimh char *strval; 465990b4856Slling 466990b4856Slling if (*props == NULL && 467990b4856Slling nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) { 468990b4856Slling (void) fprintf(stderr, 469990b4856Slling gettext("internal error: out of memory\n")); 470990b4856Slling return (1); 471990b4856Slling } 472990b4856Slling 473990b4856Slling proplist = *props; 474990b4856Slling 4750a48a24eStimh if (poolprop) { 47657221772SChristopher Siden const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION); 47757221772SChristopher Siden 478d2aa06e8SAndrew Stormont if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL && 479ad135b5dSChristopher Siden !zpool_prop_feature(propname)) { 4800a48a24eStimh (void) fprintf(stderr, gettext("property '%s' is " 4810a48a24eStimh "not a valid pool property\n"), propname); 4820a48a24eStimh return (2); 4830a48a24eStimh } 48457221772SChristopher Siden 48557221772SChristopher Siden /* 48657221772SChristopher Siden * feature@ properties and version should not be specified 48757221772SChristopher Siden * at the same time. 48857221772SChristopher Siden */ 4894ae5f5f0SAlan Somers if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) && 49057221772SChristopher Siden nvlist_exists(proplist, vname)) || 49157221772SChristopher Siden (prop == ZPOOL_PROP_VERSION && 49257221772SChristopher Siden prop_list_contains_feature(proplist))) { 49357221772SChristopher Siden (void) fprintf(stderr, gettext("'feature@' and " 49457221772SChristopher Siden "'version' properties cannot be specified " 49557221772SChristopher Siden "together\n")); 49657221772SChristopher Siden return (2); 49757221772SChristopher Siden } 49857221772SChristopher Siden 49957221772SChristopher Siden 500ad135b5dSChristopher Siden if (zpool_prop_feature(propname)) 501ad135b5dSChristopher Siden normnm = propname; 502ad135b5dSChristopher Siden else 503ad135b5dSChristopher Siden normnm = zpool_prop_to_name(prop); 5040a48a24eStimh } else { 50514843421SMatthew Ahrens if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) { 50614843421SMatthew Ahrens normnm = zfs_prop_to_name(fprop); 50714843421SMatthew Ahrens } else { 50814843421SMatthew Ahrens normnm = propname; 5090a48a24eStimh } 510990b4856Slling } 511990b4856Slling 5120a48a24eStimh if (nvlist_lookup_string(proplist, normnm, &strval) == 0 && 5130a48a24eStimh prop != ZPOOL_PROP_CACHEFILE) { 514990b4856Slling (void) fprintf(stderr, gettext("property '%s' " 515990b4856Slling "specified multiple times\n"), propname); 516990b4856Slling return (2); 517990b4856Slling } 518990b4856Slling 5190a48a24eStimh if (nvlist_add_string(proplist, normnm, propval) != 0) { 520990b4856Slling (void) fprintf(stderr, gettext("internal " 521990b4856Slling "error: out of memory\n")); 522990b4856Slling return (1); 523990b4856Slling } 524990b4856Slling 525990b4856Slling return (0); 526990b4856Slling } 527990b4856Slling 52804e56356SAndriy Gapon /* 52904e56356SAndriy Gapon * Set a default property pair (name, string-value) in a property nvlist 53004e56356SAndriy Gapon */ 53104e56356SAndriy Gapon static int 53204e56356SAndriy Gapon add_prop_list_default(const char *propname, char *propval, nvlist_t **props, 53304e56356SAndriy Gapon boolean_t poolprop) 53404e56356SAndriy Gapon { 53504e56356SAndriy Gapon char *pval; 53604e56356SAndriy Gapon 53704e56356SAndriy Gapon if (nvlist_lookup_string(*props, propname, &pval) == 0) 53804e56356SAndriy Gapon return (0); 53904e56356SAndriy Gapon 54004e56356SAndriy Gapon return (add_prop_list(propname, propval, props, poolprop)); 54104e56356SAndriy Gapon } 54204e56356SAndriy Gapon 543fa9e4066Sahrens /* 544663207adSDon Brady * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ... 545fa9e4066Sahrens * 546fa9e4066Sahrens * -f Force addition of devices, even if they appear in use 547663207adSDon Brady * -g Display guid for individual vdev name. 548663207adSDon Brady * -L Follow links when resolving vdev path name. 549fa9e4066Sahrens * -n Do not add the devices, but display the resulting layout if 550fa9e4066Sahrens * they were to be added. 551663207adSDon Brady * -P Display full path for vdev name. 552*5711d393Sloli * -o Set property=value. 553fa9e4066Sahrens * 554fa9e4066Sahrens * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 555fa9e4066Sahrens * handled by get_vdev_spec(), which constructs the nvlist needed to pass to 556fa9e4066Sahrens * libzfs. 557fa9e4066Sahrens */ 558fa9e4066Sahrens int 559fa9e4066Sahrens zpool_do_add(int argc, char **argv) 560fa9e4066Sahrens { 56199653d4eSeschrock boolean_t force = B_FALSE; 56299653d4eSeschrock boolean_t dryrun = B_FALSE; 563663207adSDon Brady int name_flags = 0; 564fa9e4066Sahrens int c; 565fa9e4066Sahrens nvlist_t *nvroot; 566fa9e4066Sahrens char *poolname; 5677855d95bSToomas Soome zpool_boot_label_t boot_type; 5687855d95bSToomas Soome uint64_t boot_size; 569fa9e4066Sahrens int ret; 570fa9e4066Sahrens zpool_handle_t *zhp; 571fa9e4066Sahrens nvlist_t *config; 572*5711d393Sloli nvlist_t *props = NULL; 573*5711d393Sloli char *propval; 574fa9e4066Sahrens 575fa9e4066Sahrens /* check options */ 576*5711d393Sloli while ((c = getopt(argc, argv, "fgLnPo:")) != -1) { 577fa9e4066Sahrens switch (c) { 578fa9e4066Sahrens case 'f': 57999653d4eSeschrock force = B_TRUE; 580fa9e4066Sahrens break; 581663207adSDon Brady case 'g': 582663207adSDon Brady name_flags |= VDEV_NAME_GUID; 583663207adSDon Brady break; 584663207adSDon Brady case 'L': 585663207adSDon Brady name_flags |= VDEV_NAME_FOLLOW_LINKS; 586663207adSDon Brady break; 587fa9e4066Sahrens case 'n': 58899653d4eSeschrock dryrun = B_TRUE; 589fa9e4066Sahrens break; 590663207adSDon Brady case 'P': 591663207adSDon Brady name_flags |= VDEV_NAME_PATH; 592663207adSDon Brady break; 593*5711d393Sloli case 'o': 594*5711d393Sloli if ((propval = strchr(optarg, '=')) == NULL) { 595*5711d393Sloli (void) fprintf(stderr, gettext("missing " 596*5711d393Sloli "'=' for -o option\n")); 597*5711d393Sloli usage(B_FALSE); 598*5711d393Sloli } 599*5711d393Sloli *propval = '\0'; 600*5711d393Sloli propval++; 601*5711d393Sloli 602*5711d393Sloli if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) || 603*5711d393Sloli (add_prop_list(optarg, propval, &props, B_TRUE))) 604*5711d393Sloli usage(B_FALSE); 605*5711d393Sloli break; 606fa9e4066Sahrens case '?': 607fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 608fa9e4066Sahrens optopt); 60999653d4eSeschrock usage(B_FALSE); 610fa9e4066Sahrens } 611fa9e4066Sahrens } 612fa9e4066Sahrens 613fa9e4066Sahrens argc -= optind; 614fa9e4066Sahrens argv += optind; 615fa9e4066Sahrens 616fa9e4066Sahrens /* get pool name and check number of arguments */ 617fa9e4066Sahrens if (argc < 1) { 618fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 61999653d4eSeschrock usage(B_FALSE); 620fa9e4066Sahrens } 621fa9e4066Sahrens if (argc < 2) { 622fa9e4066Sahrens (void) fprintf(stderr, gettext("missing vdev specification\n")); 62399653d4eSeschrock usage(B_FALSE); 624fa9e4066Sahrens } 625fa9e4066Sahrens 626fa9e4066Sahrens poolname = argv[0]; 627fa9e4066Sahrens 628fa9e4066Sahrens argc--; 629fa9e4066Sahrens argv++; 630fa9e4066Sahrens 63199653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 632fa9e4066Sahrens return (1); 633fa9e4066Sahrens 634088e9d47Seschrock if ((config = zpool_get_config(zhp, NULL)) == NULL) { 635fa9e4066Sahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 636fa9e4066Sahrens poolname); 637fa9e4066Sahrens zpool_close(zhp); 638fa9e4066Sahrens return (1); 639fa9e4066Sahrens } 640fa9e4066Sahrens 6417855d95bSToomas Soome if (zpool_is_bootable(zhp)) 6427855d95bSToomas Soome boot_type = ZPOOL_COPY_BOOT_LABEL; 6437855d95bSToomas Soome else 6447855d95bSToomas Soome boot_type = ZPOOL_NO_BOOT_LABEL; 6457855d95bSToomas Soome 646*5711d393Sloli /* unless manually specified use "ashift" pool property (if set) */ 647*5711d393Sloli if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) { 648*5711d393Sloli int intval; 649*5711d393Sloli zprop_source_t src; 650*5711d393Sloli char strval[ZPOOL_MAXPROPLEN]; 651*5711d393Sloli 652*5711d393Sloli intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src); 653*5711d393Sloli if (src != ZPROP_SRC_DEFAULT) { 654*5711d393Sloli (void) sprintf(strval, "%" PRId32, intval); 655*5711d393Sloli verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval, 656*5711d393Sloli &props, B_TRUE) == 0); 657*5711d393Sloli } 658*5711d393Sloli } 659*5711d393Sloli 660fa9e4066Sahrens /* pass off to get_vdev_spec for processing */ 6617855d95bSToomas Soome boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 662*5711d393Sloli nvroot = make_root_vdev(zhp, props, force, !force, B_FALSE, dryrun, 6637855d95bSToomas Soome boot_type, boot_size, argc, argv); 664fa9e4066Sahrens if (nvroot == NULL) { 665fa9e4066Sahrens zpool_close(zhp); 666fa9e4066Sahrens return (1); 667fa9e4066Sahrens } 668fa9e4066Sahrens 669fa9e4066Sahrens if (dryrun) { 670fa9e4066Sahrens nvlist_t *poolnvroot; 671fa9e4066Sahrens 672fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 673fa9e4066Sahrens &poolnvroot) == 0); 674fa9e4066Sahrens 675fa9e4066Sahrens (void) printf(gettext("would update '%s' to the following " 676fa9e4066Sahrens "configuration:\n"), zpool_get_name(zhp)); 677fa9e4066Sahrens 6788654d025Sperrin /* print original main pool and new tree */ 679663207adSDon Brady print_vdev_tree(zhp, poolname, poolnvroot, 0, "", 680663207adSDon Brady name_flags | VDEV_NAME_TYPE_ID); 681663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, "", name_flags); 682663207adSDon Brady 683663207adSDon Brady /* print other classes: 'dedup', 'special', and 'log' */ 684663207adSDon Brady print_vdev_tree(zhp, "dedup", poolnvroot, 0, 685663207adSDon Brady VDEV_ALLOC_BIAS_DEDUP, name_flags); 686663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_DEDUP, 687663207adSDon Brady name_flags); 688663207adSDon Brady 689663207adSDon Brady print_vdev_tree(zhp, "special", poolnvroot, 0, 690663207adSDon Brady VDEV_ALLOC_BIAS_SPECIAL, name_flags); 691663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_SPECIAL, 692663207adSDon Brady name_flags); 693663207adSDon Brady 694663207adSDon Brady print_vdev_tree(zhp, "logs", poolnvroot, 0, VDEV_ALLOC_BIAS_LOG, 695663207adSDon Brady name_flags); 696663207adSDon Brady print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_LOG, 697663207adSDon Brady name_flags); 698fa9e4066Sahrens 699fa9e4066Sahrens ret = 0; 700fa9e4066Sahrens } else { 701fa9e4066Sahrens ret = (zpool_add(zhp, nvroot) != 0); 702fa9e4066Sahrens } 703fa9e4066Sahrens 704*5711d393Sloli nvlist_free(props); 70599653d4eSeschrock nvlist_free(nvroot); 70699653d4eSeschrock zpool_close(zhp); 70799653d4eSeschrock 70899653d4eSeschrock return (ret); 70999653d4eSeschrock } 71099653d4eSeschrock 71199653d4eSeschrock /* 7123f9d6ad7SLin Ling * zpool remove <pool> <vdev> ... 71399653d4eSeschrock * 7145cabbc6bSPrashanth Sreenivasa * Removes the given vdev from the pool. 71599653d4eSeschrock */ 71699653d4eSeschrock int 71799653d4eSeschrock zpool_do_remove(int argc, char **argv) 71899653d4eSeschrock { 71999653d4eSeschrock char *poolname; 720fa94a07fSbrendan int i, ret = 0; 72199653d4eSeschrock zpool_handle_t *zhp; 7225cabbc6bSPrashanth Sreenivasa boolean_t stop = B_FALSE; 7235cabbc6bSPrashanth Sreenivasa boolean_t noop = B_FALSE; 7245cabbc6bSPrashanth Sreenivasa boolean_t parsable = B_FALSE; 7255cabbc6bSPrashanth Sreenivasa char c; 72699653d4eSeschrock 7275cabbc6bSPrashanth Sreenivasa /* check options */ 7285cabbc6bSPrashanth Sreenivasa while ((c = getopt(argc, argv, "nps")) != -1) { 7295cabbc6bSPrashanth Sreenivasa switch (c) { 7305cabbc6bSPrashanth Sreenivasa case 'n': 7315cabbc6bSPrashanth Sreenivasa noop = B_TRUE; 7325cabbc6bSPrashanth Sreenivasa break; 7335cabbc6bSPrashanth Sreenivasa case 'p': 7345cabbc6bSPrashanth Sreenivasa parsable = B_TRUE; 7355cabbc6bSPrashanth Sreenivasa break; 7365cabbc6bSPrashanth Sreenivasa case 's': 7375cabbc6bSPrashanth Sreenivasa stop = B_TRUE; 7385cabbc6bSPrashanth Sreenivasa break; 7395cabbc6bSPrashanth Sreenivasa case '?': 7405cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("invalid option '%c'\n"), 7415cabbc6bSPrashanth Sreenivasa optopt); 7425cabbc6bSPrashanth Sreenivasa usage(B_FALSE); 7435cabbc6bSPrashanth Sreenivasa } 7445cabbc6bSPrashanth Sreenivasa } 7455cabbc6bSPrashanth Sreenivasa 7465cabbc6bSPrashanth Sreenivasa argc -= optind; 7475cabbc6bSPrashanth Sreenivasa argv += optind; 74899653d4eSeschrock 74999653d4eSeschrock /* get pool name and check number of arguments */ 75099653d4eSeschrock if (argc < 1) { 75199653d4eSeschrock (void) fprintf(stderr, gettext("missing pool name argument\n")); 75299653d4eSeschrock usage(B_FALSE); 75399653d4eSeschrock } 75499653d4eSeschrock 75599653d4eSeschrock poolname = argv[0]; 75699653d4eSeschrock 75799653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 75899653d4eSeschrock return (1); 75999653d4eSeschrock 7605cabbc6bSPrashanth Sreenivasa if (stop && noop) { 7615cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("stop request ignored\n")); 7625cabbc6bSPrashanth Sreenivasa return (0); 7635cabbc6bSPrashanth Sreenivasa } 7645cabbc6bSPrashanth Sreenivasa 7655cabbc6bSPrashanth Sreenivasa if (stop) { 7665cabbc6bSPrashanth Sreenivasa if (argc > 1) { 7675cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("too many arguments\n")); 7685cabbc6bSPrashanth Sreenivasa usage(B_FALSE); 7695cabbc6bSPrashanth Sreenivasa } 7705cabbc6bSPrashanth Sreenivasa if (zpool_vdev_remove_cancel(zhp) != 0) 771fa94a07fSbrendan ret = 1; 7725cabbc6bSPrashanth Sreenivasa } else { 7735cabbc6bSPrashanth Sreenivasa if (argc < 2) { 7745cabbc6bSPrashanth Sreenivasa (void) fprintf(stderr, gettext("missing device\n")); 7755cabbc6bSPrashanth Sreenivasa usage(B_FALSE); 7765cabbc6bSPrashanth Sreenivasa } 7775cabbc6bSPrashanth Sreenivasa 7785cabbc6bSPrashanth Sreenivasa for (i = 1; i < argc; i++) { 7795cabbc6bSPrashanth Sreenivasa if (noop) { 7805cabbc6bSPrashanth Sreenivasa uint64_t size; 7815cabbc6bSPrashanth Sreenivasa 7825cabbc6bSPrashanth Sreenivasa if (zpool_vdev_indirect_size(zhp, argv[i], 7835cabbc6bSPrashanth Sreenivasa &size) != 0) { 7845cabbc6bSPrashanth Sreenivasa ret = 1; 7855cabbc6bSPrashanth Sreenivasa break; 7865cabbc6bSPrashanth Sreenivasa } 7875cabbc6bSPrashanth Sreenivasa if (parsable) { 7885cabbc6bSPrashanth Sreenivasa (void) printf("%s %llu\n", 7895cabbc6bSPrashanth Sreenivasa argv[i], size); 7905cabbc6bSPrashanth Sreenivasa } else { 7915cabbc6bSPrashanth Sreenivasa char valstr[32]; 7925cabbc6bSPrashanth Sreenivasa zfs_nicenum(size, valstr, 7935cabbc6bSPrashanth Sreenivasa sizeof (valstr)); 7945cabbc6bSPrashanth Sreenivasa (void) printf("Memory that will be " 7955cabbc6bSPrashanth Sreenivasa "used after removing %s: %s\n", 7965cabbc6bSPrashanth Sreenivasa argv[i], valstr); 7975cabbc6bSPrashanth Sreenivasa } 7985cabbc6bSPrashanth Sreenivasa } else { 7995cabbc6bSPrashanth Sreenivasa if (zpool_vdev_remove(zhp, argv[i]) != 0) 8005cabbc6bSPrashanth Sreenivasa ret = 1; 8015cabbc6bSPrashanth Sreenivasa } 8025cabbc6bSPrashanth Sreenivasa } 803fa94a07fSbrendan } 80499653d4eSeschrock 805fa9e4066Sahrens return (ret); 806fa9e4066Sahrens } 807fa9e4066Sahrens 8086401734dSWill Andrews /* 8096401734dSWill Andrews * zpool labelclear [-f] <vdev> 8106401734dSWill Andrews * 8116401734dSWill Andrews * -f Force clearing the label for the vdevs which are members of 8126401734dSWill Andrews * the exported or foreign pools. 8136401734dSWill Andrews * 8146401734dSWill Andrews * Verifies that the vdev is not active and zeros out the label information 8156401734dSWill Andrews * on the device. 8166401734dSWill Andrews */ 8176401734dSWill Andrews int 8186401734dSWill Andrews zpool_do_labelclear(int argc, char **argv) 8196401734dSWill Andrews { 8206401734dSWill Andrews char vdev[MAXPATHLEN]; 8216401734dSWill Andrews char *name = NULL; 8226401734dSWill Andrews struct stat st; 8236401734dSWill Andrews int c, fd, ret = 0; 8246401734dSWill Andrews nvlist_t *config; 8256401734dSWill Andrews pool_state_t state; 8266401734dSWill Andrews boolean_t inuse = B_FALSE; 8276401734dSWill Andrews boolean_t force = B_FALSE; 8286401734dSWill Andrews 8296401734dSWill Andrews /* check options */ 8306401734dSWill Andrews while ((c = getopt(argc, argv, "f")) != -1) { 8316401734dSWill Andrews switch (c) { 8326401734dSWill Andrews case 'f': 8336401734dSWill Andrews force = B_TRUE; 8346401734dSWill Andrews break; 8356401734dSWill Andrews default: 8366401734dSWill Andrews (void) fprintf(stderr, gettext("invalid option '%c'\n"), 8376401734dSWill Andrews optopt); 8386401734dSWill Andrews usage(B_FALSE); 8396401734dSWill Andrews } 8406401734dSWill Andrews } 8416401734dSWill Andrews 8426401734dSWill Andrews argc -= optind; 8436401734dSWill Andrews argv += optind; 8446401734dSWill Andrews 8456401734dSWill Andrews /* get vdev name */ 8466401734dSWill Andrews if (argc < 1) { 8476401734dSWill Andrews (void) fprintf(stderr, gettext("missing vdev name\n")); 8486401734dSWill Andrews usage(B_FALSE); 8496401734dSWill Andrews } 8506401734dSWill Andrews if (argc > 1) { 8516401734dSWill Andrews (void) fprintf(stderr, gettext("too many arguments\n")); 8526401734dSWill Andrews usage(B_FALSE); 8536401734dSWill Andrews } 8546401734dSWill Andrews 8556401734dSWill Andrews /* 8566401734dSWill Andrews * Check if we were given absolute path and use it as is. 8576401734dSWill Andrews * Otherwise if the provided vdev name doesn't point to a file, 8586401734dSWill Andrews * try prepending dsk path and appending s0. 8596401734dSWill Andrews */ 8606401734dSWill Andrews (void) strlcpy(vdev, argv[0], sizeof (vdev)); 8616401734dSWill Andrews if (vdev[0] != '/' && stat(vdev, &st) != 0) { 8626401734dSWill Andrews char *s; 8636401734dSWill Andrews 8646401734dSWill Andrews (void) snprintf(vdev, sizeof (vdev), "%s/%s", 8656401734dSWill Andrews ZFS_DISK_ROOT, argv[0]); 8666401734dSWill Andrews if ((s = strrchr(argv[0], 's')) == NULL || 8676401734dSWill Andrews !isdigit(*(s + 1))) 8686401734dSWill Andrews (void) strlcat(vdev, "s0", sizeof (vdev)); 8696401734dSWill Andrews if (stat(vdev, &st) != 0) { 8706401734dSWill Andrews (void) fprintf(stderr, gettext( 8716401734dSWill Andrews "failed to find device %s, try specifying absolute " 8726401734dSWill Andrews "path instead\n"), argv[0]); 8736401734dSWill Andrews return (1); 8746401734dSWill Andrews } 8756401734dSWill Andrews } 8766401734dSWill Andrews 8776401734dSWill Andrews if ((fd = open(vdev, O_RDWR)) < 0) { 8786401734dSWill Andrews (void) fprintf(stderr, gettext("failed to open %s: %s\n"), 8796401734dSWill Andrews vdev, strerror(errno)); 8806401734dSWill Andrews return (1); 8816401734dSWill Andrews } 8826401734dSWill Andrews 883c861bfbdSAlan Somers if (zpool_read_label(fd, &config) != 0) { 8846401734dSWill Andrews (void) fprintf(stderr, 8856401734dSWill Andrews gettext("failed to read label from %s\n"), vdev); 8866401734dSWill Andrews return (1); 8876401734dSWill Andrews } 8886401734dSWill Andrews nvlist_free(config); 8896401734dSWill Andrews 8906401734dSWill Andrews ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse); 8916401734dSWill Andrews if (ret != 0) { 8926401734dSWill Andrews (void) fprintf(stderr, 8936401734dSWill Andrews gettext("failed to check state for %s\n"), vdev); 8946401734dSWill Andrews return (1); 8956401734dSWill Andrews } 8966401734dSWill Andrews 8976401734dSWill Andrews if (!inuse) 8986401734dSWill Andrews goto wipe_label; 8996401734dSWill Andrews 9006401734dSWill Andrews switch (state) { 9016401734dSWill Andrews default: 9026401734dSWill Andrews case POOL_STATE_ACTIVE: 9036401734dSWill Andrews case POOL_STATE_SPARE: 9046401734dSWill Andrews case POOL_STATE_L2CACHE: 9056401734dSWill Andrews (void) fprintf(stderr, gettext( 9066401734dSWill Andrews "%s is a member (%s) of pool \"%s\"\n"), 9076401734dSWill Andrews vdev, zpool_pool_state_to_name(state), name); 9086401734dSWill Andrews ret = 1; 9096401734dSWill Andrews goto errout; 9106401734dSWill Andrews 9116401734dSWill Andrews case POOL_STATE_EXPORTED: 9126401734dSWill Andrews if (force) 9136401734dSWill Andrews break; 9146401734dSWill Andrews (void) fprintf(stderr, gettext( 9156401734dSWill Andrews "use '-f' to override the following error:\n" 9166401734dSWill Andrews "%s is a member of exported pool \"%s\"\n"), 9176401734dSWill Andrews vdev, name); 9186401734dSWill Andrews ret = 1; 9196401734dSWill Andrews goto errout; 9206401734dSWill Andrews 9216401734dSWill Andrews case POOL_STATE_POTENTIALLY_ACTIVE: 9226401734dSWill Andrews if (force) 9236401734dSWill Andrews break; 9246401734dSWill Andrews (void) fprintf(stderr, gettext( 9256401734dSWill Andrews "use '-f' to override the following error:\n" 9266401734dSWill Andrews "%s is a member of potentially active pool \"%s\"\n"), 9276401734dSWill Andrews vdev, name); 9286401734dSWill Andrews ret = 1; 9296401734dSWill Andrews goto errout; 9306401734dSWill Andrews 9316401734dSWill Andrews case POOL_STATE_DESTROYED: 9326401734dSWill Andrews /* inuse should never be set for a destroyed pool */ 9336401734dSWill Andrews assert(0); 9346401734dSWill Andrews break; 9356401734dSWill Andrews } 9366401734dSWill Andrews 9376401734dSWill Andrews wipe_label: 9386401734dSWill Andrews ret = zpool_clear_label(fd); 9396401734dSWill Andrews if (ret != 0) { 9406401734dSWill Andrews (void) fprintf(stderr, 9416401734dSWill Andrews gettext("failed to clear label for %s\n"), vdev); 9426401734dSWill Andrews } 9436401734dSWill Andrews 9446401734dSWill Andrews errout: 9456401734dSWill Andrews free(name); 9466401734dSWill Andrews (void) close(fd); 9476401734dSWill Andrews 9486401734dSWill Andrews return (ret); 9496401734dSWill Andrews } 9506401734dSWill Andrews 951fa9e4066Sahrens /* 9527855d95bSToomas Soome * zpool create [-fnd] [-B] [-o property=value] ... 9530a48a24eStimh * [-O file-system-property=value] ... 95404e56356SAndriy Gapon * [-R root] [-m mountpoint] [-t tempname] <pool> <dev> ... 955fa9e4066Sahrens * 9567855d95bSToomas Soome * -B Create boot partition. 957fa9e4066Sahrens * -f Force creation, even if devices appear in use 958fa9e4066Sahrens * -n Do not create the pool, but display the resulting layout if it 959fa9e4066Sahrens * were to be created. 96004e56356SAndriy Gapon * -R Create a pool under an alternate root 96104e56356SAndriy Gapon * -m Set default mountpoint for the root dataset. By default it's 962ad135b5dSChristopher Siden * '/<pool>' 96304e56356SAndriy Gapon * -t Use the temporary name until the pool is exported. 964990b4856Slling * -o Set property=value. 965ad135b5dSChristopher Siden * -d Don't automatically enable all supported pool features 966ad135b5dSChristopher Siden * (individual features can be enabled with -o). 9670a48a24eStimh * -O Set fsproperty=value in the pool's root file system 968fa9e4066Sahrens * 969b1b8ab34Slling * Creates the named pool according to the given vdev specification. The 970fa9e4066Sahrens * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once 971fa9e4066Sahrens * we get the nvlist back from get_vdev_spec(), we either print out the contents 972fa9e4066Sahrens * (if '-n' was specified), or pass it to libzfs to do the creation. 973fa9e4066Sahrens */ 9747855d95bSToomas Soome 9757855d95bSToomas Soome #define SYSTEM256 (256 * 1024 * 1024) 976fa9e4066Sahrens int 977fa9e4066Sahrens zpool_do_create(int argc, char **argv) 978fa9e4066Sahrens { 97999653d4eSeschrock boolean_t force = B_FALSE; 98099653d4eSeschrock boolean_t dryrun = B_FALSE; 981ad135b5dSChristopher Siden boolean_t enable_all_pool_feat = B_TRUE; 9827855d95bSToomas Soome zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL; 9837855d95bSToomas Soome uint64_t boot_size = 0; 984fa9e4066Sahrens int c; 985990b4856Slling nvlist_t *nvroot = NULL; 986fa9e4066Sahrens char *poolname; 98704e56356SAndriy Gapon char *tname = NULL; 988990b4856Slling int ret = 1; 989fa9e4066Sahrens char *altroot = NULL; 990fa9e4066Sahrens char *mountpoint = NULL; 9910a48a24eStimh nvlist_t *fsprops = NULL; 992990b4856Slling nvlist_t *props = NULL; 9932f8aaab3Seschrock char *propval; 994fa9e4066Sahrens 995fa9e4066Sahrens /* check options */ 99604e56356SAndriy Gapon while ((c = getopt(argc, argv, ":fndBR:m:o:O:t:")) != -1) { 997fa9e4066Sahrens switch (c) { 998fa9e4066Sahrens case 'f': 99999653d4eSeschrock force = B_TRUE; 1000fa9e4066Sahrens break; 1001fa9e4066Sahrens case 'n': 100299653d4eSeschrock dryrun = B_TRUE; 1003fa9e4066Sahrens break; 1004ad135b5dSChristopher Siden case 'd': 1005ad135b5dSChristopher Siden enable_all_pool_feat = B_FALSE; 1006ad135b5dSChristopher Siden break; 10077855d95bSToomas Soome case 'B': 10087855d95bSToomas Soome /* 10097855d95bSToomas Soome * We should create the system partition. 10107855d95bSToomas Soome * Also make sure the size is set. 10117855d95bSToomas Soome */ 10127855d95bSToomas Soome boot_type = ZPOOL_CREATE_BOOT_LABEL; 10137855d95bSToomas Soome if (boot_size == 0) 10147855d95bSToomas Soome boot_size = SYSTEM256; 10157855d95bSToomas Soome break; 1016fa9e4066Sahrens case 'R': 1017fa9e4066Sahrens altroot = optarg; 1018990b4856Slling if (add_prop_list(zpool_prop_to_name( 10190a48a24eStimh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 1020990b4856Slling goto errout; 102104e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name( 10220a48a24eStimh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 1023990b4856Slling goto errout; 1024fa9e4066Sahrens break; 1025fa9e4066Sahrens case 'm': 10268b713775SWill Andrews /* Equivalent to -O mountpoint=optarg */ 1027fa9e4066Sahrens mountpoint = optarg; 1028fa9e4066Sahrens break; 1029990b4856Slling case 'o': 1030990b4856Slling if ((propval = strchr(optarg, '=')) == NULL) { 1031990b4856Slling (void) fprintf(stderr, gettext("missing " 1032990b4856Slling "'=' for -o option\n")); 1033990b4856Slling goto errout; 1034990b4856Slling } 1035990b4856Slling *propval = '\0'; 1036990b4856Slling propval++; 1037990b4856Slling 10380a48a24eStimh if (add_prop_list(optarg, propval, &props, B_TRUE)) 10390a48a24eStimh goto errout; 1040ad135b5dSChristopher Siden 10417855d95bSToomas Soome /* 10427855d95bSToomas Soome * Get bootsize value for make_root_vdev(). 10437855d95bSToomas Soome */ 10447855d95bSToomas Soome if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) { 10457855d95bSToomas Soome if (zfs_nicestrtonum(g_zfs, propval, 10467855d95bSToomas Soome &boot_size) < 0 || boot_size == 0) { 10477855d95bSToomas Soome (void) fprintf(stderr, 10487855d95bSToomas Soome gettext("bad boot partition size " 10497855d95bSToomas Soome "'%s': %s\n"), propval, 10507855d95bSToomas Soome libzfs_error_description(g_zfs)); 10517855d95bSToomas Soome goto errout; 10527855d95bSToomas Soome } 10537855d95bSToomas Soome } 10547855d95bSToomas Soome 1055ad135b5dSChristopher Siden /* 1056ad135b5dSChristopher Siden * If the user is creating a pool that doesn't support 1057ad135b5dSChristopher Siden * feature flags, don't enable any features. 1058ad135b5dSChristopher Siden */ 1059ad135b5dSChristopher Siden if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) { 1060ad135b5dSChristopher Siden char *end; 1061ad135b5dSChristopher Siden u_longlong_t ver; 1062ad135b5dSChristopher Siden 1063ad135b5dSChristopher Siden ver = strtoull(propval, &end, 10); 1064ad135b5dSChristopher Siden if (*end == '\0' && 1065ad135b5dSChristopher Siden ver < SPA_VERSION_FEATURES) { 1066ad135b5dSChristopher Siden enable_all_pool_feat = B_FALSE; 1067ad135b5dSChristopher Siden } 1068ad135b5dSChristopher Siden } 1069c423721fSXin Li if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT) 1070c423721fSXin Li altroot = propval; 10710a48a24eStimh break; 10720a48a24eStimh case 'O': 10730a48a24eStimh if ((propval = strchr(optarg, '=')) == NULL) { 10740a48a24eStimh (void) fprintf(stderr, gettext("missing " 10750a48a24eStimh "'=' for -O option\n")); 10760a48a24eStimh goto errout; 10770a48a24eStimh } 10780a48a24eStimh *propval = '\0'; 10790a48a24eStimh propval++; 10800a48a24eStimh 10818b713775SWill Andrews /* 10828b713775SWill Andrews * Mountpoints are checked and then added later. 10838b713775SWill Andrews * Uniquely among properties, they can be specified 10848b713775SWill Andrews * more than once, to avoid conflict with -m. 10858b713775SWill Andrews */ 10868b713775SWill Andrews if (0 == strcmp(optarg, 10878b713775SWill Andrews zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) { 10888b713775SWill Andrews mountpoint = propval; 10898b713775SWill Andrews } else if (add_prop_list(optarg, propval, &fsprops, 10908b713775SWill Andrews B_FALSE)) { 1091990b4856Slling goto errout; 10928b713775SWill Andrews } 1093990b4856Slling break; 109404e56356SAndriy Gapon case 't': 109504e56356SAndriy Gapon /* 109604e56356SAndriy Gapon * Sanity check temporary pool name. 109704e56356SAndriy Gapon */ 109804e56356SAndriy Gapon if (strchr(optarg, '/') != NULL) { 109904e56356SAndriy Gapon (void) fprintf(stderr, gettext("cannot create " 110004e56356SAndriy Gapon "'%s': invalid character '/' in temporary " 110104e56356SAndriy Gapon "name\n"), optarg); 110204e56356SAndriy Gapon (void) fprintf(stderr, gettext("use 'zfs " 110304e56356SAndriy Gapon "create' to create a dataset\n")); 110404e56356SAndriy Gapon goto errout; 110504e56356SAndriy Gapon } 110604e56356SAndriy Gapon 110704e56356SAndriy Gapon if (add_prop_list(zpool_prop_to_name( 110804e56356SAndriy Gapon ZPOOL_PROP_TNAME), optarg, &props, B_TRUE)) 110904e56356SAndriy Gapon goto errout; 111004e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name( 111104e56356SAndriy Gapon ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 111204e56356SAndriy Gapon goto errout; 111304e56356SAndriy Gapon tname = optarg; 111404e56356SAndriy Gapon break; 1115fa9e4066Sahrens case ':': 1116fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 1117fa9e4066Sahrens "'%c' option\n"), optopt); 1118990b4856Slling goto badusage; 1119fa9e4066Sahrens case '?': 1120fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1121fa9e4066Sahrens optopt); 1122990b4856Slling goto badusage; 1123fa9e4066Sahrens } 1124fa9e4066Sahrens } 1125fa9e4066Sahrens 1126fa9e4066Sahrens argc -= optind; 1127fa9e4066Sahrens argv += optind; 1128fa9e4066Sahrens 1129fa9e4066Sahrens /* get pool name and check number of arguments */ 1130fa9e4066Sahrens if (argc < 1) { 1131fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 1132990b4856Slling goto badusage; 1133fa9e4066Sahrens } 1134fa9e4066Sahrens if (argc < 2) { 1135fa9e4066Sahrens (void) fprintf(stderr, gettext("missing vdev specification\n")); 1136990b4856Slling goto badusage; 1137fa9e4066Sahrens } 1138fa9e4066Sahrens 1139fa9e4066Sahrens poolname = argv[0]; 1140fa9e4066Sahrens 1141fa9e4066Sahrens /* 1142fa9e4066Sahrens * As a special case, check for use of '/' in the name, and direct the 1143fa9e4066Sahrens * user to use 'zfs create' instead. 1144fa9e4066Sahrens */ 1145fa9e4066Sahrens if (strchr(poolname, '/') != NULL) { 1146fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot create '%s': invalid " 1147fa9e4066Sahrens "character '/' in pool name\n"), poolname); 1148fa9e4066Sahrens (void) fprintf(stderr, gettext("use 'zfs create' to " 1149fa9e4066Sahrens "create a dataset\n")); 1150990b4856Slling goto errout; 1151fa9e4066Sahrens } 1152fa9e4066Sahrens 11537855d95bSToomas Soome /* 11547855d95bSToomas Soome * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used, 11557855d95bSToomas Soome * and not set otherwise. 11567855d95bSToomas Soome */ 11577855d95bSToomas Soome if (boot_type == ZPOOL_CREATE_BOOT_LABEL) { 11587855d95bSToomas Soome const char *propname; 11597855d95bSToomas Soome char *strptr, *buf = NULL; 11607855d95bSToomas Soome int rv; 11617855d95bSToomas Soome 11627855d95bSToomas Soome propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 11637855d95bSToomas Soome if (nvlist_lookup_string(props, propname, &strptr) != 0) { 11647855d95bSToomas Soome (void) asprintf(&buf, "%" PRIu64, boot_size); 11657855d95bSToomas Soome if (buf == NULL) { 11667855d95bSToomas Soome (void) fprintf(stderr, 11677855d95bSToomas Soome gettext("internal error: out of memory\n")); 11687855d95bSToomas Soome goto errout; 11697855d95bSToomas Soome } 11707855d95bSToomas Soome rv = add_prop_list(propname, buf, &props, B_TRUE); 11717855d95bSToomas Soome free(buf); 11727855d95bSToomas Soome if (rv != 0) 11737855d95bSToomas Soome goto errout; 11747855d95bSToomas Soome } 11757855d95bSToomas Soome } else { 11767855d95bSToomas Soome const char *propname; 11777855d95bSToomas Soome char *strptr; 11787855d95bSToomas Soome 11797855d95bSToomas Soome propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE); 11807855d95bSToomas Soome if (nvlist_lookup_string(props, propname, &strptr) == 0) { 11817855d95bSToomas Soome (void) fprintf(stderr, gettext("error: setting boot " 11827855d95bSToomas Soome "partition size requires option '-B'\n")); 11837855d95bSToomas Soome goto errout; 11847855d95bSToomas Soome } 11857855d95bSToomas Soome } 11867855d95bSToomas Soome 1187fa9e4066Sahrens /* pass off to get_vdev_spec for bulk processing */ 1188*5711d393Sloli nvroot = make_root_vdev(NULL, props, force, !force, B_FALSE, dryrun, 11897855d95bSToomas Soome boot_type, boot_size, argc - 1, argv + 1); 1190fa9e4066Sahrens if (nvroot == NULL) 11910a48a24eStimh goto errout; 1192fa9e4066Sahrens 119399653d4eSeschrock /* make_root_vdev() allows 0 toplevel children if there are spares */ 1194b7b97454Sperrin if (!zfs_allocatable_devs(nvroot)) { 119599653d4eSeschrock (void) fprintf(stderr, gettext("invalid vdev " 119699653d4eSeschrock "specification: at least one toplevel vdev must be " 119799653d4eSeschrock "specified\n")); 1198990b4856Slling goto errout; 119999653d4eSeschrock } 120099653d4eSeschrock 1201fa9e4066Sahrens if (altroot != NULL && altroot[0] != '/') { 1202fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid alternate root '%s': " 1203e9dbad6fSeschrock "must be an absolute path\n"), altroot); 1204990b4856Slling goto errout; 1205fa9e4066Sahrens } 1206fa9e4066Sahrens 1207fa9e4066Sahrens /* 1208fa9e4066Sahrens * Check the validity of the mountpoint and direct the user to use the 1209fa9e4066Sahrens * '-m' mountpoint option if it looks like its in use. 1210fa9e4066Sahrens */ 1211fa9e4066Sahrens if (mountpoint == NULL || 1212fa9e4066Sahrens (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 1213fa9e4066Sahrens strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) { 1214fa9e4066Sahrens char buf[MAXPATHLEN]; 121511022c7cStimh DIR *dirp; 1216fa9e4066Sahrens 1217fa9e4066Sahrens if (mountpoint && mountpoint[0] != '/') { 1218fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid mountpoint " 1219fa9e4066Sahrens "'%s': must be an absolute path, 'legacy', or " 1220fa9e4066Sahrens "'none'\n"), mountpoint); 1221990b4856Slling goto errout; 1222fa9e4066Sahrens } 1223fa9e4066Sahrens 1224fa9e4066Sahrens if (mountpoint == NULL) { 1225fa9e4066Sahrens if (altroot != NULL) 1226fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s/%s", 1227fa9e4066Sahrens altroot, poolname); 1228fa9e4066Sahrens else 1229fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "/%s", 1230fa9e4066Sahrens poolname); 1231fa9e4066Sahrens } else { 1232fa9e4066Sahrens if (altroot != NULL) 1233fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s%s", 1234fa9e4066Sahrens altroot, mountpoint); 1235fa9e4066Sahrens else 1236fa9e4066Sahrens (void) snprintf(buf, sizeof (buf), "%s", 1237fa9e4066Sahrens mountpoint); 1238fa9e4066Sahrens } 1239fa9e4066Sahrens 124011022c7cStimh if ((dirp = opendir(buf)) == NULL && errno != ENOENT) { 124111022c7cStimh (void) fprintf(stderr, gettext("mountpoint '%s' : " 124211022c7cStimh "%s\n"), buf, strerror(errno)); 1243fa9e4066Sahrens (void) fprintf(stderr, gettext("use '-m' " 1244fa9e4066Sahrens "option to provide a different default\n")); 1245990b4856Slling goto errout; 124611022c7cStimh } else if (dirp) { 124711022c7cStimh int count = 0; 124811022c7cStimh 124911022c7cStimh while (count < 3 && readdir(dirp) != NULL) 125011022c7cStimh count++; 125111022c7cStimh (void) closedir(dirp); 125211022c7cStimh 125311022c7cStimh if (count > 2) { 125411022c7cStimh (void) fprintf(stderr, gettext("mountpoint " 125511022c7cStimh "'%s' exists and is not empty\n"), buf); 125611022c7cStimh (void) fprintf(stderr, gettext("use '-m' " 125711022c7cStimh "option to provide a " 125811022c7cStimh "different default\n")); 125911022c7cStimh goto errout; 126011022c7cStimh } 1261fa9e4066Sahrens } 1262fa9e4066Sahrens } 1263fa9e4066Sahrens 12648b713775SWill Andrews /* 12658b713775SWill Andrews * Now that the mountpoint's validity has been checked, ensure that 12668b713775SWill Andrews * the property is set appropriately prior to creating the pool. 12678b713775SWill Andrews */ 12688b713775SWill Andrews if (mountpoint != NULL) { 12698b713775SWill Andrews ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 12708b713775SWill Andrews mountpoint, &fsprops, B_FALSE); 12718b713775SWill Andrews if (ret != 0) 12728b713775SWill Andrews goto errout; 12738b713775SWill Andrews } 12748b713775SWill Andrews 12758b713775SWill Andrews ret = 1; 1276fa9e4066Sahrens if (dryrun) { 1277fa9e4066Sahrens /* 1278fa9e4066Sahrens * For a dry run invocation, print out a basic message and run 1279fa9e4066Sahrens * through all the vdevs in the list and print out in an 1280fa9e4066Sahrens * appropriate hierarchy. 1281fa9e4066Sahrens */ 1282fa9e4066Sahrens (void) printf(gettext("would create '%s' with the " 1283fa9e4066Sahrens "following layout:\n\n"), poolname); 1284fa9e4066Sahrens 1285663207adSDon Brady print_vdev_tree(NULL, poolname, nvroot, 0, "", 0); 1286663207adSDon Brady print_vdev_tree(NULL, "dedup", nvroot, 0, 1287663207adSDon Brady VDEV_ALLOC_BIAS_DEDUP, 0); 1288663207adSDon Brady print_vdev_tree(NULL, "special", nvroot, 0, 1289663207adSDon Brady VDEV_ALLOC_BIAS_SPECIAL, 0); 1290663207adSDon Brady print_vdev_tree(NULL, "logs", nvroot, 0, 1291663207adSDon Brady VDEV_ALLOC_BIAS_LOG, 0); 1292fa9e4066Sahrens 1293fa9e4066Sahrens ret = 0; 1294fa9e4066Sahrens } else { 1295fa9e4066Sahrens /* 1296fa9e4066Sahrens * Hand off to libzfs. 1297fa9e4066Sahrens */ 1298ad135b5dSChristopher Siden if (enable_all_pool_feat) { 12992acef22dSMatthew Ahrens spa_feature_t i; 1300ad135b5dSChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 1301ad135b5dSChristopher Siden char propname[MAXPATHLEN]; 1302ad135b5dSChristopher Siden zfeature_info_t *feat = &spa_feature_table[i]; 1303ad135b5dSChristopher Siden 1304ad135b5dSChristopher Siden (void) snprintf(propname, sizeof (propname), 1305ad135b5dSChristopher Siden "feature@%s", feat->fi_uname); 1306ad135b5dSChristopher Siden 1307ad135b5dSChristopher Siden /* 1308ad135b5dSChristopher Siden * Skip feature if user specified it manually 1309ad135b5dSChristopher Siden * on the command line. 1310ad135b5dSChristopher Siden */ 1311ad135b5dSChristopher Siden if (nvlist_exists(props, propname)) 1312ad135b5dSChristopher Siden continue; 1313ad135b5dSChristopher Siden 13148b713775SWill Andrews ret = add_prop_list(propname, 13158b713775SWill Andrews ZFS_FEATURE_ENABLED, &props, B_TRUE); 13168b713775SWill Andrews if (ret != 0) 1317ad135b5dSChristopher Siden goto errout; 1318ad135b5dSChristopher Siden } 1319ad135b5dSChristopher Siden } 13208b713775SWill Andrews 13218b713775SWill Andrews ret = 1; 13220a48a24eStimh if (zpool_create(g_zfs, poolname, 13230a48a24eStimh nvroot, props, fsprops) == 0) { 132404e56356SAndriy Gapon zfs_handle_t *pool = zfs_open(g_zfs, 132504e56356SAndriy Gapon tname ? tname : poolname, ZFS_TYPE_FILESYSTEM); 1326fa9e4066Sahrens if (pool != NULL) { 1327fa9e4066Sahrens if (zfs_mount(pool, NULL, 0) == 0) 1328da6c28aaSamw ret = zfs_shareall(pool); 1329fa9e4066Sahrens zfs_close(pool); 1330fa9e4066Sahrens } 133199653d4eSeschrock } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { 133299653d4eSeschrock (void) fprintf(stderr, gettext("pool name may have " 133399653d4eSeschrock "been omitted\n")); 1334fa9e4066Sahrens } 1335fa9e4066Sahrens } 1336fa9e4066Sahrens 1337990b4856Slling errout: 13382f8aaab3Seschrock nvlist_free(nvroot); 13390a48a24eStimh nvlist_free(fsprops); 13402f8aaab3Seschrock nvlist_free(props); 1341fa9e4066Sahrens return (ret); 1342990b4856Slling badusage: 13430a48a24eStimh nvlist_free(fsprops); 1344990b4856Slling nvlist_free(props); 1345990b4856Slling usage(B_FALSE); 1346990b4856Slling return (2); 1347fa9e4066Sahrens } 1348fa9e4066Sahrens 1349fa9e4066Sahrens /* 1350fa9e4066Sahrens * zpool destroy <pool> 1351fa9e4066Sahrens * 135204e56356SAndriy Gapon * -f Forcefully unmount any datasets 1353fa9e4066Sahrens * 1354fa9e4066Sahrens * Destroy the given pool. Automatically unmounts any datasets in the pool. 1355fa9e4066Sahrens */ 1356fa9e4066Sahrens int 1357fa9e4066Sahrens zpool_do_destroy(int argc, char **argv) 1358fa9e4066Sahrens { 135999653d4eSeschrock boolean_t force = B_FALSE; 1360fa9e4066Sahrens int c; 1361fa9e4066Sahrens char *pool; 1362fa9e4066Sahrens zpool_handle_t *zhp; 1363fa9e4066Sahrens int ret; 1364fa9e4066Sahrens 1365fa9e4066Sahrens /* check options */ 1366fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) { 1367fa9e4066Sahrens switch (c) { 1368fa9e4066Sahrens case 'f': 136999653d4eSeschrock force = B_TRUE; 1370fa9e4066Sahrens break; 1371fa9e4066Sahrens case '?': 1372fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1373fa9e4066Sahrens optopt); 137499653d4eSeschrock usage(B_FALSE); 1375fa9e4066Sahrens } 1376fa9e4066Sahrens } 1377fa9e4066Sahrens 1378fa9e4066Sahrens argc -= optind; 1379fa9e4066Sahrens argv += optind; 1380fa9e4066Sahrens 1381fa9e4066Sahrens /* check arguments */ 1382fa9e4066Sahrens if (argc < 1) { 1383fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool argument\n")); 138499653d4eSeschrock usage(B_FALSE); 1385fa9e4066Sahrens } 1386fa9e4066Sahrens if (argc > 1) { 1387fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 138899653d4eSeschrock usage(B_FALSE); 1389fa9e4066Sahrens } 1390fa9e4066Sahrens 1391fa9e4066Sahrens pool = argv[0]; 1392fa9e4066Sahrens 139399653d4eSeschrock if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 1394fa9e4066Sahrens /* 1395fa9e4066Sahrens * As a special case, check for use of '/' in the name, and 1396fa9e4066Sahrens * direct the user to use 'zfs destroy' instead. 1397fa9e4066Sahrens */ 1398fa9e4066Sahrens if (strchr(pool, '/') != NULL) 1399fa9e4066Sahrens (void) fprintf(stderr, gettext("use 'zfs destroy' to " 1400fa9e4066Sahrens "destroy a dataset\n")); 1401fa9e4066Sahrens return (1); 1402fa9e4066Sahrens } 1403fa9e4066Sahrens 1404f3861e1aSahl if (zpool_disable_datasets(zhp, force) != 0) { 1405fa9e4066Sahrens (void) fprintf(stderr, gettext("could not destroy '%s': " 1406fa9e4066Sahrens "could not unmount datasets\n"), zpool_get_name(zhp)); 1407fa9e4066Sahrens return (1); 1408fa9e4066Sahrens } 1409fa9e4066Sahrens 14104445fffbSMatthew Ahrens /* The history must be logged as part of the export */ 14114445fffbSMatthew Ahrens log_history = B_FALSE; 14124445fffbSMatthew Ahrens 14134445fffbSMatthew Ahrens ret = (zpool_destroy(zhp, history_str) != 0); 1414fa9e4066Sahrens 1415fa9e4066Sahrens zpool_close(zhp); 1416fa9e4066Sahrens 1417fa9e4066Sahrens return (ret); 1418fa9e4066Sahrens } 1419fa9e4066Sahrens 1420fa9e4066Sahrens /* 1421fa9e4066Sahrens * zpool export [-f] <pool> ... 1422fa9e4066Sahrens * 1423fa9e4066Sahrens * -f Forcefully unmount datasets 1424fa9e4066Sahrens * 1425b1b8ab34Slling * Export the given pools. By default, the command will attempt to cleanly 1426fa9e4066Sahrens * unmount any active datasets within the pool. If the '-f' flag is specified, 1427fa9e4066Sahrens * then the datasets will be forcefully unmounted. 1428fa9e4066Sahrens */ 1429fa9e4066Sahrens int 1430fa9e4066Sahrens zpool_do_export(int argc, char **argv) 1431fa9e4066Sahrens { 143299653d4eSeschrock boolean_t force = B_FALSE; 1433394ab0cbSGeorge Wilson boolean_t hardforce = B_FALSE; 1434fa9e4066Sahrens int c; 1435fa9e4066Sahrens zpool_handle_t *zhp; 1436fa9e4066Sahrens int ret; 1437fa9e4066Sahrens int i; 1438fa9e4066Sahrens 1439fa9e4066Sahrens /* check options */ 1440394ab0cbSGeorge Wilson while ((c = getopt(argc, argv, "fF")) != -1) { 1441fa9e4066Sahrens switch (c) { 1442fa9e4066Sahrens case 'f': 144399653d4eSeschrock force = B_TRUE; 1444fa9e4066Sahrens break; 1445394ab0cbSGeorge Wilson case 'F': 1446394ab0cbSGeorge Wilson hardforce = B_TRUE; 1447394ab0cbSGeorge Wilson break; 1448fa9e4066Sahrens case '?': 1449fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1450fa9e4066Sahrens optopt); 145199653d4eSeschrock usage(B_FALSE); 1452fa9e4066Sahrens } 1453fa9e4066Sahrens } 1454fa9e4066Sahrens 1455fa9e4066Sahrens argc -= optind; 1456fa9e4066Sahrens argv += optind; 1457fa9e4066Sahrens 1458fa9e4066Sahrens /* check arguments */ 1459fa9e4066Sahrens if (argc < 1) { 1460fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool argument\n")); 146199653d4eSeschrock usage(B_FALSE); 1462fa9e4066Sahrens } 1463fa9e4066Sahrens 1464fa9e4066Sahrens ret = 0; 1465fa9e4066Sahrens for (i = 0; i < argc; i++) { 146699653d4eSeschrock if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) { 1467fa9e4066Sahrens ret = 1; 1468fa9e4066Sahrens continue; 1469fa9e4066Sahrens } 1470fa9e4066Sahrens 1471f3861e1aSahl if (zpool_disable_datasets(zhp, force) != 0) { 1472fa9e4066Sahrens ret = 1; 1473fa9e4066Sahrens zpool_close(zhp); 1474fa9e4066Sahrens continue; 1475fa9e4066Sahrens } 1476fa9e4066Sahrens 14774445fffbSMatthew Ahrens /* The history must be logged as part of the export */ 14784445fffbSMatthew Ahrens log_history = B_FALSE; 14794445fffbSMatthew Ahrens 1480394ab0cbSGeorge Wilson if (hardforce) { 14814445fffbSMatthew Ahrens if (zpool_export_force(zhp, history_str) != 0) 1482394ab0cbSGeorge Wilson ret = 1; 14834445fffbSMatthew Ahrens } else if (zpool_export(zhp, force, history_str) != 0) { 1484fa9e4066Sahrens ret = 1; 1485394ab0cbSGeorge Wilson } 1486fa9e4066Sahrens 1487fa9e4066Sahrens zpool_close(zhp); 1488fa9e4066Sahrens } 1489fa9e4066Sahrens 1490fa9e4066Sahrens return (ret); 1491fa9e4066Sahrens } 1492fa9e4066Sahrens 1493fa9e4066Sahrens /* 1494fa9e4066Sahrens * Given a vdev configuration, determine the maximum width needed for the device 1495fa9e4066Sahrens * name column. 1496fa9e4066Sahrens */ 1497fa9e4066Sahrens static int 1498663207adSDon Brady max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max, 1499663207adSDon Brady int name_flags) 1500fa9e4066Sahrens { 1501663207adSDon Brady char *name; 1502fa9e4066Sahrens nvlist_t **child; 1503fa9e4066Sahrens uint_t c, children; 1504fa9e4066Sahrens int ret; 1505fa9e4066Sahrens 1506663207adSDon Brady name = zpool_vdev_name(g_zfs, zhp, nv, name_flags | VDEV_NAME_TYPE_ID); 1507fa9e4066Sahrens if (strlen(name) + depth > max) 1508fa9e4066Sahrens max = strlen(name) + depth; 1509fa9e4066Sahrens 1510afefbcddSeschrock free(name); 1511afefbcddSeschrock 151299653d4eSeschrock if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 151399653d4eSeschrock &child, &children) == 0) { 151499653d4eSeschrock for (c = 0; c < children; c++) 151599653d4eSeschrock if ((ret = max_width(zhp, child[c], depth + 2, 1516663207adSDon Brady max, name_flags)) > max) 151799653d4eSeschrock max = ret; 151899653d4eSeschrock } 151999653d4eSeschrock 1520fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1521fa94a07fSbrendan &child, &children) == 0) { 1522fa94a07fSbrendan for (c = 0; c < children; c++) 1523fa94a07fSbrendan if ((ret = max_width(zhp, child[c], depth + 2, 1524663207adSDon Brady max, name_flags)) > max) 1525fa94a07fSbrendan max = ret; 1526fa94a07fSbrendan } 1527fa94a07fSbrendan 1528fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 152999653d4eSeschrock &child, &children) == 0) { 153099653d4eSeschrock for (c = 0; c < children; c++) 153199653d4eSeschrock if ((ret = max_width(zhp, child[c], depth + 2, 1532663207adSDon Brady max, name_flags)) > max) 153399653d4eSeschrock max = ret; 153499653d4eSeschrock } 1535fa9e4066Sahrens 1536fa9e4066Sahrens return (max); 1537fa9e4066Sahrens } 1538fa9e4066Sahrens 1539e6ca193dSGeorge Wilson typedef struct spare_cbdata { 1540e6ca193dSGeorge Wilson uint64_t cb_guid; 1541e6ca193dSGeorge Wilson zpool_handle_t *cb_zhp; 1542e6ca193dSGeorge Wilson } spare_cbdata_t; 1543e6ca193dSGeorge Wilson 1544e6ca193dSGeorge Wilson static boolean_t 1545e6ca193dSGeorge Wilson find_vdev(nvlist_t *nv, uint64_t search) 1546e6ca193dSGeorge Wilson { 1547e6ca193dSGeorge Wilson uint64_t guid; 1548e6ca193dSGeorge Wilson nvlist_t **child; 1549e6ca193dSGeorge Wilson uint_t c, children; 1550e6ca193dSGeorge Wilson 1551e6ca193dSGeorge Wilson if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 1552e6ca193dSGeorge Wilson search == guid) 1553e6ca193dSGeorge Wilson return (B_TRUE); 1554e6ca193dSGeorge Wilson 1555e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1556e6ca193dSGeorge Wilson &child, &children) == 0) { 1557e6ca193dSGeorge Wilson for (c = 0; c < children; c++) 1558e6ca193dSGeorge Wilson if (find_vdev(child[c], search)) 1559e6ca193dSGeorge Wilson return (B_TRUE); 1560e6ca193dSGeorge Wilson } 1561e6ca193dSGeorge Wilson 1562e6ca193dSGeorge Wilson return (B_FALSE); 1563e6ca193dSGeorge Wilson } 1564e6ca193dSGeorge Wilson 1565e6ca193dSGeorge Wilson static int 1566e6ca193dSGeorge Wilson find_spare(zpool_handle_t *zhp, void *data) 1567e6ca193dSGeorge Wilson { 1568e6ca193dSGeorge Wilson spare_cbdata_t *cbp = data; 1569e6ca193dSGeorge Wilson nvlist_t *config, *nvroot; 1570e6ca193dSGeorge Wilson 1571e6ca193dSGeorge Wilson config = zpool_get_config(zhp, NULL); 1572e6ca193dSGeorge Wilson verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1573e6ca193dSGeorge Wilson &nvroot) == 0); 1574e6ca193dSGeorge Wilson 1575e6ca193dSGeorge Wilson if (find_vdev(nvroot, cbp->cb_guid)) { 1576e6ca193dSGeorge Wilson cbp->cb_zhp = zhp; 1577e6ca193dSGeorge Wilson return (1); 1578e6ca193dSGeorge Wilson } 1579e6ca193dSGeorge Wilson 1580e6ca193dSGeorge Wilson zpool_close(zhp); 1581e6ca193dSGeorge Wilson return (0); 1582e6ca193dSGeorge Wilson } 1583e6ca193dSGeorge Wilson 1584663207adSDon Brady typedef struct status_cbdata { 1585663207adSDon Brady int cb_count; 1586663207adSDon Brady int cb_name_flags; 1587663207adSDon Brady int cb_namewidth; 1588663207adSDon Brady boolean_t cb_allpools; 1589663207adSDon Brady boolean_t cb_verbose; 1590663207adSDon Brady boolean_t cb_explain; 1591663207adSDon Brady boolean_t cb_first; 1592663207adSDon Brady boolean_t cb_dedup_stats; 1593663207adSDon Brady boolean_t cb_print_status; 1594663207adSDon Brady } status_cbdata_t; 1595663207adSDon Brady 1596e6ca193dSGeorge Wilson /* 1597e6ca193dSGeorge Wilson * Print out configuration state as requested by status_callback. 1598e6ca193dSGeorge Wilson */ 1599663207adSDon Brady static void 1600663207adSDon Brady print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name, 1601663207adSDon Brady nvlist_t *nv, int depth, boolean_t isspare) 1602e6ca193dSGeorge Wilson { 160364dee23eSTony Hutter nvlist_t **child, *root; 1604e6ca193dSGeorge Wilson uint_t c, children; 16053f9d6ad7SLin Ling pool_scan_stat_t *ps = NULL; 1606e6ca193dSGeorge Wilson vdev_stat_t *vs; 16073f9d6ad7SLin Ling char rbuf[6], wbuf[6], cbuf[6]; 1608e6ca193dSGeorge Wilson char *vname; 1609e6ca193dSGeorge Wilson uint64_t notpresent; 1610663207adSDon Brady spare_cbdata_t spare_cb; 16116401734dSWill Andrews const char *state; 16125cabbc6bSPrashanth Sreenivasa char *type; 1613e6ca193dSGeorge Wilson 1614e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1615e6ca193dSGeorge Wilson &child, &children) != 0) 1616e6ca193dSGeorge Wilson children = 0; 1617e6ca193dSGeorge Wilson 16183f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 16193f9d6ad7SLin Ling (uint64_t **)&vs, &c) == 0); 16203f9d6ad7SLin Ling 16215cabbc6bSPrashanth Sreenivasa verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 16225cabbc6bSPrashanth Sreenivasa 16235cabbc6bSPrashanth Sreenivasa if (strcmp(type, VDEV_TYPE_INDIRECT) == 0) 16245cabbc6bSPrashanth Sreenivasa return; 16255cabbc6bSPrashanth Sreenivasa 1626e6ca193dSGeorge Wilson state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1627e6ca193dSGeorge Wilson if (isspare) { 1628e6ca193dSGeorge Wilson /* 1629e6ca193dSGeorge Wilson * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 1630e6ca193dSGeorge Wilson * online drives. 1631e6ca193dSGeorge Wilson */ 1632e6ca193dSGeorge Wilson if (vs->vs_aux == VDEV_AUX_SPARED) 1633e6ca193dSGeorge Wilson state = "INUSE"; 1634e6ca193dSGeorge Wilson else if (vs->vs_state == VDEV_STATE_HEALTHY) 1635e6ca193dSGeorge Wilson state = "AVAIL"; 1636e6ca193dSGeorge Wilson } 1637e6ca193dSGeorge Wilson 1638663207adSDon Brady (void) printf("\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth, 1639e6ca193dSGeorge Wilson name, state); 1640e6ca193dSGeorge Wilson 1641e6ca193dSGeorge Wilson if (!isspare) { 1642e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 1643e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 1644e6ca193dSGeorge Wilson zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 1645e6ca193dSGeorge Wilson (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 1646e6ca193dSGeorge Wilson } 1647e6ca193dSGeorge Wilson 1648e6ca193dSGeorge Wilson if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1649e6ca193dSGeorge Wilson ¬present) == 0) { 1650e6ca193dSGeorge Wilson char *path; 1651e6ca193dSGeorge Wilson verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 1652e6ca193dSGeorge Wilson (void) printf(" was %s", path); 1653e6ca193dSGeorge Wilson } else if (vs->vs_aux != 0) { 1654e6ca193dSGeorge Wilson (void) printf(" "); 1655e6ca193dSGeorge Wilson 1656e6ca193dSGeorge Wilson switch (vs->vs_aux) { 1657e6ca193dSGeorge Wilson case VDEV_AUX_OPEN_FAILED: 1658e6ca193dSGeorge Wilson (void) printf(gettext("cannot open")); 1659e6ca193dSGeorge Wilson break; 1660e6ca193dSGeorge Wilson 1661e6ca193dSGeorge Wilson case VDEV_AUX_BAD_GUID_SUM: 1662e6ca193dSGeorge Wilson (void) printf(gettext("missing device")); 1663e6ca193dSGeorge Wilson break; 1664e6ca193dSGeorge Wilson 1665e6ca193dSGeorge Wilson case VDEV_AUX_NO_REPLICAS: 1666e6ca193dSGeorge Wilson (void) printf(gettext("insufficient replicas")); 1667e6ca193dSGeorge Wilson break; 1668e6ca193dSGeorge Wilson 1669e6ca193dSGeorge Wilson case VDEV_AUX_VERSION_NEWER: 1670e6ca193dSGeorge Wilson (void) printf(gettext("newer version")); 1671e6ca193dSGeorge Wilson break; 1672e6ca193dSGeorge Wilson 1673ad135b5dSChristopher Siden case VDEV_AUX_UNSUP_FEAT: 1674ad135b5dSChristopher Siden (void) printf(gettext("unsupported feature(s)")); 1675ad135b5dSChristopher Siden break; 1676ad135b5dSChristopher Siden 1677e6ca193dSGeorge Wilson case VDEV_AUX_SPARED: 1678e6ca193dSGeorge Wilson verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 1679663207adSDon Brady &spare_cb.cb_guid) == 0); 1680663207adSDon Brady if (zpool_iter(g_zfs, find_spare, &spare_cb) == 1) { 1681663207adSDon Brady if (strcmp(zpool_get_name(spare_cb.cb_zhp), 1682e6ca193dSGeorge Wilson zpool_get_name(zhp)) == 0) 1683e6ca193dSGeorge Wilson (void) printf(gettext("currently in " 1684e6ca193dSGeorge Wilson "use")); 1685e6ca193dSGeorge Wilson else 1686e6ca193dSGeorge Wilson (void) printf(gettext("in use by " 1687e6ca193dSGeorge Wilson "pool '%s'"), 1688663207adSDon Brady zpool_get_name(spare_cb.cb_zhp)); 1689663207adSDon Brady zpool_close(spare_cb.cb_zhp); 1690e6ca193dSGeorge Wilson } else { 1691e6ca193dSGeorge Wilson (void) printf(gettext("currently in use")); 1692e6ca193dSGeorge Wilson } 1693e6ca193dSGeorge Wilson break; 1694e6ca193dSGeorge Wilson 1695e6ca193dSGeorge Wilson case VDEV_AUX_ERR_EXCEEDED: 1696e6ca193dSGeorge Wilson (void) printf(gettext("too many errors")); 1697e6ca193dSGeorge Wilson break; 1698e6ca193dSGeorge Wilson 1699e6ca193dSGeorge Wilson case VDEV_AUX_IO_FAILURE: 1700e6ca193dSGeorge Wilson (void) printf(gettext("experienced I/O failures")); 1701e6ca193dSGeorge Wilson break; 1702e6ca193dSGeorge Wilson 1703e6ca193dSGeorge Wilson case VDEV_AUX_BAD_LOG: 1704e6ca193dSGeorge Wilson (void) printf(gettext("bad intent log")); 1705e6ca193dSGeorge Wilson break; 1706e6ca193dSGeorge Wilson 1707069f55e2SEric Schrock case VDEV_AUX_EXTERNAL: 1708069f55e2SEric Schrock (void) printf(gettext("external device fault")); 1709069f55e2SEric Schrock break; 1710069f55e2SEric Schrock 17111195e687SMark J Musante case VDEV_AUX_SPLIT_POOL: 17121195e687SMark J Musante (void) printf(gettext("split into new pool")); 17131195e687SMark J Musante break; 17141195e687SMark J Musante 1715e0f1c0afSOlaf Faaland case VDEV_AUX_ACTIVE: 1716e0f1c0afSOlaf Faaland (void) printf(gettext("currently in use")); 1717e0f1c0afSOlaf Faaland break; 1718e0f1c0afSOlaf Faaland 17196f793812SPavel Zakharov case VDEV_AUX_CHILDREN_OFFLINE: 17206f793812SPavel Zakharov (void) printf(gettext("all children offline")); 17216f793812SPavel Zakharov break; 17226f793812SPavel Zakharov 1723e6ca193dSGeorge Wilson default: 1724e6ca193dSGeorge Wilson (void) printf(gettext("corrupted data")); 1725e6ca193dSGeorge Wilson break; 1726e6ca193dSGeorge Wilson } 17273f9d6ad7SLin Ling } 17283f9d6ad7SLin Ling 172964dee23eSTony Hutter /* The root vdev has the scrub/resilver stats */ 173064dee23eSTony Hutter root = fnvlist_lookup_nvlist(zpool_get_config(zhp, NULL), 173164dee23eSTony Hutter ZPOOL_CONFIG_VDEV_TREE); 173264dee23eSTony Hutter (void) nvlist_lookup_uint64_array(root, ZPOOL_CONFIG_SCAN_STATS, 17333f9d6ad7SLin Ling (uint64_t **)&ps, &c); 17343f9d6ad7SLin Ling 1735e4c795beSTom Caputi if (ps != NULL && ps->pss_state == DSS_SCANNING && children == 0) { 1736e4c795beSTom Caputi if (vs->vs_scan_processed != 0) { 1737e4c795beSTom Caputi (void) printf(gettext(" (%s)"), 1738e4c795beSTom Caputi (ps->pss_func == POOL_SCAN_RESILVER) ? 1739e4c795beSTom Caputi "resilvering" : "repairing"); 1740e4c795beSTom Caputi } else if (vs->vs_resilver_deferred) { 1741e4c795beSTom Caputi (void) printf(gettext(" (awaiting resilver)")); 1742e4c795beSTom Caputi } 1743e6ca193dSGeorge Wilson } 1744e6ca193dSGeorge Wilson 1745094e47e9SGeorge Wilson if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE || 1746094e47e9SGeorge Wilson vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED || 1747094e47e9SGeorge Wilson vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) && 1748094e47e9SGeorge Wilson !vs->vs_scan_removing) { 1749094e47e9SGeorge Wilson char zbuf[1024]; 1750094e47e9SGeorge Wilson char tbuf[256]; 1751094e47e9SGeorge Wilson struct tm zaction_ts; 1752094e47e9SGeorge Wilson 1753094e47e9SGeorge Wilson time_t t = vs->vs_initialize_action_time; 1754094e47e9SGeorge Wilson int initialize_pct = 100; 1755094e47e9SGeorge Wilson if (vs->vs_initialize_state != VDEV_INITIALIZE_COMPLETE) { 1756094e47e9SGeorge Wilson initialize_pct = (vs->vs_initialize_bytes_done * 100 / 1757094e47e9SGeorge Wilson (vs->vs_initialize_bytes_est + 1)); 1758094e47e9SGeorge Wilson } 1759094e47e9SGeorge Wilson 1760094e47e9SGeorge Wilson (void) localtime_r(&t, &zaction_ts); 1761094e47e9SGeorge Wilson (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts); 1762094e47e9SGeorge Wilson 1763094e47e9SGeorge Wilson switch (vs->vs_initialize_state) { 1764094e47e9SGeorge Wilson case VDEV_INITIALIZE_SUSPENDED: 1765094e47e9SGeorge Wilson (void) snprintf(zbuf, sizeof (zbuf), 1766094e47e9SGeorge Wilson ", suspended, started at %s", tbuf); 1767094e47e9SGeorge Wilson break; 1768094e47e9SGeorge Wilson case VDEV_INITIALIZE_ACTIVE: 1769094e47e9SGeorge Wilson (void) snprintf(zbuf, sizeof (zbuf), 1770094e47e9SGeorge Wilson ", started at %s", tbuf); 1771094e47e9SGeorge Wilson break; 1772094e47e9SGeorge Wilson case VDEV_INITIALIZE_COMPLETE: 1773094e47e9SGeorge Wilson (void) snprintf(zbuf, sizeof (zbuf), 1774094e47e9SGeorge Wilson ", completed at %s", tbuf); 1775094e47e9SGeorge Wilson break; 1776094e47e9SGeorge Wilson } 1777094e47e9SGeorge Wilson 1778094e47e9SGeorge Wilson (void) printf(gettext(" (%d%% initialized%s)"), 1779094e47e9SGeorge Wilson initialize_pct, zbuf); 1780094e47e9SGeorge Wilson } 1781094e47e9SGeorge Wilson 1782e6ca193dSGeorge Wilson (void) printf("\n"); 1783e6ca193dSGeorge Wilson 1784e6ca193dSGeorge Wilson for (c = 0; c < children; c++) { 178588ecc943SGeorge Wilson uint64_t islog = B_FALSE, ishole = B_FALSE; 1786e6ca193dSGeorge Wilson 178788ecc943SGeorge Wilson /* Don't print logs or holes here */ 1788e6ca193dSGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 178988ecc943SGeorge Wilson &islog); 179088ecc943SGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, 179188ecc943SGeorge Wilson &ishole); 179288ecc943SGeorge Wilson if (islog || ishole) 1793e6ca193dSGeorge Wilson continue; 1794663207adSDon Brady /* Only print normal classes here */ 1795663207adSDon Brady if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 1796663207adSDon Brady continue; 1797663207adSDon Brady 1798663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 1799663207adSDon Brady cb->cb_name_flags | VDEV_NAME_TYPE_ID); 180064dee23eSTony Hutter 1801663207adSDon Brady print_status_config(zhp, cb, vname, child[c], depth + 2, 1802663207adSDon Brady isspare); 1803e6ca193dSGeorge Wilson free(vname); 1804e6ca193dSGeorge Wilson } 1805e6ca193dSGeorge Wilson } 1806e6ca193dSGeorge Wilson 1807fa9e4066Sahrens /* 1808fa9e4066Sahrens * Print the configuration of an exported pool. Iterate over all vdevs in the 1809fa9e4066Sahrens * pool, printing out the name and status for each one. 1810fa9e4066Sahrens */ 1811663207adSDon Brady static void 1812663207adSDon Brady print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv, 1813663207adSDon Brady int depth) 1814fa9e4066Sahrens { 1815fa9e4066Sahrens nvlist_t **child; 1816fa9e4066Sahrens uint_t c, children; 1817fa9e4066Sahrens vdev_stat_t *vs; 1818afefbcddSeschrock char *type, *vname; 1819fa9e4066Sahrens 1820fa9e4066Sahrens verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 182188ecc943SGeorge Wilson if (strcmp(type, VDEV_TYPE_MISSING) == 0 || 182288ecc943SGeorge Wilson strcmp(type, VDEV_TYPE_HOLE) == 0) 1823fa9e4066Sahrens return; 1824fa9e4066Sahrens 18253f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 1826fa9e4066Sahrens (uint64_t **)&vs, &c) == 0); 1827fa9e4066Sahrens 1828663207adSDon Brady (void) printf("\t%*s%-*s", depth, "", cb->cb_namewidth - depth, name); 1829990b4856Slling (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); 1830fa9e4066Sahrens 1831fa9e4066Sahrens if (vs->vs_aux != 0) { 18323d7072f8Seschrock (void) printf(" "); 1833fa9e4066Sahrens 1834fa9e4066Sahrens switch (vs->vs_aux) { 1835fa9e4066Sahrens case VDEV_AUX_OPEN_FAILED: 1836fa9e4066Sahrens (void) printf(gettext("cannot open")); 1837fa9e4066Sahrens break; 1838fa9e4066Sahrens 1839fa9e4066Sahrens case VDEV_AUX_BAD_GUID_SUM: 1840fa9e4066Sahrens (void) printf(gettext("missing device")); 1841fa9e4066Sahrens break; 1842fa9e4066Sahrens 1843fa9e4066Sahrens case VDEV_AUX_NO_REPLICAS: 1844fa9e4066Sahrens (void) printf(gettext("insufficient replicas")); 1845fa9e4066Sahrens break; 1846fa9e4066Sahrens 1847eaca9bbdSeschrock case VDEV_AUX_VERSION_NEWER: 1848eaca9bbdSeschrock (void) printf(gettext("newer version")); 1849eaca9bbdSeschrock break; 1850eaca9bbdSeschrock 1851ad135b5dSChristopher Siden case VDEV_AUX_UNSUP_FEAT: 1852ad135b5dSChristopher Siden (void) printf(gettext("unsupported feature(s)")); 1853ad135b5dSChristopher Siden break; 1854ad135b5dSChristopher Siden 18553d7072f8Seschrock case VDEV_AUX_ERR_EXCEEDED: 18563d7072f8Seschrock (void) printf(gettext("too many errors")); 18573d7072f8Seschrock break; 18583d7072f8Seschrock 1859e0f1c0afSOlaf Faaland case VDEV_AUX_ACTIVE: 1860e0f1c0afSOlaf Faaland (void) printf(gettext("currently in use")); 1861e0f1c0afSOlaf Faaland break; 1862e0f1c0afSOlaf Faaland 18636f793812SPavel Zakharov case VDEV_AUX_CHILDREN_OFFLINE: 18646f793812SPavel Zakharov (void) printf(gettext("all children offline")); 18656f793812SPavel Zakharov break; 18666f793812SPavel Zakharov 1867fa9e4066Sahrens default: 1868fa9e4066Sahrens (void) printf(gettext("corrupted data")); 1869fa9e4066Sahrens break; 1870fa9e4066Sahrens } 1871fa9e4066Sahrens } 1872fa9e4066Sahrens (void) printf("\n"); 1873fa9e4066Sahrens 1874fa9e4066Sahrens if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1875fa9e4066Sahrens &child, &children) != 0) 1876fa9e4066Sahrens return; 1877fa9e4066Sahrens 1878afefbcddSeschrock for (c = 0; c < children; c++) { 18798654d025Sperrin uint64_t is_log = B_FALSE; 18808654d025Sperrin 18818654d025Sperrin (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 18828654d025Sperrin &is_log); 1883e6ca193dSGeorge Wilson if (is_log) 18848654d025Sperrin continue; 1885663207adSDon Brady if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 1886663207adSDon Brady continue; 18878654d025Sperrin 1888663207adSDon Brady vname = zpool_vdev_name(g_zfs, NULL, child[c], 1889663207adSDon Brady cb->cb_name_flags | VDEV_NAME_TYPE_ID); 1890663207adSDon Brady print_import_config(cb, vname, child[c], depth + 2); 1891afefbcddSeschrock free(vname); 1892afefbcddSeschrock } 189399653d4eSeschrock 1894fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1895fa94a07fSbrendan &child, &children) == 0) { 1896fa94a07fSbrendan (void) printf(gettext("\tcache\n")); 1897fa94a07fSbrendan for (c = 0; c < children; c++) { 1898663207adSDon Brady vname = zpool_vdev_name(g_zfs, NULL, child[c], 1899663207adSDon Brady cb->cb_name_flags); 1900fa94a07fSbrendan (void) printf("\t %s\n", vname); 1901fa94a07fSbrendan free(vname); 1902fa94a07fSbrendan } 1903fa94a07fSbrendan } 190499653d4eSeschrock 1905fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1906fa94a07fSbrendan &child, &children) == 0) { 1907fa94a07fSbrendan (void) printf(gettext("\tspares\n")); 1908fa94a07fSbrendan for (c = 0; c < children; c++) { 1909663207adSDon Brady vname = zpool_vdev_name(g_zfs, NULL, child[c], 1910663207adSDon Brady cb->cb_name_flags); 1911fa94a07fSbrendan (void) printf("\t %s\n", vname); 1912fa94a07fSbrendan free(vname); 1913fa94a07fSbrendan } 191499653d4eSeschrock } 1915fa9e4066Sahrens } 1916fa9e4066Sahrens 1917e6ca193dSGeorge Wilson /* 1918663207adSDon Brady * Print specialized class vdevs. 1919663207adSDon Brady * 1920663207adSDon Brady * These are recorded as top level vdevs in the main pool child array 1921663207adSDon Brady * but with "is_log" set to 1 or an "alloc_bias" string. We use either 1922663207adSDon Brady * print_status_config() or print_import_config() to print the top level 1923663207adSDon Brady * class vdevs then any of their children (eg mirrored slogs) are printed 1924663207adSDon Brady * recursively - which works because only the top level vdev is marked. 1925e6ca193dSGeorge Wilson */ 1926e6ca193dSGeorge Wilson static void 1927663207adSDon Brady print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv, 1928663207adSDon Brady const char *class) 1929e6ca193dSGeorge Wilson { 1930e6ca193dSGeorge Wilson uint_t c, children; 1931e6ca193dSGeorge Wilson nvlist_t **child; 1932663207adSDon Brady boolean_t printed = B_FALSE; 1933663207adSDon Brady 1934663207adSDon Brady assert(zhp != NULL || !cb->cb_verbose); 1935e6ca193dSGeorge Wilson 1936e6ca193dSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, 1937e6ca193dSGeorge Wilson &children) != 0) 1938e6ca193dSGeorge Wilson return; 1939e6ca193dSGeorge Wilson 1940e6ca193dSGeorge Wilson for (c = 0; c < children; c++) { 1941e6ca193dSGeorge Wilson uint64_t is_log = B_FALSE; 1942663207adSDon Brady char *bias = NULL; 1943663207adSDon Brady char *type = NULL; 1944e6ca193dSGeorge Wilson 1945e6ca193dSGeorge Wilson (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1946e6ca193dSGeorge Wilson &is_log); 1947663207adSDon Brady 1948663207adSDon Brady if (is_log) { 1949663207adSDon Brady bias = VDEV_ALLOC_CLASS_LOGS; 1950663207adSDon Brady } else { 1951663207adSDon Brady (void) nvlist_lookup_string(child[c], 1952663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &bias); 1953663207adSDon Brady (void) nvlist_lookup_string(child[c], 1954663207adSDon Brady ZPOOL_CONFIG_TYPE, &type); 1955663207adSDon Brady } 1956663207adSDon Brady 1957663207adSDon Brady if (bias == NULL || strcmp(bias, class) != 0) 1958e6ca193dSGeorge Wilson continue; 1959663207adSDon Brady if (!is_log && strcmp(type, VDEV_TYPE_INDIRECT) == 0) 1960663207adSDon Brady continue; 1961663207adSDon Brady 1962663207adSDon Brady if (!printed) { 1963663207adSDon Brady (void) printf("\t%s\t\n", gettext(class)); 1964663207adSDon Brady printed = B_TRUE; 1965663207adSDon Brady } 1966663207adSDon Brady 1967663207adSDon Brady char *name = zpool_vdev_name(g_zfs, zhp, child[c], 1968663207adSDon Brady cb->cb_name_flags | VDEV_NAME_TYPE_ID); 1969663207adSDon Brady if (cb->cb_print_status) 1970663207adSDon Brady print_status_config(zhp, cb, name, child[c], 2, 1971663207adSDon Brady B_FALSE); 1972e6ca193dSGeorge Wilson else 1973663207adSDon Brady print_import_config(cb, name, child[c], 2); 1974e6ca193dSGeorge Wilson free(name); 1975e6ca193dSGeorge Wilson } 1976e6ca193dSGeorge Wilson } 1977468c413aSTim Haley 1978fa9e4066Sahrens /* 1979fa9e4066Sahrens * Display the status for the given pool. 1980fa9e4066Sahrens */ 1981fa9e4066Sahrens static void 1982fa9e4066Sahrens show_import(nvlist_t *config) 1983fa9e4066Sahrens { 1984fa9e4066Sahrens uint64_t pool_state; 1985fa9e4066Sahrens vdev_stat_t *vs; 1986fa9e4066Sahrens char *name; 1987fa9e4066Sahrens uint64_t guid; 1988e0f1c0afSOlaf Faaland uint64_t hostid = 0; 1989fa9e4066Sahrens char *msgid; 1990e0f1c0afSOlaf Faaland char *hostname = "unknown"; 1991e0f1c0afSOlaf Faaland nvlist_t *nvroot, *nvinfo; 1992fa9e4066Sahrens int reason; 1993eb633035STom Caputi zpool_errata_t errata; 199446657f8dSmmusante const char *health; 1995fa9e4066Sahrens uint_t vsc; 19968704186eSDan McDonald char *comment; 1997663207adSDon Brady status_cbdata_t cb = { 0 }; 1998fa9e4066Sahrens 1999fa9e4066Sahrens verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 2000fa9e4066Sahrens &name) == 0); 2001fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 2002fa9e4066Sahrens &guid) == 0); 2003fa9e4066Sahrens verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 2004fa9e4066Sahrens &pool_state) == 0); 2005fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2006fa9e4066Sahrens &nvroot) == 0); 2007fa9e4066Sahrens 20083f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 2009fa9e4066Sahrens (uint64_t **)&vs, &vsc) == 0); 2010990b4856Slling health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 2011fa9e4066Sahrens 2012eb633035STom Caputi reason = zpool_import_status(config, &msgid, &errata); 2013fa9e4066Sahrens 20148704186eSDan McDonald (void) printf(gettext(" pool: %s\n"), name); 20158704186eSDan McDonald (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); 20168704186eSDan McDonald (void) printf(gettext(" state: %s"), health); 20174c58d714Sdarrenm if (pool_state == POOL_STATE_DESTROYED) 2018b1b8ab34Slling (void) printf(gettext(" (DESTROYED)")); 20194c58d714Sdarrenm (void) printf("\n"); 2020fa9e4066Sahrens 2021fa9e4066Sahrens switch (reason) { 2022fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_R: 2023fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_NR: 2024fa9e4066Sahrens case ZPOOL_STATUS_BAD_GUID_SUM: 20258704186eSDan McDonald (void) printf(gettext(" status: One or more devices are " 20268704186eSDan McDonald "missing from the system.\n")); 2027fa9e4066Sahrens break; 2028fa9e4066Sahrens 2029fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_R: 2030fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_NR: 20318704186eSDan McDonald (void) printf(gettext(" status: One or more devices contains " 2032fa9e4066Sahrens "corrupted data.\n")); 2033fa9e4066Sahrens break; 2034fa9e4066Sahrens 2035fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_DATA: 20368704186eSDan McDonald (void) printf( 20378704186eSDan McDonald gettext(" status: The pool data is corrupted.\n")); 2038fa9e4066Sahrens break; 2039fa9e4066Sahrens 2040441d80aaSlling case ZPOOL_STATUS_OFFLINE_DEV: 20418704186eSDan McDonald (void) printf(gettext(" status: One or more devices " 2042441d80aaSlling "are offlined.\n")); 2043441d80aaSlling break; 2044441d80aaSlling 2045ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_POOL: 20468704186eSDan McDonald (void) printf(gettext(" status: The pool metadata is " 2047ea8dc4b6Seschrock "corrupted.\n")); 2048ea8dc4b6Seschrock break; 2049ea8dc4b6Seschrock 2050eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_OLDER: 205157221772SChristopher Siden (void) printf(gettext(" status: The pool is formatted using a " 205257221772SChristopher Siden "legacy on-disk version.\n")); 2053eaca9bbdSeschrock break; 2054eaca9bbdSeschrock 2055eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 20568704186eSDan McDonald (void) printf(gettext(" status: The pool is formatted using an " 2057eaca9bbdSeschrock "incompatible version.\n")); 2058eaca9bbdSeschrock break; 2059b87f3af3Sperrin 206057221772SChristopher Siden case ZPOOL_STATUS_FEAT_DISABLED: 206157221772SChristopher Siden (void) printf(gettext(" status: Some supported features are " 206257221772SChristopher Siden "not enabled on the pool.\n")); 206357221772SChristopher Siden break; 206457221772SChristopher Siden 2065ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ: 2066ad135b5dSChristopher Siden (void) printf(gettext("status: The pool uses the following " 2067edc8ef7dSToomas Soome "feature(s) not supported on this system:\n")); 2068ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 2069ad135b5dSChristopher Siden break; 2070ad135b5dSChristopher Siden 2071ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 2072ad135b5dSChristopher Siden (void) printf(gettext("status: The pool can only be accessed " 2073ad135b5dSChristopher Siden "in read-only mode on this system. It\n\tcannot be " 2074ad135b5dSChristopher Siden "accessed in read-write mode because it uses the " 2075ad135b5dSChristopher Siden "following\n\tfeature(s) not supported on this system:\n")); 2076ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 2077ad135b5dSChristopher Siden break; 2078ad135b5dSChristopher Siden 2079e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_ACTIVE: 2080e0f1c0afSOlaf Faaland (void) printf(gettext(" status: The pool is currently " 2081e0f1c0afSOlaf Faaland "imported by another system.\n")); 2082e0f1c0afSOlaf Faaland break; 2083e0f1c0afSOlaf Faaland 2084e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_REQUIRED: 2085e0f1c0afSOlaf Faaland (void) printf(gettext(" status: The pool has the " 2086e0f1c0afSOlaf Faaland "multihost property on. It cannot\n\tbe safely imported " 2087e0f1c0afSOlaf Faaland "when the system hostid is not set.\n")); 2088e0f1c0afSOlaf Faaland break; 2089e0f1c0afSOlaf Faaland 209095173954Sek case ZPOOL_STATUS_HOSTID_MISMATCH: 20918704186eSDan McDonald (void) printf(gettext(" status: The pool was last accessed by " 209295173954Sek "another system.\n")); 209395173954Sek break; 2094b87f3af3Sperrin 20953d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_R: 20963d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_NR: 20978704186eSDan McDonald (void) printf(gettext(" status: One or more devices are " 20983d7072f8Seschrock "faulted.\n")); 20993d7072f8Seschrock break; 21003d7072f8Seschrock 2101b87f3af3Sperrin case ZPOOL_STATUS_BAD_LOG: 21028704186eSDan McDonald (void) printf(gettext(" status: An intent log record cannot be " 2103b87f3af3Sperrin "read.\n")); 2104b87f3af3Sperrin break; 2105b87f3af3Sperrin 21063f9d6ad7SLin Ling case ZPOOL_STATUS_RESILVERING: 21078704186eSDan McDonald (void) printf(gettext(" status: One or more devices were being " 21083f9d6ad7SLin Ling "resilvered.\n")); 21093f9d6ad7SLin Ling break; 21103f9d6ad7SLin Ling 2111eb633035STom Caputi case ZPOOL_STATUS_ERRATA: 2112eb633035STom Caputi (void) printf(gettext(" status: Errata #%d detected.\n"), 2113eb633035STom Caputi errata); 2114eb633035STom Caputi break; 2115eb633035STom Caputi 2116fa9e4066Sahrens default: 2117fa9e4066Sahrens /* 2118fa9e4066Sahrens * No other status can be seen when importing pools. 2119fa9e4066Sahrens */ 2120fa9e4066Sahrens assert(reason == ZPOOL_STATUS_OK); 2121fa9e4066Sahrens } 2122fa9e4066Sahrens 2123fa9e4066Sahrens /* 2124fa9e4066Sahrens * Print out an action according to the overall state of the pool. 2125fa9e4066Sahrens */ 212646657f8dSmmusante if (vs->vs_state == VDEV_STATE_HEALTHY) { 212757221772SChristopher Siden if (reason == ZPOOL_STATUS_VERSION_OLDER || 212857221772SChristopher Siden reason == ZPOOL_STATUS_FEAT_DISABLED) { 21298704186eSDan McDonald (void) printf(gettext(" action: The pool can be " 2130eaca9bbdSeschrock "imported using its name or numeric identifier, " 2131eaca9bbdSeschrock "though\n\tsome features will not be available " 2132eaca9bbdSeschrock "without an explicit 'zpool upgrade'.\n")); 213357221772SChristopher Siden } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) { 21348704186eSDan McDonald (void) printf(gettext(" action: The pool can be " 213595173954Sek "imported using its name or numeric " 213695173954Sek "identifier and\n\tthe '-f' flag.\n")); 2137eb633035STom Caputi } else if (reason == ZPOOL_STATUS_ERRATA) { 2138eb633035STom Caputi switch (errata) { 2139eb633035STom Caputi case ZPOOL_ERRATA_NONE: 2140eb633035STom Caputi break; 2141eb633035STom Caputi 2142eb633035STom Caputi case ZPOOL_ERRATA_ZOL_2094_SCRUB: 2143eb633035STom Caputi (void) printf(gettext(" action: The pool can " 2144eb633035STom Caputi "be imported using its name or numeric " 2145eb633035STom Caputi "identifier,\n\thowever there is a compat" 2146eb633035STom Caputi "ibility issue which should be corrected" 2147eb633035STom Caputi "\n\tby running 'zpool scrub'\n")); 2148eb633035STom Caputi break; 2149eb633035STom Caputi 2150eb633035STom Caputi case ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY: 2151eb633035STom Caputi (void) printf(gettext(" action: The pool can" 2152eb633035STom Caputi "not be imported with this version of ZFS " 2153eb633035STom Caputi "due to\n\tan active asynchronous destroy. " 2154eb633035STom Caputi "Revert to an earlier version\n\tand " 2155eb633035STom Caputi "allow the destroy to complete before " 2156eb633035STom Caputi "updating.\n")); 2157eb633035STom Caputi break; 2158eb633035STom Caputi 2159eb633035STom Caputi case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION: 2160eb633035STom Caputi (void) printf(gettext(" action: Existing " 2161eb633035STom Caputi "encrypted datasets contain an on-disk " 2162eb633035STom Caputi "incompatibility, which\n\tneeds to be " 2163eb633035STom Caputi "corrected. Backup these datasets to new " 2164eb633035STom Caputi "encrypted datasets\n\tand destroy the " 2165eb633035STom Caputi "old ones.\n")); 2166eb633035STom Caputi break; 2167eb633035STom Caputi case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION: 2168eb633035STom Caputi (void) printf(gettext(" action: Any existing " 2169eb633035STom Caputi "encrypted datasets contain an on-disk " 2170eb633035STom Caputi "incompatibility which\n\tmay cause " 2171eb633035STom Caputi "on-disk corruption with 'zfs recv' and " 2172eb633035STom Caputi "which needs to be\n\tcorrected. Enable " 2173eb633035STom Caputi "the bookmark_v2 feature and backup " 2174eb633035STom Caputi "these datasets to new encrypted " 2175eb633035STom Caputi "datasets and\n\tdestroy the old ones. " 2176eb633035STom Caputi "If this pool does not contain any " 2177eb633035STom Caputi "encrypted datasets, simply enable\n\t" 2178eb633035STom Caputi "the bookmark_v2 feature.\n")); 2179eb633035STom Caputi break; 2180eb633035STom Caputi default: 2181eb633035STom Caputi /* 2182eb633035STom Caputi * All errata must contain an action message. 2183eb633035STom Caputi */ 2184eb633035STom Caputi assert(0); 2185eb633035STom Caputi } 218657221772SChristopher Siden } else { 21878704186eSDan McDonald (void) printf(gettext(" action: The pool can be " 2188eaca9bbdSeschrock "imported using its name or numeric " 2189eaca9bbdSeschrock "identifier.\n")); 219057221772SChristopher Siden } 219146657f8dSmmusante } else if (vs->vs_state == VDEV_STATE_DEGRADED) { 21928704186eSDan McDonald (void) printf(gettext(" action: The pool can be imported " 2193fa9e4066Sahrens "despite missing or damaged devices. The\n\tfault " 2194eaca9bbdSeschrock "tolerance of the pool may be compromised if imported.\n")); 2195fa9e4066Sahrens } else { 2196eaca9bbdSeschrock switch (reason) { 2197eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 21988704186eSDan McDonald (void) printf(gettext(" action: The pool cannot be " 2199eaca9bbdSeschrock "imported. Access the pool on a system running " 2200eaca9bbdSeschrock "newer\n\tsoftware, or recreate the pool from " 2201eaca9bbdSeschrock "backup.\n")); 2202eaca9bbdSeschrock break; 2203ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ: 2204ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be " 2205ad135b5dSChristopher Siden "imported. Access the pool on a system that " 2206ad135b5dSChristopher Siden "supports\n\tthe required feature(s), or recreate " 2207ad135b5dSChristopher Siden "the pool from backup.\n")); 2208ad135b5dSChristopher Siden break; 2209ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 2210ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be " 2211ad135b5dSChristopher Siden "imported in read-write mode. Import the pool " 2212ad135b5dSChristopher Siden "with\n" 2213ad135b5dSChristopher Siden "\t\"-o readonly=on\", access the pool on a system " 2214ad135b5dSChristopher Siden "that supports the\n\trequired feature(s), or " 2215ad135b5dSChristopher Siden "recreate the pool from backup.\n")); 2216ad135b5dSChristopher Siden break; 2217eaca9bbdSeschrock case ZPOOL_STATUS_MISSING_DEV_R: 2218eaca9bbdSeschrock case ZPOOL_STATUS_MISSING_DEV_NR: 2219eaca9bbdSeschrock case ZPOOL_STATUS_BAD_GUID_SUM: 22208704186eSDan McDonald (void) printf(gettext(" action: The pool cannot be " 2221fa9e4066Sahrens "imported. Attach the missing\n\tdevices and try " 2222fa9e4066Sahrens "again.\n")); 2223eaca9bbdSeschrock break; 2224e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_ACTIVE: 2225e0f1c0afSOlaf Faaland VERIFY0(nvlist_lookup_nvlist(config, 2226e0f1c0afSOlaf Faaland ZPOOL_CONFIG_LOAD_INFO, &nvinfo)); 2227e0f1c0afSOlaf Faaland 2228e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME)) 2229e0f1c0afSOlaf Faaland hostname = fnvlist_lookup_string(nvinfo, 2230e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTNAME); 2231e0f1c0afSOlaf Faaland 2232e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID)) 2233e0f1c0afSOlaf Faaland hostid = fnvlist_lookup_uint64(nvinfo, 2234e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTID); 2235e0f1c0afSOlaf Faaland 2236e0f1c0afSOlaf Faaland (void) printf(gettext(" action: The pool must be " 2237e0f1c0afSOlaf Faaland "exported from %s (hostid=%lx)\n\tbefore it " 2238e0f1c0afSOlaf Faaland "can be safely imported.\n"), hostname, 2239e0f1c0afSOlaf Faaland (unsigned long) hostid); 2240e0f1c0afSOlaf Faaland break; 2241e0f1c0afSOlaf Faaland case ZPOOL_STATUS_HOSTID_REQUIRED: 2242e0f1c0afSOlaf Faaland (void) printf(gettext(" action: Check the SMF " 2243e0f1c0afSOlaf Faaland "svc:/system/hostid service.\n")); 2244e0f1c0afSOlaf Faaland break; 2245eaca9bbdSeschrock default: 22468704186eSDan McDonald (void) printf(gettext(" action: The pool cannot be " 2247fa9e4066Sahrens "imported due to damaged devices or data.\n")); 2248eaca9bbdSeschrock } 2249eaca9bbdSeschrock } 2250eaca9bbdSeschrock 22518704186eSDan McDonald /* Print the comment attached to the pool. */ 22528704186eSDan McDonald if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0) 22538704186eSDan McDonald (void) printf(gettext("comment: %s\n"), comment); 22548704186eSDan McDonald 225546657f8dSmmusante /* 225646657f8dSmmusante * If the state is "closed" or "can't open", and the aux state 225746657f8dSmmusante * is "corrupt data": 225846657f8dSmmusante */ 225946657f8dSmmusante if (((vs->vs_state == VDEV_STATE_CLOSED) || 226046657f8dSmmusante (vs->vs_state == VDEV_STATE_CANT_OPEN)) && 226146657f8dSmmusante (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) { 2262eaca9bbdSeschrock if (pool_state == POOL_STATE_DESTROYED) 2263eaca9bbdSeschrock (void) printf(gettext("\tThe pool was destroyed, " 2264eaca9bbdSeschrock "but can be imported using the '-Df' flags.\n")); 2265eaca9bbdSeschrock else if (pool_state != POOL_STATE_EXPORTED) 2266eaca9bbdSeschrock (void) printf(gettext("\tThe pool may be active on " 226718ce54dfSek "another system, but can be imported using\n\t" 2268eaca9bbdSeschrock "the '-f' flag.\n")); 2269fa9e4066Sahrens } 2270fa9e4066Sahrens 2271fa9e4066Sahrens if (msgid != NULL) 2272654b400cSJoshua M. Clulow (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 2273fa9e4066Sahrens msgid); 2274fa9e4066Sahrens 22758704186eSDan McDonald (void) printf(gettext(" config:\n\n")); 2276fa9e4066Sahrens 2277663207adSDon Brady cb.cb_namewidth = max_width(NULL, nvroot, 0, 0, 0); 2278663207adSDon Brady if (cb.cb_namewidth < 10) 2279663207adSDon Brady cb.cb_namewidth = 10; 22808654d025Sperrin 2281663207adSDon Brady print_import_config(&cb, name, nvroot, 0); 2282663207adSDon Brady 2283663207adSDon Brady print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_DEDUP); 2284663207adSDon Brady print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_SPECIAL); 2285663207adSDon Brady print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_CLASS_LOGS); 2286fa9e4066Sahrens 2287fa9e4066Sahrens if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 228846657f8dSmmusante (void) printf(gettext("\n\tAdditional devices are known to " 2289fa9e4066Sahrens "be part of this pool, though their\n\texact " 229046657f8dSmmusante "configuration cannot be determined.\n")); 2291fa9e4066Sahrens } 2292fa9e4066Sahrens } 2293fa9e4066Sahrens 2294e0f1c0afSOlaf Faaland static boolean_t 2295e0f1c0afSOlaf Faaland zfs_force_import_required(nvlist_t *config) 2296e0f1c0afSOlaf Faaland { 2297e0f1c0afSOlaf Faaland uint64_t state; 2298e0f1c0afSOlaf Faaland uint64_t hostid = 0; 2299e0f1c0afSOlaf Faaland nvlist_t *nvinfo; 2300e0f1c0afSOlaf Faaland 2301e0f1c0afSOlaf Faaland state = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE); 2302e0f1c0afSOlaf Faaland (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid); 2303e0f1c0afSOlaf Faaland 2304e0f1c0afSOlaf Faaland if (state != POOL_STATE_EXPORTED && hostid != get_system_hostid()) 2305e0f1c0afSOlaf Faaland return (B_TRUE); 2306e0f1c0afSOlaf Faaland 2307e0f1c0afSOlaf Faaland nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO); 2308e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) { 2309e0f1c0afSOlaf Faaland mmp_state_t mmp_state = fnvlist_lookup_uint64(nvinfo, 2310e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_STATE); 2311e0f1c0afSOlaf Faaland 2312e0f1c0afSOlaf Faaland if (mmp_state != MMP_STATE_INACTIVE) 2313e0f1c0afSOlaf Faaland return (B_TRUE); 2314e0f1c0afSOlaf Faaland } 2315e0f1c0afSOlaf Faaland 2316e0f1c0afSOlaf Faaland return (B_FALSE); 2317e0f1c0afSOlaf Faaland } 2318e0f1c0afSOlaf Faaland 2319fa9e4066Sahrens /* 2320fa9e4066Sahrens * Perform the import for the given configuration. This passes the heavy 2321990b4856Slling * lifting off to zpool_import_props(), and then mounts the datasets contained 2322990b4856Slling * within the pool. 2323fa9e4066Sahrens */ 2324fa9e4066Sahrens static int 2325fa9e4066Sahrens do_import(nvlist_t *config, const char *newname, const char *mntopts, 23264b964adaSGeorge Wilson nvlist_t *props, int flags) 2327fa9e4066Sahrens { 2328eb633035STom Caputi int ret = 0; 2329fa9e4066Sahrens zpool_handle_t *zhp; 2330fa9e4066Sahrens char *name; 2331eaca9bbdSeschrock uint64_t version; 2332fa9e4066Sahrens 2333e0f1c0afSOlaf Faaland name = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME); 2334e0f1c0afSOlaf Faaland version = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION); 2335fa9e4066Sahrens 2336ad135b5dSChristopher Siden if (!SPA_VERSION_IS_SUPPORTED(version)) { 2337eaca9bbdSeschrock (void) fprintf(stderr, gettext("cannot import '%s': pool " 2338ad135b5dSChristopher Siden "is formatted using an unsupported ZFS version\n"), name); 2339eaca9bbdSeschrock return (1); 2340e0f1c0afSOlaf Faaland } else if (zfs_force_import_required(config) && 23414b964adaSGeorge Wilson !(flags & ZFS_IMPORT_ANY_HOST)) { 2342e0f1c0afSOlaf Faaland mmp_state_t mmp_state = MMP_STATE_INACTIVE; 2343e0f1c0afSOlaf Faaland nvlist_t *nvinfo; 2344e0f1c0afSOlaf Faaland 2345e0f1c0afSOlaf Faaland nvinfo = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO); 2346e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_STATE)) 2347e0f1c0afSOlaf Faaland mmp_state = fnvlist_lookup_uint64(nvinfo, 2348e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_STATE); 2349e0f1c0afSOlaf Faaland 2350e0f1c0afSOlaf Faaland if (mmp_state == MMP_STATE_ACTIVE) { 2351e0f1c0afSOlaf Faaland char *hostname = "<unknown>"; 2352e0f1c0afSOlaf Faaland uint64_t hostid = 0; 2353e0f1c0afSOlaf Faaland 2354e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTNAME)) 2355e0f1c0afSOlaf Faaland hostname = fnvlist_lookup_string(nvinfo, 2356e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTNAME); 2357e0f1c0afSOlaf Faaland 2358e0f1c0afSOlaf Faaland if (nvlist_exists(nvinfo, ZPOOL_CONFIG_MMP_HOSTID)) 2359e0f1c0afSOlaf Faaland hostid = fnvlist_lookup_uint64(nvinfo, 2360e0f1c0afSOlaf Faaland ZPOOL_CONFIG_MMP_HOSTID); 2361e0f1c0afSOlaf Faaland 2362e0f1c0afSOlaf Faaland (void) fprintf(stderr, gettext("cannot import '%s': " 2363e0f1c0afSOlaf Faaland "pool is imported on %s (hostid: " 2364e0f1c0afSOlaf Faaland "0x%lx)\nExport the pool on the other system, " 2365e0f1c0afSOlaf Faaland "then run 'zpool import'.\n"), 2366e0f1c0afSOlaf Faaland name, hostname, (unsigned long) hostid); 2367e0f1c0afSOlaf Faaland } else if (mmp_state == MMP_STATE_NO_HOSTID) { 2368e0f1c0afSOlaf Faaland (void) fprintf(stderr, gettext("Cannot import '%s': " 2369e0f1c0afSOlaf Faaland "pool has the multihost property on and the\n" 2370e0f1c0afSOlaf Faaland "system's hostid is not set.\n"), name); 237195173954Sek } else { 2372e0f1c0afSOlaf Faaland char *hostname = "<unknown>"; 2373e0f1c0afSOlaf Faaland uint64_t timestamp = 0; 2374e0f1c0afSOlaf Faaland uint64_t hostid = 0; 2375e0f1c0afSOlaf Faaland 2376e0f1c0afSOlaf Faaland if (nvlist_exists(config, ZPOOL_CONFIG_HOSTNAME)) 2377e0f1c0afSOlaf Faaland hostname = fnvlist_lookup_string(config, 2378e0f1c0afSOlaf Faaland ZPOOL_CONFIG_HOSTNAME); 2379e0f1c0afSOlaf Faaland 2380e0f1c0afSOlaf Faaland if (nvlist_exists(config, ZPOOL_CONFIG_TIMESTAMP)) 2381e0f1c0afSOlaf Faaland timestamp = fnvlist_lookup_uint64(config, 2382e0f1c0afSOlaf Faaland ZPOOL_CONFIG_TIMESTAMP); 2383e0f1c0afSOlaf Faaland 2384e0f1c0afSOlaf Faaland if (nvlist_exists(config, ZPOOL_CONFIG_HOSTID)) 2385e0f1c0afSOlaf Faaland hostid = fnvlist_lookup_uint64(config, 2386e0f1c0afSOlaf Faaland ZPOOL_CONFIG_HOSTID); 2387e0f1c0afSOlaf Faaland 238895173954Sek (void) fprintf(stderr, gettext("cannot import '%s': " 2389e0f1c0afSOlaf Faaland "pool was previously in use from another system.\n" 2390e0f1c0afSOlaf Faaland "Last accessed by %s (hostid=%lx) at %s" 2391e0f1c0afSOlaf Faaland "The pool can be imported, use 'zpool import -f' " 2392e0f1c0afSOlaf Faaland "to import the pool.\n"), name, hostname, 2393e0f1c0afSOlaf Faaland (unsigned long)hostid, ctime((time_t *)×tamp)); 2394e0f1c0afSOlaf Faaland 239595173954Sek } 2396e0f1c0afSOlaf Faaland 2397e0f1c0afSOlaf Faaland return (1); 2398fa9e4066Sahrens } 2399fa9e4066Sahrens 24004b964adaSGeorge Wilson if (zpool_import_props(g_zfs, config, newname, props, flags) != 0) 2401fa9e4066Sahrens return (1); 2402fa9e4066Sahrens 2403fa9e4066Sahrens if (newname != NULL) 2404fa9e4066Sahrens name = (char *)newname; 2405fa9e4066Sahrens 24064f0f5e5bSVictor Latushkin if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL) 24074f0f5e5bSVictor Latushkin return (1); 2408fa9e4066Sahrens 2409eb633035STom Caputi /* 2410eb633035STom Caputi * Loading keys is best effort. We don't want to return immediately 2411eb633035STom Caputi * if it fails but we do want to give the error to the caller. 2412eb633035STom Caputi */ 2413eb633035STom Caputi if (flags & ZFS_IMPORT_LOAD_KEYS) { 2414eb633035STom Caputi ret = zfs_crypto_attempt_load_keys(g_zfs, name); 2415eb633035STom Caputi if (ret != 0) 2416eb633035STom Caputi ret = 1; 2417eb633035STom Caputi } 2418eb633035STom Caputi 2419379c004dSEric Schrock if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 2420f9af39baSGeorge Wilson !(flags & ZFS_IMPORT_ONLY) && 2421379c004dSEric Schrock zpool_enable_datasets(zhp, mntopts, 0) != 0) { 2422fa9e4066Sahrens zpool_close(zhp); 2423fa9e4066Sahrens return (1); 2424fa9e4066Sahrens } 2425fa9e4066Sahrens 2426fa9e4066Sahrens zpool_close(zhp); 2427eb633035STom Caputi return (ret); 2428fa9e4066Sahrens } 2429fa9e4066Sahrens 243086714001SSerapheim Dimitropoulos /* 243186714001SSerapheim Dimitropoulos * zpool checkpoint <pool> 243286714001SSerapheim Dimitropoulos * checkpoint --discard <pool> 243386714001SSerapheim Dimitropoulos * 243404e56356SAndriy Gapon * -d Discard the checkpoint from a checkpointed 243504e56356SAndriy Gapon * --discard pool. 243686714001SSerapheim Dimitropoulos * 243786714001SSerapheim Dimitropoulos * Checkpoints the specified pool, by taking a "snapshot" of its 243886714001SSerapheim Dimitropoulos * current state. A pool can only have one checkpoint at a time. 243986714001SSerapheim Dimitropoulos */ 244086714001SSerapheim Dimitropoulos int 244186714001SSerapheim Dimitropoulos zpool_do_checkpoint(int argc, char **argv) 244286714001SSerapheim Dimitropoulos { 244386714001SSerapheim Dimitropoulos boolean_t discard; 244486714001SSerapheim Dimitropoulos char *pool; 244586714001SSerapheim Dimitropoulos zpool_handle_t *zhp; 244686714001SSerapheim Dimitropoulos int c, err; 244786714001SSerapheim Dimitropoulos 244886714001SSerapheim Dimitropoulos struct option long_options[] = { 244986714001SSerapheim Dimitropoulos {"discard", no_argument, NULL, 'd'}, 245086714001SSerapheim Dimitropoulos {0, 0, 0, 0} 245186714001SSerapheim Dimitropoulos }; 245286714001SSerapheim Dimitropoulos 245386714001SSerapheim Dimitropoulos discard = B_FALSE; 245486714001SSerapheim Dimitropoulos while ((c = getopt_long(argc, argv, ":d", long_options, NULL)) != -1) { 245586714001SSerapheim Dimitropoulos switch (c) { 245686714001SSerapheim Dimitropoulos case 'd': 245786714001SSerapheim Dimitropoulos discard = B_TRUE; 245886714001SSerapheim Dimitropoulos break; 245986714001SSerapheim Dimitropoulos case '?': 246086714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("invalid option '%c'\n"), 246186714001SSerapheim Dimitropoulos optopt); 246286714001SSerapheim Dimitropoulos usage(B_FALSE); 246386714001SSerapheim Dimitropoulos } 246486714001SSerapheim Dimitropoulos } 246586714001SSerapheim Dimitropoulos 246686714001SSerapheim Dimitropoulos argc -= optind; 246786714001SSerapheim Dimitropoulos argv += optind; 246886714001SSerapheim Dimitropoulos 246986714001SSerapheim Dimitropoulos if (argc < 1) { 247086714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("missing pool argument\n")); 247186714001SSerapheim Dimitropoulos usage(B_FALSE); 247286714001SSerapheim Dimitropoulos } 247386714001SSerapheim Dimitropoulos 247486714001SSerapheim Dimitropoulos if (argc > 1) { 247586714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("too many arguments\n")); 247686714001SSerapheim Dimitropoulos usage(B_FALSE); 247786714001SSerapheim Dimitropoulos } 247886714001SSerapheim Dimitropoulos 247986714001SSerapheim Dimitropoulos pool = argv[0]; 248086714001SSerapheim Dimitropoulos 248186714001SSerapheim Dimitropoulos if ((zhp = zpool_open(g_zfs, pool)) == NULL) { 248286714001SSerapheim Dimitropoulos /* As a special case, check for use of '/' in the name */ 248386714001SSerapheim Dimitropoulos if (strchr(pool, '/') != NULL) 248486714001SSerapheim Dimitropoulos (void) fprintf(stderr, gettext("'zpool checkpoint' " 248586714001SSerapheim Dimitropoulos "doesn't work on datasets. To save the state " 248686714001SSerapheim Dimitropoulos "of a dataset from a specific point in time " 248786714001SSerapheim Dimitropoulos "please use 'zfs snapshot'\n")); 248886714001SSerapheim Dimitropoulos return (1); 248986714001SSerapheim Dimitropoulos } 249086714001SSerapheim Dimitropoulos 249186714001SSerapheim Dimitropoulos if (discard) 249286714001SSerapheim Dimitropoulos err = (zpool_discard_checkpoint(zhp) != 0); 249386714001SSerapheim Dimitropoulos else 249486714001SSerapheim Dimitropoulos err = (zpool_checkpoint(zhp) != 0); 249586714001SSerapheim Dimitropoulos 249686714001SSerapheim Dimitropoulos zpool_close(zhp); 249786714001SSerapheim Dimitropoulos 249886714001SSerapheim Dimitropoulos return (err); 249986714001SSerapheim Dimitropoulos } 250086714001SSerapheim Dimitropoulos 250186714001SSerapheim Dimitropoulos #define CHECKPOINT_OPT 1024 250286714001SSerapheim Dimitropoulos 2503fa9e4066Sahrens /* 25044c58d714Sdarrenm * zpool import [-d dir] [-D] 2505eb633035STom Caputi * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l] 25062f8aaab3Seschrock * [-d dir | -c cachefile] [-f] -a 2507eb633035STom Caputi * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l] 250804e56356SAndriy Gapon * [-d dir | -c cachefile] [-f] [-n] [-F] [-t] 250904e56356SAndriy Gapon * <pool | id> [newpool] 25102f8aaab3Seschrock * 251104e56356SAndriy Gapon * -c Read pool information from a cachefile instead of searching 25122f8aaab3Seschrock * devices. 2513fa9e4066Sahrens * 251404e56356SAndriy Gapon * -d Scan in a specific directory, other than /dev/dsk. More than 2515fa9e4066Sahrens * one directory can be specified using multiple '-d' options. 2516fa9e4066Sahrens * 251704e56356SAndriy Gapon * -D Scan for previously destroyed pools or import all or only 251804e56356SAndriy Gapon * specified destroyed pools. 25194c58d714Sdarrenm * 252004e56356SAndriy Gapon * -R Temporarily import the pool, with all mountpoints relative to 2521fa9e4066Sahrens * the given root. The pool will remain exported when the machine 2522fa9e4066Sahrens * is rebooted. 2523fa9e4066Sahrens * 252404e56356SAndriy Gapon * -V Import even in the presence of faulted vdevs. This is an 252504e56356SAndriy Gapon * intentionally undocumented option for testing purposes, and 252604e56356SAndriy Gapon * treats the pool configuration as complete, leaving any bad 25274f0f5e5bSVictor Latushkin * vdevs in the FAULTED state. In other words, it does verbatim 25284f0f5e5bSVictor Latushkin * import. 2529c5904d13Seschrock * 253004e56356SAndriy Gapon * -f Force import, even if it appears that the pool is active. 253104e56356SAndriy Gapon * 253204e56356SAndriy Gapon * -F Attempt rewind if necessary. 2533468c413aSTim Haley * 253404e56356SAndriy Gapon * -n See if rewind would work, but don't actually rewind. 2535468c413aSTim Haley * 253604e56356SAndriy Gapon * -N Import the pool but don't mount datasets. 2537468c413aSTim Haley * 253804e56356SAndriy Gapon * -t Use newpool as a temporary pool name instead of renaming 253904e56356SAndriy Gapon * the pool. 2540f9af39baSGeorge Wilson * 254104e56356SAndriy Gapon * -T Specify a starting txg to use for import. This option is 254204e56356SAndriy Gapon * intentionally undocumented option for testing purposes. 2543f9af39baSGeorge Wilson * 254404e56356SAndriy Gapon * -a Import all pools found. 2545fa9e4066Sahrens * 254604e56356SAndriy Gapon * -o Set property=value and/or temporary mount options (without '='). 2547eb633035STom Caputi * -l Load encryption keys while importing. 2548ecd6cf80Smarks * 254904e56356SAndriy Gapon * --rewind-to-checkpoint 255004e56356SAndriy Gapon * Import the pool and revert back to the checkpoint. 255186714001SSerapheim Dimitropoulos * 2552fa9e4066Sahrens * The import command scans for pools to import, and import pools based on pool 2553fa9e4066Sahrens * name and GUID. The pool can also be renamed as part of the import process. 2554fa9e4066Sahrens */ 2555fa9e4066Sahrens int 2556fa9e4066Sahrens zpool_do_import(int argc, char **argv) 2557fa9e4066Sahrens { 2558fa9e4066Sahrens char **searchdirs = NULL; 2559fa9e4066Sahrens int nsearch = 0; 2560fa9e4066Sahrens int c; 2561d41c4376SMark J Musante int err = 0; 25622f8aaab3Seschrock nvlist_t *pools = NULL; 256399653d4eSeschrock boolean_t do_all = B_FALSE; 256499653d4eSeschrock boolean_t do_destroyed = B_FALSE; 2565fa9e4066Sahrens char *mntopts = NULL; 2566fa9e4066Sahrens nvpair_t *elem; 2567fa9e4066Sahrens nvlist_t *config; 256824e697d4Sck uint64_t searchguid = 0; 256924e697d4Sck char *searchname = NULL; 2570990b4856Slling char *propval; 2571fa9e4066Sahrens nvlist_t *found_config; 2572468c413aSTim Haley nvlist_t *policy = NULL; 2573ecd6cf80Smarks nvlist_t *props = NULL; 257499653d4eSeschrock boolean_t first; 25754b964adaSGeorge Wilson int flags = ZFS_IMPORT_NORMAL; 2576468c413aSTim Haley uint32_t rewind_policy = ZPOOL_NO_REWIND; 2577468c413aSTim Haley boolean_t dryrun = B_FALSE; 2578468c413aSTim Haley boolean_t do_rewind = B_FALSE; 2579468c413aSTim Haley boolean_t xtreme_rewind = B_FALSE; 2580f9af39baSGeorge Wilson uint64_t pool_state, txg = -1ULL; 25812f8aaab3Seschrock char *cachefile = NULL; 2582d41c4376SMark J Musante importargs_t idata = { 0 }; 2583f9af39baSGeorge Wilson char *endptr; 2584fa9e4066Sahrens 258586714001SSerapheim Dimitropoulos 258686714001SSerapheim Dimitropoulos struct option long_options[] = { 258786714001SSerapheim Dimitropoulos {"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT}, 258886714001SSerapheim Dimitropoulos {0, 0, 0, 0} 258986714001SSerapheim Dimitropoulos }; 259086714001SSerapheim Dimitropoulos 2591fa9e4066Sahrens /* check options */ 2592eb633035STom Caputi while ((c = getopt_long(argc, argv, ":aCc:d:DEfFlmnNo:rR:tT:VX", 259386714001SSerapheim Dimitropoulos long_options, NULL)) != -1) { 2594fa9e4066Sahrens switch (c) { 2595fa9e4066Sahrens case 'a': 259699653d4eSeschrock do_all = B_TRUE; 2597fa9e4066Sahrens break; 25982f8aaab3Seschrock case 'c': 25992f8aaab3Seschrock cachefile = optarg; 26002f8aaab3Seschrock break; 2601fa9e4066Sahrens case 'd': 2602fa9e4066Sahrens if (searchdirs == NULL) { 2603fa9e4066Sahrens searchdirs = safe_malloc(sizeof (char *)); 2604fa9e4066Sahrens } else { 2605fa9e4066Sahrens char **tmp = safe_malloc((nsearch + 1) * 2606fa9e4066Sahrens sizeof (char *)); 2607fa9e4066Sahrens bcopy(searchdirs, tmp, nsearch * 2608fa9e4066Sahrens sizeof (char *)); 2609fa9e4066Sahrens free(searchdirs); 2610fa9e4066Sahrens searchdirs = tmp; 2611fa9e4066Sahrens } 2612fa9e4066Sahrens searchdirs[nsearch++] = optarg; 2613fa9e4066Sahrens break; 26144c58d714Sdarrenm case 'D': 261599653d4eSeschrock do_destroyed = B_TRUE; 26164c58d714Sdarrenm break; 2617fa9e4066Sahrens case 'f': 26184b964adaSGeorge Wilson flags |= ZFS_IMPORT_ANY_HOST; 2619fa9e4066Sahrens break; 2620c5904d13Seschrock case 'F': 2621468c413aSTim Haley do_rewind = B_TRUE; 2622468c413aSTim Haley break; 2623eb633035STom Caputi case 'l': 2624eb633035STom Caputi flags |= ZFS_IMPORT_LOAD_KEYS; 2625eb633035STom Caputi break; 26264b964adaSGeorge Wilson case 'm': 26274b964adaSGeorge Wilson flags |= ZFS_IMPORT_MISSING_LOG; 26284b964adaSGeorge Wilson break; 2629468c413aSTim Haley case 'n': 2630468c413aSTim Haley dryrun = B_TRUE; 2631c5904d13Seschrock break; 2632f9af39baSGeorge Wilson case 'N': 2633f9af39baSGeorge Wilson flags |= ZFS_IMPORT_ONLY; 2634f9af39baSGeorge Wilson break; 2635fa9e4066Sahrens case 'o': 2636990b4856Slling if ((propval = strchr(optarg, '=')) != NULL) { 2637990b4856Slling *propval = '\0'; 2638990b4856Slling propval++; 26390a48a24eStimh if (add_prop_list(optarg, propval, 26400a48a24eStimh &props, B_TRUE)) 2641990b4856Slling goto error; 2642990b4856Slling } else { 2643990b4856Slling mntopts = optarg; 2644990b4856Slling } 2645fa9e4066Sahrens break; 2646fa9e4066Sahrens case 'R': 2647990b4856Slling if (add_prop_list(zpool_prop_to_name( 26480a48a24eStimh ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 2649990b4856Slling goto error; 265004e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name( 265104e56356SAndriy Gapon ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 265204e56356SAndriy Gapon goto error; 265304e56356SAndriy Gapon break; 265404e56356SAndriy Gapon case 't': 265504e56356SAndriy Gapon flags |= ZFS_IMPORT_TEMP_NAME; 265604e56356SAndriy Gapon if (add_prop_list_default(zpool_prop_to_name( 26570a48a24eStimh ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 2658990b4856Slling goto error; 2659fa9e4066Sahrens break; 2660f9af39baSGeorge Wilson case 'T': 2661f9af39baSGeorge Wilson errno = 0; 2662e42d2059SMatthew Ahrens txg = strtoull(optarg, &endptr, 0); 2663f9af39baSGeorge Wilson if (errno != 0 || *endptr != '\0') { 2664f9af39baSGeorge Wilson (void) fprintf(stderr, 2665f9af39baSGeorge Wilson gettext("invalid txg value\n")); 2666f9af39baSGeorge Wilson usage(B_FALSE); 2667f9af39baSGeorge Wilson } 2668f9af39baSGeorge Wilson rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND; 2669f9af39baSGeorge Wilson break; 2670468c413aSTim Haley case 'V': 26714b964adaSGeorge Wilson flags |= ZFS_IMPORT_VERBATIM; 2672468c413aSTim Haley break; 2673468c413aSTim Haley case 'X': 2674468c413aSTim Haley xtreme_rewind = B_TRUE; 2675468c413aSTim Haley break; 267686714001SSerapheim Dimitropoulos case CHECKPOINT_OPT: 267786714001SSerapheim Dimitropoulos flags |= ZFS_IMPORT_CHECKPOINT; 267886714001SSerapheim Dimitropoulos break; 2679fa9e4066Sahrens case ':': 2680fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 2681fa9e4066Sahrens "'%c' option\n"), optopt); 268299653d4eSeschrock usage(B_FALSE); 2683fa9e4066Sahrens break; 2684fa9e4066Sahrens case '?': 2685fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2686fa9e4066Sahrens optopt); 268799653d4eSeschrock usage(B_FALSE); 2688fa9e4066Sahrens } 2689fa9e4066Sahrens } 2690fa9e4066Sahrens 2691fa9e4066Sahrens argc -= optind; 2692fa9e4066Sahrens argv += optind; 2693fa9e4066Sahrens 26942f8aaab3Seschrock if (cachefile && nsearch != 0) { 26952f8aaab3Seschrock (void) fprintf(stderr, gettext("-c is incompatible with -d\n")); 26962f8aaab3Seschrock usage(B_FALSE); 26972f8aaab3Seschrock } 26982f8aaab3Seschrock 2699eb633035STom Caputi if ((flags & ZFS_IMPORT_LOAD_KEYS) && (flags & ZFS_IMPORT_ONLY)) { 2700eb633035STom Caputi (void) fprintf(stderr, gettext("-l is incompatible with -N\n")); 2701eb633035STom Caputi usage(B_FALSE); 2702eb633035STom Caputi } 2703eb633035STom Caputi 2704eb633035STom Caputi if ((flags & ZFS_IMPORT_LOAD_KEYS) && !do_all && argc == 0) { 2705eb633035STom Caputi (void) fprintf(stderr, gettext("-l is only meaningful during " 2706eb633035STom Caputi "an import\n")); 2707eb633035STom Caputi usage(B_FALSE); 2708eb633035STom Caputi } 2709eb633035STom Caputi 2710468c413aSTim Haley if ((dryrun || xtreme_rewind) && !do_rewind) { 2711468c413aSTim Haley (void) fprintf(stderr, 2712468c413aSTim Haley gettext("-n or -X only meaningful with -F\n")); 2713468c413aSTim Haley usage(B_FALSE); 2714468c413aSTim Haley } 2715468c413aSTim Haley if (dryrun) 2716468c413aSTim Haley rewind_policy = ZPOOL_TRY_REWIND; 2717468c413aSTim Haley else if (do_rewind) 2718468c413aSTim Haley rewind_policy = ZPOOL_DO_REWIND; 2719468c413aSTim Haley if (xtreme_rewind) 2720468c413aSTim Haley rewind_policy |= ZPOOL_EXTREME_REWIND; 2721468c413aSTim Haley 2722468c413aSTim Haley /* In the future, we can capture further policy and include it here */ 2723468c413aSTim Haley if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 27245dafeea3SPavel Zakharov nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, txg) != 0 || 27255dafeea3SPavel Zakharov nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, 27265dafeea3SPavel Zakharov rewind_policy) != 0) 2727468c413aSTim Haley goto error; 2728468c413aSTim Haley 2729fa9e4066Sahrens if (searchdirs == NULL) { 2730fa9e4066Sahrens searchdirs = safe_malloc(sizeof (char *)); 27316401734dSWill Andrews searchdirs[0] = ZFS_DISK_ROOT; 2732fa9e4066Sahrens nsearch = 1; 2733fa9e4066Sahrens } 2734fa9e4066Sahrens 2735fa9e4066Sahrens /* check argument count */ 2736fa9e4066Sahrens if (do_all) { 2737fa9e4066Sahrens if (argc != 0) { 2738fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 273999653d4eSeschrock usage(B_FALSE); 2740fa9e4066Sahrens } 2741fa9e4066Sahrens } else { 2742fa9e4066Sahrens if (argc > 2) { 2743fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 274499653d4eSeschrock usage(B_FALSE); 2745fa9e4066Sahrens } 2746fa9e4066Sahrens 2747fa9e4066Sahrens /* 2748fa9e4066Sahrens * Check for the SYS_CONFIG privilege. We do this explicitly 2749fa9e4066Sahrens * here because otherwise any attempt to discover pools will 2750fa9e4066Sahrens * silently fail. 2751fa9e4066Sahrens */ 2752fa9e4066Sahrens if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 2753fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot " 2754fa9e4066Sahrens "discover pools: permission denied\n")); 275599653d4eSeschrock free(searchdirs); 2756468c413aSTim Haley nvlist_free(policy); 2757fa9e4066Sahrens return (1); 2758fa9e4066Sahrens } 2759fa9e4066Sahrens } 2760fa9e4066Sahrens 2761fa9e4066Sahrens /* 2762fa9e4066Sahrens * Depending on the arguments given, we do one of the following: 2763fa9e4066Sahrens * 2764fa9e4066Sahrens * <none> Iterate through all pools and display information about 2765fa9e4066Sahrens * each one. 2766fa9e4066Sahrens * 2767fa9e4066Sahrens * -a Iterate through all pools and try to import each one. 2768fa9e4066Sahrens * 2769fa9e4066Sahrens * <id> Find the pool that corresponds to the given GUID/pool 2770fa9e4066Sahrens * name and import that one. 27714c58d714Sdarrenm * 27724c58d714Sdarrenm * -D Above options applies only to destroyed pools. 2773fa9e4066Sahrens */ 2774fa9e4066Sahrens if (argc != 0) { 2775fa9e4066Sahrens char *endptr; 2776fa9e4066Sahrens 2777fa9e4066Sahrens errno = 0; 2778fa9e4066Sahrens searchguid = strtoull(argv[0], &endptr, 10); 27799edf9ebdSPrasad Joshi if (errno != 0 || *endptr != '\0') { 2780fa9e4066Sahrens searchname = argv[0]; 27819edf9ebdSPrasad Joshi searchguid = 0; 27829edf9ebdSPrasad Joshi } 2783fa9e4066Sahrens found_config = NULL; 2784fa9e4066Sahrens 278524e697d4Sck /* 2786d41c4376SMark J Musante * User specified a name or guid. Ensure it's unique. 278724e697d4Sck */ 2788d41c4376SMark J Musante idata.unique = B_TRUE; 278924e697d4Sck } 279024e697d4Sck 2791d41c4376SMark J Musante 2792d41c4376SMark J Musante idata.path = searchdirs; 2793d41c4376SMark J Musante idata.paths = nsearch; 2794d41c4376SMark J Musante idata.poolname = searchname; 2795d41c4376SMark J Musante idata.guid = searchguid; 2796d41c4376SMark J Musante idata.cachefile = cachefile; 27976f793812SPavel Zakharov idata.policy = policy; 2798d41c4376SMark J Musante 2799d41c4376SMark J Musante pools = zpool_search_import(g_zfs, &idata); 2800d41c4376SMark J Musante 2801d41c4376SMark J Musante if (pools != NULL && idata.exists && 2802d41c4376SMark J Musante (argc == 1 || strcmp(argv[0], argv[1]) == 0)) { 2803d41c4376SMark J Musante (void) fprintf(stderr, gettext("cannot import '%s': " 2804d41c4376SMark J Musante "a pool with that name already exists\n"), 2805d41c4376SMark J Musante argv[0]); 280604e56356SAndriy Gapon (void) fprintf(stderr, gettext("use the form 'zpool import " 280704e56356SAndriy Gapon "[-t] <pool | id> <newpool>' to give it a new temporary " 280804e56356SAndriy Gapon "or permanent name\n")); 2809d41c4376SMark J Musante err = 1; 2810d41c4376SMark J Musante } else if (pools == NULL && idata.exists) { 2811d41c4376SMark J Musante (void) fprintf(stderr, gettext("cannot import '%s': " 2812d41c4376SMark J Musante "a pool with that name is already created/imported,\n"), 2813d41c4376SMark J Musante argv[0]); 2814d41c4376SMark J Musante (void) fprintf(stderr, gettext("and no additional pools " 2815d41c4376SMark J Musante "with that name were found\n")); 2816d41c4376SMark J Musante err = 1; 2817d41c4376SMark J Musante } else if (pools == NULL) { 281824e697d4Sck if (argc != 0) { 281924e697d4Sck (void) fprintf(stderr, gettext("cannot import '%s': " 282024e697d4Sck "no such pool available\n"), argv[0]); 282124e697d4Sck } 2822d41c4376SMark J Musante err = 1; 2823d41c4376SMark J Musante } 2824d41c4376SMark J Musante 2825d41c4376SMark J Musante if (err == 1) { 282624e697d4Sck free(searchdirs); 2827468c413aSTim Haley nvlist_free(policy); 282824e697d4Sck return (1); 282924e697d4Sck } 283024e697d4Sck 283124e697d4Sck /* 283224e697d4Sck * At this point we have a list of import candidate configs. Even if 283324e697d4Sck * we were searching by pool name or guid, we still need to 283424e697d4Sck * post-process the list to deal with pool state and possible 283524e697d4Sck * duplicate names. 283624e697d4Sck */ 2837fa9e4066Sahrens err = 0; 2838fa9e4066Sahrens elem = NULL; 283999653d4eSeschrock first = B_TRUE; 2840fa9e4066Sahrens while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 2841fa9e4066Sahrens 2842fa9e4066Sahrens verify(nvpair_value_nvlist(elem, &config) == 0); 2843fa9e4066Sahrens 28444c58d714Sdarrenm verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 28454c58d714Sdarrenm &pool_state) == 0); 28464c58d714Sdarrenm if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) 28474c58d714Sdarrenm continue; 28484c58d714Sdarrenm if (do_destroyed && pool_state != POOL_STATE_DESTROYED) 28494c58d714Sdarrenm continue; 28504c58d714Sdarrenm 28515dafeea3SPavel Zakharov verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY, 2852468c413aSTim Haley policy) == 0); 2853468c413aSTim Haley 2854fa9e4066Sahrens if (argc == 0) { 2855fa9e4066Sahrens if (first) 285699653d4eSeschrock first = B_FALSE; 28573bb79becSeschrock else if (!do_all) 2858fa9e4066Sahrens (void) printf("\n"); 2859fa9e4066Sahrens 2860468c413aSTim Haley if (do_all) { 2861fa9e4066Sahrens err |= do_import(config, NULL, mntopts, 28624b964adaSGeorge Wilson props, flags); 2863468c413aSTim Haley } else { 2864fa9e4066Sahrens show_import(config); 2865468c413aSTim Haley } 2866fa9e4066Sahrens } else if (searchname != NULL) { 2867fa9e4066Sahrens char *name; 2868fa9e4066Sahrens 2869fa9e4066Sahrens /* 2870fa9e4066Sahrens * We are searching for a pool based on name. 2871fa9e4066Sahrens */ 2872fa9e4066Sahrens verify(nvlist_lookup_string(config, 2873fa9e4066Sahrens ZPOOL_CONFIG_POOL_NAME, &name) == 0); 2874fa9e4066Sahrens 2875fa9e4066Sahrens if (strcmp(name, searchname) == 0) { 2876fa9e4066Sahrens if (found_config != NULL) { 2877fa9e4066Sahrens (void) fprintf(stderr, gettext( 2878fa9e4066Sahrens "cannot import '%s': more than " 2879fa9e4066Sahrens "one matching pool\n"), searchname); 2880fa9e4066Sahrens (void) fprintf(stderr, gettext( 2881fa9e4066Sahrens "import by numeric ID instead\n")); 288299653d4eSeschrock err = B_TRUE; 2883fa9e4066Sahrens } 2884fa9e4066Sahrens found_config = config; 2885fa9e4066Sahrens } 2886fa9e4066Sahrens } else { 2887fa9e4066Sahrens uint64_t guid; 2888fa9e4066Sahrens 2889fa9e4066Sahrens /* 2890fa9e4066Sahrens * Search for a pool by guid. 2891fa9e4066Sahrens */ 2892fa9e4066Sahrens verify(nvlist_lookup_uint64(config, 2893fa9e4066Sahrens ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 2894fa9e4066Sahrens 2895fa9e4066Sahrens if (guid == searchguid) 2896fa9e4066Sahrens found_config = config; 2897fa9e4066Sahrens } 2898fa9e4066Sahrens } 2899fa9e4066Sahrens 2900fa9e4066Sahrens /* 2901fa9e4066Sahrens * If we were searching for a specific pool, verify that we found a 2902fa9e4066Sahrens * pool, and then do the import. 2903fa9e4066Sahrens */ 2904fa9e4066Sahrens if (argc != 0 && err == 0) { 2905fa9e4066Sahrens if (found_config == NULL) { 2906fa9e4066Sahrens (void) fprintf(stderr, gettext("cannot import '%s': " 2907fa9e4066Sahrens "no such pool available\n"), argv[0]); 290899653d4eSeschrock err = B_TRUE; 2909fa9e4066Sahrens } else { 2910fa9e4066Sahrens err |= do_import(found_config, argc == 1 ? NULL : 29114b964adaSGeorge Wilson argv[1], mntopts, props, flags); 2912fa9e4066Sahrens } 2913fa9e4066Sahrens } 2914fa9e4066Sahrens 2915fa9e4066Sahrens /* 2916fa9e4066Sahrens * If we were just looking for pools, report an error if none were 2917fa9e4066Sahrens * found. 2918fa9e4066Sahrens */ 2919fa9e4066Sahrens if (argc == 0 && first) 2920fa9e4066Sahrens (void) fprintf(stderr, 2921fa9e4066Sahrens gettext("no pools available to import\n")); 2922fa9e4066Sahrens 2923ecd6cf80Smarks error: 29242f8aaab3Seschrock nvlist_free(props); 2925fa9e4066Sahrens nvlist_free(pools); 2926468c413aSTim Haley nvlist_free(policy); 292799653d4eSeschrock free(searchdirs); 2928fa9e4066Sahrens 2929fa9e4066Sahrens return (err ? 1 : 0); 2930fa9e4066Sahrens } 2931fa9e4066Sahrens 29329c2acf00SAlek Pinchuk /* 29339c2acf00SAlek Pinchuk * zpool sync [-f] [pool] ... 29349c2acf00SAlek Pinchuk * 29359c2acf00SAlek Pinchuk * -f (undocumented) force uberblock (and config including zpool cache file) 29369c2acf00SAlek Pinchuk * update. 29379c2acf00SAlek Pinchuk * 29389c2acf00SAlek Pinchuk * Sync the specified pool(s). 29399c2acf00SAlek Pinchuk * Without arguments "zpool sync" will sync all pools. 29409c2acf00SAlek Pinchuk * This command initiates TXG sync(s) and will return after the TXG(s) commit. 29419c2acf00SAlek Pinchuk * 29429c2acf00SAlek Pinchuk */ 29439c2acf00SAlek Pinchuk static int 29449c2acf00SAlek Pinchuk zpool_do_sync(int argc, char **argv) 29459c2acf00SAlek Pinchuk { 29469c2acf00SAlek Pinchuk int ret; 29479c2acf00SAlek Pinchuk boolean_t force = B_FALSE; 29489c2acf00SAlek Pinchuk 29499c2acf00SAlek Pinchuk /* check options */ 29509c2acf00SAlek Pinchuk while ((ret = getopt(argc, argv, "f")) != -1) { 29519c2acf00SAlek Pinchuk switch (ret) { 29529c2acf00SAlek Pinchuk case 'f': 29539c2acf00SAlek Pinchuk force = B_TRUE; 29549c2acf00SAlek Pinchuk break; 29559c2acf00SAlek Pinchuk case '?': 29569c2acf00SAlek Pinchuk (void) fprintf(stderr, gettext("invalid option '%c'\n"), 29579c2acf00SAlek Pinchuk optopt); 29589c2acf00SAlek Pinchuk usage(B_FALSE); 29599c2acf00SAlek Pinchuk } 29609c2acf00SAlek Pinchuk } 29619c2acf00SAlek Pinchuk 29629c2acf00SAlek Pinchuk argc -= optind; 29639c2acf00SAlek Pinchuk argv += optind; 29649c2acf00SAlek Pinchuk 29659c2acf00SAlek Pinchuk /* if argc == 0 we will execute zpool_sync_one on all pools */ 29669c2acf00SAlek Pinchuk ret = for_each_pool(argc, argv, B_FALSE, NULL, zpool_sync_one, &force); 29679c2acf00SAlek Pinchuk 29689c2acf00SAlek Pinchuk return (ret); 29699c2acf00SAlek Pinchuk } 29709c2acf00SAlek Pinchuk 2971fa9e4066Sahrens typedef struct iostat_cbdata { 29724263d13fSGeorge Wilson boolean_t cb_verbose; 2973663207adSDon Brady int cb_name_flags; 2974fa9e4066Sahrens int cb_namewidth; 29754263d13fSGeorge Wilson int cb_iteration; 2976663207adSDon Brady boolean_t cb_scripted; 29774263d13fSGeorge Wilson zpool_list_t *cb_list; 2978fa9e4066Sahrens } iostat_cbdata_t; 2979fa9e4066Sahrens 2980fa9e4066Sahrens static void 2981fa9e4066Sahrens print_iostat_separator(iostat_cbdata_t *cb) 2982fa9e4066Sahrens { 2983fa9e4066Sahrens int i = 0; 2984fa9e4066Sahrens 2985fa9e4066Sahrens for (i = 0; i < cb->cb_namewidth; i++) 2986fa9e4066Sahrens (void) printf("-"); 2987fa9e4066Sahrens (void) printf(" ----- ----- ----- ----- ----- -----\n"); 2988fa9e4066Sahrens } 2989fa9e4066Sahrens 2990fa9e4066Sahrens static void 2991fa9e4066Sahrens print_iostat_header(iostat_cbdata_t *cb) 2992fa9e4066Sahrens { 2993fa9e4066Sahrens (void) printf("%*s capacity operations bandwidth\n", 2994fa9e4066Sahrens cb->cb_namewidth, ""); 2995485bbbf5SGeorge Wilson (void) printf("%-*s alloc free read write read write\n", 2996fa9e4066Sahrens cb->cb_namewidth, "pool"); 2997fa9e4066Sahrens print_iostat_separator(cb); 2998fa9e4066Sahrens } 2999fa9e4066Sahrens 3000fa9e4066Sahrens /* 3001fa9e4066Sahrens * Display a single statistic. 3002fa9e4066Sahrens */ 3003990b4856Slling static void 3004fa9e4066Sahrens print_one_stat(uint64_t value) 3005fa9e4066Sahrens { 3006fa9e4066Sahrens char buf[64]; 3007fa9e4066Sahrens 3008fa9e4066Sahrens zfs_nicenum(value, buf, sizeof (buf)); 3009fa9e4066Sahrens (void) printf(" %5s", buf); 3010fa9e4066Sahrens } 3011fa9e4066Sahrens 3012663207adSDon Brady static const char *class_name[] = { 3013663207adSDon Brady VDEV_ALLOC_BIAS_DEDUP, 3014663207adSDon Brady VDEV_ALLOC_BIAS_SPECIAL, 3015663207adSDon Brady VDEV_ALLOC_CLASS_LOGS 3016663207adSDon Brady }; 3017663207adSDon Brady 3018fa9e4066Sahrens /* 3019fa9e4066Sahrens * Print out all the statistics for the given vdev. This can either be the 3020fa9e4066Sahrens * toplevel configuration, or called recursively. If 'name' is NULL, then this 3021fa9e4066Sahrens * is a verbose output, and we don't want to display the toplevel pool stats. 3022fa9e4066Sahrens */ 302395fa23b1SJerry Jelinek static void 3024c67d9675Seschrock print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 3025c67d9675Seschrock nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 3026fa9e4066Sahrens { 3027fa9e4066Sahrens nvlist_t **oldchild, **newchild; 3028fa9e4066Sahrens uint_t c, children; 3029fa9e4066Sahrens vdev_stat_t *oldvs, *newvs; 3030fa9e4066Sahrens vdev_stat_t zerovs = { 0 }; 3031663207adSDon Brady char *vname; 3032fa9e4066Sahrens uint64_t tdelta; 3033fa9e4066Sahrens double scale; 3034fa9e4066Sahrens 30355cabbc6bSPrashanth Sreenivasa if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 303695fa23b1SJerry Jelinek return; 30375cabbc6bSPrashanth Sreenivasa 3038fa9e4066Sahrens if (oldnv != NULL) { 30393f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(oldnv, 30403f9d6ad7SLin Ling ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0); 3041fa9e4066Sahrens } else { 3042fa9e4066Sahrens oldvs = &zerovs; 3043fa9e4066Sahrens } 3044fa9e4066Sahrens 30453f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS, 3046fa9e4066Sahrens (uint64_t **)&newvs, &c) == 0); 3047fa9e4066Sahrens 3048fa9e4066Sahrens if (strlen(name) + depth > cb->cb_namewidth) 3049fa9e4066Sahrens (void) printf("%*s%s", depth, "", name); 3050fa9e4066Sahrens else 3051fa9e4066Sahrens (void) printf("%*s%s%*s", depth, "", name, 3052fa9e4066Sahrens (int)(cb->cb_namewidth - strlen(name) - depth), ""); 3053fa9e4066Sahrens 3054fa9e4066Sahrens tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 3055fa9e4066Sahrens 3056fa9e4066Sahrens if (tdelta == 0) 3057fa9e4066Sahrens scale = 1.0; 3058fa9e4066Sahrens else 3059fa9e4066Sahrens scale = (double)NANOSEC / tdelta; 3060fa9e4066Sahrens 3061fa9e4066Sahrens /* only toplevel vdevs have capacity stats */ 3062fa9e4066Sahrens if (newvs->vs_space == 0) { 3063fa9e4066Sahrens (void) printf(" - -"); 3064fa9e4066Sahrens } else { 3065fa9e4066Sahrens print_one_stat(newvs->vs_alloc); 3066fa9e4066Sahrens print_one_stat(newvs->vs_space - newvs->vs_alloc); 3067fa9e4066Sahrens } 3068fa9e4066Sahrens 3069fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] - 3070fa9e4066Sahrens oldvs->vs_ops[ZIO_TYPE_READ]))); 3071fa9e4066Sahrens 3072fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] - 3073fa9e4066Sahrens oldvs->vs_ops[ZIO_TYPE_WRITE]))); 3074fa9e4066Sahrens 3075fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] - 3076fa9e4066Sahrens oldvs->vs_bytes[ZIO_TYPE_READ]))); 3077fa9e4066Sahrens 3078fa9e4066Sahrens print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] - 3079fa9e4066Sahrens oldvs->vs_bytes[ZIO_TYPE_WRITE]))); 3080fa9e4066Sahrens 3081fa9e4066Sahrens (void) printf("\n"); 3082fa9e4066Sahrens 3083fa9e4066Sahrens if (!cb->cb_verbose) 308495fa23b1SJerry Jelinek return; 3085fa9e4066Sahrens 3086fa9e4066Sahrens if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 3087fa9e4066Sahrens &newchild, &children) != 0) 308895fa23b1SJerry Jelinek return; 3089fa9e4066Sahrens 3090fa9e4066Sahrens if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 3091fa9e4066Sahrens &oldchild, &c) != 0) 309295fa23b1SJerry Jelinek return; 3093fa9e4066Sahrens 3094663207adSDon Brady /* 3095663207adSDon Brady * print normal top-level devices 3096663207adSDon Brady */ 3097afefbcddSeschrock for (c = 0; c < children; c++) { 30989d439f90SMike Harsch uint64_t ishole = B_FALSE, islog = B_FALSE; 30993f9d6ad7SLin Ling 31009d439f90SMike Harsch (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE, 31019d439f90SMike Harsch &ishole); 31029d439f90SMike Harsch 31039d439f90SMike Harsch (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG, 31049d439f90SMike Harsch &islog); 31059d439f90SMike Harsch 31069d439f90SMike Harsch if (ishole || islog) 31073f9d6ad7SLin Ling continue; 31083f9d6ad7SLin Ling 3109663207adSDon Brady if (nvlist_exists(newchild[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 3110663207adSDon Brady continue; 3111663207adSDon Brady 3112663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 3113663207adSDon Brady cb->cb_name_flags); 3114c67d9675Seschrock print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 3115afefbcddSeschrock newchild[c], cb, depth + 2); 3116afefbcddSeschrock free(vname); 3117afefbcddSeschrock } 3118fa94a07fSbrendan 31199d439f90SMike Harsch /* 3120663207adSDon Brady * print all other top-level devices 31219d439f90SMike Harsch */ 3122663207adSDon Brady for (uint_t n = 0; n < 3; n++) { 31239d439f90SMike Harsch for (c = 0; c < children; c++) { 31249d439f90SMike Harsch uint64_t islog = B_FALSE; 3125663207adSDon Brady char *bias = NULL; 3126663207adSDon Brady char *type = NULL; 3127663207adSDon Brady 31289d439f90SMike Harsch (void) nvlist_lookup_uint64(newchild[c], 31299d439f90SMike Harsch ZPOOL_CONFIG_IS_LOG, &islog); 31309d439f90SMike Harsch if (islog) { 3131663207adSDon Brady bias = VDEV_ALLOC_CLASS_LOGS; 3132663207adSDon Brady } else { 3133663207adSDon Brady (void) nvlist_lookup_string(newchild[c], 3134663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &bias); 3135663207adSDon Brady (void) nvlist_lookup_string(newchild[c], 3136663207adSDon Brady ZPOOL_CONFIG_TYPE, &type); 31379d439f90SMike Harsch } 3138663207adSDon Brady if (bias == NULL || strcmp(bias, class_name[n]) != 0) 3139663207adSDon Brady continue; 3140663207adSDon Brady if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0) 3141663207adSDon Brady continue; 3142663207adSDon Brady 3143663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 3144663207adSDon Brady cb->cb_name_flags); 314595fa23b1SJerry Jelinek print_vdev_stats(zhp, vname, oldnv ? 3146663207adSDon Brady oldchild[c] : NULL, newchild[c], cb, depth + 2); 3147663207adSDon Brady free(vname); 31489d439f90SMike Harsch } 31499d439f90SMike Harsch 31509d439f90SMike Harsch } 31519d439f90SMike Harsch 3152fa94a07fSbrendan /* 3153fa94a07fSbrendan * Include level 2 ARC devices in iostat output 3154fa94a07fSbrendan */ 3155fa94a07fSbrendan if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, 3156fa94a07fSbrendan &newchild, &children) != 0) 315795fa23b1SJerry Jelinek return; 3158fa94a07fSbrendan 3159fa94a07fSbrendan if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, 3160fa94a07fSbrendan &oldchild, &c) != 0) 316195fa23b1SJerry Jelinek return; 3162fa94a07fSbrendan 3163fa94a07fSbrendan if (children > 0) { 3164fa94a07fSbrendan (void) printf("%-*s - - - - - " 3165fa94a07fSbrendan "-\n", cb->cb_namewidth, "cache"); 3166fa94a07fSbrendan for (c = 0; c < children; c++) { 316788ecc943SGeorge Wilson vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 3168663207adSDon Brady cb->cb_name_flags); 3169fa94a07fSbrendan print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 3170fa94a07fSbrendan newchild[c], cb, depth + 2); 3171fa94a07fSbrendan free(vname); 3172fa94a07fSbrendan } 3173fa94a07fSbrendan } 3174fa9e4066Sahrens } 3175fa9e4066Sahrens 3176088e9d47Seschrock static int 3177088e9d47Seschrock refresh_iostat(zpool_handle_t *zhp, void *data) 3178088e9d47Seschrock { 3179088e9d47Seschrock iostat_cbdata_t *cb = data; 318094de1d4cSeschrock boolean_t missing; 3181088e9d47Seschrock 3182088e9d47Seschrock /* 3183088e9d47Seschrock * If the pool has disappeared, remove it from the list and continue. 3184088e9d47Seschrock */ 318594de1d4cSeschrock if (zpool_refresh_stats(zhp, &missing) != 0) 318694de1d4cSeschrock return (-1); 318794de1d4cSeschrock 318894de1d4cSeschrock if (missing) 3189088e9d47Seschrock pool_list_remove(cb->cb_list, zhp); 3190088e9d47Seschrock 3191088e9d47Seschrock return (0); 3192088e9d47Seschrock } 3193088e9d47Seschrock 3194fa9e4066Sahrens /* 3195fa9e4066Sahrens * Callback to print out the iostats for the given pool. 3196fa9e4066Sahrens */ 3197fa9e4066Sahrens int 3198fa9e4066Sahrens print_iostat(zpool_handle_t *zhp, void *data) 3199fa9e4066Sahrens { 3200fa9e4066Sahrens iostat_cbdata_t *cb = data; 3201fa9e4066Sahrens nvlist_t *oldconfig, *newconfig; 3202fa9e4066Sahrens nvlist_t *oldnvroot, *newnvroot; 3203fa9e4066Sahrens 3204088e9d47Seschrock newconfig = zpool_get_config(zhp, &oldconfig); 3205fa9e4066Sahrens 3206088e9d47Seschrock if (cb->cb_iteration == 1) 3207fa9e4066Sahrens oldconfig = NULL; 3208fa9e4066Sahrens 3209fa9e4066Sahrens verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 3210fa9e4066Sahrens &newnvroot) == 0); 3211fa9e4066Sahrens 3212088e9d47Seschrock if (oldconfig == NULL) 3213fa9e4066Sahrens oldnvroot = NULL; 3214088e9d47Seschrock else 3215088e9d47Seschrock verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 3216088e9d47Seschrock &oldnvroot) == 0); 3217fa9e4066Sahrens 3218fa9e4066Sahrens /* 3219fa9e4066Sahrens * Print out the statistics for the pool. 3220fa9e4066Sahrens */ 3221c67d9675Seschrock print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 3222fa9e4066Sahrens 3223fa9e4066Sahrens if (cb->cb_verbose) 3224fa9e4066Sahrens print_iostat_separator(cb); 3225fa9e4066Sahrens 3226fa9e4066Sahrens return (0); 3227fa9e4066Sahrens } 3228fa9e4066Sahrens 3229fa9e4066Sahrens int 3230fa9e4066Sahrens get_namewidth(zpool_handle_t *zhp, void *data) 3231fa9e4066Sahrens { 3232fa9e4066Sahrens iostat_cbdata_t *cb = data; 3233fa9e4066Sahrens nvlist_t *config, *nvroot; 3234fa9e4066Sahrens 3235088e9d47Seschrock if ((config = zpool_get_config(zhp, NULL)) != NULL) { 3236fa9e4066Sahrens verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 3237fa9e4066Sahrens &nvroot) == 0); 3238fa9e4066Sahrens if (!cb->cb_verbose) 3239fa9e4066Sahrens cb->cb_namewidth = strlen(zpool_get_name(zhp)); 3240fa9e4066Sahrens else 3241e1d5e507SFrederik Wessels cb->cb_namewidth = max_width(zhp, nvroot, 0, 3242663207adSDon Brady cb->cb_namewidth, cb->cb_name_flags); 3243fa9e4066Sahrens } 3244fa9e4066Sahrens 3245fa9e4066Sahrens /* 3246fa9e4066Sahrens * The width must fall into the range [10,38]. The upper limit is the 3247fa9e4066Sahrens * maximum we can have and still fit in 80 columns. 3248fa9e4066Sahrens */ 3249fa9e4066Sahrens if (cb->cb_namewidth < 10) 3250fa9e4066Sahrens cb->cb_namewidth = 10; 3251fa9e4066Sahrens if (cb->cb_namewidth > 38) 3252fa9e4066Sahrens cb->cb_namewidth = 38; 3253fa9e4066Sahrens 3254fa9e4066Sahrens return (0); 3255fa9e4066Sahrens } 3256fa9e4066Sahrens 3257fa9e4066Sahrens /* 32583f9d6ad7SLin Ling * Parse the input string, get the 'interval' and 'count' value if there is one. 3259fa9e4066Sahrens */ 32603f9d6ad7SLin Ling static void 32613f9d6ad7SLin Ling get_interval_count(int *argcp, char **argv, unsigned long *iv, 32623f9d6ad7SLin Ling unsigned long *cnt) 3263fa9e4066Sahrens { 3264fa9e4066Sahrens unsigned long interval = 0, count = 0; 32653f9d6ad7SLin Ling int argc = *argcp, errno; 3266fa9e4066Sahrens 3267fa9e4066Sahrens /* 3268fa9e4066Sahrens * Determine if the last argument is an integer or a pool name 3269fa9e4066Sahrens */ 3270fa9e4066Sahrens if (argc > 0 && isdigit(argv[argc - 1][0])) { 3271fa9e4066Sahrens char *end; 3272fa9e4066Sahrens 3273fa9e4066Sahrens errno = 0; 3274fa9e4066Sahrens interval = strtoul(argv[argc - 1], &end, 10); 3275fa9e4066Sahrens 3276fa9e4066Sahrens if (*end == '\0' && errno == 0) { 3277fa9e4066Sahrens if (interval == 0) { 3278fa9e4066Sahrens (void) fprintf(stderr, gettext("interval " 3279fa9e4066Sahrens "cannot be zero\n")); 328099653d4eSeschrock usage(B_FALSE); 3281fa9e4066Sahrens } 3282fa9e4066Sahrens /* 3283fa9e4066Sahrens * Ignore the last parameter 3284fa9e4066Sahrens */ 3285fa9e4066Sahrens argc--; 3286fa9e4066Sahrens } else { 3287fa9e4066Sahrens /* 3288fa9e4066Sahrens * If this is not a valid number, just plow on. The 3289fa9e4066Sahrens * user will get a more informative error message later 3290fa9e4066Sahrens * on. 3291fa9e4066Sahrens */ 3292fa9e4066Sahrens interval = 0; 3293fa9e4066Sahrens } 3294fa9e4066Sahrens } 3295fa9e4066Sahrens 3296fa9e4066Sahrens /* 3297fa9e4066Sahrens * If the last argument is also an integer, then we have both a count 32983f9d6ad7SLin Ling * and an interval. 3299fa9e4066Sahrens */ 3300fa9e4066Sahrens if (argc > 0 && isdigit(argv[argc - 1][0])) { 3301fa9e4066Sahrens char *end; 3302fa9e4066Sahrens 3303fa9e4066Sahrens errno = 0; 3304fa9e4066Sahrens count = interval; 3305fa9e4066Sahrens interval = strtoul(argv[argc - 1], &end, 10); 3306fa9e4066Sahrens 3307fa9e4066Sahrens if (*end == '\0' && errno == 0) { 3308fa9e4066Sahrens if (interval == 0) { 3309fa9e4066Sahrens (void) fprintf(stderr, gettext("interval " 3310fa9e4066Sahrens "cannot be zero\n")); 331199653d4eSeschrock usage(B_FALSE); 3312fa9e4066Sahrens } 3313fa9e4066Sahrens 3314fa9e4066Sahrens /* 3315fa9e4066Sahrens * Ignore the last parameter 3316fa9e4066Sahrens */ 3317fa9e4066Sahrens argc--; 3318fa9e4066Sahrens } else { 3319fa9e4066Sahrens interval = 0; 3320fa9e4066Sahrens } 3321fa9e4066Sahrens } 3322fa9e4066Sahrens 33233f9d6ad7SLin Ling *iv = interval; 33243f9d6ad7SLin Ling *cnt = count; 33253f9d6ad7SLin Ling *argcp = argc; 33263f9d6ad7SLin Ling } 33273f9d6ad7SLin Ling 33283f9d6ad7SLin Ling static void 33293f9d6ad7SLin Ling get_timestamp_arg(char c) 33303f9d6ad7SLin Ling { 33313f9d6ad7SLin Ling if (c == 'u') 33323f9d6ad7SLin Ling timestamp_fmt = UDATE; 33333f9d6ad7SLin Ling else if (c == 'd') 33343f9d6ad7SLin Ling timestamp_fmt = DDATE; 33353f9d6ad7SLin Ling else 33363f9d6ad7SLin Ling usage(B_FALSE); 33373f9d6ad7SLin Ling } 33383f9d6ad7SLin Ling 33393f9d6ad7SLin Ling /* 3340663207adSDon Brady * zpool iostat [-gLPv] [-T d|u] [pool] ... [interval [count]] 33413f9d6ad7SLin Ling * 3342663207adSDon Brady * -g Display guid for individual vdev name. 3343663207adSDon Brady * -L Follow links when resolving vdev path name. 3344663207adSDon Brady * -P Display full path for vdev name. 33453f9d6ad7SLin Ling * -v Display statistics for individual vdevs 33463f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format 33473f9d6ad7SLin Ling * 33483f9d6ad7SLin Ling * This command can be tricky because we want to be able to deal with pool 33493f9d6ad7SLin Ling * creation/destruction as well as vdev configuration changes. The bulk of this 33503f9d6ad7SLin Ling * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 33513f9d6ad7SLin Ling * on pool_list_update() to detect the addition of new pools. Configuration 33523f9d6ad7SLin Ling * changes are all handled within libzfs. 33533f9d6ad7SLin Ling */ 33543f9d6ad7SLin Ling int 33553f9d6ad7SLin Ling zpool_do_iostat(int argc, char **argv) 33563f9d6ad7SLin Ling { 33573f9d6ad7SLin Ling int c; 33583f9d6ad7SLin Ling int ret; 33593f9d6ad7SLin Ling int npools; 33603f9d6ad7SLin Ling unsigned long interval = 0, count = 0; 33613f9d6ad7SLin Ling zpool_list_t *list; 33623f9d6ad7SLin Ling boolean_t verbose = B_FALSE; 3363663207adSDon Brady boolean_t guid = B_FALSE; 3364663207adSDon Brady boolean_t follow_links = B_FALSE; 3365663207adSDon Brady boolean_t full_name = B_FALSE; 3366663207adSDon Brady iostat_cbdata_t cb = { 0 }; 33673f9d6ad7SLin Ling 33683f9d6ad7SLin Ling /* check options */ 3369663207adSDon Brady while ((c = getopt(argc, argv, "gLPT:v")) != -1) { 33703f9d6ad7SLin Ling switch (c) { 3371663207adSDon Brady case 'g': 3372663207adSDon Brady guid = B_TRUE; 3373663207adSDon Brady break; 3374663207adSDon Brady case 'L': 3375663207adSDon Brady follow_links = B_TRUE; 3376663207adSDon Brady break; 3377663207adSDon Brady case 'P': 3378663207adSDon Brady full_name = B_TRUE; 3379663207adSDon Brady break; 33803f9d6ad7SLin Ling case 'T': 33813f9d6ad7SLin Ling get_timestamp_arg(*optarg); 33823f9d6ad7SLin Ling break; 33833f9d6ad7SLin Ling case 'v': 33843f9d6ad7SLin Ling verbose = B_TRUE; 33853f9d6ad7SLin Ling break; 33863f9d6ad7SLin Ling case '?': 33873f9d6ad7SLin Ling (void) fprintf(stderr, gettext("invalid option '%c'\n"), 33883f9d6ad7SLin Ling optopt); 33893f9d6ad7SLin Ling usage(B_FALSE); 33903f9d6ad7SLin Ling } 33913f9d6ad7SLin Ling } 33923f9d6ad7SLin Ling 33933f9d6ad7SLin Ling argc -= optind; 33943f9d6ad7SLin Ling argv += optind; 33953f9d6ad7SLin Ling 33963f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count); 33973f9d6ad7SLin Ling 3398fa9e4066Sahrens /* 3399fa9e4066Sahrens * Construct the list of all interesting pools. 3400fa9e4066Sahrens */ 3401fa9e4066Sahrens ret = 0; 3402b1b8ab34Slling if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL) 3403fa9e4066Sahrens return (1); 3404fa9e4066Sahrens 340599653d4eSeschrock if (pool_list_count(list) == 0 && argc != 0) { 340699653d4eSeschrock pool_list_free(list); 3407fa9e4066Sahrens return (1); 340899653d4eSeschrock } 3409fa9e4066Sahrens 3410fa9e4066Sahrens if (pool_list_count(list) == 0 && interval == 0) { 341199653d4eSeschrock pool_list_free(list); 3412fa9e4066Sahrens (void) fprintf(stderr, gettext("no pools available\n")); 3413fa9e4066Sahrens return (1); 3414fa9e4066Sahrens } 3415fa9e4066Sahrens 3416fa9e4066Sahrens /* 3417fa9e4066Sahrens * Enter the main iostat loop. 3418fa9e4066Sahrens */ 3419fa9e4066Sahrens cb.cb_list = list; 3420fa9e4066Sahrens cb.cb_verbose = verbose; 3421663207adSDon Brady if (guid) 3422663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_GUID; 3423663207adSDon Brady if (follow_links) 3424663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS; 3425663207adSDon Brady if (full_name) 3426663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_PATH; 3427fa9e4066Sahrens cb.cb_iteration = 0; 3428fa9e4066Sahrens cb.cb_namewidth = 0; 3429fa9e4066Sahrens 3430fa9e4066Sahrens for (;;) { 3431fa9e4066Sahrens pool_list_update(list); 3432fa9e4066Sahrens 3433fa9e4066Sahrens if ((npools = pool_list_count(list)) == 0) 3434fa9e4066Sahrens break; 3435fa9e4066Sahrens 3436088e9d47Seschrock /* 3437088e9d47Seschrock * Refresh all statistics. This is done as an explicit step 3438088e9d47Seschrock * before calculating the maximum name width, so that any 3439088e9d47Seschrock * configuration changes are properly accounted for. 3440088e9d47Seschrock */ 344199653d4eSeschrock (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb); 3442088e9d47Seschrock 3443fa9e4066Sahrens /* 3444fa9e4066Sahrens * Iterate over all pools to determine the maximum width 3445fa9e4066Sahrens * for the pool / device name column across all pools. 3446fa9e4066Sahrens */ 3447fa9e4066Sahrens cb.cb_namewidth = 0; 344899653d4eSeschrock (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 3449fa9e4066Sahrens 345026fd7700SKrishnendu Sadhukhan - Sun Microsystems if (timestamp_fmt != NODATE) 345126fd7700SKrishnendu Sadhukhan - Sun Microsystems print_timestamp(timestamp_fmt); 345226fd7700SKrishnendu Sadhukhan - Sun Microsystems 3453fa9e4066Sahrens /* 3454fa9e4066Sahrens * If it's the first time, or verbose mode, print the header. 3455fa9e4066Sahrens */ 3456fa9e4066Sahrens if (++cb.cb_iteration == 1 || verbose) 3457fa9e4066Sahrens print_iostat_header(&cb); 3458fa9e4066Sahrens 345999653d4eSeschrock (void) pool_list_iter(list, B_FALSE, print_iostat, &cb); 3460fa9e4066Sahrens 3461fa9e4066Sahrens /* 3462fa9e4066Sahrens * If there's more than one pool, and we're not in verbose mode 3463fa9e4066Sahrens * (which prints a separator for us), then print a separator. 3464fa9e4066Sahrens */ 3465fa9e4066Sahrens if (npools > 1 && !verbose) 3466fa9e4066Sahrens print_iostat_separator(&cb); 3467fa9e4066Sahrens 3468fa9e4066Sahrens if (verbose) 3469fa9e4066Sahrens (void) printf("\n"); 3470fa9e4066Sahrens 347139c23413Seschrock /* 347239c23413Seschrock * Flush the output so that redirection to a file isn't buffered 347339c23413Seschrock * indefinitely. 347439c23413Seschrock */ 347539c23413Seschrock (void) fflush(stdout); 347639c23413Seschrock 3477fa9e4066Sahrens if (interval == 0) 3478fa9e4066Sahrens break; 3479fa9e4066Sahrens 3480fa9e4066Sahrens if (count != 0 && --count == 0) 3481fa9e4066Sahrens break; 3482fa9e4066Sahrens 3483fa9e4066Sahrens (void) sleep(interval); 3484fa9e4066Sahrens } 3485fa9e4066Sahrens 3486fa9e4066Sahrens pool_list_free(list); 3487fa9e4066Sahrens 3488fa9e4066Sahrens return (ret); 3489fa9e4066Sahrens } 3490fa9e4066Sahrens 3491fa9e4066Sahrens typedef struct list_cbdata { 34924263d13fSGeorge Wilson boolean_t cb_verbose; 3493663207adSDon Brady int cb_name_flags; 34944263d13fSGeorge Wilson int cb_namewidth; 349599653d4eSeschrock boolean_t cb_scripted; 3496990b4856Slling zprop_list_t *cb_proplist; 3497c58b3526SAdam Stevko boolean_t cb_literal; 3498fa9e4066Sahrens } list_cbdata_t; 3499fa9e4066Sahrens 3500663207adSDon Brady 3501fa9e4066Sahrens /* 3502fa9e4066Sahrens * Given a list of columns to display, output appropriate headers for each one. 3503fa9e4066Sahrens */ 3504990b4856Slling static void 35054263d13fSGeorge Wilson print_header(list_cbdata_t *cb) 3506fa9e4066Sahrens { 35074263d13fSGeorge Wilson zprop_list_t *pl = cb->cb_proplist; 3508ad135b5dSChristopher Siden char headerbuf[ZPOOL_MAXPROPLEN]; 3509990b4856Slling const char *header; 3510990b4856Slling boolean_t first = B_TRUE; 3511990b4856Slling boolean_t right_justify; 35124263d13fSGeorge Wilson size_t width = 0; 3513990b4856Slling 3514990b4856Slling for (; pl != NULL; pl = pl->pl_next) { 35154263d13fSGeorge Wilson width = pl->pl_width; 35164263d13fSGeorge Wilson if (first && cb->cb_verbose) { 35174263d13fSGeorge Wilson /* 35184263d13fSGeorge Wilson * Reset the width to accommodate the verbose listing 35194263d13fSGeorge Wilson * of devices. 35204263d13fSGeorge Wilson */ 35214263d13fSGeorge Wilson width = cb->cb_namewidth; 35224263d13fSGeorge Wilson } 35234263d13fSGeorge Wilson 3524990b4856Slling if (!first) 3525fa9e4066Sahrens (void) printf(" "); 3526fa9e4066Sahrens else 3527990b4856Slling first = B_FALSE; 3528990b4856Slling 3529ad135b5dSChristopher Siden right_justify = B_FALSE; 3530ad135b5dSChristopher Siden if (pl->pl_prop != ZPROP_INVAL) { 3531ad135b5dSChristopher Siden header = zpool_prop_column_name(pl->pl_prop); 3532ad135b5dSChristopher Siden right_justify = zpool_prop_align_right(pl->pl_prop); 3533ad135b5dSChristopher Siden } else { 3534ad135b5dSChristopher Siden int i; 3535ad135b5dSChristopher Siden 3536ad135b5dSChristopher Siden for (i = 0; pl->pl_user_prop[i] != '\0'; i++) 3537ad135b5dSChristopher Siden headerbuf[i] = toupper(pl->pl_user_prop[i]); 3538ad135b5dSChristopher Siden headerbuf[i] = '\0'; 3539ad135b5dSChristopher Siden header = headerbuf; 3540ad135b5dSChristopher Siden } 3541fa9e4066Sahrens 3542990b4856Slling if (pl->pl_next == NULL && !right_justify) 3543990b4856Slling (void) printf("%s", header); 3544990b4856Slling else if (right_justify) 35454263d13fSGeorge Wilson (void) printf("%*s", width, header); 3546990b4856Slling else 35474263d13fSGeorge Wilson (void) printf("%-*s", width, header); 35484263d13fSGeorge Wilson 3549fa9e4066Sahrens } 3550fa9e4066Sahrens 3551fa9e4066Sahrens (void) printf("\n"); 3552fa9e4066Sahrens } 3553fa9e4066Sahrens 3554990b4856Slling /* 3555990b4856Slling * Given a pool and a list of properties, print out all the properties according 3556663207adSDon Brady * to the described layout. Used by zpool_do_list(). 3557990b4856Slling */ 3558990b4856Slling static void 35594263d13fSGeorge Wilson print_pool(zpool_handle_t *zhp, list_cbdata_t *cb) 3560fa9e4066Sahrens { 35614263d13fSGeorge Wilson zprop_list_t *pl = cb->cb_proplist; 3562990b4856Slling boolean_t first = B_TRUE; 3563990b4856Slling char property[ZPOOL_MAXPROPLEN]; 3564990b4856Slling char *propstr; 3565990b4856Slling boolean_t right_justify; 35664263d13fSGeorge Wilson size_t width; 3567990b4856Slling 3568990b4856Slling for (; pl != NULL; pl = pl->pl_next) { 35694263d13fSGeorge Wilson 35704263d13fSGeorge Wilson width = pl->pl_width; 35714263d13fSGeorge Wilson if (first && cb->cb_verbose) { 35724263d13fSGeorge Wilson /* 35734263d13fSGeorge Wilson * Reset the width to accommodate the verbose listing 35744263d13fSGeorge Wilson * of devices. 35754263d13fSGeorge Wilson */ 35764263d13fSGeorge Wilson width = cb->cb_namewidth; 35774263d13fSGeorge Wilson } 35784263d13fSGeorge Wilson 3579990b4856Slling if (!first) { 35804263d13fSGeorge Wilson if (cb->cb_scripted) 3581fa9e4066Sahrens (void) printf("\t"); 3582fa9e4066Sahrens else 3583fa9e4066Sahrens (void) printf(" "); 3584990b4856Slling } else { 3585990b4856Slling first = B_FALSE; 3586fa9e4066Sahrens } 3587fa9e4066Sahrens 3588990b4856Slling right_justify = B_FALSE; 3589990b4856Slling if (pl->pl_prop != ZPROP_INVAL) { 35907a09f97bSGeorge Wilson if (zpool_get_prop(zhp, pl->pl_prop, property, 3591c58b3526SAdam Stevko sizeof (property), NULL, cb->cb_literal) != 0) 3592990b4856Slling propstr = "-"; 3593fa9e4066Sahrens else 3594990b4856Slling propstr = property; 3595fa9e4066Sahrens 3596990b4856Slling right_justify = zpool_prop_align_right(pl->pl_prop); 3597ad135b5dSChristopher Siden } else if ((zpool_prop_feature(pl->pl_user_prop) || 3598ad135b5dSChristopher Siden zpool_prop_unsupported(pl->pl_user_prop)) && 3599ad135b5dSChristopher Siden zpool_prop_get_feature(zhp, pl->pl_user_prop, property, 3600ad135b5dSChristopher Siden sizeof (property)) == 0) { 3601ad135b5dSChristopher Siden propstr = property; 3602990b4856Slling } else { 3603990b4856Slling propstr = "-"; 3604990b4856Slling } 3605fa9e4066Sahrens 3606fa9e4066Sahrens 3607990b4856Slling /* 3608990b4856Slling * If this is being called in scripted mode, or if this is the 3609990b4856Slling * last column and it is left-justified, don't include a width 3610990b4856Slling * format specifier. 3611990b4856Slling */ 36124263d13fSGeorge Wilson if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify)) 3613990b4856Slling (void) printf("%s", propstr); 3614990b4856Slling else if (right_justify) 3615990b4856Slling (void) printf("%*s", width, propstr); 3616990b4856Slling else 3617990b4856Slling (void) printf("%-*s", width, propstr); 3618990b4856Slling } 3619fa9e4066Sahrens 3620990b4856Slling (void) printf("\n"); 3621990b4856Slling } 3622fa9e4066Sahrens 36234263d13fSGeorge Wilson static void 36247a09f97bSGeorge Wilson print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted, 36257a09f97bSGeorge Wilson boolean_t valid) 36264263d13fSGeorge Wilson { 36274263d13fSGeorge Wilson char propval[64]; 36284263d13fSGeorge Wilson boolean_t fixed; 36294263d13fSGeorge Wilson size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL); 36304263d13fSGeorge Wilson 36317a09f97bSGeorge Wilson switch (prop) { 36327a09f97bSGeorge Wilson case ZPOOL_PROP_EXPANDSZ: 363386714001SSerapheim Dimitropoulos case ZPOOL_PROP_CHECKPOINT: 36347a09f97bSGeorge Wilson if (value == 0) 36357a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval)); 36367a09f97bSGeorge Wilson else 36377a09f97bSGeorge Wilson zfs_nicenum(value, propval, sizeof (propval)); 36387a09f97bSGeorge Wilson break; 36397a09f97bSGeorge Wilson case ZPOOL_PROP_FRAGMENTATION: 36407a09f97bSGeorge Wilson if (value == ZFS_FRAG_INVALID) { 36417a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval)); 36427a09f97bSGeorge Wilson } else { 36437a09f97bSGeorge Wilson (void) snprintf(propval, sizeof (propval), "%llu%%", 36447a09f97bSGeorge Wilson value); 36457a09f97bSGeorge Wilson } 36467a09f97bSGeorge Wilson break; 36477a09f97bSGeorge Wilson case ZPOOL_PROP_CAPACITY: 3648663207adSDon Brady (void) snprintf(propval, sizeof (propval), 3649663207adSDon Brady value < 1000 ? "%1.2f%%" : value < 10000 ? 3650663207adSDon Brady "%2.1f%%" : "%3.0f%%", value / 100.0); 36517a09f97bSGeorge Wilson break; 36527a09f97bSGeorge Wilson default: 36532e4c9986SGeorge Wilson zfs_nicenum(value, propval, sizeof (propval)); 36547a09f97bSGeorge Wilson } 36557a09f97bSGeorge Wilson 36567a09f97bSGeorge Wilson if (!valid) 36577a09f97bSGeorge Wilson (void) strlcpy(propval, "-", sizeof (propval)); 36584263d13fSGeorge Wilson 36594263d13fSGeorge Wilson if (scripted) 36604263d13fSGeorge Wilson (void) printf("\t%s", propval); 36614263d13fSGeorge Wilson else 36624263d13fSGeorge Wilson (void) printf(" %*s", width, propval); 36634263d13fSGeorge Wilson } 36644263d13fSGeorge Wilson 3665663207adSDon Brady /* 3666663207adSDon Brady * print static default line per vdev 3667663207adSDon Brady */ 36684263d13fSGeorge Wilson void 36694263d13fSGeorge Wilson print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 36704263d13fSGeorge Wilson list_cbdata_t *cb, int depth) 36714263d13fSGeorge Wilson { 36724263d13fSGeorge Wilson nvlist_t **child; 36734263d13fSGeorge Wilson vdev_stat_t *vs; 36744263d13fSGeorge Wilson uint_t c, children; 36754263d13fSGeorge Wilson char *vname; 36764263d13fSGeorge Wilson boolean_t scripted = cb->cb_scripted; 367752244c09SJohn Wren Kennedy uint64_t islog = B_FALSE; 367852244c09SJohn Wren Kennedy char *dashes = "%-*s - - - - - -\n"; 36794263d13fSGeorge Wilson 36804263d13fSGeorge Wilson verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 36814263d13fSGeorge Wilson (uint64_t **)&vs, &c) == 0); 36824263d13fSGeorge Wilson 36834263d13fSGeorge Wilson if (name != NULL) { 36847a09f97bSGeorge Wilson boolean_t toplevel = (vs->vs_space != 0); 36857a09f97bSGeorge Wilson uint64_t cap; 36867a09f97bSGeorge Wilson 36875cabbc6bSPrashanth Sreenivasa if (strcmp(name, VDEV_TYPE_INDIRECT) == 0) 36885cabbc6bSPrashanth Sreenivasa return; 36895cabbc6bSPrashanth Sreenivasa 36904263d13fSGeorge Wilson if (scripted) 36914263d13fSGeorge Wilson (void) printf("\t%s", name); 36924263d13fSGeorge Wilson else if (strlen(name) + depth > cb->cb_namewidth) 36934263d13fSGeorge Wilson (void) printf("%*s%s", depth, "", name); 36944263d13fSGeorge Wilson else 36954263d13fSGeorge Wilson (void) printf("%*s%s%*s", depth, "", name, 36964263d13fSGeorge Wilson (int)(cb->cb_namewidth - strlen(name) - depth), ""); 36974263d13fSGeorge Wilson 36987a09f97bSGeorge Wilson /* 36997a09f97bSGeorge Wilson * Print the properties for the individual vdevs. Some 37007a09f97bSGeorge Wilson * properties are only applicable to toplevel vdevs. The 37017a09f97bSGeorge Wilson * 'toplevel' boolean value is passed to the print_one_column() 37027a09f97bSGeorge Wilson * to indicate that the value is valid. 37037a09f97bSGeorge Wilson */ 37047a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted, 37057a09f97bSGeorge Wilson toplevel); 37067a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted, 37077a09f97bSGeorge Wilson toplevel); 37087a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc, 37097a09f97bSGeorge Wilson scripted, toplevel); 371086714001SSerapheim Dimitropoulos print_one_column(ZPOOL_PROP_CHECKPOINT, 371186714001SSerapheim Dimitropoulos vs->vs_checkpoint_space, scripted, toplevel); 37127a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted, 37137a09f97bSGeorge Wilson B_TRUE); 37147a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_FRAGMENTATION, 37157a09f97bSGeorge Wilson vs->vs_fragmentation, scripted, 37167a09f97bSGeorge Wilson (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel)); 37177a09f97bSGeorge Wilson cap = (vs->vs_space == 0) ? 0 : 3718663207adSDon Brady (vs->vs_alloc * 10000 / vs->vs_space); 37197a09f97bSGeorge Wilson print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel); 37204263d13fSGeorge Wilson (void) printf("\n"); 37214263d13fSGeorge Wilson } 37224263d13fSGeorge Wilson 37234263d13fSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 37244263d13fSGeorge Wilson &child, &children) != 0) 37254263d13fSGeorge Wilson return; 37264263d13fSGeorge Wilson 3727663207adSDon Brady /* list the normal vdevs first */ 37284263d13fSGeorge Wilson for (c = 0; c < children; c++) { 37294263d13fSGeorge Wilson uint64_t ishole = B_FALSE; 37304263d13fSGeorge Wilson 37314263d13fSGeorge Wilson if (nvlist_lookup_uint64(child[c], 37324263d13fSGeorge Wilson ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole) 37334263d13fSGeorge Wilson continue; 37344263d13fSGeorge Wilson 373552244c09SJohn Wren Kennedy if (nvlist_lookup_uint64(child[c], 3736663207adSDon Brady ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) 373752244c09SJohn Wren Kennedy continue; 373852244c09SJohn Wren Kennedy 3739663207adSDon Brady if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS)) 3740663207adSDon Brady continue; 3741663207adSDon Brady 3742663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 3743663207adSDon Brady cb->cb_name_flags); 37444263d13fSGeorge Wilson print_list_stats(zhp, vname, child[c], cb, depth + 2); 37454263d13fSGeorge Wilson free(vname); 37464263d13fSGeorge Wilson } 37474263d13fSGeorge Wilson 3748663207adSDon Brady /* list the classes: 'logs', 'dedup', and 'special' */ 3749663207adSDon Brady for (uint_t n = 0; n < 3; n++) { 3750663207adSDon Brady boolean_t printed = B_FALSE; 3751663207adSDon Brady 375252244c09SJohn Wren Kennedy for (c = 0; c < children; c++) { 3753663207adSDon Brady char *bias = NULL; 3754663207adSDon Brady char *type = NULL; 3755663207adSDon Brady 375652244c09SJohn Wren Kennedy if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 3757663207adSDon Brady &islog) == 0 && islog) { 3758663207adSDon Brady bias = VDEV_ALLOC_CLASS_LOGS; 3759663207adSDon Brady } else { 3760663207adSDon Brady (void) nvlist_lookup_string(child[c], 3761663207adSDon Brady ZPOOL_CONFIG_ALLOCATION_BIAS, &bias); 3762663207adSDon Brady (void) nvlist_lookup_string(child[c], 3763663207adSDon Brady ZPOOL_CONFIG_TYPE, &type); 3764663207adSDon Brady } 3765663207adSDon Brady if (bias == NULL || strcmp(bias, class_name[n]) != 0) 3766663207adSDon Brady continue; 3767663207adSDon Brady if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0) 376852244c09SJohn Wren Kennedy continue; 3769663207adSDon Brady 3770663207adSDon Brady if (!printed) { 3771663207adSDon Brady /* LINTED E_SEC_PRINTF_VAR_FMT */ 3772663207adSDon Brady (void) printf(dashes, cb->cb_namewidth, 3773663207adSDon Brady class_name[n]); 3774663207adSDon Brady printed = B_TRUE; 3775663207adSDon Brady } 3776663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 3777663207adSDon Brady cb->cb_name_flags); 377852244c09SJohn Wren Kennedy print_list_stats(zhp, vname, child[c], cb, depth + 2); 377952244c09SJohn Wren Kennedy free(vname); 378052244c09SJohn Wren Kennedy } 378152244c09SJohn Wren Kennedy } 378252244c09SJohn Wren Kennedy 37834263d13fSGeorge Wilson if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 378452244c09SJohn Wren Kennedy &child, &children) == 0 && children > 0) { 378552244c09SJohn Wren Kennedy /* LINTED E_SEC_PRINTF_VAR_FMT */ 378652244c09SJohn Wren Kennedy (void) printf(dashes, cb->cb_namewidth, "cache"); 378752244c09SJohn Wren Kennedy for (c = 0; c < children; c++) { 3788663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 3789663207adSDon Brady cb->cb_name_flags); 379052244c09SJohn Wren Kennedy print_list_stats(zhp, vname, child[c], cb, depth + 2); 379152244c09SJohn Wren Kennedy free(vname); 379252244c09SJohn Wren Kennedy } 379352244c09SJohn Wren Kennedy } 37944263d13fSGeorge Wilson 379552244c09SJohn Wren Kennedy if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child, 379652244c09SJohn Wren Kennedy &children) == 0 && children > 0) { 379752244c09SJohn Wren Kennedy /* LINTED E_SEC_PRINTF_VAR_FMT */ 379852244c09SJohn Wren Kennedy (void) printf(dashes, cb->cb_namewidth, "spare"); 37994263d13fSGeorge Wilson for (c = 0; c < children; c++) { 3800663207adSDon Brady vname = zpool_vdev_name(g_zfs, zhp, child[c], 3801663207adSDon Brady cb->cb_name_flags); 38024263d13fSGeorge Wilson print_list_stats(zhp, vname, child[c], cb, depth + 2); 38034263d13fSGeorge Wilson free(vname); 38044263d13fSGeorge Wilson } 38054263d13fSGeorge Wilson } 38064263d13fSGeorge Wilson } 38074263d13fSGeorge Wilson 3808990b4856Slling /* 3809990b4856Slling * Generic callback function to list a pool. 3810990b4856Slling */ 3811990b4856Slling int 3812990b4856Slling list_callback(zpool_handle_t *zhp, void *data) 3813990b4856Slling { 3814990b4856Slling list_cbdata_t *cbp = data; 38154263d13fSGeorge Wilson nvlist_t *config; 38164263d13fSGeorge Wilson nvlist_t *nvroot; 3817fa9e4066Sahrens 38184263d13fSGeorge Wilson config = zpool_get_config(zhp, NULL); 3819fa9e4066Sahrens 3820663207adSDon Brady if (cbp->cb_verbose) { 3821663207adSDon Brady config = zpool_get_config(zhp, NULL); 3822663207adSDon Brady 3823663207adSDon Brady verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 3824663207adSDon Brady &nvroot) == 0); 3825663207adSDon Brady } 3826663207adSDon Brady 3827663207adSDon Brady if (cbp->cb_verbose) 3828663207adSDon Brady cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0, 3829663207adSDon Brady cbp->cb_name_flags); 3830663207adSDon Brady 38314263d13fSGeorge Wilson print_pool(zhp, cbp); 38324263d13fSGeorge Wilson 3833663207adSDon Brady if (cbp->cb_verbose) 3834663207adSDon Brady print_list_stats(zhp, NULL, nvroot, cbp, 0); 3835fa9e4066Sahrens 3836fa9e4066Sahrens return (0); 3837fa9e4066Sahrens } 3838fa9e4066Sahrens 3839fa9e4066Sahrens /* 3840663207adSDon Brady * zpool list [-gHLP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]] 3841fa9e4066Sahrens * 3842663207adSDon Brady * -g Display guid for individual vdev name. 3843990b4856Slling * -H Scripted mode. Don't display headers, and separate properties 3844990b4856Slling * by a single tab. 3845663207adSDon Brady * -L Follow links when resolving vdev path name. 3846990b4856Slling * -o List of properties to display. Defaults to 38477a09f97bSGeorge Wilson * "name,size,allocated,free,expandsize,fragmentation,capacity," 38487a09f97bSGeorge Wilson * "dedupratio,health,altroot" 384904e56356SAndriy Gapon * -p Diplay values in parsable (exact) format. 3850663207adSDon Brady * -P Display full path for vdev name. 38513f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format 3852fa9e4066Sahrens * 3853fa9e4066Sahrens * List all pools in the system, whether or not they're healthy. Output space 3854fa9e4066Sahrens * statistics for each one, as well as health status summary. 3855fa9e4066Sahrens */ 3856fa9e4066Sahrens int 3857fa9e4066Sahrens zpool_do_list(int argc, char **argv) 3858fa9e4066Sahrens { 3859fa9e4066Sahrens int c; 3860fa9e4066Sahrens int ret; 3861fa9e4066Sahrens list_cbdata_t cb = { 0 }; 3862990b4856Slling static char default_props[] = 386386714001SSerapheim Dimitropoulos "name,size,allocated,free,checkpoint,expandsize,fragmentation," 386486714001SSerapheim Dimitropoulos "capacity,dedupratio,health,altroot"; 3865990b4856Slling char *props = default_props; 38663f9d6ad7SLin Ling unsigned long interval = 0, count = 0; 38674263d13fSGeorge Wilson zpool_list_t *list; 38684263d13fSGeorge Wilson boolean_t first = B_TRUE; 3869fa9e4066Sahrens 3870fa9e4066Sahrens /* check options */ 3871663207adSDon Brady while ((c = getopt(argc, argv, ":gHLo:pPT:v")) != -1) { 3872fa9e4066Sahrens switch (c) { 3873663207adSDon Brady case 'g': 3874663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_GUID; 3875663207adSDon Brady break; 3876fa9e4066Sahrens case 'H': 387799653d4eSeschrock cb.cb_scripted = B_TRUE; 3878fa9e4066Sahrens break; 3879663207adSDon Brady case 'L': 3880663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS; 3881663207adSDon Brady break; 3882fa9e4066Sahrens case 'o': 3883990b4856Slling props = optarg; 3884fa9e4066Sahrens break; 3885663207adSDon Brady case 'P': 3886663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_PATH; 3887663207adSDon Brady break; 3888c58b3526SAdam Stevko case 'p': 3889c58b3526SAdam Stevko cb.cb_literal = B_TRUE; 3890c58b3526SAdam Stevko break; 38913f9d6ad7SLin Ling case 'T': 38923f9d6ad7SLin Ling get_timestamp_arg(*optarg); 38933f9d6ad7SLin Ling break; 38944263d13fSGeorge Wilson case 'v': 38954263d13fSGeorge Wilson cb.cb_verbose = B_TRUE; 3896663207adSDon Brady cb.cb_namewidth = 8; /* 8 until precalc is avail */ 38974263d13fSGeorge Wilson break; 3898fa9e4066Sahrens case ':': 3899fa9e4066Sahrens (void) fprintf(stderr, gettext("missing argument for " 3900fa9e4066Sahrens "'%c' option\n"), optopt); 390199653d4eSeschrock usage(B_FALSE); 3902fa9e4066Sahrens break; 3903fa9e4066Sahrens case '?': 3904fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3905fa9e4066Sahrens optopt); 390699653d4eSeschrock usage(B_FALSE); 3907fa9e4066Sahrens } 3908fa9e4066Sahrens } 3909fa9e4066Sahrens 3910fa9e4066Sahrens argc -= optind; 3911fa9e4066Sahrens argv += optind; 3912fa9e4066Sahrens 39133f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count); 39143f9d6ad7SLin Ling 3915990b4856Slling if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) 3916990b4856Slling usage(B_FALSE); 3917fa9e4066Sahrens 39183f9d6ad7SLin Ling for (;;) { 3919cd67d23dSGeorge Wilson if ((list = pool_list_get(argc, argv, &cb.cb_proplist, 3920cd67d23dSGeorge Wilson &ret)) == NULL) 3921cd67d23dSGeorge Wilson return (1); 39224263d13fSGeorge Wilson 39234263d13fSGeorge Wilson if (pool_list_count(list) == 0) 39244263d13fSGeorge Wilson break; 39254263d13fSGeorge Wilson 39264263d13fSGeorge Wilson cb.cb_namewidth = 0; 39274263d13fSGeorge Wilson (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 3928990b4856Slling 39293f9d6ad7SLin Ling if (timestamp_fmt != NODATE) 39303f9d6ad7SLin Ling print_timestamp(timestamp_fmt); 3931fa9e4066Sahrens 39324263d13fSGeorge Wilson if (!cb.cb_scripted && (first || cb.cb_verbose)) { 39334263d13fSGeorge Wilson print_header(&cb); 39344263d13fSGeorge Wilson first = B_FALSE; 39353f9d6ad7SLin Ling } 39364263d13fSGeorge Wilson ret = pool_list_iter(list, B_TRUE, list_callback, &cb); 39373f9d6ad7SLin Ling 39383f9d6ad7SLin Ling if (interval == 0) 39393f9d6ad7SLin Ling break; 39403f9d6ad7SLin Ling 39413f9d6ad7SLin Ling if (count != 0 && --count == 0) 39423f9d6ad7SLin Ling break; 39433f9d6ad7SLin Ling 3944cd67d23dSGeorge Wilson pool_list_free(list); 39453f9d6ad7SLin Ling (void) sleep(interval); 3946fa9e4066Sahrens } 3947fa9e4066Sahrens 3948cd67d23dSGeorge Wilson if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) { 3949cd67d23dSGeorge Wilson (void) printf(gettext("no pools available\n")); 3950cd67d23dSGeorge Wilson ret = 0; 3951cd67d23dSGeorge Wilson } 3952cd67d23dSGeorge Wilson 3953cd67d23dSGeorge Wilson pool_list_free(list); 39543f9d6ad7SLin Ling zprop_free_list(cb.cb_proplist); 3955fa9e4066Sahrens return (ret); 3956fa9e4066Sahrens } 3957fa9e4066Sahrens 3958fa9e4066Sahrens static int 3959fa9e4066Sahrens zpool_do_attach_or_replace(int argc, char **argv, int replacing) 3960fa9e4066Sahrens { 396199653d4eSeschrock boolean_t force = B_FALSE; 3962fa9e4066Sahrens int c; 3963fa9e4066Sahrens nvlist_t *nvroot; 3964fa9e4066Sahrens char *poolname, *old_disk, *new_disk; 3965fa9e4066Sahrens zpool_handle_t *zhp; 39667855d95bSToomas Soome zpool_boot_label_t boot_type; 39677855d95bSToomas Soome uint64_t boot_size; 3968*5711d393Sloli nvlist_t *props = NULL; 3969*5711d393Sloli char *propval; 397099653d4eSeschrock int ret; 3971fa9e4066Sahrens 3972fa9e4066Sahrens /* check options */ 3973*5711d393Sloli while ((c = getopt(argc, argv, "fo:")) != -1) { 3974fa9e4066Sahrens switch (c) { 3975fa9e4066Sahrens case 'f': 397699653d4eSeschrock force = B_TRUE; 3977fa9e4066Sahrens break; 3978*5711d393Sloli case 'o': 3979*5711d393Sloli if ((propval = strchr(optarg, '=')) == NULL) { 3980*5711d393Sloli (void) fprintf(stderr, gettext("missing " 3981*5711d393Sloli "'=' for -o option\n")); 3982*5711d393Sloli usage(B_FALSE); 3983*5711d393Sloli } 3984*5711d393Sloli *propval = '\0'; 3985*5711d393Sloli propval++; 3986*5711d393Sloli 3987*5711d393Sloli if ((strcmp(optarg, ZPOOL_CONFIG_ASHIFT) != 0) || 3988*5711d393Sloli (add_prop_list(optarg, propval, &props, B_TRUE))) 3989*5711d393Sloli usage(B_FALSE); 3990*5711d393Sloli break; 3991fa9e4066Sahrens case '?': 3992fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3993fa9e4066Sahrens optopt); 399499653d4eSeschrock usage(B_FALSE); 3995fa9e4066Sahrens } 3996fa9e4066Sahrens } 3997fa9e4066Sahrens 3998fa9e4066Sahrens argc -= optind; 3999fa9e4066Sahrens argv += optind; 4000fa9e4066Sahrens 4001fa9e4066Sahrens /* get pool name and check number of arguments */ 4002fa9e4066Sahrens if (argc < 1) { 4003fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 400499653d4eSeschrock usage(B_FALSE); 4005fa9e4066Sahrens } 4006fa9e4066Sahrens 4007fa9e4066Sahrens poolname = argv[0]; 4008fa9e4066Sahrens 4009fa9e4066Sahrens if (argc < 2) { 4010fa9e4066Sahrens (void) fprintf(stderr, 4011fa9e4066Sahrens gettext("missing <device> specification\n")); 401299653d4eSeschrock usage(B_FALSE); 4013fa9e4066Sahrens } 4014fa9e4066Sahrens 4015fa9e4066Sahrens old_disk = argv[1]; 4016fa9e4066Sahrens 4017fa9e4066Sahrens if (argc < 3) { 4018fa9e4066Sahrens if (!replacing) { 4019fa9e4066Sahrens (void) fprintf(stderr, 4020fa9e4066Sahrens gettext("missing <new_device> specification\n")); 402199653d4eSeschrock usage(B_FALSE); 4022fa9e4066Sahrens } 4023fa9e4066Sahrens new_disk = old_disk; 4024fa9e4066Sahrens argc -= 1; 4025fa9e4066Sahrens argv += 1; 4026fa9e4066Sahrens } else { 4027fa9e4066Sahrens new_disk = argv[2]; 4028fa9e4066Sahrens argc -= 2; 4029fa9e4066Sahrens argv += 2; 4030fa9e4066Sahrens } 4031fa9e4066Sahrens 4032fa9e4066Sahrens if (argc > 1) { 4033fa9e4066Sahrens (void) fprintf(stderr, gettext("too many arguments\n")); 403499653d4eSeschrock usage(B_FALSE); 4035fa9e4066Sahrens } 4036fa9e4066Sahrens 403799653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 4038fa9e4066Sahrens return (1); 4039fa9e4066Sahrens 40408488aeb5Staylor if (zpool_get_config(zhp, NULL) == NULL) { 4041fa9e4066Sahrens (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 4042fa9e4066Sahrens poolname); 4043fa9e4066Sahrens zpool_close(zhp); 4044fa9e4066Sahrens return (1); 4045fa9e4066Sahrens } 4046fa9e4066Sahrens 40477855d95bSToomas Soome if (zpool_is_bootable(zhp)) 40487855d95bSToomas Soome boot_type = ZPOOL_COPY_BOOT_LABEL; 40497855d95bSToomas Soome else 40507855d95bSToomas Soome boot_type = ZPOOL_NO_BOOT_LABEL; 40517855d95bSToomas Soome 40527855d95bSToomas Soome boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL); 4053*5711d393Sloli 4054*5711d393Sloli /* unless manually specified use "ashift" pool property (if set) */ 4055*5711d393Sloli if (!nvlist_exists(props, ZPOOL_CONFIG_ASHIFT)) { 4056*5711d393Sloli int intval; 4057*5711d393Sloli zprop_source_t src; 4058*5711d393Sloli char strval[ZPOOL_MAXPROPLEN]; 4059*5711d393Sloli 4060*5711d393Sloli intval = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, &src); 4061*5711d393Sloli if (src != ZPROP_SRC_DEFAULT) { 4062*5711d393Sloli (void) sprintf(strval, "%" PRId32, intval); 4063*5711d393Sloli verify(add_prop_list(ZPOOL_CONFIG_ASHIFT, strval, 4064*5711d393Sloli &props, B_TRUE) == 0); 4065*5711d393Sloli } 4066*5711d393Sloli } 4067*5711d393Sloli 4068*5711d393Sloli nvroot = make_root_vdev(zhp, props, force, B_FALSE, replacing, B_FALSE, 40697855d95bSToomas Soome boot_type, boot_size, argc, argv); 4070fa9e4066Sahrens if (nvroot == NULL) { 4071fa9e4066Sahrens zpool_close(zhp); 4072fa9e4066Sahrens return (1); 4073fa9e4066Sahrens } 4074fa9e4066Sahrens 407599653d4eSeschrock ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); 407699653d4eSeschrock 407799653d4eSeschrock nvlist_free(nvroot); 407899653d4eSeschrock zpool_close(zhp); 407999653d4eSeschrock 408099653d4eSeschrock return (ret); 4081fa9e4066Sahrens } 4082fa9e4066Sahrens 4083fa9e4066Sahrens /* 4084fa9e4066Sahrens * zpool replace [-f] <pool> <device> <new_device> 4085fa9e4066Sahrens * 4086fa9e4066Sahrens * -f Force attach, even if <new_device> appears to be in use. 4087fa9e4066Sahrens * 4088fa9e4066Sahrens * Replace <device> with <new_device>. 4089fa9e4066Sahrens */ 4090fa9e4066Sahrens /* ARGSUSED */ 4091fa9e4066Sahrens int 4092fa9e4066Sahrens zpool_do_replace(int argc, char **argv) 4093fa9e4066Sahrens { 4094fa9e4066Sahrens return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 4095fa9e4066Sahrens } 4096fa9e4066Sahrens 4097fa9e4066Sahrens /* 4098*5711d393Sloli * zpool attach [-f] [-o property=value] <pool> <device> <new_device> 4099fa9e4066Sahrens * 4100fa9e4066Sahrens * -f Force attach, even if <new_device> appears to be in use. 4101*5711d393Sloli * -o Set property=value. 4102fa9e4066Sahrens * 4103fa9e4066Sahrens * Attach <new_device> to the mirror containing <device>. If <device> is not 4104fa9e4066Sahrens * part of a mirror, then <device> will be transformed into a mirror of 4105fa9e4066Sahrens * <device> and <new_device>. In either case, <new_device> will begin life 4106fa9e4066Sahrens * with a DTL of [0, now], and will immediately begin to resilver itself. 4107fa9e4066Sahrens */ 4108fa9e4066Sahrens int 4109fa9e4066Sahrens zpool_do_attach(int argc, char **argv) 4110fa9e4066Sahrens { 4111fa9e4066Sahrens return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 4112fa9e4066Sahrens } 4113fa9e4066Sahrens 4114fa9e4066Sahrens /* 4115fa9e4066Sahrens * zpool detach [-f] <pool> <device> 4116fa9e4066Sahrens * 4117fa9e4066Sahrens * -f Force detach of <device>, even if DTLs argue against it 4118fa9e4066Sahrens * (not supported yet) 4119fa9e4066Sahrens * 4120fa9e4066Sahrens * Detach a device from a mirror. The operation will be refused if <device> 4121fa9e4066Sahrens * is the last device in the mirror, or if the DTLs indicate that this device 4122fa9e4066Sahrens * has the only valid copy of some data. 4123fa9e4066Sahrens */ 4124fa9e4066Sahrens /* ARGSUSED */ 4125fa9e4066Sahrens int 4126fa9e4066Sahrens zpool_do_detach(int argc, char **argv) 4127fa9e4066Sahrens { 4128fa9e4066Sahrens int c; 4129fa9e4066Sahrens char *poolname, *path; 4130fa9e4066Sahrens zpool_handle_t *zhp; 413199653d4eSeschrock int ret; 4132fa9e4066Sahrens 4133fa9e4066Sahrens /* check options */ 4134fa9e4066Sahrens while ((c = getopt(argc, argv, "f")) != -1) { 4135fa9e4066Sahrens switch (c) { 4136fa9e4066Sahrens case 'f': 4137fa9e4066Sahrens case '?': 4138fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4139fa9e4066Sahrens optopt); 414099653d4eSeschrock usage(B_FALSE); 4141fa9e4066Sahrens } 4142fa9e4066Sahrens } 4143fa9e4066Sahrens 4144fa9e4066Sahrens argc -= optind; 4145fa9e4066Sahrens argv += optind; 4146fa9e4066Sahrens 4147fa9e4066Sahrens /* get pool name and check number of arguments */ 4148fa9e4066Sahrens if (argc < 1) { 4149fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 415099653d4eSeschrock usage(B_FALSE); 4151fa9e4066Sahrens } 4152fa9e4066Sahrens 4153fa9e4066Sahrens if (argc < 2) { 4154fa9e4066Sahrens (void) fprintf(stderr, 4155fa9e4066Sahrens gettext("missing <device> specification\n")); 415699653d4eSeschrock usage(B_FALSE); 4157fa9e4066Sahrens } 4158fa9e4066Sahrens 4159fa9e4066Sahrens poolname = argv[0]; 4160fa9e4066Sahrens path = argv[1]; 4161fa9e4066Sahrens 416299653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 4163fa9e4066Sahrens return (1); 4164fa9e4066Sahrens 416599653d4eSeschrock ret = zpool_vdev_detach(zhp, path); 416699653d4eSeschrock 416799653d4eSeschrock zpool_close(zhp); 416899653d4eSeschrock 416999653d4eSeschrock return (ret); 4170fa9e4066Sahrens } 4171fa9e4066Sahrens 41721195e687SMark J Musante /* 4173663207adSDon Brady * zpool split [-gLnP] [-o prop=val] ... 41741195e687SMark J Musante * [-o mntopt] ... 41751195e687SMark J Musante * [-R altroot] <pool> <newpool> [<device> ...] 41761195e687SMark J Musante * 4177663207adSDon Brady * -g Display guid for individual vdev name. 4178663207adSDon Brady * -L Follow links when resolving vdev path name. 41791195e687SMark J Musante * -n Do not split the pool, but display the resulting layout if 41801195e687SMark J Musante * it were to be split. 41811195e687SMark J Musante * -o Set property=value, or set mount options. 4182663207adSDon Brady * -P Display full path for vdev name. 41831195e687SMark J Musante * -R Mount the split-off pool under an alternate root. 4184eb633035STom Caputi * -l Load encryption keys while importing. 41851195e687SMark J Musante * 41861195e687SMark J Musante * Splits the named pool and gives it the new pool name. Devices to be split 41871195e687SMark J Musante * off may be listed, provided that no more than one device is specified 41881195e687SMark J Musante * per top-level vdev mirror. The newly split pool is left in an exported 41891195e687SMark J Musante * state unless -R is specified. 41901195e687SMark J Musante * 41911195e687SMark J Musante * Restrictions: the top-level of the pool pool must only be made up of 41921195e687SMark J Musante * mirrors; all devices in the pool must be healthy; no device may be 41931195e687SMark J Musante * undergoing a resilvering operation. 41941195e687SMark J Musante */ 41951195e687SMark J Musante int 41961195e687SMark J Musante zpool_do_split(int argc, char **argv) 41971195e687SMark J Musante { 41981195e687SMark J Musante char *srcpool, *newpool, *propval; 41991195e687SMark J Musante char *mntopts = NULL; 42001195e687SMark J Musante splitflags_t flags; 42011195e687SMark J Musante int c, ret = 0; 4202eb633035STom Caputi boolean_t loadkeys = B_FALSE; 42031195e687SMark J Musante zpool_handle_t *zhp; 42041195e687SMark J Musante nvlist_t *config, *props = NULL; 42051195e687SMark J Musante 42061195e687SMark J Musante flags.dryrun = B_FALSE; 42071195e687SMark J Musante flags.import = B_FALSE; 4208663207adSDon Brady flags.name_flags = 0; 42091195e687SMark J Musante 42101195e687SMark J Musante /* check options */ 4211eb633035STom Caputi while ((c = getopt(argc, argv, ":gLR:lno:P")) != -1) { 42121195e687SMark J Musante switch (c) { 4213663207adSDon Brady case 'g': 4214663207adSDon Brady flags.name_flags |= VDEV_NAME_GUID; 4215663207adSDon Brady break; 4216663207adSDon Brady case 'L': 4217663207adSDon Brady flags.name_flags |= VDEV_NAME_FOLLOW_LINKS; 4218663207adSDon Brady break; 42191195e687SMark J Musante case 'R': 42201195e687SMark J Musante flags.import = B_TRUE; 42211195e687SMark J Musante if (add_prop_list( 42221195e687SMark J Musante zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg, 42231195e687SMark J Musante &props, B_TRUE) != 0) { 4224aab83bb8SJosef 'Jeff' Sipek nvlist_free(props); 42251195e687SMark J Musante usage(B_FALSE); 42261195e687SMark J Musante } 42271195e687SMark J Musante break; 4228eb633035STom Caputi case 'l': 4229eb633035STom Caputi loadkeys = B_TRUE; 4230eb633035STom Caputi break; 42311195e687SMark J Musante case 'n': 42321195e687SMark J Musante flags.dryrun = B_TRUE; 42331195e687SMark J Musante break; 42341195e687SMark J Musante case 'o': 42351195e687SMark J Musante if ((propval = strchr(optarg, '=')) != NULL) { 42361195e687SMark J Musante *propval = '\0'; 42371195e687SMark J Musante propval++; 42381195e687SMark J Musante if (add_prop_list(optarg, propval, 42391195e687SMark J Musante &props, B_TRUE) != 0) { 4240aab83bb8SJosef 'Jeff' Sipek nvlist_free(props); 42411195e687SMark J Musante usage(B_FALSE); 42421195e687SMark J Musante } 42431195e687SMark J Musante } else { 42441195e687SMark J Musante mntopts = optarg; 42451195e687SMark J Musante } 42461195e687SMark J Musante break; 4247663207adSDon Brady case 'P': 4248663207adSDon Brady flags.name_flags |= VDEV_NAME_PATH; 4249663207adSDon Brady break; 42501195e687SMark J Musante case ':': 42511195e687SMark J Musante (void) fprintf(stderr, gettext("missing argument for " 42521195e687SMark J Musante "'%c' option\n"), optopt); 42531195e687SMark J Musante usage(B_FALSE); 42541195e687SMark J Musante break; 42551195e687SMark J Musante case '?': 42561195e687SMark J Musante (void) fprintf(stderr, gettext("invalid option '%c'\n"), 42571195e687SMark J Musante optopt); 42581195e687SMark J Musante usage(B_FALSE); 42591195e687SMark J Musante break; 42601195e687SMark J Musante } 42611195e687SMark J Musante } 42621195e687SMark J Musante 42631195e687SMark J Musante if (!flags.import && mntopts != NULL) { 42641195e687SMark J Musante (void) fprintf(stderr, gettext("setting mntopts is only " 42651195e687SMark J Musante "valid when importing the pool\n")); 42661195e687SMark J Musante usage(B_FALSE); 42671195e687SMark J Musante } 42681195e687SMark J Musante 4269eb633035STom Caputi if (!flags.import && loadkeys) { 4270eb633035STom Caputi (void) fprintf(stderr, gettext("loading keys is only " 4271eb633035STom Caputi "valid when importing the pool\n")); 4272eb633035STom Caputi usage(B_FALSE); 4273eb633035STom Caputi } 4274eb633035STom Caputi 42751195e687SMark J Musante argc -= optind; 42761195e687SMark J Musante argv += optind; 42771195e687SMark J Musante 42781195e687SMark J Musante if (argc < 1) { 42791195e687SMark J Musante (void) fprintf(stderr, gettext("Missing pool name\n")); 42801195e687SMark J Musante usage(B_FALSE); 42811195e687SMark J Musante } 42821195e687SMark J Musante if (argc < 2) { 42831195e687SMark J Musante (void) fprintf(stderr, gettext("Missing new pool name\n")); 42841195e687SMark J Musante usage(B_FALSE); 42851195e687SMark J Musante } 42861195e687SMark J Musante 42871195e687SMark J Musante srcpool = argv[0]; 42881195e687SMark J Musante newpool = argv[1]; 42891195e687SMark J Musante 42901195e687SMark J Musante argc -= 2; 42911195e687SMark J Musante argv += 2; 42921195e687SMark J Musante 42931195e687SMark J Musante if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) 42941195e687SMark J Musante return (1); 42951195e687SMark J Musante 42961195e687SMark J Musante config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv); 42971195e687SMark J Musante if (config == NULL) { 42981195e687SMark J Musante ret = 1; 42991195e687SMark J Musante } else { 43001195e687SMark J Musante if (flags.dryrun) { 43011195e687SMark J Musante (void) printf(gettext("would create '%s' with the " 43021195e687SMark J Musante "following layout:\n\n"), newpool); 4303663207adSDon Brady print_vdev_tree(NULL, newpool, config, 0, "", 4304663207adSDon Brady flags.name_flags); 43051195e687SMark J Musante } 43061195e687SMark J Musante nvlist_free(config); 43071195e687SMark J Musante } 43081195e687SMark J Musante 43091195e687SMark J Musante zpool_close(zhp); 43101195e687SMark J Musante 43111195e687SMark J Musante if (ret != 0 || flags.dryrun || !flags.import) 43121195e687SMark J Musante return (ret); 43131195e687SMark J Musante 43141195e687SMark J Musante /* 43151195e687SMark J Musante * The split was successful. Now we need to open the new 43161195e687SMark J Musante * pool and import it. 43171195e687SMark J Musante */ 43181195e687SMark J Musante if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) 43191195e687SMark J Musante return (1); 4320eb633035STom Caputi 4321eb633035STom Caputi if (loadkeys) { 4322eb633035STom Caputi ret = zfs_crypto_attempt_load_keys(g_zfs, newpool); 4323eb633035STom Caputi if (ret != 0) 4324eb633035STom Caputi ret = 1; 4325eb633035STom Caputi } 4326eb633035STom Caputi 43271195e687SMark J Musante if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 43281195e687SMark J Musante zpool_enable_datasets(zhp, mntopts, 0) != 0) { 43291195e687SMark J Musante ret = 1; 4330fe7cd8aaSCyril Plisko (void) fprintf(stderr, gettext("Split was successful, but " 43311195e687SMark J Musante "the datasets could not all be mounted\n")); 43321195e687SMark J Musante (void) fprintf(stderr, gettext("Try doing '%s' with a " 43331195e687SMark J Musante "different altroot\n"), "zpool import"); 43341195e687SMark J Musante } 43351195e687SMark J Musante zpool_close(zhp); 43361195e687SMark J Musante 43371195e687SMark J Musante return (ret); 43381195e687SMark J Musante } 43391195e687SMark J Musante 43401195e687SMark J Musante 43411195e687SMark J Musante 4342fa9e4066Sahrens /* 4343441d80aaSlling * zpool online <pool> <device> ... 4344fa9e4066Sahrens */ 4345fa9e4066Sahrens int 4346fa9e4066Sahrens zpool_do_online(int argc, char **argv) 4347fa9e4066Sahrens { 4348fa9e4066Sahrens int c, i; 4349fa9e4066Sahrens char *poolname; 4350fa9e4066Sahrens zpool_handle_t *zhp; 4351fa9e4066Sahrens int ret = 0; 43523d7072f8Seschrock vdev_state_t newstate; 4353573ca77eSGeorge Wilson int flags = 0; 4354fa9e4066Sahrens 4355fa9e4066Sahrens /* check options */ 4356573ca77eSGeorge Wilson while ((c = getopt(argc, argv, "et")) != -1) { 4357fa9e4066Sahrens switch (c) { 4358573ca77eSGeorge Wilson case 'e': 4359573ca77eSGeorge Wilson flags |= ZFS_ONLINE_EXPAND; 4360573ca77eSGeorge Wilson break; 4361fa9e4066Sahrens case 't': 4362fa9e4066Sahrens case '?': 4363fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4364fa9e4066Sahrens optopt); 436599653d4eSeschrock usage(B_FALSE); 4366fa9e4066Sahrens } 4367fa9e4066Sahrens } 4368fa9e4066Sahrens 4369fa9e4066Sahrens argc -= optind; 4370fa9e4066Sahrens argv += optind; 4371fa9e4066Sahrens 4372fa9e4066Sahrens /* get pool name and check number of arguments */ 4373fa9e4066Sahrens if (argc < 1) { 4374fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name\n")); 437599653d4eSeschrock usage(B_FALSE); 4376fa9e4066Sahrens } 4377fa9e4066Sahrens if (argc < 2) { 4378fa9e4066Sahrens (void) fprintf(stderr, gettext("missing device name\n")); 437999653d4eSeschrock usage(B_FALSE); 4380fa9e4066Sahrens } 4381fa9e4066Sahrens 4382fa9e4066Sahrens poolname = argv[0]; 4383fa9e4066Sahrens 438499653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 4385fa9e4066Sahrens return (1); 4386fa9e4066Sahrens 43873d7072f8Seschrock for (i = 1; i < argc; i++) { 4388573ca77eSGeorge Wilson if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) { 43893d7072f8Seschrock if (newstate != VDEV_STATE_HEALTHY) { 43903d7072f8Seschrock (void) printf(gettext("warning: device '%s' " 43913d7072f8Seschrock "onlined, but remains in faulted state\n"), 43923d7072f8Seschrock argv[i]); 43933d7072f8Seschrock if (newstate == VDEV_STATE_FAULTED) 43943d7072f8Seschrock (void) printf(gettext("use 'zpool " 43953d7072f8Seschrock "clear' to restore a faulted " 43963d7072f8Seschrock "device\n")); 43973d7072f8Seschrock else 43983d7072f8Seschrock (void) printf(gettext("use 'zpool " 43993d7072f8Seschrock "replace' to replace devices " 44003d7072f8Seschrock "that are no longer present\n")); 44013d7072f8Seschrock } 44023d7072f8Seschrock } else { 4403fa9e4066Sahrens ret = 1; 44043d7072f8Seschrock } 44053d7072f8Seschrock } 4406fa9e4066Sahrens 440799653d4eSeschrock zpool_close(zhp); 440899653d4eSeschrock 4409fa9e4066Sahrens return (ret); 4410fa9e4066Sahrens } 4411fa9e4066Sahrens 4412fa9e4066Sahrens /* 4413441d80aaSlling * zpool offline [-ft] <pool> <device> ... 4414fa9e4066Sahrens * 4415fa9e4066Sahrens * -f Force the device into the offline state, even if doing 4416fa9e4066Sahrens * so would appear to compromise pool availability. 4417fa9e4066Sahrens * (not supported yet) 4418fa9e4066Sahrens * 4419fa9e4066Sahrens * -t Only take the device off-line temporarily. The offline 4420fa9e4066Sahrens * state will not be persistent across reboots. 4421fa9e4066Sahrens */ 4422fa9e4066Sahrens /* ARGSUSED */ 4423fa9e4066Sahrens int 4424fa9e4066Sahrens zpool_do_offline(int argc, char **argv) 4425fa9e4066Sahrens { 4426fa9e4066Sahrens int c, i; 4427fa9e4066Sahrens char *poolname; 4428fa9e4066Sahrens zpool_handle_t *zhp; 442999653d4eSeschrock int ret = 0; 443099653d4eSeschrock boolean_t istmp = B_FALSE; 4431fa9e4066Sahrens 4432fa9e4066Sahrens /* check options */ 4433fa9e4066Sahrens while ((c = getopt(argc, argv, "ft")) != -1) { 4434fa9e4066Sahrens switch (c) { 4435fa9e4066Sahrens case 't': 443699653d4eSeschrock istmp = B_TRUE; 4437441d80aaSlling break; 4438441d80aaSlling case 'f': 4439fa9e4066Sahrens case '?': 4440fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4441fa9e4066Sahrens optopt); 444299653d4eSeschrock usage(B_FALSE); 4443fa9e4066Sahrens } 4444fa9e4066Sahrens } 4445fa9e4066Sahrens 4446fa9e4066Sahrens argc -= optind; 4447fa9e4066Sahrens argv += optind; 4448fa9e4066Sahrens 4449fa9e4066Sahrens /* get pool name and check number of arguments */ 4450fa9e4066Sahrens if (argc < 1) { 4451fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name\n")); 445299653d4eSeschrock usage(B_FALSE); 4453fa9e4066Sahrens } 4454fa9e4066Sahrens if (argc < 2) { 4455fa9e4066Sahrens (void) fprintf(stderr, gettext("missing device name\n")); 445699653d4eSeschrock usage(B_FALSE); 4457fa9e4066Sahrens } 4458fa9e4066Sahrens 4459fa9e4066Sahrens poolname = argv[0]; 4460fa9e4066Sahrens 446199653d4eSeschrock if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 4462fa9e4066Sahrens return (1); 4463fa9e4066Sahrens 44643d7072f8Seschrock for (i = 1; i < argc; i++) { 44653d7072f8Seschrock if (zpool_vdev_offline(zhp, argv[i], istmp) != 0) 4466fa9e4066Sahrens ret = 1; 44673d7072f8Seschrock } 4468fa9e4066Sahrens 446999653d4eSeschrock zpool_close(zhp); 447099653d4eSeschrock 4471fa9e4066Sahrens return (ret); 4472fa9e4066Sahrens } 4473fa9e4066Sahrens 4474ea8dc4b6Seschrock /* 4475ea8dc4b6Seschrock * zpool clear <pool> [device] 4476ea8dc4b6Seschrock * 4477ea8dc4b6Seschrock * Clear all errors associated with a pool or a particular device. 4478ea8dc4b6Seschrock */ 4479ea8dc4b6Seschrock int 4480ea8dc4b6Seschrock zpool_do_clear(int argc, char **argv) 4481ea8dc4b6Seschrock { 4482468c413aSTim Haley int c; 4483ea8dc4b6Seschrock int ret = 0; 4484468c413aSTim Haley boolean_t dryrun = B_FALSE; 4485468c413aSTim Haley boolean_t do_rewind = B_FALSE; 4486468c413aSTim Haley boolean_t xtreme_rewind = B_FALSE; 4487468c413aSTim Haley uint32_t rewind_policy = ZPOOL_NO_REWIND; 4488468c413aSTim Haley nvlist_t *policy = NULL; 4489ea8dc4b6Seschrock zpool_handle_t *zhp; 4490ea8dc4b6Seschrock char *pool, *device; 4491ea8dc4b6Seschrock 4492468c413aSTim Haley /* check options */ 4493468c413aSTim Haley while ((c = getopt(argc, argv, "FnX")) != -1) { 4494468c413aSTim Haley switch (c) { 4495468c413aSTim Haley case 'F': 4496468c413aSTim Haley do_rewind = B_TRUE; 4497468c413aSTim Haley break; 4498468c413aSTim Haley case 'n': 4499468c413aSTim Haley dryrun = B_TRUE; 4500468c413aSTim Haley break; 4501468c413aSTim Haley case 'X': 4502468c413aSTim Haley xtreme_rewind = B_TRUE; 4503468c413aSTim Haley break; 4504468c413aSTim Haley case '?': 4505468c413aSTim Haley (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4506468c413aSTim Haley optopt); 4507468c413aSTim Haley usage(B_FALSE); 4508468c413aSTim Haley } 4509468c413aSTim Haley } 4510468c413aSTim Haley 4511468c413aSTim Haley argc -= optind; 4512468c413aSTim Haley argv += optind; 4513468c413aSTim Haley 4514468c413aSTim Haley if (argc < 1) { 4515ea8dc4b6Seschrock (void) fprintf(stderr, gettext("missing pool name\n")); 451699653d4eSeschrock usage(B_FALSE); 4517ea8dc4b6Seschrock } 4518ea8dc4b6Seschrock 4519468c413aSTim Haley if (argc > 2) { 4520ea8dc4b6Seschrock (void) fprintf(stderr, gettext("too many arguments\n")); 452199653d4eSeschrock usage(B_FALSE); 4522ea8dc4b6Seschrock } 4523ea8dc4b6Seschrock 4524468c413aSTim Haley if ((dryrun || xtreme_rewind) && !do_rewind) { 4525468c413aSTim Haley (void) fprintf(stderr, 4526468c413aSTim Haley gettext("-n or -X only meaningful with -F\n")); 4527468c413aSTim Haley usage(B_FALSE); 4528468c413aSTim Haley } 4529468c413aSTim Haley if (dryrun) 4530468c413aSTim Haley rewind_policy = ZPOOL_TRY_REWIND; 4531468c413aSTim Haley else if (do_rewind) 4532468c413aSTim Haley rewind_policy = ZPOOL_DO_REWIND; 4533468c413aSTim Haley if (xtreme_rewind) 4534468c413aSTim Haley rewind_policy |= ZPOOL_EXTREME_REWIND; 4535468c413aSTim Haley 4536468c413aSTim Haley /* In future, further rewind policy choices can be passed along here */ 4537468c413aSTim Haley if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 45385dafeea3SPavel Zakharov nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, 45395dafeea3SPavel Zakharov rewind_policy) != 0) { 4540468c413aSTim Haley return (1); 45415dafeea3SPavel Zakharov } 4542468c413aSTim Haley 4543468c413aSTim Haley pool = argv[0]; 4544468c413aSTim Haley device = argc == 2 ? argv[1] : NULL; 4545ea8dc4b6Seschrock 4546468c413aSTim Haley if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 4547468c413aSTim Haley nvlist_free(policy); 4548ea8dc4b6Seschrock return (1); 4549468c413aSTim Haley } 4550ea8dc4b6Seschrock 4551468c413aSTim Haley if (zpool_clear(zhp, device, policy) != 0) 4552ea8dc4b6Seschrock ret = 1; 4553ea8dc4b6Seschrock 4554ea8dc4b6Seschrock zpool_close(zhp); 4555ea8dc4b6Seschrock 4556468c413aSTim Haley nvlist_free(policy); 4557468c413aSTim Haley 4558ea8dc4b6Seschrock return (ret); 4559ea8dc4b6Seschrock } 4560ea8dc4b6Seschrock 4561e9103aaeSGarrett D'Amore /* 4562e9103aaeSGarrett D'Amore * zpool reguid <pool> 4563e9103aaeSGarrett D'Amore */ 4564e9103aaeSGarrett D'Amore int 4565e9103aaeSGarrett D'Amore zpool_do_reguid(int argc, char **argv) 4566e9103aaeSGarrett D'Amore { 4567e9103aaeSGarrett D'Amore int c; 4568e9103aaeSGarrett D'Amore char *poolname; 4569e9103aaeSGarrett D'Amore zpool_handle_t *zhp; 4570e9103aaeSGarrett D'Amore int ret = 0; 4571e9103aaeSGarrett D'Amore 4572e9103aaeSGarrett D'Amore /* check options */ 4573e9103aaeSGarrett D'Amore while ((c = getopt(argc, argv, "")) != -1) { 4574e9103aaeSGarrett D'Amore switch (c) { 4575e9103aaeSGarrett D'Amore case '?': 4576e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4577e9103aaeSGarrett D'Amore optopt); 4578e9103aaeSGarrett D'Amore usage(B_FALSE); 4579e9103aaeSGarrett D'Amore } 4580e9103aaeSGarrett D'Amore } 4581e9103aaeSGarrett D'Amore 4582e9103aaeSGarrett D'Amore argc -= optind; 4583e9103aaeSGarrett D'Amore argv += optind; 4584e9103aaeSGarrett D'Amore 4585e9103aaeSGarrett D'Amore /* get pool name and check number of arguments */ 4586e9103aaeSGarrett D'Amore if (argc < 1) { 4587e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("missing pool name\n")); 4588e9103aaeSGarrett D'Amore usage(B_FALSE); 4589e9103aaeSGarrett D'Amore } 4590e9103aaeSGarrett D'Amore 4591e9103aaeSGarrett D'Amore if (argc > 1) { 4592e9103aaeSGarrett D'Amore (void) fprintf(stderr, gettext("too many arguments\n")); 4593e9103aaeSGarrett D'Amore usage(B_FALSE); 4594e9103aaeSGarrett D'Amore } 4595e9103aaeSGarrett D'Amore 4596e9103aaeSGarrett D'Amore poolname = argv[0]; 4597e9103aaeSGarrett D'Amore if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 4598e9103aaeSGarrett D'Amore return (1); 4599e9103aaeSGarrett D'Amore 4600e9103aaeSGarrett D'Amore ret = zpool_reguid(zhp); 4601e9103aaeSGarrett D'Amore 4602e9103aaeSGarrett D'Amore zpool_close(zhp); 4603e9103aaeSGarrett D'Amore return (ret); 4604e9103aaeSGarrett D'Amore } 4605e9103aaeSGarrett D'Amore 4606e9103aaeSGarrett D'Amore 46074263d13fSGeorge Wilson /* 46084263d13fSGeorge Wilson * zpool reopen <pool> 46094263d13fSGeorge Wilson * 46104263d13fSGeorge Wilson * Reopen the pool so that the kernel can update the sizes of all vdevs. 46114263d13fSGeorge Wilson */ 46124263d13fSGeorge Wilson int 46134263d13fSGeorge Wilson zpool_do_reopen(int argc, char **argv) 46144263d13fSGeorge Wilson { 461531d7e8faSGeorge Wilson int c; 46164263d13fSGeorge Wilson int ret = 0; 46174263d13fSGeorge Wilson zpool_handle_t *zhp; 46184263d13fSGeorge Wilson char *pool; 46194263d13fSGeorge Wilson 462031d7e8faSGeorge Wilson /* check options */ 462131d7e8faSGeorge Wilson while ((c = getopt(argc, argv, "")) != -1) { 462231d7e8faSGeorge Wilson switch (c) { 462331d7e8faSGeorge Wilson case '?': 462431d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("invalid option '%c'\n"), 462531d7e8faSGeorge Wilson optopt); 462631d7e8faSGeorge Wilson usage(B_FALSE); 462731d7e8faSGeorge Wilson } 462831d7e8faSGeorge Wilson } 462931d7e8faSGeorge Wilson 46304263d13fSGeorge Wilson argc--; 46314263d13fSGeorge Wilson argv++; 46324263d13fSGeorge Wilson 463331d7e8faSGeorge Wilson if (argc < 1) { 463431d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("missing pool name\n")); 463531d7e8faSGeorge Wilson usage(B_FALSE); 463631d7e8faSGeorge Wilson } 463731d7e8faSGeorge Wilson 463831d7e8faSGeorge Wilson if (argc > 1) { 463931d7e8faSGeorge Wilson (void) fprintf(stderr, gettext("too many arguments\n")); 464031d7e8faSGeorge Wilson usage(B_FALSE); 464131d7e8faSGeorge Wilson } 46424263d13fSGeorge Wilson 46434263d13fSGeorge Wilson pool = argv[0]; 46444263d13fSGeorge Wilson if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) 46454263d13fSGeorge Wilson return (1); 46464263d13fSGeorge Wilson 46474263d13fSGeorge Wilson ret = zpool_reopen(zhp); 46484263d13fSGeorge Wilson zpool_close(zhp); 46494263d13fSGeorge Wilson return (ret); 46504263d13fSGeorge Wilson } 46514263d13fSGeorge Wilson 4652fa9e4066Sahrens typedef struct scrub_cbdata { 4653fa9e4066Sahrens int cb_type; 465406eeb2adSek int cb_argc; 465506eeb2adSek char **cb_argv; 46561702cce7SAlek Pinchuk pool_scrub_cmd_t cb_scrub_cmd; 4657fa9e4066Sahrens } scrub_cbdata_t; 4658fa9e4066Sahrens 465986714001SSerapheim Dimitropoulos static boolean_t 466086714001SSerapheim Dimitropoulos zpool_has_checkpoint(zpool_handle_t *zhp) 466186714001SSerapheim Dimitropoulos { 466286714001SSerapheim Dimitropoulos nvlist_t *config, *nvroot; 466386714001SSerapheim Dimitropoulos 466486714001SSerapheim Dimitropoulos config = zpool_get_config(zhp, NULL); 466586714001SSerapheim Dimitropoulos 466686714001SSerapheim Dimitropoulos if (config != NULL) { 466786714001SSerapheim Dimitropoulos pool_checkpoint_stat_t *pcs = NULL; 466886714001SSerapheim Dimitropoulos uint_t c; 466986714001SSerapheim Dimitropoulos 467086714001SSerapheim Dimitropoulos nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 467186714001SSerapheim Dimitropoulos (void) nvlist_lookup_uint64_array(nvroot, 467286714001SSerapheim Dimitropoulos ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 467386714001SSerapheim Dimitropoulos 467486714001SSerapheim Dimitropoulos if (pcs == NULL || pcs->pcs_state == CS_NONE) 467586714001SSerapheim Dimitropoulos return (B_FALSE); 467686714001SSerapheim Dimitropoulos 467786714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS || 467886714001SSerapheim Dimitropoulos pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 467986714001SSerapheim Dimitropoulos return (B_TRUE); 468086714001SSerapheim Dimitropoulos } 468186714001SSerapheim Dimitropoulos 468286714001SSerapheim Dimitropoulos return (B_FALSE); 468386714001SSerapheim Dimitropoulos } 468486714001SSerapheim Dimitropoulos 4685fa9e4066Sahrens int 4686fa9e4066Sahrens scrub_callback(zpool_handle_t *zhp, void *data) 4687fa9e4066Sahrens { 4688fa9e4066Sahrens scrub_cbdata_t *cb = data; 468906eeb2adSek int err; 4690fa9e4066Sahrens 4691ea8dc4b6Seschrock /* 4692ea8dc4b6Seschrock * Ignore faulted pools. 4693ea8dc4b6Seschrock */ 4694ea8dc4b6Seschrock if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 4695e4c795beSTom Caputi (void) fprintf(stderr, gettext("cannot scan '%s': pool is " 4696ea8dc4b6Seschrock "currently unavailable\n"), zpool_get_name(zhp)); 4697ea8dc4b6Seschrock return (1); 4698ea8dc4b6Seschrock } 4699ea8dc4b6Seschrock 47001702cce7SAlek Pinchuk err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd); 470106eeb2adSek 470286714001SSerapheim Dimitropoulos if (err == 0 && zpool_has_checkpoint(zhp) && 470386714001SSerapheim Dimitropoulos cb->cb_type == POOL_SCAN_SCRUB) { 470486714001SSerapheim Dimitropoulos (void) printf(gettext("warning: will not scrub state that " 470586714001SSerapheim Dimitropoulos "belongs to the checkpoint of pool '%s'\n"), 470686714001SSerapheim Dimitropoulos zpool_get_name(zhp)); 470786714001SSerapheim Dimitropoulos } 470886714001SSerapheim Dimitropoulos 470906eeb2adSek return (err != 0); 4710fa9e4066Sahrens } 4711fa9e4066Sahrens 4712fa9e4066Sahrens /* 47131702cce7SAlek Pinchuk * zpool scrub [-s | -p] <pool> ... 4714fa9e4066Sahrens * 4715fa9e4066Sahrens * -s Stop. Stops any in-progress scrub. 47161702cce7SAlek Pinchuk * -p Pause. Pause in-progress scrub. 4717fa9e4066Sahrens */ 4718fa9e4066Sahrens int 4719fa9e4066Sahrens zpool_do_scrub(int argc, char **argv) 4720fa9e4066Sahrens { 4721fa9e4066Sahrens int c; 4722fa9e4066Sahrens scrub_cbdata_t cb; 4723fa9e4066Sahrens 47243f9d6ad7SLin Ling cb.cb_type = POOL_SCAN_SCRUB; 47251702cce7SAlek Pinchuk cb.cb_scrub_cmd = POOL_SCRUB_NORMAL; 4726fa9e4066Sahrens 4727fa9e4066Sahrens /* check options */ 47281702cce7SAlek Pinchuk while ((c = getopt(argc, argv, "sp")) != -1) { 4729fa9e4066Sahrens switch (c) { 4730fa9e4066Sahrens case 's': 47313f9d6ad7SLin Ling cb.cb_type = POOL_SCAN_NONE; 4732fa9e4066Sahrens break; 47331702cce7SAlek Pinchuk case 'p': 47341702cce7SAlek Pinchuk cb.cb_scrub_cmd = POOL_SCRUB_PAUSE; 47351702cce7SAlek Pinchuk break; 4736fa9e4066Sahrens case '?': 4737fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4738fa9e4066Sahrens optopt); 473999653d4eSeschrock usage(B_FALSE); 4740fa9e4066Sahrens } 4741fa9e4066Sahrens } 4742fa9e4066Sahrens 47431702cce7SAlek Pinchuk if (cb.cb_type == POOL_SCAN_NONE && 47441702cce7SAlek Pinchuk cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) { 47451702cce7SAlek Pinchuk (void) fprintf(stderr, gettext("invalid option combination: " 47461702cce7SAlek Pinchuk "-s and -p are mutually exclusive\n")); 47471702cce7SAlek Pinchuk usage(B_FALSE); 47481702cce7SAlek Pinchuk } 47491702cce7SAlek Pinchuk 475006eeb2adSek cb.cb_argc = argc; 475106eeb2adSek cb.cb_argv = argv; 4752fa9e4066Sahrens argc -= optind; 4753fa9e4066Sahrens argv += optind; 4754fa9e4066Sahrens 4755e4c795beSTom Caputi if (argc < 1) { 4756e4c795beSTom Caputi (void) fprintf(stderr, gettext("missing pool name argument\n")); 4757e4c795beSTom Caputi usage(B_FALSE); 4758e4c795beSTom Caputi } 4759e4c795beSTom Caputi 4760e4c795beSTom Caputi return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 4761e4c795beSTom Caputi } 4762e4c795beSTom Caputi 4763e4c795beSTom Caputi /* 4764e4c795beSTom Caputi * zpool resilver <pool> ... 4765e4c795beSTom Caputi * 4766e4c795beSTom Caputi * Restarts any in-progress resilver 4767e4c795beSTom Caputi */ 4768e4c795beSTom Caputi int 4769e4c795beSTom Caputi zpool_do_resilver(int argc, char **argv) 4770e4c795beSTom Caputi { 4771e4c795beSTom Caputi int c; 4772e4c795beSTom Caputi scrub_cbdata_t cb; 4773e4c795beSTom Caputi 4774e4c795beSTom Caputi cb.cb_type = POOL_SCAN_RESILVER; 4775e4c795beSTom Caputi cb.cb_scrub_cmd = POOL_SCRUB_NORMAL; 4776e4c795beSTom Caputi cb.cb_argc = argc; 4777e4c795beSTom Caputi cb.cb_argv = argv; 4778e4c795beSTom Caputi 4779e4c795beSTom Caputi /* check options */ 4780e4c795beSTom Caputi while ((c = getopt(argc, argv, "")) != -1) { 4781e4c795beSTom Caputi switch (c) { 4782e4c795beSTom Caputi case '?': 4783e4c795beSTom Caputi (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4784e4c795beSTom Caputi optopt); 4785e4c795beSTom Caputi usage(B_FALSE); 4786e4c795beSTom Caputi } 4787e4c795beSTom Caputi } 4788e4c795beSTom Caputi 4789e4c795beSTom Caputi argc -= optind; 4790e4c795beSTom Caputi argv += optind; 4791e4c795beSTom Caputi 4792fa9e4066Sahrens if (argc < 1) { 4793fa9e4066Sahrens (void) fprintf(stderr, gettext("missing pool name argument\n")); 479499653d4eSeschrock usage(B_FALSE); 4795fa9e4066Sahrens } 4796fa9e4066Sahrens 4797b1b8ab34Slling return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 4798fa9e4066Sahrens } 4799fa9e4066Sahrens 4800094e47e9SGeorge Wilson static void 4801094e47e9SGeorge Wilson zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res) 4802094e47e9SGeorge Wilson { 4803094e47e9SGeorge Wilson uint_t children = 0; 4804094e47e9SGeorge Wilson nvlist_t **child; 4805094e47e9SGeorge Wilson uint_t i; 4806094e47e9SGeorge Wilson 4807094e47e9SGeorge Wilson (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 4808094e47e9SGeorge Wilson &child, &children); 4809094e47e9SGeorge Wilson 4810094e47e9SGeorge Wilson if (children == 0) { 4811094e47e9SGeorge Wilson char *path = zpool_vdev_name(g_zfs, zhp, nvroot, B_FALSE); 4812094e47e9SGeorge Wilson fnvlist_add_boolean(res, path); 4813094e47e9SGeorge Wilson free(path); 4814094e47e9SGeorge Wilson return; 4815094e47e9SGeorge Wilson } 4816094e47e9SGeorge Wilson 4817094e47e9SGeorge Wilson for (i = 0; i < children; i++) { 4818094e47e9SGeorge Wilson zpool_collect_leaves(zhp, child[i], res); 4819094e47e9SGeorge Wilson } 4820094e47e9SGeorge Wilson } 4821094e47e9SGeorge Wilson 4822094e47e9SGeorge Wilson /* 4823094e47e9SGeorge Wilson * zpool initialize [-cs] <pool> [<vdev> ...] 4824094e47e9SGeorge Wilson * Initialize all unused blocks in the specified vdevs, or all vdevs in the pool 4825094e47e9SGeorge Wilson * if none specified. 4826094e47e9SGeorge Wilson * 4827094e47e9SGeorge Wilson * -c Cancel. Ends active initializing. 4828094e47e9SGeorge Wilson * -s Suspend. Initializing can then be restarted with no flags. 4829094e47e9SGeorge Wilson */ 4830094e47e9SGeorge Wilson int 4831094e47e9SGeorge Wilson zpool_do_initialize(int argc, char **argv) 4832094e47e9SGeorge Wilson { 4833094e47e9SGeorge Wilson int c; 4834094e47e9SGeorge Wilson char *poolname; 4835094e47e9SGeorge Wilson zpool_handle_t *zhp; 4836094e47e9SGeorge Wilson nvlist_t *vdevs; 4837094e47e9SGeorge Wilson int err = 0; 4838094e47e9SGeorge Wilson 4839094e47e9SGeorge Wilson struct option long_options[] = { 4840094e47e9SGeorge Wilson {"cancel", no_argument, NULL, 'c'}, 4841094e47e9SGeorge Wilson {"suspend", no_argument, NULL, 's'}, 4842094e47e9SGeorge Wilson {0, 0, 0, 0} 4843094e47e9SGeorge Wilson }; 4844094e47e9SGeorge Wilson 4845094e47e9SGeorge Wilson pool_initialize_func_t cmd_type = POOL_INITIALIZE_DO; 4846094e47e9SGeorge Wilson while ((c = getopt_long(argc, argv, "cs", long_options, NULL)) != -1) { 4847094e47e9SGeorge Wilson switch (c) { 4848094e47e9SGeorge Wilson case 'c': 4849094e47e9SGeorge Wilson if (cmd_type != POOL_INITIALIZE_DO) { 4850094e47e9SGeorge Wilson (void) fprintf(stderr, gettext("-c cannot be " 4851094e47e9SGeorge Wilson "combined with other options\n")); 4852094e47e9SGeorge Wilson usage(B_FALSE); 4853094e47e9SGeorge Wilson } 4854094e47e9SGeorge Wilson cmd_type = POOL_INITIALIZE_CANCEL; 4855094e47e9SGeorge Wilson break; 4856094e47e9SGeorge Wilson case 's': 4857094e47e9SGeorge Wilson if (cmd_type != POOL_INITIALIZE_DO) { 4858094e47e9SGeorge Wilson (void) fprintf(stderr, gettext("-s cannot be " 4859094e47e9SGeorge Wilson "combined with other options\n")); 4860094e47e9SGeorge Wilson usage(B_FALSE); 4861094e47e9SGeorge Wilson } 4862094e47e9SGeorge Wilson cmd_type = POOL_INITIALIZE_SUSPEND; 4863094e47e9SGeorge Wilson break; 4864094e47e9SGeorge Wilson case '?': 4865094e47e9SGeorge Wilson if (optopt != 0) { 4866094e47e9SGeorge Wilson (void) fprintf(stderr, 4867094e47e9SGeorge Wilson gettext("invalid option '%c'\n"), optopt); 4868094e47e9SGeorge Wilson } else { 4869094e47e9SGeorge Wilson (void) fprintf(stderr, 4870094e47e9SGeorge Wilson gettext("invalid option '%s'\n"), 4871094e47e9SGeorge Wilson argv[optind - 1]); 4872094e47e9SGeorge Wilson } 4873094e47e9SGeorge Wilson usage(B_FALSE); 4874094e47e9SGeorge Wilson } 4875094e47e9SGeorge Wilson } 4876094e47e9SGeorge Wilson 4877094e47e9SGeorge Wilson argc -= optind; 4878094e47e9SGeorge Wilson argv += optind; 4879094e47e9SGeorge Wilson 4880094e47e9SGeorge Wilson if (argc < 1) { 4881094e47e9SGeorge Wilson (void) fprintf(stderr, gettext("missing pool name argument\n")); 4882094e47e9SGeorge Wilson usage(B_FALSE); 4883094e47e9SGeorge Wilson return (-1); 4884094e47e9SGeorge Wilson } 4885094e47e9SGeorge Wilson 4886094e47e9SGeorge Wilson poolname = argv[0]; 4887094e47e9SGeorge Wilson zhp = zpool_open(g_zfs, poolname); 4888094e47e9SGeorge Wilson if (zhp == NULL) 4889094e47e9SGeorge Wilson return (-1); 4890094e47e9SGeorge Wilson 4891094e47e9SGeorge Wilson vdevs = fnvlist_alloc(); 4892094e47e9SGeorge Wilson if (argc == 1) { 4893094e47e9SGeorge Wilson /* no individual leaf vdevs specified, so add them all */ 4894094e47e9SGeorge Wilson nvlist_t *config = zpool_get_config(zhp, NULL); 4895094e47e9SGeorge Wilson nvlist_t *nvroot = fnvlist_lookup_nvlist(config, 4896094e47e9SGeorge Wilson ZPOOL_CONFIG_VDEV_TREE); 4897094e47e9SGeorge Wilson zpool_collect_leaves(zhp, nvroot, vdevs); 4898094e47e9SGeorge Wilson } else { 4899094e47e9SGeorge Wilson int i; 4900094e47e9SGeorge Wilson for (i = 1; i < argc; i++) { 4901094e47e9SGeorge Wilson fnvlist_add_boolean(vdevs, argv[i]); 4902094e47e9SGeorge Wilson } 4903094e47e9SGeorge Wilson } 4904094e47e9SGeorge Wilson 4905094e47e9SGeorge Wilson err = zpool_initialize(zhp, cmd_type, vdevs); 4906094e47e9SGeorge Wilson 4907094e47e9SGeorge Wilson fnvlist_free(vdevs); 4908094e47e9SGeorge Wilson zpool_close(zhp); 4909094e47e9SGeorge Wilson 4910094e47e9SGeorge Wilson return (err); 4911094e47e9SGeorge Wilson } 4912094e47e9SGeorge Wilson 4913fa9e4066Sahrens /* 4914fa9e4066Sahrens * Print out detailed scrub status. 4915fa9e4066Sahrens */ 49165cabbc6bSPrashanth Sreenivasa static void 49173f9d6ad7SLin Ling print_scan_status(pool_scan_stat_t *ps) 4918fa9e4066Sahrens { 49191702cce7SAlek Pinchuk time_t start, end, pause; 4920a3874b8bSToomas Soome uint64_t total_secs_left; 4921a3874b8bSToomas Soome uint64_t elapsed, secs_left, mins_left, hours_left, days_left; 4922a3874b8bSToomas Soome uint64_t pass_scanned, scanned, pass_issued, issued, total; 4923a3874b8bSToomas Soome uint_t scan_rate, issue_rate; 4924fa9e4066Sahrens double fraction_done; 4925a3874b8bSToomas Soome char processed_buf[7], scanned_buf[7], issued_buf[7], total_buf[7]; 4926a3874b8bSToomas Soome char srate_buf[7], irate_buf[7]; 4927fa9e4066Sahrens 4928ce72e614SYuri Pankov (void) printf(gettext(" scan: ")); 4929fa9e4066Sahrens 49303f9d6ad7SLin Ling /* If there's never been a scan, there's not much to say. */ 49313f9d6ad7SLin Ling if (ps == NULL || ps->pss_func == POOL_SCAN_NONE || 49323f9d6ad7SLin Ling ps->pss_func >= POOL_SCAN_FUNCS) { 4933fa9e4066Sahrens (void) printf(gettext("none requested\n")); 4934fa9e4066Sahrens return; 4935fa9e4066Sahrens } 4936fa9e4066Sahrens 49373f9d6ad7SLin Ling start = ps->pss_start_time; 49383f9d6ad7SLin Ling end = ps->pss_end_time; 49391702cce7SAlek Pinchuk pause = ps->pss_pass_scrub_pause; 4940a3874b8bSToomas Soome 49413f9d6ad7SLin Ling zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf)); 4942fa9e4066Sahrens 49433f9d6ad7SLin Ling assert(ps->pss_func == POOL_SCAN_SCRUB || 49443f9d6ad7SLin Ling ps->pss_func == POOL_SCAN_RESILVER); 4945a3874b8bSToomas Soome 49463f9d6ad7SLin Ling /* 49473f9d6ad7SLin Ling * Scan is finished or canceled. 49483f9d6ad7SLin Ling */ 49493f9d6ad7SLin Ling if (ps->pss_state == DSS_FINISHED) { 4950a3874b8bSToomas Soome total_secs_left = end - start; 4951a3874b8bSToomas Soome days_left = total_secs_left / 60 / 60 / 24; 4952a3874b8bSToomas Soome hours_left = (total_secs_left / 60 / 60) % 24; 4953a3874b8bSToomas Soome mins_left = (total_secs_left / 60) % 60; 4954a3874b8bSToomas Soome secs_left = (total_secs_left % 60); 49553f9d6ad7SLin Ling 49563f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) { 4957a3874b8bSToomas Soome (void) printf(gettext("scrub repaired %s " 4958a3874b8bSToomas Soome "in %llu days %02llu:%02llu:%02llu " 4959a3874b8bSToomas Soome "with %llu errors on %s"), processed_buf, 4960a3874b8bSToomas Soome (u_longlong_t)days_left, (u_longlong_t)hours_left, 4961a3874b8bSToomas Soome (u_longlong_t)mins_left, (u_longlong_t)secs_left, 4962a3874b8bSToomas Soome (u_longlong_t)ps->pss_errors, ctime(&end)); 49633f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) { 4964a3874b8bSToomas Soome (void) printf(gettext("resilvered %s " 4965a3874b8bSToomas Soome "in %llu days %02llu:%02llu:%02llu " 4966a3874b8bSToomas Soome "with %llu errors on %s"), processed_buf, 4967a3874b8bSToomas Soome (u_longlong_t)days_left, (u_longlong_t)hours_left, 4968a3874b8bSToomas Soome (u_longlong_t)mins_left, (u_longlong_t)secs_left, 4969a3874b8bSToomas Soome (u_longlong_t)ps->pss_errors, ctime(&end)); 49703f9d6ad7SLin Ling } 49713f9d6ad7SLin Ling return; 49723f9d6ad7SLin Ling } else if (ps->pss_state == DSS_CANCELED) { 49733f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) { 49743f9d6ad7SLin Ling (void) printf(gettext("scrub canceled on %s"), 49753f9d6ad7SLin Ling ctime(&end)); 49763f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) { 49773f9d6ad7SLin Ling (void) printf(gettext("resilver canceled on %s"), 49783f9d6ad7SLin Ling ctime(&end)); 49793f9d6ad7SLin Ling } 4980fa9e4066Sahrens return; 4981fa9e4066Sahrens } 4982fa9e4066Sahrens 49833f9d6ad7SLin Ling assert(ps->pss_state == DSS_SCANNING); 49843f9d6ad7SLin Ling 4985a3874b8bSToomas Soome /* Scan is in progress. Resilvers can't be paused. */ 49863f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_SCRUB) { 49871702cce7SAlek Pinchuk if (pause == 0) { 49881702cce7SAlek Pinchuk (void) printf(gettext("scrub in progress since %s"), 49891702cce7SAlek Pinchuk ctime(&start)); 49901702cce7SAlek Pinchuk } else { 4991a3874b8bSToomas Soome (void) printf(gettext("scrub paused since %s"), 4992a3874b8bSToomas Soome ctime(&pause)); 4993a3874b8bSToomas Soome (void) printf(gettext("\tscrub started on %s"), 49941702cce7SAlek Pinchuk ctime(&start)); 49951702cce7SAlek Pinchuk } 49963f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_RESILVER) { 49973f9d6ad7SLin Ling (void) printf(gettext("resilver in progress since %s"), 49983f9d6ad7SLin Ling ctime(&start)); 49993f9d6ad7SLin Ling } 5000fa9e4066Sahrens 5001a3874b8bSToomas Soome scanned = ps->pss_examined; 5002a3874b8bSToomas Soome pass_scanned = ps->pss_pass_exam; 5003a3874b8bSToomas Soome issued = ps->pss_issued; 5004a3874b8bSToomas Soome pass_issued = ps->pss_pass_issued; 50053f9d6ad7SLin Ling total = ps->pss_to_examine; 50063f9d6ad7SLin Ling 5007a3874b8bSToomas Soome /* we are only done with a block once we have issued the IO for it */ 5008a3874b8bSToomas Soome fraction_done = (double)issued / total; 5009a3874b8bSToomas Soome 5010a3874b8bSToomas Soome /* elapsed time for this pass, rounding up to 1 if it's 0 */ 50113f9d6ad7SLin Ling elapsed = time(NULL) - ps->pss_pass_start; 50121702cce7SAlek Pinchuk elapsed -= ps->pss_pass_scrub_spent_paused; 5013a3874b8bSToomas Soome elapsed = (elapsed != 0) ? elapsed : 1; 5014a3874b8bSToomas Soome 5015a3874b8bSToomas Soome scan_rate = pass_scanned / elapsed; 5016a3874b8bSToomas Soome issue_rate = pass_issued / elapsed; 50173db6627cSTom Caputi total_secs_left = (issue_rate != 0 && total >= issued) ? 5018a3874b8bSToomas Soome ((total - issued) / issue_rate) : UINT64_MAX; 5019a3874b8bSToomas Soome 5020a3874b8bSToomas Soome days_left = total_secs_left / 60 / 60 / 24; 5021a3874b8bSToomas Soome hours_left = (total_secs_left / 60 / 60) % 24; 5022a3874b8bSToomas Soome mins_left = (total_secs_left / 60) % 60; 5023a3874b8bSToomas Soome secs_left = (total_secs_left % 60); 5024a3874b8bSToomas Soome 5025a3874b8bSToomas Soome /* format all of the numbers we will be reporting */ 5026a3874b8bSToomas Soome zfs_nicenum(scanned, scanned_buf, sizeof (scanned_buf)); 5027a3874b8bSToomas Soome zfs_nicenum(issued, issued_buf, sizeof (issued_buf)); 50283f9d6ad7SLin Ling zfs_nicenum(total, total_buf, sizeof (total_buf)); 5029a3874b8bSToomas Soome zfs_nicenum(scan_rate, srate_buf, sizeof (srate_buf)); 5030a3874b8bSToomas Soome zfs_nicenum(issue_rate, irate_buf, sizeof (irate_buf)); 50313f9d6ad7SLin Ling 5032a3874b8bSToomas Soome /* do not print estimated time if we have a paused scrub */ 50331702cce7SAlek Pinchuk if (pause == 0) { 5034a3874b8bSToomas Soome (void) printf(gettext("\t%s scanned at %s/s, " 5035a3874b8bSToomas Soome "%s issued at %s/s, %s total\n"), 5036a3874b8bSToomas Soome scanned_buf, srate_buf, issued_buf, irate_buf, total_buf); 503773d314ceSLin Ling } else { 5038a3874b8bSToomas Soome (void) printf(gettext("\t%s scanned, %s issued, %s total\n"), 5039a3874b8bSToomas Soome scanned_buf, issued_buf, total_buf); 504073d314ceSLin Ling } 50413f9d6ad7SLin Ling 50423f9d6ad7SLin Ling if (ps->pss_func == POOL_SCAN_RESILVER) { 5043a3874b8bSToomas Soome (void) printf(gettext("\t%s resilvered, %.2f%% done"), 50443f9d6ad7SLin Ling processed_buf, 100 * fraction_done); 50453f9d6ad7SLin Ling } else if (ps->pss_func == POOL_SCAN_SCRUB) { 5046a3874b8bSToomas Soome (void) printf(gettext("\t%s repaired, %.2f%% done"), 50473f9d6ad7SLin Ling processed_buf, 100 * fraction_done); 50483f9d6ad7SLin Ling } 5049a3874b8bSToomas Soome 5050a3874b8bSToomas Soome if (pause == 0) { 50513db6627cSTom Caputi if (total_secs_left != UINT64_MAX && 50523db6627cSTom Caputi issue_rate >= 10 * 1024 * 1024) { 5053a3874b8bSToomas Soome (void) printf(gettext(", %llu days " 5054a3874b8bSToomas Soome "%02llu:%02llu:%02llu to go\n"), 5055a3874b8bSToomas Soome (u_longlong_t)days_left, (u_longlong_t)hours_left, 5056a3874b8bSToomas Soome (u_longlong_t)mins_left, (u_longlong_t)secs_left); 5057a3874b8bSToomas Soome } else { 5058a3874b8bSToomas Soome (void) printf(gettext(", no estimated " 5059a3874b8bSToomas Soome "completion time\n")); 5060a3874b8bSToomas Soome } 5061a3874b8bSToomas Soome } else { 5062a3874b8bSToomas Soome (void) printf(gettext("\n")); 5063a3874b8bSToomas Soome } 5064fa9e4066Sahrens } 5065fa9e4066Sahrens 506686714001SSerapheim Dimitropoulos /* 506786714001SSerapheim Dimitropoulos * As we don't scrub checkpointed blocks, we want to warn the 506886714001SSerapheim Dimitropoulos * user that we skipped scanning some blocks if a checkpoint exists 506986714001SSerapheim Dimitropoulos * or existed at any time during the scan. 507086714001SSerapheim Dimitropoulos */ 507186714001SSerapheim Dimitropoulos static void 507286714001SSerapheim Dimitropoulos print_checkpoint_scan_warning(pool_scan_stat_t *ps, pool_checkpoint_stat_t *pcs) 507386714001SSerapheim Dimitropoulos { 507486714001SSerapheim Dimitropoulos if (ps == NULL || pcs == NULL) 507586714001SSerapheim Dimitropoulos return; 507686714001SSerapheim Dimitropoulos 507786714001SSerapheim Dimitropoulos if (pcs->pcs_state == CS_NONE || 507886714001SSerapheim Dimitropoulos pcs->pcs_state == CS_CHECKPOINT_DISCARDING) 507986714001SSerapheim Dimitropoulos return; 508086714001SSerapheim Dimitropoulos 508186714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_EXISTS); 508286714001SSerapheim Dimitropoulos 508386714001SSerapheim Dimitropoulos if (ps->pss_state == DSS_NONE) 508486714001SSerapheim Dimitropoulos return; 508586714001SSerapheim Dimitropoulos 508686714001SSerapheim Dimitropoulos if ((ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) && 508786714001SSerapheim Dimitropoulos ps->pss_end_time < pcs->pcs_start_time) 508886714001SSerapheim Dimitropoulos return; 508986714001SSerapheim Dimitropoulos 509086714001SSerapheim Dimitropoulos if (ps->pss_state == DSS_FINISHED || ps->pss_state == DSS_CANCELED) { 509186714001SSerapheim Dimitropoulos (void) printf(gettext(" scan warning: skipped blocks " 509286714001SSerapheim Dimitropoulos "that are only referenced by the checkpoint.\n")); 509386714001SSerapheim Dimitropoulos } else { 509486714001SSerapheim Dimitropoulos assert(ps->pss_state == DSS_SCANNING); 509586714001SSerapheim Dimitropoulos (void) printf(gettext(" scan warning: skipping blocks " 509686714001SSerapheim Dimitropoulos "that are only referenced by the checkpoint.\n")); 509786714001SSerapheim Dimitropoulos } 509886714001SSerapheim Dimitropoulos } 509986714001SSerapheim Dimitropoulos 51005cabbc6bSPrashanth Sreenivasa /* 51015cabbc6bSPrashanth Sreenivasa * Print out detailed removal status. 51025cabbc6bSPrashanth Sreenivasa */ 51035cabbc6bSPrashanth Sreenivasa static void 51045cabbc6bSPrashanth Sreenivasa print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs) 51055cabbc6bSPrashanth Sreenivasa { 51065cabbc6bSPrashanth Sreenivasa char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7]; 51075cabbc6bSPrashanth Sreenivasa time_t start, end; 51085cabbc6bSPrashanth Sreenivasa nvlist_t *config, *nvroot; 51095cabbc6bSPrashanth Sreenivasa nvlist_t **child; 51105cabbc6bSPrashanth Sreenivasa uint_t children; 51115cabbc6bSPrashanth Sreenivasa char *vdev_name; 51125cabbc6bSPrashanth Sreenivasa 51135cabbc6bSPrashanth Sreenivasa if (prs == NULL || prs->prs_state == DSS_NONE) 51145cabbc6bSPrashanth Sreenivasa return; 51155cabbc6bSPrashanth Sreenivasa 51165cabbc6bSPrashanth Sreenivasa /* 51175cabbc6bSPrashanth Sreenivasa * Determine name of vdev. 51185cabbc6bSPrashanth Sreenivasa */ 51195cabbc6bSPrashanth Sreenivasa config = zpool_get_config(zhp, NULL); 51205cabbc6bSPrashanth Sreenivasa nvroot = fnvlist_lookup_nvlist(config, 51215cabbc6bSPrashanth Sreenivasa ZPOOL_CONFIG_VDEV_TREE); 51225cabbc6bSPrashanth Sreenivasa verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, 51235cabbc6bSPrashanth Sreenivasa &child, &children) == 0); 51245cabbc6bSPrashanth Sreenivasa assert(prs->prs_removing_vdev < children); 51255cabbc6bSPrashanth Sreenivasa vdev_name = zpool_vdev_name(g_zfs, zhp, 51265cabbc6bSPrashanth Sreenivasa child[prs->prs_removing_vdev], B_TRUE); 51275cabbc6bSPrashanth Sreenivasa 51285cabbc6bSPrashanth Sreenivasa (void) printf(gettext("remove: ")); 51295cabbc6bSPrashanth Sreenivasa 51305cabbc6bSPrashanth Sreenivasa start = prs->prs_start_time; 51315cabbc6bSPrashanth Sreenivasa end = prs->prs_end_time; 51325cabbc6bSPrashanth Sreenivasa zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf)); 51335cabbc6bSPrashanth Sreenivasa 51345cabbc6bSPrashanth Sreenivasa /* 51355cabbc6bSPrashanth Sreenivasa * Removal is finished or canceled. 51365cabbc6bSPrashanth Sreenivasa */ 51375cabbc6bSPrashanth Sreenivasa if (prs->prs_state == DSS_FINISHED) { 51385cabbc6bSPrashanth Sreenivasa uint64_t minutes_taken = (end - start) / 60; 51395cabbc6bSPrashanth Sreenivasa 51405cabbc6bSPrashanth Sreenivasa (void) printf(gettext("Removal of vdev %llu copied %s " 51415cabbc6bSPrashanth Sreenivasa "in %lluh%um, completed on %s"), 51425cabbc6bSPrashanth Sreenivasa (longlong_t)prs->prs_removing_vdev, 51435cabbc6bSPrashanth Sreenivasa copied_buf, 51445cabbc6bSPrashanth Sreenivasa (u_longlong_t)(minutes_taken / 60), 51455cabbc6bSPrashanth Sreenivasa (uint_t)(minutes_taken % 60), 51465cabbc6bSPrashanth Sreenivasa ctime((time_t *)&end)); 51475cabbc6bSPrashanth Sreenivasa } else if (prs->prs_state == DSS_CANCELED) { 51485cabbc6bSPrashanth Sreenivasa (void) printf(gettext("Removal of %s canceled on %s"), 51495cabbc6bSPrashanth Sreenivasa vdev_name, ctime(&end)); 51505cabbc6bSPrashanth Sreenivasa } else { 51515cabbc6bSPrashanth Sreenivasa uint64_t copied, total, elapsed, mins_left, hours_left; 51525cabbc6bSPrashanth Sreenivasa double fraction_done; 51535cabbc6bSPrashanth Sreenivasa uint_t rate; 51545cabbc6bSPrashanth Sreenivasa 51555cabbc6bSPrashanth Sreenivasa assert(prs->prs_state == DSS_SCANNING); 51565cabbc6bSPrashanth Sreenivasa 51575cabbc6bSPrashanth Sreenivasa /* 51585cabbc6bSPrashanth Sreenivasa * Removal is in progress. 51595cabbc6bSPrashanth Sreenivasa */ 51605cabbc6bSPrashanth Sreenivasa (void) printf(gettext( 51615cabbc6bSPrashanth Sreenivasa "Evacuation of %s in progress since %s"), 51625cabbc6bSPrashanth Sreenivasa vdev_name, ctime(&start)); 51635cabbc6bSPrashanth Sreenivasa 51645cabbc6bSPrashanth Sreenivasa copied = prs->prs_copied > 0 ? prs->prs_copied : 1; 51655cabbc6bSPrashanth Sreenivasa total = prs->prs_to_copy; 51665cabbc6bSPrashanth Sreenivasa fraction_done = (double)copied / total; 51675cabbc6bSPrashanth Sreenivasa 51685cabbc6bSPrashanth Sreenivasa /* elapsed time for this pass */ 51695cabbc6bSPrashanth Sreenivasa elapsed = time(NULL) - prs->prs_start_time; 51705cabbc6bSPrashanth Sreenivasa elapsed = elapsed > 0 ? elapsed : 1; 51715cabbc6bSPrashanth Sreenivasa rate = copied / elapsed; 51725cabbc6bSPrashanth Sreenivasa rate = rate > 0 ? rate : 1; 51735cabbc6bSPrashanth Sreenivasa mins_left = ((total - copied) / rate) / 60; 51745cabbc6bSPrashanth Sreenivasa hours_left = mins_left / 60; 51755cabbc6bSPrashanth Sreenivasa 51765cabbc6bSPrashanth Sreenivasa zfs_nicenum(copied, examined_buf, sizeof (examined_buf)); 51775cabbc6bSPrashanth Sreenivasa zfs_nicenum(total, total_buf, sizeof (total_buf)); 51785cabbc6bSPrashanth Sreenivasa zfs_nicenum(rate, rate_buf, sizeof (rate_buf)); 51795cabbc6bSPrashanth Sreenivasa 51805cabbc6bSPrashanth Sreenivasa /* 51815cabbc6bSPrashanth Sreenivasa * do not print estimated time if hours_left is more than 51825cabbc6bSPrashanth Sreenivasa * 30 days 51835cabbc6bSPrashanth Sreenivasa */ 51845cabbc6bSPrashanth Sreenivasa (void) printf(gettext(" %s copied out of %s at %s/s, " 51855cabbc6bSPrashanth Sreenivasa "%.2f%% done"), 51865cabbc6bSPrashanth Sreenivasa examined_buf, total_buf, rate_buf, 100 * fraction_done); 51875cabbc6bSPrashanth Sreenivasa if (hours_left < (30 * 24)) { 51885cabbc6bSPrashanth Sreenivasa (void) printf(gettext(", %lluh%um to go\n"), 51895cabbc6bSPrashanth Sreenivasa (u_longlong_t)hours_left, (uint_t)(mins_left % 60)); 51905cabbc6bSPrashanth Sreenivasa } else { 51915cabbc6bSPrashanth Sreenivasa (void) printf(gettext( 51925cabbc6bSPrashanth Sreenivasa ", (copy is slow, no estimated time)\n")); 51935cabbc6bSPrashanth Sreenivasa } 51945cabbc6bSPrashanth Sreenivasa } 51955cabbc6bSPrashanth Sreenivasa 51965cabbc6bSPrashanth Sreenivasa if (prs->prs_mapping_memory > 0) { 51975cabbc6bSPrashanth Sreenivasa char mem_buf[7]; 51985cabbc6bSPrashanth Sreenivasa zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf)); 51995cabbc6bSPrashanth Sreenivasa (void) printf(gettext(" %s memory used for " 52005cabbc6bSPrashanth Sreenivasa "removed device mappings\n"), 52015cabbc6bSPrashanth Sreenivasa mem_buf); 52025cabbc6bSPrashanth Sreenivasa } 52035cabbc6bSPrashanth Sreenivasa } 52045cabbc6bSPrashanth Sreenivasa 520586714001SSerapheim Dimitropoulos static void 520686714001SSerapheim Dimitropoulos print_checkpoint_status(pool_checkpoint_stat_t *pcs) 520786714001SSerapheim Dimitropoulos { 520886714001SSerapheim Dimitropoulos time_t start; 520986714001SSerapheim Dimitropoulos char space_buf[7]; 521086714001SSerapheim Dimitropoulos 521186714001SSerapheim Dimitropoulos if (pcs == NULL || pcs->pcs_state == CS_NONE) 521286714001SSerapheim Dimitropoulos return; 521386714001SSerapheim Dimitropoulos 521486714001SSerapheim Dimitropoulos (void) printf(gettext("checkpoint: ")); 521586714001SSerapheim Dimitropoulos 521686714001SSerapheim Dimitropoulos start = pcs->pcs_start_time; 521786714001SSerapheim Dimitropoulos zfs_nicenum(pcs->pcs_space, space_buf, sizeof (space_buf)); 521886714001SSerapheim Dimitropoulos 521986714001SSerapheim Dimitropoulos if (pcs->pcs_state == CS_CHECKPOINT_EXISTS) { 522086714001SSerapheim Dimitropoulos char *date = ctime(&start); 522186714001SSerapheim Dimitropoulos 522286714001SSerapheim Dimitropoulos /* 522386714001SSerapheim Dimitropoulos * ctime() adds a newline at the end of the generated 522486714001SSerapheim Dimitropoulos * string, thus the weird format specifier and the 522586714001SSerapheim Dimitropoulos * strlen() call used to chop it off from the output. 522686714001SSerapheim Dimitropoulos */ 522786714001SSerapheim Dimitropoulos (void) printf(gettext("created %.*s, consumes %s\n"), 522886714001SSerapheim Dimitropoulos strlen(date) - 1, date, space_buf); 522986714001SSerapheim Dimitropoulos return; 523086714001SSerapheim Dimitropoulos } 523186714001SSerapheim Dimitropoulos 523286714001SSerapheim Dimitropoulos assert(pcs->pcs_state == CS_CHECKPOINT_DISCARDING); 523386714001SSerapheim Dimitropoulos 523486714001SSerapheim Dimitropoulos (void) printf(gettext("discarding, %s remaining.\n"), 523586714001SSerapheim Dimitropoulos space_buf); 523686714001SSerapheim Dimitropoulos } 523786714001SSerapheim Dimitropoulos 5238ea8dc4b6Seschrock static void 5239ea8dc4b6Seschrock print_error_log(zpool_handle_t *zhp) 5240ea8dc4b6Seschrock { 524175519f38Sek nvlist_t *nverrlist = NULL; 524255434c77Sek nvpair_t *elem; 524355434c77Sek char *pathname; 524455434c77Sek size_t len = MAXPATHLEN * 2; 5245ea8dc4b6Seschrock 524655434c77Sek if (zpool_get_errlog(zhp, &nverrlist) != 0) { 5247ea8dc4b6Seschrock (void) printf("errors: List of errors unavailable " 5248ea8dc4b6Seschrock "(insufficient privileges)\n"); 5249ea8dc4b6Seschrock return; 5250ea8dc4b6Seschrock } 5251ea8dc4b6Seschrock 525255434c77Sek (void) printf("errors: Permanent errors have been " 525355434c77Sek "detected in the following files:\n\n"); 5254ea8dc4b6Seschrock 525555434c77Sek pathname = safe_malloc(len); 525655434c77Sek elem = NULL; 525755434c77Sek while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 525855434c77Sek nvlist_t *nv; 525955434c77Sek uint64_t dsobj, obj; 526055434c77Sek 526155434c77Sek verify(nvpair_value_nvlist(elem, &nv) == 0); 526255434c77Sek verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 526355434c77Sek &dsobj) == 0); 526455434c77Sek verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 526555434c77Sek &obj) == 0); 526655434c77Sek zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 526755434c77Sek (void) printf("%7s %s\n", "", pathname); 526855434c77Sek } 526955434c77Sek free(pathname); 527055434c77Sek nvlist_free(nverrlist); 5271ea8dc4b6Seschrock } 5272ea8dc4b6Seschrock 527399653d4eSeschrock static void 5274663207adSDon Brady print_spares(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **spares, 5275663207adSDon Brady uint_t nspares) 527699653d4eSeschrock { 527799653d4eSeschrock uint_t i; 527899653d4eSeschrock char *name; 527999653d4eSeschrock 528099653d4eSeschrock if (nspares == 0) 528199653d4eSeschrock return; 528299653d4eSeschrock 528399653d4eSeschrock (void) printf(gettext("\tspares\n")); 528499653d4eSeschrock 528599653d4eSeschrock for (i = 0; i < nspares; i++) { 5286663207adSDon Brady name = zpool_vdev_name(g_zfs, zhp, spares[i], 5287663207adSDon Brady cb->cb_name_flags); 5288663207adSDon Brady print_status_config(zhp, cb, name, spares[i], 2, B_TRUE); 528999653d4eSeschrock free(name); 529099653d4eSeschrock } 529199653d4eSeschrock } 529299653d4eSeschrock 5293fa94a07fSbrendan static void 5294663207adSDon Brady print_l2cache(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **l2cache, 5295663207adSDon Brady uint_t nl2cache) 5296fa94a07fSbrendan { 5297fa94a07fSbrendan uint_t i; 5298fa94a07fSbrendan char *name; 5299fa94a07fSbrendan 5300fa94a07fSbrendan if (nl2cache == 0) 5301fa94a07fSbrendan return; 5302fa94a07fSbrendan 5303fa94a07fSbrendan (void) printf(gettext("\tcache\n")); 5304fa94a07fSbrendan 5305fa94a07fSbrendan for (i = 0; i < nl2cache; i++) { 5306663207adSDon Brady name = zpool_vdev_name(g_zfs, zhp, l2cache[i], 5307663207adSDon Brady cb->cb_name_flags); 5308663207adSDon Brady print_status_config(zhp, cb, name, l2cache[i], 2, B_FALSE); 5309aa8cf21aSNeil Perrin free(name); 5310aa8cf21aSNeil Perrin } 5311aa8cf21aSNeil Perrin } 5312aa8cf21aSNeil Perrin 53139eb19f4dSGeorge Wilson static void 53149eb19f4dSGeorge Wilson print_dedup_stats(nvlist_t *config) 53159eb19f4dSGeorge Wilson { 53169eb19f4dSGeorge Wilson ddt_histogram_t *ddh; 53179eb19f4dSGeorge Wilson ddt_stat_t *dds; 53189eb19f4dSGeorge Wilson ddt_object_t *ddo; 53199eb19f4dSGeorge Wilson uint_t c; 53209eb19f4dSGeorge Wilson 53219eb19f4dSGeorge Wilson /* 53229eb19f4dSGeorge Wilson * If the pool was faulted then we may not have been able to 53232384d9f8SGeorge Wilson * obtain the config. Otherwise, if we have anything in the dedup 53249eb19f4dSGeorge Wilson * table continue processing the stats. 53259eb19f4dSGeorge Wilson */ 53269eb19f4dSGeorge Wilson if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS, 5327ce72e614SYuri Pankov (uint64_t **)&ddo, &c) != 0) 53289eb19f4dSGeorge Wilson return; 53299eb19f4dSGeorge Wilson 53309eb19f4dSGeorge Wilson (void) printf("\n"); 5331ce72e614SYuri Pankov (void) printf(gettext(" dedup: ")); 5332ce72e614SYuri Pankov if (ddo->ddo_count == 0) { 5333ce72e614SYuri Pankov (void) printf(gettext("no DDT entries\n")); 5334ce72e614SYuri Pankov return; 5335ce72e614SYuri Pankov } 5336ce72e614SYuri Pankov 53379eb19f4dSGeorge Wilson (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n", 53389eb19f4dSGeorge Wilson (u_longlong_t)ddo->ddo_count, 53399eb19f4dSGeorge Wilson (u_longlong_t)ddo->ddo_dspace, 53409eb19f4dSGeorge Wilson (u_longlong_t)ddo->ddo_mspace); 53419eb19f4dSGeorge Wilson 53429eb19f4dSGeorge Wilson verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS, 53439eb19f4dSGeorge Wilson (uint64_t **)&dds, &c) == 0); 53449eb19f4dSGeorge Wilson verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM, 53459eb19f4dSGeorge Wilson (uint64_t **)&ddh, &c) == 0); 53469eb19f4dSGeorge Wilson zpool_dump_ddt(dds, ddh); 53479eb19f4dSGeorge Wilson } 53489eb19f4dSGeorge Wilson 5349fa9e4066Sahrens /* 5350fa9e4066Sahrens * Display a summary of pool status. Displays a summary such as: 5351fa9e4066Sahrens * 5352fa9e4066Sahrens * pool: tank 5353fa9e4066Sahrens * status: DEGRADED 5354fa9e4066Sahrens * reason: One or more devices ... 5355654b400cSJoshua M. Clulow * see: http://illumos.org/msg/ZFS-xxxx-01 5356fa9e4066Sahrens * config: 5357fa9e4066Sahrens * mirror DEGRADED 5358fa9e4066Sahrens * c1t0d0 OK 5359ea8dc4b6Seschrock * c2t0d0 UNAVAIL 5360fa9e4066Sahrens * 5361fa9e4066Sahrens * When given the '-v' option, we print out the complete config. If the '-e' 5362fa9e4066Sahrens * option is specified, then we print out error rate information as well. 5363fa9e4066Sahrens */ 5364fa9e4066Sahrens int 5365fa9e4066Sahrens status_callback(zpool_handle_t *zhp, void *data) 5366fa9e4066Sahrens { 5367fa9e4066Sahrens status_cbdata_t *cbp = data; 5368fa9e4066Sahrens nvlist_t *config, *nvroot; 5369fa9e4066Sahrens char *msgid; 5370fa9e4066Sahrens int reason; 5371eb633035STom Caputi zpool_errata_t errata; 537246657f8dSmmusante const char *health; 537346657f8dSmmusante uint_t c; 537446657f8dSmmusante vdev_stat_t *vs; 5375fa9e4066Sahrens 5376088e9d47Seschrock config = zpool_get_config(zhp, NULL); 5377eb633035STom Caputi reason = zpool_get_status(zhp, &msgid, &errata); 5378fa9e4066Sahrens 5379fa9e4066Sahrens cbp->cb_count++; 5380fa9e4066Sahrens 5381fa9e4066Sahrens /* 5382fa9e4066Sahrens * If we were given 'zpool status -x', only report those pools with 5383fa9e4066Sahrens * problems. 5384fa9e4066Sahrens */ 5385b3a6f804STim Connors if (cbp->cb_explain && 5386b3a6f804STim Connors (reason == ZPOOL_STATUS_OK || 5387b3a6f804STim Connors reason == ZPOOL_STATUS_VERSION_OLDER || 5388b3a6f804STim Connors reason == ZPOOL_STATUS_FEAT_DISABLED)) { 5389e9dbad6fSeschrock if (!cbp->cb_allpools) { 5390e9dbad6fSeschrock (void) printf(gettext("pool '%s' is healthy\n"), 5391e9dbad6fSeschrock zpool_get_name(zhp)); 5392e9dbad6fSeschrock if (cbp->cb_first) 5393e9dbad6fSeschrock cbp->cb_first = B_FALSE; 5394e9dbad6fSeschrock } 5395fa9e4066Sahrens return (0); 5396e9dbad6fSeschrock } 5397fa9e4066Sahrens 5398fa9e4066Sahrens if (cbp->cb_first) 539999653d4eSeschrock cbp->cb_first = B_FALSE; 5400fa9e4066Sahrens else 5401fa9e4066Sahrens (void) printf("\n"); 5402fa9e4066Sahrens 54035cabbc6bSPrashanth Sreenivasa nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE); 54043f9d6ad7SLin Ling verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 540546657f8dSmmusante (uint64_t **)&vs, &c) == 0); 5406990b4856Slling health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 5407fa9e4066Sahrens 5408fa9e4066Sahrens (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 5409fa9e4066Sahrens (void) printf(gettext(" state: %s\n"), health); 5410fa9e4066Sahrens 5411fa9e4066Sahrens switch (reason) { 5412fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_R: 5413fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 5414fa9e4066Sahrens "be opened. Sufficient replicas exist for\n\tthe pool to " 5415fa9e4066Sahrens "continue functioning in a degraded state.\n")); 5416fa9e4066Sahrens (void) printf(gettext("action: Attach the missing device and " 5417fa9e4066Sahrens "online it using 'zpool online'.\n")); 5418fa9e4066Sahrens break; 5419fa9e4066Sahrens 5420fa9e4066Sahrens case ZPOOL_STATUS_MISSING_DEV_NR: 5421fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 5422fa9e4066Sahrens "be opened. There are insufficient\n\treplicas for the " 5423fa9e4066Sahrens "pool to continue functioning.\n")); 5424fa9e4066Sahrens (void) printf(gettext("action: Attach the missing device and " 5425fa9e4066Sahrens "online it using 'zpool online'.\n")); 5426fa9e4066Sahrens break; 5427fa9e4066Sahrens 5428fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_R: 5429fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 5430fa9e4066Sahrens "be used because the label is missing or\n\tinvalid. " 5431fa9e4066Sahrens "Sufficient replicas exist for the pool to continue\n\t" 5432fa9e4066Sahrens "functioning in a degraded state.\n")); 5433fa9e4066Sahrens (void) printf(gettext("action: Replace the device using " 5434fa9e4066Sahrens "'zpool replace'.\n")); 5435fa9e4066Sahrens break; 5436fa9e4066Sahrens 5437fa9e4066Sahrens case ZPOOL_STATUS_CORRUPT_LABEL_NR: 5438fa9e4066Sahrens (void) printf(gettext("status: One or more devices could not " 5439b1b8ab34Slling "be used because the label is missing \n\tor invalid. " 5440fa9e4066Sahrens "There are insufficient replicas for the pool to " 5441fa9e4066Sahrens "continue\n\tfunctioning.\n")); 5442468c413aSTim Haley zpool_explain_recover(zpool_get_handle(zhp), 5443468c413aSTim Haley zpool_get_name(zhp), reason, config); 5444fa9e4066Sahrens break; 5445fa9e4066Sahrens 5446fa9e4066Sahrens case ZPOOL_STATUS_FAILING_DEV: 5447fa9e4066Sahrens (void) printf(gettext("status: One or more devices has " 5448fa9e4066Sahrens "experienced an unrecoverable error. An\n\tattempt was " 5449fa9e4066Sahrens "made to correct the error. Applications are " 5450fa9e4066Sahrens "unaffected.\n")); 5451fa9e4066Sahrens (void) printf(gettext("action: Determine if the device needs " 5452fa9e4066Sahrens "to be replaced, and clear the errors\n\tusing " 5453ea8dc4b6Seschrock "'zpool clear' or replace the device with 'zpool " 5454fa9e4066Sahrens "replace'.\n")); 5455fa9e4066Sahrens break; 5456fa9e4066Sahrens 5457fa9e4066Sahrens case ZPOOL_STATUS_OFFLINE_DEV: 5458fa9e4066Sahrens (void) printf(gettext("status: One or more devices has " 5459d7d4af51Smmusante "been taken offline by the administrator.\n\tSufficient " 5460fa9e4066Sahrens "replicas exist for the pool to continue functioning in " 5461fa9e4066Sahrens "a\n\tdegraded state.\n")); 5462fa9e4066Sahrens (void) printf(gettext("action: Online the device using " 5463fa9e4066Sahrens "'zpool online' or replace the device with\n\t'zpool " 5464fa9e4066Sahrens "replace'.\n")); 5465fa9e4066Sahrens break; 5466fa9e4066Sahrens 5467c25309d4SGeorge Wilson case ZPOOL_STATUS_REMOVED_DEV: 5468c25309d4SGeorge Wilson (void) printf(gettext("status: One or more devices has " 5469c25309d4SGeorge Wilson "been removed by the administrator.\n\tSufficient " 5470c25309d4SGeorge Wilson "replicas exist for the pool to continue functioning in " 5471c25309d4SGeorge Wilson "a\n\tdegraded state.\n")); 5472c25309d4SGeorge Wilson (void) printf(gettext("action: Online the device using " 5473c25309d4SGeorge Wilson "'zpool online' or replace the device with\n\t'zpool " 5474c25309d4SGeorge Wilson "replace'.\n")); 5475c25309d4SGeorge Wilson break; 5476c25309d4SGeorge Wilson 5477fa9e4066Sahrens case ZPOOL_STATUS_RESILVERING: 5478fa9e4066Sahrens (void) printf(gettext("status: One or more devices is " 5479fa9e4066Sahrens "currently being resilvered. The pool will\n\tcontinue " 5480fa9e4066Sahrens "to function, possibly in a degraded state.\n")); 5481fa9e4066Sahrens (void) printf(gettext("action: Wait for the resilver to " 5482fa9e4066Sahrens "complete.\n")); 5483fa9e4066Sahrens break; 5484fa9e4066Sahrens 5485ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_DATA: 5486ea8dc4b6Seschrock (void) printf(gettext("status: One or more devices has " 5487ea8dc4b6Seschrock "experienced an error resulting in data\n\tcorruption. " 5488ea8dc4b6Seschrock "Applications may be affected.\n")); 5489ea8dc4b6Seschrock (void) printf(gettext("action: Restore the file in question " 5490ea8dc4b6Seschrock "if possible. Otherwise restore the\n\tentire pool from " 5491ea8dc4b6Seschrock "backup.\n")); 5492ea8dc4b6Seschrock break; 5493ea8dc4b6Seschrock 5494ea8dc4b6Seschrock case ZPOOL_STATUS_CORRUPT_POOL: 5495ea8dc4b6Seschrock (void) printf(gettext("status: The pool metadata is corrupted " 5496ea8dc4b6Seschrock "and the pool cannot be opened.\n")); 5497468c413aSTim Haley zpool_explain_recover(zpool_get_handle(zhp), 5498468c413aSTim Haley zpool_get_name(zhp), reason, config); 5499ea8dc4b6Seschrock break; 5500ea8dc4b6Seschrock 5501eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_OLDER: 550257221772SChristopher Siden (void) printf(gettext("status: The pool is formatted using a " 550357221772SChristopher Siden "legacy on-disk format. The pool can\n\tstill be used, " 550457221772SChristopher Siden "but some features are unavailable.\n")); 5505eaca9bbdSeschrock (void) printf(gettext("action: Upgrade the pool using 'zpool " 5506eaca9bbdSeschrock "upgrade'. Once this is done, the\n\tpool will no longer " 550757221772SChristopher Siden "be accessible on software that does not support feature\n" 550857221772SChristopher Siden "\tflags.\n")); 5509eaca9bbdSeschrock break; 5510eaca9bbdSeschrock 5511eaca9bbdSeschrock case ZPOOL_STATUS_VERSION_NEWER: 5512eaca9bbdSeschrock (void) printf(gettext("status: The pool has been upgraded to a " 5513eaca9bbdSeschrock "newer, incompatible on-disk version.\n\tThe pool cannot " 5514eaca9bbdSeschrock "be accessed on this system.\n")); 5515eaca9bbdSeschrock (void) printf(gettext("action: Access the pool from a system " 5516eaca9bbdSeschrock "running more recent software, or\n\trestore the pool from " 5517eaca9bbdSeschrock "backup.\n")); 5518eaca9bbdSeschrock break; 5519eaca9bbdSeschrock 552057221772SChristopher Siden case ZPOOL_STATUS_FEAT_DISABLED: 552157221772SChristopher Siden (void) printf(gettext("status: Some supported features are not " 552257221772SChristopher Siden "enabled on the pool. The pool can\n\tstill be used, but " 552357221772SChristopher Siden "some features are unavailable.\n")); 552457221772SChristopher Siden (void) printf(gettext("action: Enable all features using " 552557221772SChristopher Siden "'zpool upgrade'. Once this is done,\n\tthe pool may no " 552657221772SChristopher Siden "longer be accessible by software that does not support\n\t" 552757221772SChristopher Siden "the features. See zpool-features(5) for details.\n")); 552857221772SChristopher Siden break; 552957221772SChristopher Siden 5530ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_READ: 5531ad135b5dSChristopher Siden (void) printf(gettext("status: The pool cannot be accessed on " 5532ad135b5dSChristopher Siden "this system because it uses the\n\tfollowing feature(s) " 5533ad135b5dSChristopher Siden "not supported on this system:\n")); 5534ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 5535ad135b5dSChristopher Siden (void) printf("\n"); 5536ad135b5dSChristopher Siden (void) printf(gettext("action: Access the pool from a system " 5537ad135b5dSChristopher Siden "that supports the required feature(s),\n\tor restore the " 5538ad135b5dSChristopher Siden "pool from backup.\n")); 5539ad135b5dSChristopher Siden break; 5540ad135b5dSChristopher Siden 5541ad135b5dSChristopher Siden case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 5542ad135b5dSChristopher Siden (void) printf(gettext("status: The pool can only be accessed " 5543ad135b5dSChristopher Siden "in read-only mode on this system. It\n\tcannot be " 5544ad135b5dSChristopher Siden "accessed in read-write mode because it uses the " 5545ad135b5dSChristopher Siden "following\n\tfeature(s) not supported on this system:\n")); 5546ad135b5dSChristopher Siden zpool_print_unsup_feat(config); 5547ad135b5dSChristopher Siden (void) printf("\n"); 5548ad135b5dSChristopher Siden (void) printf(gettext("action: The pool cannot be accessed in " 5549ad135b5dSChristopher Siden "read-write mode. Import the pool with\n" 5550ad135b5dSChristopher Siden "\t\"-o readonly=on\", access the pool from a system that " 5551ad135b5dSChristopher Siden "supports the\n\trequired feature(s), or restore the " 5552ad135b5dSChristopher Siden "pool from backup.\n")); 5553ad135b5dSChristopher Siden break; 5554ad135b5dSChristopher Siden 55553d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_R: 55563d7072f8Seschrock (void) printf(gettext("status: One or more devices are " 55573d7072f8Seschrock "faulted in response to persistent errors.\n\tSufficient " 55583d7072f8Seschrock "replicas exist for the pool to continue functioning " 55593d7072f8Seschrock "in a\n\tdegraded state.\n")); 55603d7072f8Seschrock (void) printf(gettext("action: Replace the faulted device, " 55613d7072f8Seschrock "or use 'zpool clear' to mark the device\n\trepaired.\n")); 55623d7072f8Seschrock break; 55633d7072f8Seschrock 55643d7072f8Seschrock case ZPOOL_STATUS_FAULTED_DEV_NR: 55653d7072f8Seschrock (void) printf(gettext("status: One or more devices are " 55663d7072f8Seschrock "faulted in response to persistent errors. There are " 55673d7072f8Seschrock "insufficient replicas for the pool to\n\tcontinue " 55683d7072f8Seschrock "functioning.\n")); 55693d7072f8Seschrock (void) printf(gettext("action: Destroy and re-create the pool " 55703d7072f8Seschrock "from a backup source. Manually marking the device\n" 55713d7072f8Seschrock "\trepaired using 'zpool clear' may allow some data " 55723d7072f8Seschrock "to be recovered.\n")); 55733d7072f8Seschrock break; 55743d7072f8Seschrock 5575e0f1c0afSOlaf Faaland case ZPOOL_STATUS_IO_FAILURE_MMP: 5576e0f1c0afSOlaf Faaland (void) printf(gettext("status: The pool is suspended because " 5577e0f1c0afSOlaf Faaland "multihost writes failed or were delayed;\n\tanother " 5578e0f1c0afSOlaf Faaland "system could import the pool undetected.\n")); 5579e0f1c0afSOlaf Faaland (void) printf(gettext("action: Make sure the pool's devices " 5580e0f1c0afSOlaf Faaland "are connected, then reboot your system and\n\timport the " 5581e0f1c0afSOlaf Faaland "pool.\n")); 5582e0f1c0afSOlaf Faaland break; 5583e0f1c0afSOlaf Faaland 558432b87932Sek case ZPOOL_STATUS_IO_FAILURE_WAIT: 558532b87932Sek case ZPOOL_STATUS_IO_FAILURE_CONTINUE: 558632b87932Sek (void) printf(gettext("status: One or more devices are " 55878a79c1b5Sek "faulted in response to IO failures.\n")); 558832b87932Sek (void) printf(gettext("action: Make sure the affected devices " 558932b87932Sek "are connected, then run 'zpool clear'.\n")); 559032b87932Sek break; 559132b87932Sek 5592b87f3af3Sperrin case ZPOOL_STATUS_BAD_LOG: 5593b87f3af3Sperrin (void) printf(gettext("status: An intent log record " 5594b87f3af3Sperrin "could not be read.\n" 5595b87f3af3Sperrin "\tWaiting for adminstrator intervention to fix the " 5596b87f3af3Sperrin "faulted pool.\n")); 5597b87f3af3Sperrin (void) printf(gettext("action: Either restore the affected " 5598b87f3af3Sperrin "device(s) and run 'zpool online',\n" 5599b87f3af3Sperrin "\tor ignore the intent log records by running " 5600b87f3af3Sperrin "'zpool clear'.\n")); 5601b87f3af3Sperrin break; 5602b87f3af3Sperrin 5603eb633035STom Caputi case ZPOOL_STATUS_ERRATA: 5604eb633035STom Caputi (void) printf(gettext("status: Errata #%d detected.\n"), 5605eb633035STom Caputi errata); 5606eb633035STom Caputi 5607eb633035STom Caputi switch (errata) { 5608eb633035STom Caputi case ZPOOL_ERRATA_NONE: 5609eb633035STom Caputi break; 5610eb633035STom Caputi 5611eb633035STom Caputi case ZPOOL_ERRATA_ZOL_2094_SCRUB: 5612eb633035STom Caputi (void) printf(gettext("action: To correct the issue " 5613eb633035STom Caputi "run 'zpool scrub'.\n")); 5614eb633035STom Caputi break; 5615eb633035STom Caputi 5616eb633035STom Caputi case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION: 5617eb633035STom Caputi (void) printf(gettext("\tExisting encrypted datasets " 5618eb633035STom Caputi "contain an on-disk incompatibility\n\twhich " 5619eb633035STom Caputi "needs to be corrected.\n")); 5620eb633035STom Caputi (void) printf(gettext("action: To correct the issue " 5621eb633035STom Caputi "backup existing encrypted datasets to new\n\t" 5622eb633035STom Caputi "encrypted datasets and destroy the old ones. " 5623eb633035STom Caputi "'zfs mount -o ro' can\n\tbe used to temporarily " 5624eb633035STom Caputi "mount existing encrypted datasets readonly.\n")); 5625eb633035STom Caputi break; 5626eb633035STom Caputi 5627eb633035STom Caputi case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION: 5628eb633035STom Caputi (void) printf(gettext("\tExisting encrypted datasets " 5629eb633035STom Caputi "contain an on-disk incompatibility\n\twhich " 5630eb633035STom Caputi "needs to be corrected.\n")); 5631eb633035STom Caputi (void) printf(gettext("action: To correct the issue " 5632eb633035STom Caputi "enable the bookmark_v2 feature and " 5633eb633035STom Caputi "backup\n\tany existing encrypted datasets to " 5634eb633035STom Caputi "new encrypted datasets and\n\tdestroy the old " 5635eb633035STom Caputi "ones. If this pool does not contain any\n\t" 5636eb633035STom Caputi "encrypted datasets, simply enable the " 5637eb633035STom Caputi "bookmark_v2 feature\n")); 5638eb633035STom Caputi break; 5639eb633035STom Caputi 5640eb633035STom Caputi default: 5641eb633035STom Caputi /* 5642eb633035STom Caputi * All errata which allow the pool to be imported 5643eb633035STom Caputi * must contain an action message. 5644eb633035STom Caputi */ 5645eb633035STom Caputi assert(0); 5646eb633035STom Caputi } 5647eb633035STom Caputi break; 5648eb633035STom Caputi 5649fa9e4066Sahrens default: 5650fa9e4066Sahrens /* 5651fa9e4066Sahrens * The remaining errors can't actually be generated, yet. 5652fa9e4066Sahrens */ 5653fa9e4066Sahrens assert(reason == ZPOOL_STATUS_OK); 5654fa9e4066Sahrens } 5655fa9e4066Sahrens 5656fa9e4066Sahrens if (msgid != NULL) 5657654b400cSJoshua M. Clulow (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 5658fa9e4066Sahrens msgid); 5659fa9e4066Sahrens 5660fa9e4066Sahrens if (config != NULL) { 5661ea8dc4b6Seschrock uint64_t nerr; 5662fa94a07fSbrendan nvlist_t **spares, **l2cache; 5663fa94a07fSbrendan uint_t nspares, nl2cache; 566486714001SSerapheim Dimitropoulos pool_checkpoint_stat_t *pcs = NULL; 56653f9d6ad7SLin Ling pool_scan_stat_t *ps = NULL; 56665cabbc6bSPrashanth Sreenivasa pool_removal_stat_t *prs = NULL; 5667fa9e4066Sahrens 566886714001SSerapheim Dimitropoulos (void) nvlist_lookup_uint64_array(nvroot, 566986714001SSerapheim Dimitropoulos ZPOOL_CONFIG_CHECKPOINT_STATS, (uint64_t **)&pcs, &c); 56703f9d6ad7SLin Ling (void) nvlist_lookup_uint64_array(nvroot, 56713f9d6ad7SLin Ling ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c); 56725cabbc6bSPrashanth Sreenivasa (void) nvlist_lookup_uint64_array(nvroot, 56735cabbc6bSPrashanth Sreenivasa ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c); 567486714001SSerapheim Dimitropoulos 567586714001SSerapheim Dimitropoulos print_scan_status(ps); 567686714001SSerapheim Dimitropoulos print_checkpoint_scan_warning(ps, pcs); 56775cabbc6bSPrashanth Sreenivasa print_removal_status(zhp, prs); 567886714001SSerapheim Dimitropoulos print_checkpoint_status(pcs); 56795cabbc6bSPrashanth Sreenivasa 5680663207adSDon Brady cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0, 5681663207adSDon Brady cbp->cb_name_flags); 5682663207adSDon Brady if (cbp->cb_namewidth < 10) 5683663207adSDon Brady cbp->cb_namewidth = 10; 5684fa9e4066Sahrens 5685fa9e4066Sahrens (void) printf(gettext("config:\n\n")); 5686663207adSDon Brady (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), 5687663207adSDon Brady cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE", 5688663207adSDon Brady "CKSUM"); 5689663207adSDon Brady 5690663207adSDon Brady print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0, 5691663207adSDon Brady B_FALSE); 5692663207adSDon Brady 5693663207adSDon Brady print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_DEDUP); 5694663207adSDon Brady print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_SPECIAL); 5695663207adSDon Brady print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_CLASS_LOGS); 569699653d4eSeschrock 5697fa94a07fSbrendan if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 5698fa94a07fSbrendan &l2cache, &nl2cache) == 0) 5699663207adSDon Brady print_l2cache(zhp, cbp, l2cache, nl2cache); 5700fa94a07fSbrendan 570199653d4eSeschrock if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 570299653d4eSeschrock &spares, &nspares) == 0) 5703663207adSDon Brady print_spares(zhp, cbp, spares, nspares); 5704ea8dc4b6Seschrock 5705ea8dc4b6Seschrock if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 5706ea8dc4b6Seschrock &nerr) == 0) { 570755434c77Sek nvlist_t *nverrlist = NULL; 570855434c77Sek 5709ea8dc4b6Seschrock /* 5710ea8dc4b6Seschrock * If the approximate error count is small, get a 5711ea8dc4b6Seschrock * precise count by fetching the entire log and 5712ea8dc4b6Seschrock * uniquifying the results. 5713ea8dc4b6Seschrock */ 571475519f38Sek if (nerr > 0 && nerr < 100 && !cbp->cb_verbose && 571555434c77Sek zpool_get_errlog(zhp, &nverrlist) == 0) { 571655434c77Sek nvpair_t *elem; 571755434c77Sek 571855434c77Sek elem = NULL; 571955434c77Sek nerr = 0; 572055434c77Sek while ((elem = nvlist_next_nvpair(nverrlist, 572155434c77Sek elem)) != NULL) { 572255434c77Sek nerr++; 572355434c77Sek } 572455434c77Sek } 572555434c77Sek nvlist_free(nverrlist); 5726ea8dc4b6Seschrock 5727ea8dc4b6Seschrock (void) printf("\n"); 572899653d4eSeschrock 5729ea8dc4b6Seschrock if (nerr == 0) 5730ea8dc4b6Seschrock (void) printf(gettext("errors: No known data " 5731ea8dc4b6Seschrock "errors\n")); 5732ea8dc4b6Seschrock else if (!cbp->cb_verbose) 5733e9dbad6fSeschrock (void) printf(gettext("errors: %llu data " 57345ad82045Snd "errors, use '-v' for a list\n"), 57355ad82045Snd (u_longlong_t)nerr); 5736ea8dc4b6Seschrock else 5737ea8dc4b6Seschrock print_error_log(zhp); 5738ea8dc4b6Seschrock } 57399eb19f4dSGeorge Wilson 57409eb19f4dSGeorge Wilson if (cbp->cb_dedup_stats) 57419eb19f4dSGeorge Wilson print_dedup_stats(config); 5742fa9e4066Sahrens } else { 5743fa9e4066Sahrens (void) printf(gettext("config: The configuration cannot be " 5744fa9e4066Sahrens "determined.\n")); 5745fa9e4066Sahrens } 5746fa9e4066Sahrens 5747fa9e4066Sahrens return (0); 5748fa9e4066Sahrens } 5749fa9e4066Sahrens 5750fa9e4066Sahrens /* 5751663207adSDon Brady * zpool status [-gLPvx] [-T d|u] [pool] ... [interval [count]] 5752fa9e4066Sahrens * 5753663207adSDon Brady * -g Display guid for individual vdev name. 5754663207adSDon Brady * -L Follow links when resolving vdev path name. 5755663207adSDon Brady * -P Display full path for vdev name. 5756fa9e4066Sahrens * -v Display complete error logs 5757fa9e4066Sahrens * -x Display only pools with potential problems 57589eb19f4dSGeorge Wilson * -D Display dedup status (undocumented) 57593f9d6ad7SLin Ling * -T Display a timestamp in date(1) or Unix format 5760fa9e4066Sahrens * 5761fa9e4066Sahrens * Describes the health status of all pools or some subset. 5762fa9e4066Sahrens */ 5763fa9e4066Sahrens int 5764fa9e4066Sahrens zpool_do_status(int argc, char **argv) 5765fa9e4066Sahrens { 5766fa9e4066Sahrens int c; 5767fa9e4066Sahrens int ret; 57683f9d6ad7SLin Ling unsigned long interval = 0, count = 0; 5769fa9e4066Sahrens status_cbdata_t cb = { 0 }; 5770fa9e4066Sahrens 5771fa9e4066Sahrens /* check options */ 5772663207adSDon Brady while ((c = getopt(argc, argv, "gLPvxDT:")) != -1) { 5773fa9e4066Sahrens switch (c) { 5774663207adSDon Brady case 'g': 5775663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_GUID; 5776663207adSDon Brady break; 5777663207adSDon Brady case 'L': 5778663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS; 5779663207adSDon Brady break; 5780663207adSDon Brady case 'P': 5781663207adSDon Brady cb.cb_name_flags |= VDEV_NAME_PATH; 5782663207adSDon Brady break; 5783fa9e4066Sahrens case 'v': 578499653d4eSeschrock cb.cb_verbose = B_TRUE; 5785fa9e4066Sahrens break; 5786fa9e4066Sahrens case 'x': 578799653d4eSeschrock cb.cb_explain = B_TRUE; 5788fa9e4066Sahrens break; 57899eb19f4dSGeorge Wilson case 'D': 57909eb19f4dSGeorge Wilson cb.cb_dedup_stats = B_TRUE; 57919eb19f4dSGeorge Wilson break; 57923f9d6ad7SLin Ling case 'T': 57933f9d6ad7SLin Ling get_timestamp_arg(*optarg); 57943f9d6ad7SLin Ling break; 5795fa9e4066Sahrens case '?': 5796fa9e4066Sahrens (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5797fa9e4066Sahrens optopt); 579899653d4eSeschrock usage(B_FALSE); 5799fa9e4066Sahrens } 5800fa9e4066Sahrens } 5801fa9e4066Sahrens 5802fa9e4066Sahrens argc -= optind; 5803fa9e4066Sahrens argv += optind; 5804fa9e4066Sahrens 58053f9d6ad7SLin Ling get_interval_count(&argc, argv, &interval, &count); 5806fa9e4066Sahrens 5807e9dbad6fSeschrock if (argc == 0) 5808e9dbad6fSeschrock cb.cb_allpools = B_TRUE; 5809e9dbad6fSeschrock 58103f9d6ad7SLin Ling cb.cb_first = B_TRUE; 5811663207adSDon Brady cb.cb_print_status = B_TRUE; 5812fa9e4066Sahrens 58133f9d6ad7SLin Ling for (;;) { 58143f9d6ad7SLin Ling if (timestamp_fmt != NODATE) 58153f9d6ad7SLin Ling print_timestamp(timestamp_fmt); 5816fa9e4066Sahrens 58173f9d6ad7SLin Ling ret = for_each_pool(argc, argv, B_TRUE, NULL, 58183f9d6ad7SLin Ling status_callback, &cb); 58193f9d6ad7SLin Ling 58203f9d6ad7SLin Ling if (argc == 0 && cb.cb_count == 0) 58213f9d6ad7SLin Ling (void) printf(gettext("no pools available\n")); 58223f9d6ad7SLin Ling else if (cb.cb_explain && cb.cb_first && cb.cb_allpools) 58233f9d6ad7SLin Ling (void) printf(gettext("all pools are healthy\n")); 58243f9d6ad7SLin Ling 58253f9d6ad7SLin Ling if (ret != 0) 58263f9d6ad7SLin Ling return (ret); 58273f9d6ad7SLin Ling 58283f9d6ad7SLin Ling if (interval == 0) 58293f9d6ad7SLin Ling break; 58303f9d6ad7SLin Ling 58313f9d6ad7SLin Ling if (count != 0 && --count == 0) 58323f9d6ad7SLin Ling break; 58333f9d6ad7SLin Ling 58343f9d6ad7SLin Ling (void) sleep(interval); 58353f9d6ad7SLin Ling } 58363f9d6ad7SLin Ling 58373f9d6ad7SLin Ling return (0); 5838fa9e4066Sahrens } 5839fa9e4066Sahrens 5840eaca9bbdSeschrock typedef struct upgrade_cbdata { 5841eaca9bbdSeschrock int cb_first; 584206eeb2adSek int cb_argc; 5843990b4856Slling uint64_t cb_version; 584406eeb2adSek char **cb_argv; 5845eaca9bbdSeschrock } upgrade_cbdata_t; 5846eaca9bbdSeschrock 584757221772SChristopher Siden static int 584857221772SChristopher Siden upgrade_version(zpool_handle_t *zhp, uint64_t version) 584957221772SChristopher Siden { 585057221772SChristopher Siden int ret; 585157221772SChristopher Siden nvlist_t *config; 585257221772SChristopher Siden uint64_t oldversion; 585357221772SChristopher Siden 585457221772SChristopher Siden config = zpool_get_config(zhp, NULL); 585557221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 585657221772SChristopher Siden &oldversion) == 0); 585757221772SChristopher Siden 585857221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(oldversion)); 585957221772SChristopher Siden assert(oldversion < version); 586057221772SChristopher Siden 586157221772SChristopher Siden ret = zpool_upgrade(zhp, version); 586257221772SChristopher Siden if (ret != 0) 586357221772SChristopher Siden return (ret); 586457221772SChristopher Siden 586557221772SChristopher Siden if (version >= SPA_VERSION_FEATURES) { 586657221772SChristopher Siden (void) printf(gettext("Successfully upgraded " 586757221772SChristopher Siden "'%s' from version %llu to feature flags.\n"), 586857221772SChristopher Siden zpool_get_name(zhp), oldversion); 586957221772SChristopher Siden } else { 587057221772SChristopher Siden (void) printf(gettext("Successfully upgraded " 587157221772SChristopher Siden "'%s' from version %llu to version %llu.\n"), 587257221772SChristopher Siden zpool_get_name(zhp), oldversion, version); 587357221772SChristopher Siden } 587457221772SChristopher Siden 587557221772SChristopher Siden return (0); 587657221772SChristopher Siden } 587757221772SChristopher Siden 587857221772SChristopher Siden static int 587957221772SChristopher Siden upgrade_enable_all(zpool_handle_t *zhp, int *countp) 588057221772SChristopher Siden { 588157221772SChristopher Siden int i, ret, count; 588257221772SChristopher Siden boolean_t firstff = B_TRUE; 588357221772SChristopher Siden nvlist_t *enabled = zpool_get_features(zhp); 588457221772SChristopher Siden 588557221772SChristopher Siden count = 0; 588657221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 588757221772SChristopher Siden const char *fname = spa_feature_table[i].fi_uname; 588857221772SChristopher Siden const char *fguid = spa_feature_table[i].fi_guid; 588957221772SChristopher Siden if (!nvlist_exists(enabled, fguid)) { 589057221772SChristopher Siden char *propname; 589157221772SChristopher Siden verify(-1 != asprintf(&propname, "feature@%s", fname)); 589257221772SChristopher Siden ret = zpool_set_prop(zhp, propname, 589357221772SChristopher Siden ZFS_FEATURE_ENABLED); 589457221772SChristopher Siden if (ret != 0) { 589557221772SChristopher Siden free(propname); 589657221772SChristopher Siden return (ret); 589757221772SChristopher Siden } 589857221772SChristopher Siden count++; 589957221772SChristopher Siden 590057221772SChristopher Siden if (firstff) { 590157221772SChristopher Siden (void) printf(gettext("Enabled the " 590257221772SChristopher Siden "following features on '%s':\n"), 590357221772SChristopher Siden zpool_get_name(zhp)); 590457221772SChristopher Siden firstff = B_FALSE; 590557221772SChristopher Siden } 590657221772SChristopher Siden (void) printf(gettext(" %s\n"), fname); 590757221772SChristopher Siden free(propname); 590857221772SChristopher Siden } 590957221772SChristopher Siden } 591057221772SChristopher Siden 591157221772SChristopher Siden if (countp != NULL) 591257221772SChristopher Siden *countp = count; 591357221772SChristopher Siden return (0); 591457221772SChristopher Siden } 591557221772SChristopher Siden 5916eaca9bbdSeschrock static int 5917eaca9bbdSeschrock upgrade_cb(zpool_handle_t *zhp, void *arg) 5918eaca9bbdSeschrock { 5919eaca9bbdSeschrock upgrade_cbdata_t *cbp = arg; 5920eaca9bbdSeschrock nvlist_t *config; 5921eaca9bbdSeschrock uint64_t version; 592257221772SChristopher Siden boolean_t printnl = B_FALSE; 592357221772SChristopher Siden int ret; 5924eaca9bbdSeschrock 5925eaca9bbdSeschrock config = zpool_get_config(zhp, NULL); 5926eaca9bbdSeschrock verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 5927eaca9bbdSeschrock &version) == 0); 5928eaca9bbdSeschrock 592957221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(version)); 5930eaca9bbdSeschrock 593157221772SChristopher Siden if (version < cbp->cb_version) { 593257221772SChristopher Siden cbp->cb_first = B_FALSE; 593357221772SChristopher Siden ret = upgrade_version(zhp, cbp->cb_version); 593457221772SChristopher Siden if (ret != 0) 593557221772SChristopher Siden return (ret); 593657221772SChristopher Siden printnl = B_TRUE; 593757221772SChristopher Siden 593857221772SChristopher Siden /* 593957221772SChristopher Siden * If they did "zpool upgrade -a", then we could 594057221772SChristopher Siden * be doing ioctls to different pools. We need 594157221772SChristopher Siden * to log this history once to each pool, and bypass 594257221772SChristopher Siden * the normal history logging that happens in main(). 594357221772SChristopher Siden */ 594457221772SChristopher Siden (void) zpool_log_history(g_zfs, history_str); 594557221772SChristopher Siden log_history = B_FALSE; 594657221772SChristopher Siden } 594757221772SChristopher Siden 594857221772SChristopher Siden if (cbp->cb_version >= SPA_VERSION_FEATURES) { 594957221772SChristopher Siden int count; 595057221772SChristopher Siden ret = upgrade_enable_all(zhp, &count); 595157221772SChristopher Siden if (ret != 0) 595257221772SChristopher Siden return (ret); 595357221772SChristopher Siden 595457221772SChristopher Siden if (count > 0) { 595599653d4eSeschrock cbp->cb_first = B_FALSE; 595657221772SChristopher Siden printnl = B_TRUE; 5957eaca9bbdSeschrock } 595857221772SChristopher Siden } 5959eaca9bbdSeschrock 596057221772SChristopher Siden if (printnl) { 596157221772SChristopher Siden (void) printf(gettext("\n")); 596257221772SChristopher Siden } 596357221772SChristopher Siden 596457221772SChristopher Siden return (0); 596557221772SChristopher Siden } 596657221772SChristopher Siden 596757221772SChristopher Siden static int 596857221772SChristopher Siden upgrade_list_older_cb(zpool_handle_t *zhp, void *arg) 596957221772SChristopher Siden { 597057221772SChristopher Siden upgrade_cbdata_t *cbp = arg; 597157221772SChristopher Siden nvlist_t *config; 597257221772SChristopher Siden uint64_t version; 597357221772SChristopher Siden 597457221772SChristopher Siden config = zpool_get_config(zhp, NULL); 597557221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 597657221772SChristopher Siden &version) == 0); 597757221772SChristopher Siden 597857221772SChristopher Siden assert(SPA_VERSION_IS_SUPPORTED(version)); 597957221772SChristopher Siden 598057221772SChristopher Siden if (version < SPA_VERSION_FEATURES) { 5981eaca9bbdSeschrock if (cbp->cb_first) { 5982eaca9bbdSeschrock (void) printf(gettext("The following pools are " 598357221772SChristopher Siden "formatted with legacy version numbers and can\n" 598457221772SChristopher Siden "be upgraded to use feature flags. After " 598557221772SChristopher Siden "being upgraded, these pools\nwill no " 598657221772SChristopher Siden "longer be accessible by software that does not " 598757221772SChristopher Siden "support feature\nflags.\n\n")); 5988eaca9bbdSeschrock (void) printf(gettext("VER POOL\n")); 5989eaca9bbdSeschrock (void) printf(gettext("--- ------------\n")); 599099653d4eSeschrock cbp->cb_first = B_FALSE; 5991eaca9bbdSeschrock } 5992eaca9bbdSeschrock 59935ad82045Snd (void) printf("%2llu %s\n", (u_longlong_t)version, 5994eaca9bbdSeschrock zpool_get_name(zhp)); 5995eaca9bbdSeschrock } 5996eaca9bbdSeschrock 599757221772SChristopher Siden return (0); 599857221772SChristopher Siden } 599957221772SChristopher Siden 600057221772SChristopher Siden static int 600157221772SChristopher Siden upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg) 600257221772SChristopher Siden { 600357221772SChristopher Siden upgrade_cbdata_t *cbp = arg; 600457221772SChristopher Siden nvlist_t *config; 600557221772SChristopher Siden uint64_t version; 600657221772SChristopher Siden 600757221772SChristopher Siden config = zpool_get_config(zhp, NULL); 600857221772SChristopher Siden verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 600957221772SChristopher Siden &version) == 0); 601057221772SChristopher Siden 601157221772SChristopher Siden if (version >= SPA_VERSION_FEATURES) { 601257221772SChristopher Siden int i; 601357221772SChristopher Siden boolean_t poolfirst = B_TRUE; 601457221772SChristopher Siden nvlist_t *enabled = zpool_get_features(zhp); 601557221772SChristopher Siden 601657221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 601757221772SChristopher Siden const char *fguid = spa_feature_table[i].fi_guid; 601857221772SChristopher Siden const char *fname = spa_feature_table[i].fi_uname; 601957221772SChristopher Siden if (!nvlist_exists(enabled, fguid)) { 602057221772SChristopher Siden if (cbp->cb_first) { 602157221772SChristopher Siden (void) printf(gettext("\nSome " 602257221772SChristopher Siden "supported features are not " 602357221772SChristopher Siden "enabled on the following pools. " 602457221772SChristopher Siden "Once a\nfeature is enabled the " 602557221772SChristopher Siden "pool may become incompatible with " 602657221772SChristopher Siden "software\nthat does not support " 602757221772SChristopher Siden "the feature. See " 602857221772SChristopher Siden "zpool-features(5) for " 602957221772SChristopher Siden "details.\n\n")); 603057221772SChristopher Siden (void) printf(gettext("POOL " 603157221772SChristopher Siden "FEATURE\n")); 603257221772SChristopher Siden (void) printf(gettext("------" 603357221772SChristopher Siden "---------\n")); 603457221772SChristopher Siden cbp->cb_first = B_FALSE; 603557221772SChristopher Siden } 603657221772SChristopher Siden 603757221772SChristopher Siden if (poolfirst) { 603857221772SChristopher Siden (void) printf(gettext("%s\n"), 603957221772SChristopher Siden zpool_get_name(zhp)); 604057221772SChristopher Siden poolfirst = B_FALSE; 604157221772SChristopher Siden } 604257221772SChristopher Siden 604357221772SChristopher Siden (void) printf(gettext(" %s\n"), fname); 604457221772SChristopher Siden } 604557221772SChristopher Siden } 604657221772SChristopher Siden } 604757221772SChristopher Siden 604857221772SChristopher Siden return (0); 6049eaca9bbdSeschrock } 6050eaca9bbdSeschrock 6051eaca9bbdSeschrock /* ARGSUSED */ 6052eaca9bbdSeschrock static int 605306eeb2adSek upgrade_one(zpool_handle_t *zhp, void *data) 6054eaca9bbdSeschrock { 605557221772SChristopher Siden boolean_t printnl = B_FALSE; 6056990b4856Slling upgrade_cbdata_t *cbp = data; 6057990b4856Slling uint64_t cur_version; 6058eaca9bbdSeschrock int ret; 6059eaca9bbdSeschrock 60608654d025Sperrin if (strcmp("log", zpool_get_name(zhp)) == 0) { 60618654d025Sperrin (void) printf(gettext("'log' is now a reserved word\n" 60628654d025Sperrin "Pool 'log' must be renamed using export and import" 60638654d025Sperrin " to upgrade.\n")); 60648654d025Sperrin return (1); 60658654d025Sperrin } 6066990b4856Slling 6067990b4856Slling cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 6068e6c728e1Sbrendan if (cur_version > cbp->cb_version) { 6069eaca9bbdSeschrock (void) printf(gettext("Pool '%s' is already formatted " 607057221772SChristopher Siden "using more current version '%llu'.\n\n"), 6071e6c728e1Sbrendan zpool_get_name(zhp), cur_version); 6072e6c728e1Sbrendan return (0); 6073e6c728e1Sbrendan } 607457221772SChristopher Siden 607557221772SChristopher Siden if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) { 6076e6c728e1Sbrendan (void) printf(gettext("Pool '%s' is already formatted " 607757221772SChristopher Siden "using version %llu.\n\n"), zpool_get_name(zhp), 607857221772SChristopher Siden cbp->cb_version); 6079eaca9bbdSeschrock return (0); 6080eaca9bbdSeschrock } 6081eaca9bbdSeschrock 608257221772SChristopher Siden if (cur_version != cbp->cb_version) { 608357221772SChristopher Siden printnl = B_TRUE; 608457221772SChristopher Siden ret = upgrade_version(zhp, cbp->cb_version); 608557221772SChristopher Siden if (ret != 0) 608657221772SChristopher Siden return (ret); 608757221772SChristopher Siden } 608806eeb2adSek 608957221772SChristopher Siden if (cbp->cb_version >= SPA_VERSION_FEATURES) { 609057221772SChristopher Siden int count = 0; 609157221772SChristopher Siden ret = upgrade_enable_all(zhp, &count); 609257221772SChristopher Siden if (ret != 0) 609357221772SChristopher Siden return (ret); 609457221772SChristopher Siden 609557221772SChristopher Siden if (count != 0) { 609657221772SChristopher Siden printnl = B_TRUE; 609757221772SChristopher Siden } else if (cur_version == SPA_VERSION) { 609857221772SChristopher Siden (void) printf(gettext("Pool '%s' already has all " 609957221772SChristopher Siden "supported features enabled.\n"), 610057221772SChristopher Siden zpool_get_name(zhp)); 610157221772SChristopher Siden } 610257221772SChristopher Siden } 610357221772SChristopher Siden 610457221772SChristopher Siden if (printnl) { 610557221772SChristopher Siden (void) printf(gettext("\n")); 610606eeb2adSek } 6107eaca9bbdSeschrock 610857221772SChristopher Siden return (0); 6109eaca9bbdSeschrock } 6110eaca9bbdSeschrock 6111eaca9bbdSeschrock /* 6112eaca9bbdSeschrock * zpool upgrade 6113eaca9bbdSeschrock * zpool upgrade -v 6114990b4856Slling * zpool upgrade [-V version] <-a | pool ...> 6115eaca9bbdSeschrock * 6116eaca9bbdSeschrock * With no arguments, display downrev'd ZFS pool available for upgrade. 6117eaca9bbdSeschrock * Individual pools can be upgraded by specifying the pool, and '-a' will 6118eaca9bbdSeschrock * upgrade all pools. 6119eaca9bbdSeschrock */ 6120eaca9bbdSeschrock int 6121eaca9bbdSeschrock zpool_do_upgrade(int argc, char **argv) 6122eaca9bbdSeschrock { 6123eaca9bbdSeschrock int c; 6124eaca9bbdSeschrock upgrade_cbdata_t cb = { 0 }; 6125eaca9bbdSeschrock int ret = 0; 6126eaca9bbdSeschrock boolean_t showversions = B_FALSE; 612757221772SChristopher Siden boolean_t upgradeall = B_FALSE; 6128990b4856Slling char *end; 6129990b4856Slling 6130eaca9bbdSeschrock 6131eaca9bbdSeschrock /* check options */ 6132478ed9adSEric Taylor while ((c = getopt(argc, argv, ":avV:")) != -1) { 6133eaca9bbdSeschrock switch (c) { 6134eaca9bbdSeschrock case 'a': 613557221772SChristopher Siden upgradeall = B_TRUE; 6136eaca9bbdSeschrock break; 6137eaca9bbdSeschrock case 'v': 6138eaca9bbdSeschrock showversions = B_TRUE; 6139eaca9bbdSeschrock break; 6140990b4856Slling case 'V': 6141990b4856Slling cb.cb_version = strtoll(optarg, &end, 10); 6142ad135b5dSChristopher Siden if (*end != '\0' || 6143ad135b5dSChristopher Siden !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) { 6144990b4856Slling (void) fprintf(stderr, 6145990b4856Slling gettext("invalid version '%s'\n"), optarg); 6146990b4856Slling usage(B_FALSE); 6147990b4856Slling } 6148990b4856Slling break; 6149478ed9adSEric Taylor case ':': 6150478ed9adSEric Taylor (void) fprintf(stderr, gettext("missing argument for " 6151478ed9adSEric Taylor "'%c' option\n"), optopt); 6152478ed9adSEric Taylor usage(B_FALSE); 6153478ed9adSEric Taylor break; 6154eaca9bbdSeschrock case '?': 6155eaca9bbdSeschrock (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6156eaca9bbdSeschrock optopt); 615799653d4eSeschrock usage(B_FALSE); 6158eaca9bbdSeschrock } 6159eaca9bbdSeschrock } 6160eaca9bbdSeschrock 616106eeb2adSek cb.cb_argc = argc; 616206eeb2adSek cb.cb_argv = argv; 6163eaca9bbdSeschrock argc -= optind; 6164eaca9bbdSeschrock argv += optind; 6165eaca9bbdSeschrock 6166351420b3Slling if (cb.cb_version == 0) { 6167351420b3Slling cb.cb_version = SPA_VERSION; 616857221772SChristopher Siden } else if (!upgradeall && argc == 0) { 6169351420b3Slling (void) fprintf(stderr, gettext("-V option is " 6170351420b3Slling "incompatible with other arguments\n")); 6171351420b3Slling usage(B_FALSE); 6172351420b3Slling } 6173351420b3Slling 6174eaca9bbdSeschrock if (showversions) { 617557221772SChristopher Siden if (upgradeall || argc != 0) { 6176eaca9bbdSeschrock (void) fprintf(stderr, gettext("-v option is " 6177eaca9bbdSeschrock "incompatible with other arguments\n")); 617899653d4eSeschrock usage(B_FALSE); 6179eaca9bbdSeschrock } 618057221772SChristopher Siden } else if (upgradeall) { 6181eaca9bbdSeschrock if (argc != 0) { 6182351420b3Slling (void) fprintf(stderr, gettext("-a option should not " 6183351420b3Slling "be used along with a pool name\n")); 618499653d4eSeschrock usage(B_FALSE); 6185eaca9bbdSeschrock } 6186eaca9bbdSeschrock } 6187eaca9bbdSeschrock 6188ad135b5dSChristopher Siden (void) printf(gettext("This system supports ZFS pool feature " 6189ad135b5dSChristopher Siden "flags.\n\n")); 6190eaca9bbdSeschrock if (showversions) { 619157221772SChristopher Siden int i; 619257221772SChristopher Siden 619357221772SChristopher Siden (void) printf(gettext("The following features are " 619457221772SChristopher Siden "supported:\n\n")); 619557221772SChristopher Siden (void) printf(gettext("FEAT DESCRIPTION\n")); 619657221772SChristopher Siden (void) printf("----------------------------------------------" 619757221772SChristopher Siden "---------------\n"); 619857221772SChristopher Siden for (i = 0; i < SPA_FEATURES; i++) { 619957221772SChristopher Siden zfeature_info_t *fi = &spa_feature_table[i]; 6200ca0cc391SMatthew Ahrens const char *ro = 6201ca0cc391SMatthew Ahrens (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ? 620257221772SChristopher Siden " (read-only compatible)" : ""; 620357221772SChristopher Siden 620457221772SChristopher Siden (void) printf("%-37s%s\n", fi->fi_uname, ro); 620557221772SChristopher Siden (void) printf(" %s\n", fi->fi_desc); 620657221772SChristopher Siden } 620757221772SChristopher Siden (void) printf("\n"); 620857221772SChristopher Siden 620957221772SChristopher Siden (void) printf(gettext("The following legacy versions are also " 6210d7d4af51Smmusante "supported:\n\n")); 6211eaca9bbdSeschrock (void) printf(gettext("VER DESCRIPTION\n")); 6212eaca9bbdSeschrock (void) printf("--- -----------------------------------------" 6213eaca9bbdSeschrock "---------------\n"); 621499653d4eSeschrock (void) printf(gettext(" 1 Initial ZFS version\n")); 621544cd46caSbillm (void) printf(gettext(" 2 Ditto blocks " 621644cd46caSbillm "(replicated metadata)\n")); 621799653d4eSeschrock (void) printf(gettext(" 3 Hot spares and double parity " 621899653d4eSeschrock "RAID-Z\n")); 6219d7306b64Sek (void) printf(gettext(" 4 zpool history\n")); 6220c9431fa1Sahl (void) printf(gettext(" 5 Compression using the gzip " 6221c9431fa1Sahl "algorithm\n")); 6222990b4856Slling (void) printf(gettext(" 6 bootfs pool property\n")); 62238654d025Sperrin (void) printf(gettext(" 7 Separate intent log devices\n")); 6224ecd6cf80Smarks (void) printf(gettext(" 8 Delegated administration\n")); 62258eed72d4Sck (void) printf(gettext(" 9 refquota and refreservation " 6226a9799022Sck "properties\n")); 6227fa94a07fSbrendan (void) printf(gettext(" 10 Cache devices\n")); 6228088f3894Sahrens (void) printf(gettext(" 11 Improved scrub performance\n")); 6229bb0ade09Sahrens (void) printf(gettext(" 12 Snapshot properties\n")); 623074e7dc98SMatthew Ahrens (void) printf(gettext(" 13 snapused property\n")); 623114843421SMatthew Ahrens (void) printf(gettext(" 14 passthrough-x aclinherit\n")); 623214843421SMatthew Ahrens (void) printf(gettext(" 15 user/group space accounting\n")); 6233478ed9adSEric Taylor (void) printf(gettext(" 16 stmf property support\n")); 62347aeab329SAdam Leventhal (void) printf(gettext(" 17 Triple-parity RAID-Z\n")); 6235b24ab676SJeff Bonwick (void) printf(gettext(" 18 Snapshot user holds\n")); 623688ecc943SGeorge Wilson (void) printf(gettext(" 19 Log device removal\n")); 6237b24ab676SJeff Bonwick (void) printf(gettext(" 20 Compression using zle " 6238b24ab676SJeff Bonwick "(zero-length encoding)\n")); 6239b24ab676SJeff Bonwick (void) printf(gettext(" 21 Deduplication\n")); 624092241e0bSTom Erickson (void) printf(gettext(" 22 Received properties\n")); 62416e1f5caaSNeil Perrin (void) printf(gettext(" 23 Slim ZIL\n")); 62420a586ceaSMark Shellenbaum (void) printf(gettext(" 24 System attributes\n")); 62433f9d6ad7SLin Ling (void) printf(gettext(" 25 Improved scrub stats\n")); 6244cde58dbcSMatthew Ahrens (void) printf(gettext(" 26 Improved snapshot deletion " 6245cde58dbcSMatthew Ahrens "performance\n")); 62466e0cbcaaSMatthew Ahrens (void) printf(gettext(" 27 Improved snapshot creation " 62476e0cbcaaSMatthew Ahrens "performance\n")); 6248cb04b873SMark J Musante (void) printf(gettext(" 28 Multiple vdev replacements\n")); 6249b24ab676SJeff Bonwick (void) printf(gettext("\nFor more information on a particular " 62509a8685acSstephanie scheffler "version, including supported releases,\n")); 62519a8685acSstephanie scheffler (void) printf(gettext("see the ZFS Administration Guide.\n\n")); 625257221772SChristopher Siden } else if (argc == 0 && upgradeall) { 625357221772SChristopher Siden cb.cb_first = B_TRUE; 625499653d4eSeschrock ret = zpool_iter(g_zfs, upgrade_cb, &cb); 625557221772SChristopher Siden if (ret == 0 && cb.cb_first) { 625657221772SChristopher Siden if (cb.cb_version == SPA_VERSION) { 625757221772SChristopher Siden (void) printf(gettext("All pools are already " 625857221772SChristopher Siden "formatted using feature flags.\n\n")); 625957221772SChristopher Siden (void) printf(gettext("Every feature flags " 626057221772SChristopher Siden "pool already has all supported features " 626157221772SChristopher Siden "enabled.\n")); 626257221772SChristopher Siden } else { 626357221772SChristopher Siden (void) printf(gettext("All pools are already " 626457221772SChristopher Siden "formatted with version %llu or higher.\n"), 626557221772SChristopher Siden cb.cb_version); 6266eaca9bbdSeschrock } 6267eaca9bbdSeschrock } 626857221772SChristopher Siden } else if (argc == 0) { 626957221772SChristopher Siden cb.cb_first = B_TRUE; 627057221772SChristopher Siden ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb); 627157221772SChristopher Siden assert(ret == 0); 6272eaca9bbdSeschrock 627357221772SChristopher Siden if (cb.cb_first) { 627457221772SChristopher Siden (void) printf(gettext("All pools are formatted " 627557221772SChristopher Siden "using feature flags.\n\n")); 627657221772SChristopher Siden } else { 627757221772SChristopher Siden (void) printf(gettext("\nUse 'zpool upgrade -v' " 627857221772SChristopher Siden "for a list of available legacy versions.\n")); 627957221772SChristopher Siden } 628057221772SChristopher Siden 628157221772SChristopher Siden cb.cb_first = B_TRUE; 628257221772SChristopher Siden ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb); 628357221772SChristopher Siden assert(ret == 0); 628457221772SChristopher Siden 628557221772SChristopher Siden if (cb.cb_first) { 628657221772SChristopher Siden (void) printf(gettext("Every feature flags pool has " 628757221772SChristopher Siden "all supported features enabled.\n")); 628857221772SChristopher Siden } else { 628957221772SChristopher Siden (void) printf(gettext("\n")); 6290eaca9bbdSeschrock } 6291eaca9bbdSeschrock } else { 6292b1b8ab34Slling ret = for_each_pool(argc, argv, B_FALSE, NULL, 6293b1b8ab34Slling upgrade_one, &cb); 629406eeb2adSek } 629506eeb2adSek 629606eeb2adSek return (ret); 629706eeb2adSek } 629806eeb2adSek 6299ecd6cf80Smarks typedef struct hist_cbdata { 6300ecd6cf80Smarks boolean_t first; 63014445fffbSMatthew Ahrens boolean_t longfmt; 63024445fffbSMatthew Ahrens boolean_t internal; 6303ecd6cf80Smarks } hist_cbdata_t; 6304ecd6cf80Smarks 630506eeb2adSek /* 630606eeb2adSek * Print out the command history for a specific pool. 630706eeb2adSek */ 630806eeb2adSek static int 630906eeb2adSek get_history_one(zpool_handle_t *zhp, void *data) 631006eeb2adSek { 631106eeb2adSek nvlist_t *nvhis; 631206eeb2adSek nvlist_t **records; 631306eeb2adSek uint_t numrecords; 631406eeb2adSek int ret, i; 6315ecd6cf80Smarks hist_cbdata_t *cb = (hist_cbdata_t *)data; 631606eeb2adSek 6317ecd6cf80Smarks cb->first = B_FALSE; 631806eeb2adSek 631906eeb2adSek (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); 632006eeb2adSek 632106eeb2adSek if ((ret = zpool_get_history(zhp, &nvhis)) != 0) 632206eeb2adSek return (ret); 632306eeb2adSek 632406eeb2adSek verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, 632506eeb2adSek &records, &numrecords) == 0); 632606eeb2adSek for (i = 0; i < numrecords; i++) { 63274445fffbSMatthew Ahrens nvlist_t *rec = records[i]; 63284445fffbSMatthew Ahrens char tbuf[30] = ""; 6329ecd6cf80Smarks 63304445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_TIME)) { 63314445fffbSMatthew Ahrens time_t tsec; 63324445fffbSMatthew Ahrens struct tm t; 63334445fffbSMatthew Ahrens 63344445fffbSMatthew Ahrens tsec = fnvlist_lookup_uint64(records[i], 63354445fffbSMatthew Ahrens ZPOOL_HIST_TIME); 63364445fffbSMatthew Ahrens (void) localtime_r(&tsec, &t); 63374445fffbSMatthew Ahrens (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 63384445fffbSMatthew Ahrens } 6339ecd6cf80Smarks 63404445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_CMD)) { 63414445fffbSMatthew Ahrens (void) printf("%s %s", tbuf, 63424445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_CMD)); 63434445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) { 63444445fffbSMatthew Ahrens int ievent = 63454445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT); 63464445fffbSMatthew Ahrens if (!cb->internal) 63474445fffbSMatthew Ahrens continue; 63484445fffbSMatthew Ahrens if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) { 63494445fffbSMatthew Ahrens (void) printf("%s unrecognized record:\n", 63504445fffbSMatthew Ahrens tbuf); 63514445fffbSMatthew Ahrens dump_nvlist(rec, 4); 63524445fffbSMatthew Ahrens continue; 63534445fffbSMatthew Ahrens } 63544445fffbSMatthew Ahrens (void) printf("%s [internal %s txg:%lld] %s", tbuf, 63554445fffbSMatthew Ahrens zfs_history_event_names[ievent], 63564445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 63574445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR)); 63584445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) { 63594445fffbSMatthew Ahrens if (!cb->internal) 6360ecd6cf80Smarks continue; 63614445fffbSMatthew Ahrens (void) printf("%s [txg:%lld] %s", tbuf, 63624445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 63634445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME)); 63644445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) { 63654445fffbSMatthew Ahrens (void) printf(" %s (%llu)", 63664445fffbSMatthew Ahrens fnvlist_lookup_string(rec, 63674445fffbSMatthew Ahrens ZPOOL_HIST_DSNAME), 63684445fffbSMatthew Ahrens fnvlist_lookup_uint64(rec, 63694445fffbSMatthew Ahrens ZPOOL_HIST_DSID)); 63704445fffbSMatthew Ahrens } 63714445fffbSMatthew Ahrens (void) printf(" %s", fnvlist_lookup_string(rec, 63724445fffbSMatthew Ahrens ZPOOL_HIST_INT_STR)); 63734445fffbSMatthew Ahrens } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) { 63744445fffbSMatthew Ahrens if (!cb->internal) 63754445fffbSMatthew Ahrens continue; 63764445fffbSMatthew Ahrens (void) printf("%s ioctl %s\n", tbuf, 63774445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL)); 63784445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) { 63794445fffbSMatthew Ahrens (void) printf(" input:\n"); 63804445fffbSMatthew Ahrens dump_nvlist(fnvlist_lookup_nvlist(rec, 63814445fffbSMatthew Ahrens ZPOOL_HIST_INPUT_NVL), 8); 63824445fffbSMatthew Ahrens } 63834445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) { 63844445fffbSMatthew Ahrens (void) printf(" output:\n"); 63854445fffbSMatthew Ahrens dump_nvlist(fnvlist_lookup_nvlist(rec, 63864445fffbSMatthew Ahrens ZPOOL_HIST_OUTPUT_NVL), 8); 63874445fffbSMatthew Ahrens } 6388dfc11533SChris Williamson if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) { 6389dfc11533SChris Williamson (void) printf(" errno: %lld\n", 6390dfc11533SChris Williamson fnvlist_lookup_int64(rec, 6391dfc11533SChris Williamson ZPOOL_HIST_ERRNO)); 6392dfc11533SChris Williamson } 63934445fffbSMatthew Ahrens } else { 63944445fffbSMatthew Ahrens if (!cb->internal) 6395ecd6cf80Smarks continue; 63964445fffbSMatthew Ahrens (void) printf("%s unrecognized record:\n", tbuf); 63974445fffbSMatthew Ahrens dump_nvlist(rec, 4); 639806eeb2adSek } 6399ecd6cf80Smarks 6400ecd6cf80Smarks if (!cb->longfmt) { 6401ecd6cf80Smarks (void) printf("\n"); 6402ecd6cf80Smarks continue; 6403ecd6cf80Smarks } 6404ecd6cf80Smarks (void) printf(" ["); 64054445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_WHO)) { 64064445fffbSMatthew Ahrens uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO); 64074445fffbSMatthew Ahrens struct passwd *pwd = getpwuid(who); 64084445fffbSMatthew Ahrens (void) printf("user %d ", (int)who); 64094445fffbSMatthew Ahrens if (pwd != NULL) 64104445fffbSMatthew Ahrens (void) printf("(%s) ", pwd->pw_name); 6411ecd6cf80Smarks } 64124445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_HOST)) { 64134445fffbSMatthew Ahrens (void) printf("on %s", 64144445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_HOST)); 6415ecd6cf80Smarks } 64164445fffbSMatthew Ahrens if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) { 64174445fffbSMatthew Ahrens (void) printf(":%s", 64184445fffbSMatthew Ahrens fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE)); 6419ecd6cf80Smarks } 6420ecd6cf80Smarks (void) printf("]"); 6421ecd6cf80Smarks (void) printf("\n"); 642206eeb2adSek } 642306eeb2adSek (void) printf("\n"); 642406eeb2adSek nvlist_free(nvhis); 642506eeb2adSek 642606eeb2adSek return (ret); 642706eeb2adSek } 642806eeb2adSek 642906eeb2adSek /* 643006eeb2adSek * zpool history <pool> 643106eeb2adSek * 643206eeb2adSek * Displays the history of commands that modified pools. 643306eeb2adSek */ 643406eeb2adSek int 643506eeb2adSek zpool_do_history(int argc, char **argv) 643606eeb2adSek { 6437ecd6cf80Smarks hist_cbdata_t cbdata = { 0 }; 643806eeb2adSek int ret; 6439ecd6cf80Smarks int c; 644006eeb2adSek 6441ecd6cf80Smarks cbdata.first = B_TRUE; 6442ecd6cf80Smarks /* check options */ 6443ecd6cf80Smarks while ((c = getopt(argc, argv, "li")) != -1) { 6444ecd6cf80Smarks switch (c) { 6445ecd6cf80Smarks case 'l': 64464445fffbSMatthew Ahrens cbdata.longfmt = B_TRUE; 6447ecd6cf80Smarks break; 6448ecd6cf80Smarks case 'i': 64494445fffbSMatthew Ahrens cbdata.internal = B_TRUE; 6450ecd6cf80Smarks break; 6451ecd6cf80Smarks case '?': 6452ecd6cf80Smarks (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6453ecd6cf80Smarks optopt); 6454ecd6cf80Smarks usage(B_FALSE); 6455ecd6cf80Smarks } 6456ecd6cf80Smarks } 645706eeb2adSek argc -= optind; 645806eeb2adSek argv += optind; 645906eeb2adSek 6460b1b8ab34Slling ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one, 6461ecd6cf80Smarks &cbdata); 646206eeb2adSek 6463ecd6cf80Smarks if (argc == 0 && cbdata.first == B_TRUE) { 646406eeb2adSek (void) printf(gettext("no pools available\n")); 646506eeb2adSek return (0); 6466eaca9bbdSeschrock } 6467eaca9bbdSeschrock 6468eaca9bbdSeschrock return (ret); 6469eaca9bbdSeschrock } 6470eaca9bbdSeschrock 6471b1b8ab34Slling static int 6472b1b8ab34Slling get_callback(zpool_handle_t *zhp, void *data) 6473b1b8ab34Slling { 6474990b4856Slling zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; 6475b1b8ab34Slling char value[MAXNAMELEN]; 6476990b4856Slling zprop_source_t srctype; 6477990b4856Slling zprop_list_t *pl; 6478b1b8ab34Slling 6479b1b8ab34Slling for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 6480b1b8ab34Slling 6481b1b8ab34Slling /* 6482990b4856Slling * Skip the special fake placeholder. This will also skip 6483990b4856Slling * over the name property when 'all' is specified. 6484b1b8ab34Slling */ 6485990b4856Slling if (pl->pl_prop == ZPOOL_PROP_NAME && 6486b1b8ab34Slling pl == cbp->cb_proplist) 6487b1b8ab34Slling continue; 6488b1b8ab34Slling 6489ad135b5dSChristopher Siden if (pl->pl_prop == ZPROP_INVAL && 6490ad135b5dSChristopher Siden (zpool_prop_feature(pl->pl_user_prop) || 6491ad135b5dSChristopher Siden zpool_prop_unsupported(pl->pl_user_prop))) { 6492ad135b5dSChristopher Siden srctype = ZPROP_SRC_LOCAL; 6493b1b8ab34Slling 6494ad135b5dSChristopher Siden if (zpool_prop_get_feature(zhp, pl->pl_user_prop, 6495ad135b5dSChristopher Siden value, sizeof (value)) == 0) { 6496ad135b5dSChristopher Siden zprop_print_one_property(zpool_get_name(zhp), 6497ad135b5dSChristopher Siden cbp, pl->pl_user_prop, value, srctype, 6498ad135b5dSChristopher Siden NULL, NULL); 6499ad135b5dSChristopher Siden } 6500ad135b5dSChristopher Siden } else { 6501ad135b5dSChristopher Siden if (zpool_get_prop(zhp, pl->pl_prop, value, 6502c58b3526SAdam Stevko sizeof (value), &srctype, cbp->cb_literal) != 0) 6503ad135b5dSChristopher Siden continue; 6504ad135b5dSChristopher Siden 6505ad135b5dSChristopher Siden zprop_print_one_property(zpool_get_name(zhp), cbp, 6506ad135b5dSChristopher Siden zpool_prop_to_name(pl->pl_prop), value, srctype, 6507ad135b5dSChristopher Siden NULL, NULL); 6508ad135b5dSChristopher Siden } 6509b1b8ab34Slling } 6510b1b8ab34Slling return (0); 6511b1b8ab34Slling } 6512b1b8ab34Slling 6513c58b3526SAdam Stevko /* 6514c58b3526SAdam Stevko * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ... 6515c58b3526SAdam Stevko * 6516c58b3526SAdam Stevko * -H Scripted mode. Don't display headers, and separate properties 6517c58b3526SAdam Stevko * by a single tab. 6518c58b3526SAdam Stevko * -o List of columns to display. Defaults to 6519c58b3526SAdam Stevko * "name,property,value,source". 652004e56356SAndriy Gapon * -p Diplay values in parsable (exact) format. 6521c58b3526SAdam Stevko * 6522c58b3526SAdam Stevko * Get properties of pools in the system. Output space statistics 6523c58b3526SAdam Stevko * for each one as well as other attributes. 6524c58b3526SAdam Stevko */ 6525b1b8ab34Slling int 6526b1b8ab34Slling zpool_do_get(int argc, char **argv) 6527b1b8ab34Slling { 6528990b4856Slling zprop_get_cbdata_t cb = { 0 }; 6529990b4856Slling zprop_list_t fake_name = { 0 }; 6530b1b8ab34Slling int ret; 6531c58b3526SAdam Stevko int c, i; 6532c58b3526SAdam Stevko char *value; 6533b1b8ab34Slling 6534b1b8ab34Slling cb.cb_first = B_TRUE; 6535c58b3526SAdam Stevko 6536c58b3526SAdam Stevko /* 6537c58b3526SAdam Stevko * Set up default columns and sources. 6538c58b3526SAdam Stevko */ 6539990b4856Slling cb.cb_sources = ZPROP_SRC_ALL; 6540b1b8ab34Slling cb.cb_columns[0] = GET_COL_NAME; 6541b1b8ab34Slling cb.cb_columns[1] = GET_COL_PROPERTY; 6542b1b8ab34Slling cb.cb_columns[2] = GET_COL_VALUE; 6543b1b8ab34Slling cb.cb_columns[3] = GET_COL_SOURCE; 6544990b4856Slling cb.cb_type = ZFS_TYPE_POOL; 6545b1b8ab34Slling 6546c58b3526SAdam Stevko /* check options */ 6547c58b3526SAdam Stevko while ((c = getopt(argc, argv, ":Hpo:")) != -1) { 6548c58b3526SAdam Stevko switch (c) { 6549c58b3526SAdam Stevko case 'p': 6550c58b3526SAdam Stevko cb.cb_literal = B_TRUE; 6551c58b3526SAdam Stevko break; 6552c58b3526SAdam Stevko case 'H': 6553c58b3526SAdam Stevko cb.cb_scripted = B_TRUE; 6554c58b3526SAdam Stevko break; 6555c58b3526SAdam Stevko case 'o': 6556c58b3526SAdam Stevko bzero(&cb.cb_columns, sizeof (cb.cb_columns)); 6557c58b3526SAdam Stevko i = 0; 6558c58b3526SAdam Stevko while (*optarg != '\0') { 6559c58b3526SAdam Stevko static char *col_subopts[] = 6560c58b3526SAdam Stevko { "name", "property", "value", "source", 6561c58b3526SAdam Stevko "all", NULL }; 6562c58b3526SAdam Stevko 6563c58b3526SAdam Stevko if (i == ZFS_GET_NCOLS) { 6564c58b3526SAdam Stevko (void) fprintf(stderr, gettext("too " 6565c58b3526SAdam Stevko "many fields given to -o " 6566c58b3526SAdam Stevko "option\n")); 6567c58b3526SAdam Stevko usage(B_FALSE); 6568c58b3526SAdam Stevko } 6569c58b3526SAdam Stevko 6570c58b3526SAdam Stevko switch (getsubopt(&optarg, col_subopts, 6571c58b3526SAdam Stevko &value)) { 6572c58b3526SAdam Stevko case 0: 6573c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_NAME; 6574c58b3526SAdam Stevko break; 6575c58b3526SAdam Stevko case 1: 6576c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_PROPERTY; 6577c58b3526SAdam Stevko break; 6578c58b3526SAdam Stevko case 2: 6579c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_VALUE; 6580c58b3526SAdam Stevko break; 6581c58b3526SAdam Stevko case 3: 6582c58b3526SAdam Stevko cb.cb_columns[i++] = GET_COL_SOURCE; 6583c58b3526SAdam Stevko break; 6584c58b3526SAdam Stevko case 4: 6585c58b3526SAdam Stevko if (i > 0) { 6586c58b3526SAdam Stevko (void) fprintf(stderr, 6587c58b3526SAdam Stevko gettext("\"all\" conflicts " 6588c58b3526SAdam Stevko "with specific fields " 6589c58b3526SAdam Stevko "given to -o option\n")); 6590c58b3526SAdam Stevko usage(B_FALSE); 6591c58b3526SAdam Stevko } 6592c58b3526SAdam Stevko cb.cb_columns[0] = GET_COL_NAME; 6593c58b3526SAdam Stevko cb.cb_columns[1] = GET_COL_PROPERTY; 6594c58b3526SAdam Stevko cb.cb_columns[2] = GET_COL_VALUE; 6595c58b3526SAdam Stevko cb.cb_columns[3] = GET_COL_SOURCE; 6596c58b3526SAdam Stevko i = ZFS_GET_NCOLS; 6597c58b3526SAdam Stevko break; 6598c58b3526SAdam Stevko default: 6599c58b3526SAdam Stevko (void) fprintf(stderr, 6600c58b3526SAdam Stevko gettext("invalid column name " 6601c58b3526SAdam Stevko "'%s'\n"), value); 6602c58b3526SAdam Stevko usage(B_FALSE); 6603c58b3526SAdam Stevko } 6604c58b3526SAdam Stevko } 6605c58b3526SAdam Stevko break; 6606c58b3526SAdam Stevko case '?': 6607c58b3526SAdam Stevko (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6608c58b3526SAdam Stevko optopt); 6609c58b3526SAdam Stevko usage(B_FALSE); 6610c58b3526SAdam Stevko } 6611c58b3526SAdam Stevko } 6612c58b3526SAdam Stevko 6613c58b3526SAdam Stevko argc -= optind; 6614c58b3526SAdam Stevko argv += optind; 6615c58b3526SAdam Stevko 6616c58b3526SAdam Stevko if (argc < 1) { 6617c58b3526SAdam Stevko (void) fprintf(stderr, gettext("missing property " 6618c58b3526SAdam Stevko "argument\n")); 6619c58b3526SAdam Stevko usage(B_FALSE); 6620c58b3526SAdam Stevko } 6621c58b3526SAdam Stevko 6622c58b3526SAdam Stevko if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist, 6623990b4856Slling ZFS_TYPE_POOL) != 0) 6624b1b8ab34Slling usage(B_FALSE); 6625b1b8ab34Slling 6626c58b3526SAdam Stevko argc--; 6627c58b3526SAdam Stevko argv++; 6628c58b3526SAdam Stevko 6629b1b8ab34Slling if (cb.cb_proplist != NULL) { 6630990b4856Slling fake_name.pl_prop = ZPOOL_PROP_NAME; 6631b1b8ab34Slling fake_name.pl_width = strlen(gettext("NAME")); 6632b1b8ab34Slling fake_name.pl_next = cb.cb_proplist; 6633b1b8ab34Slling cb.cb_proplist = &fake_name; 6634b1b8ab34Slling } 6635b1b8ab34Slling 6636c58b3526SAdam Stevko ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, 6637b1b8ab34Slling get_callback, &cb); 6638b1b8ab34Slling 6639b1b8ab34Slling if (cb.cb_proplist == &fake_name) 6640990b4856Slling zprop_free_list(fake_name.pl_next); 6641b1b8ab34Slling else 6642990b4856Slling zprop_free_list(cb.cb_proplist); 6643b1b8ab34Slling 6644b1b8ab34Slling return (ret); 6645b1b8ab34Slling } 6646b1b8ab34Slling 6647b1b8ab34Slling typedef struct set_cbdata { 6648b1b8ab34Slling char *cb_propname; 6649b1b8ab34Slling char *cb_value; 6650b1b8ab34Slling boolean_t cb_any_successful; 6651b1b8ab34Slling } set_cbdata_t; 6652b1b8ab34Slling 6653b1b8ab34Slling int 6654b1b8ab34Slling set_callback(zpool_handle_t *zhp, void *data) 6655b1b8ab34Slling { 6656b1b8ab34Slling int error; 6657b1b8ab34Slling set_cbdata_t *cb = (set_cbdata_t *)data; 6658b1b8ab34Slling 6659b1b8ab34Slling error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value); 6660b1b8ab34Slling 6661b1b8ab34Slling if (!error) 6662b1b8ab34Slling cb->cb_any_successful = B_TRUE; 6663b1b8ab34Slling 6664b1b8ab34Slling return (error); 6665b1b8ab34Slling } 6666b1b8ab34Slling 6667b1b8ab34Slling int 6668b1b8ab34Slling zpool_do_set(int argc, char **argv) 6669b1b8ab34Slling { 6670b1b8ab34Slling set_cbdata_t cb = { 0 }; 6671b1b8ab34Slling int error; 6672b1b8ab34Slling 6673b1b8ab34Slling if (argc > 1 && argv[1][0] == '-') { 6674b1b8ab34Slling (void) fprintf(stderr, gettext("invalid option '%c'\n"), 6675b1b8ab34Slling argv[1][1]); 6676b1b8ab34Slling usage(B_FALSE); 6677b1b8ab34Slling } 6678b1b8ab34Slling 6679b1b8ab34Slling if (argc < 2) { 6680b1b8ab34Slling (void) fprintf(stderr, gettext("missing property=value " 6681b1b8ab34Slling "argument\n")); 6682b1b8ab34Slling usage(B_FALSE); 6683b1b8ab34Slling } 6684b1b8ab34Slling 6685b1b8ab34Slling if (argc < 3) { 6686b1b8ab34Slling (void) fprintf(stderr, gettext("missing pool name\n")); 6687b1b8ab34Slling usage(B_FALSE); 6688b1b8ab34Slling } 6689b1b8ab34Slling 6690b1b8ab34Slling if (argc > 3) { 6691b1b8ab34Slling (void) fprintf(stderr, gettext("too many pool names\n")); 6692b1b8ab34Slling usage(B_FALSE); 6693b1b8ab34Slling } 6694b1b8ab34Slling 6695b1b8ab34Slling cb.cb_propname = argv[1]; 6696b1b8ab34Slling cb.cb_value = strchr(cb.cb_propname, '='); 6697b1b8ab34Slling if (cb.cb_value == NULL) { 6698b1b8ab34Slling (void) fprintf(stderr, gettext("missing value in " 6699b1b8ab34Slling "property=value argument\n")); 6700b1b8ab34Slling usage(B_FALSE); 6701b1b8ab34Slling } 6702b1b8ab34Slling 6703b1b8ab34Slling *(cb.cb_value) = '\0'; 6704b1b8ab34Slling cb.cb_value++; 6705b1b8ab34Slling 6706b1b8ab34Slling error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, 6707b1b8ab34Slling set_callback, &cb); 6708b1b8ab34Slling 6709b1b8ab34Slling return (error); 6710b1b8ab34Slling } 6711b1b8ab34Slling 6712b1b8ab34Slling static int 6713b1b8ab34Slling find_command_idx(char *command, int *idx) 6714b1b8ab34Slling { 6715b1b8ab34Slling int i; 6716b1b8ab34Slling 6717b1b8ab34Slling for (i = 0; i < NCOMMAND; i++) { 6718b1b8ab34Slling if (command_table[i].name == NULL) 6719b1b8ab34Slling continue; 6720b1b8ab34Slling 6721b1b8ab34Slling if (strcmp(command, command_table[i].name) == 0) { 6722b1b8ab34Slling *idx = i; 6723b1b8ab34Slling return (0); 6724b1b8ab34Slling } 6725b1b8ab34Slling } 6726b1b8ab34Slling return (1); 6727b1b8ab34Slling } 6728b1b8ab34Slling 6729fa9e4066Sahrens int 6730fa9e4066Sahrens main(int argc, char **argv) 6731fa9e4066Sahrens { 6732b327cd3fSIgor Kozhukhov int ret = 0; 6733fa9e4066Sahrens int i; 6734fa9e4066Sahrens char *cmdname; 6735fa9e4066Sahrens 6736fa9e4066Sahrens (void) setlocale(LC_ALL, ""); 6737fa9e4066Sahrens (void) textdomain(TEXT_DOMAIN); 6738fa9e4066Sahrens 673999653d4eSeschrock if ((g_zfs = libzfs_init()) == NULL) { 674099653d4eSeschrock (void) fprintf(stderr, gettext("internal error: failed to " 6741203a47d8Snd "initialize ZFS library\n")); 674299653d4eSeschrock return (1); 674399653d4eSeschrock } 674499653d4eSeschrock 674599653d4eSeschrock libzfs_print_on_error(g_zfs, B_TRUE); 674699653d4eSeschrock 6747fa9e4066Sahrens opterr = 0; 6748fa9e4066Sahrens 6749fa9e4066Sahrens /* 6750fa9e4066Sahrens * Make sure the user has specified some command. 6751fa9e4066Sahrens */ 6752fa9e4066Sahrens if (argc < 2) { 6753fa9e4066Sahrens (void) fprintf(stderr, gettext("missing command\n")); 675499653d4eSeschrock usage(B_FALSE); 6755fa9e4066Sahrens } 6756fa9e4066Sahrens 6757fa9e4066Sahrens cmdname = argv[1]; 6758fa9e4066Sahrens 6759fa9e4066Sahrens /* 6760fa9e4066Sahrens * Special case '-?' 6761fa9e4066Sahrens */ 6762fa9e4066Sahrens if (strcmp(cmdname, "-?") == 0) 676399653d4eSeschrock usage(B_TRUE); 6764fa9e4066Sahrens 67654445fffbSMatthew Ahrens zfs_save_arguments(argc, argv, history_str, sizeof (history_str)); 67662a6b87f0Sek 6767fa9e4066Sahrens /* 6768fa9e4066Sahrens * Run the appropriate command. 6769fa9e4066Sahrens */ 6770b1b8ab34Slling if (find_command_idx(cmdname, &i) == 0) { 6771b1b8ab34Slling current_command = &command_table[i]; 6772b1b8ab34Slling ret = command_table[i].func(argc - 1, argv + 1); 677391ebeef5Sahrens } else if (strchr(cmdname, '=')) { 677491ebeef5Sahrens verify(find_command_idx("set", &i) == 0); 677591ebeef5Sahrens current_command = &command_table[i]; 677691ebeef5Sahrens ret = command_table[i].func(argc, argv); 677791ebeef5Sahrens } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 677891ebeef5Sahrens /* 677991ebeef5Sahrens * 'freeze' is a vile debugging abomination, so we treat 678091ebeef5Sahrens * it as such. 678191ebeef5Sahrens */ 6782ea8dc4b6Seschrock char buf[16384]; 6783ea8dc4b6Seschrock int fd = open(ZFS_DEV, O_RDWR); 6784fa9e4066Sahrens (void) strcpy((void *)buf, argv[2]); 6785fa9e4066Sahrens return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf)); 678691ebeef5Sahrens } else { 6787fa9e4066Sahrens (void) fprintf(stderr, gettext("unrecognized " 6788fa9e4066Sahrens "command '%s'\n"), cmdname); 678999653d4eSeschrock usage(B_FALSE); 6790fa9e4066Sahrens } 6791fa9e4066Sahrens 67924445fffbSMatthew Ahrens if (ret == 0 && log_history) 67934445fffbSMatthew Ahrens (void) zpool_log_history(g_zfs, history_str); 67944445fffbSMatthew Ahrens 679599653d4eSeschrock libzfs_fini(g_zfs); 679699653d4eSeschrock 6797fa9e4066Sahrens /* 6798fa9e4066Sahrens * The 'ZFS_ABORT' environment variable causes us to dump core on exit 6799fa9e4066Sahrens * for the purposes of running ::findleaks. 6800fa9e4066Sahrens */ 6801fa9e4066Sahrens if (getenv("ZFS_ABORT") != NULL) { 6802fa9e4066Sahrens (void) printf("dumping core by request\n"); 6803fa9e4066Sahrens abort(); 6804fa9e4066Sahrens } 6805fa9e4066Sahrens 6806fa9e4066Sahrens return (ret); 6807fa9e4066Sahrens } 6808