zpool_main.c revision 254591
1198157Srrs/* 2198157Srrs * CDDL HEADER START 3198157Srrs * 4198157Srrs * The contents of this file are subject to the terms of the 5198157Srrs * Common Development and Distribution License (the "License"). 6198157Srrs * You may not use this file except in compliance with the License. 7198157Srrs * 8198157Srrs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9198157Srrs * or http://www.opensolaris.org/os/licensing. 10198157Srrs * See the License for the specific language governing permissions 11198157Srrs * and limitations under the License. 12198157Srrs * 13198157Srrs * When distributing Covered Code, include this CDDL HEADER in each 14198157Srrs * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15198157Srrs * If applicable, add the following below this CDDL HEADER, with the 16198157Srrs * fields enclosed by brackets "[]" replaced with your own identifying 17198157Srrs * information: Portions Copyright [yyyy] [name of copyright owner] 18198157Srrs * 19198157Srrs * CDDL HEADER END 20198157Srrs */ 21198157Srrs 22198157Srrs/* 23198157Srrs * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24198157Srrs * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 25198157Srrs * Copyright (c) 2012 by Delphix. All rights reserved. 26198157Srrs * Copyright (c) 2012 by Frederik Wessels. All rights reserved. 27198157Srrs * Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved. 28198157Srrs */ 29212759Sjchandra 30198157Srrs#include <solaris.h> 31198157Srrs#include <assert.h> 32198157Srrs#include <ctype.h> 33198157Srrs#include <dirent.h> 34198157Srrs#include <errno.h> 35198157Srrs#include <fcntl.h> 36198157Srrs#include <libgen.h> 37198157Srrs#include <libintl.h> 38198157Srrs#include <libuutil.h> 39198157Srrs#include <locale.h> 40198157Srrs#include <stdio.h> 41198157Srrs#include <stdlib.h> 42198157Srrs#include <string.h> 43198157Srrs#include <strings.h> 44198157Srrs#include <unistd.h> 45198157Srrs#include <priv.h> 46198157Srrs#include <pwd.h> 47198157Srrs#include <zone.h> 48198157Srrs#include <sys/time.h> 49198157Srrs#include <zfs_prop.h> 50198157Srrs#include <sys/fs/zfs.h> 51198157Srrs#include <sys/stat.h> 52198157Srrs 53198157Srrs#include <libzfs.h> 54198157Srrs 55198157Srrs#include "zpool_util.h" 56198157Srrs#include "zfs_comutil.h" 57198157Srrs#include "zfeature_common.h" 58198157Srrs 59198157Srrs#include "statcommon.h" 60198157Srrs 61198157Srrsstatic int zpool_do_create(int, char **); 62198157Srrsstatic int zpool_do_destroy(int, char **); 63198157Srrs 64198157Srrsstatic int zpool_do_add(int, char **); 65198157Srrsstatic int zpool_do_remove(int, char **); 66198157Srrsstatic int zpool_do_labelclear(int, char **); 67198157Srrs 68198157Srrsstatic int zpool_do_list(int, char **); 69198157Srrsstatic int zpool_do_iostat(int, char **); 70198157Srrsstatic int zpool_do_status(int, char **); 71198157Srrs 72198157Srrsstatic int zpool_do_online(int, char **); 73198157Srrsstatic int zpool_do_offline(int, char **); 74198157Srrsstatic int zpool_do_clear(int, char **); 75198157Srrsstatic int zpool_do_reopen(int, char **); 76198157Srrs 77198157Srrsstatic int zpool_do_reguid(int, char **); 78198157Srrs 79198157Srrsstatic int zpool_do_attach(int, char **); 80198157Srrsstatic int zpool_do_detach(int, char **); 81198157Srrsstatic int zpool_do_replace(int, char **); 82198157Srrsstatic int zpool_do_split(int, char **); 83198157Srrs 84198157Srrsstatic int zpool_do_scrub(int, char **); 85198157Srrs 86198157Srrsstatic int zpool_do_import(int, char **); 87198157Srrsstatic int zpool_do_export(int, char **); 88198157Srrs 89198157Srrsstatic int zpool_do_upgrade(int, char **); 90198157Srrs 91198157Srrsstatic int zpool_do_history(int, char **); 92198157Srrs 93198157Srrsstatic int zpool_do_get(int, char **); 94198157Srrsstatic int zpool_do_set(int, char **); 95198157Srrs 96198157Srrs/* 97198157Srrs * These libumem hooks provide a reasonable set of defaults for the allocator's 98198157Srrs * debugging facilities. 99198157Srrs */ 100198157Srrs 101198157Srrs#ifdef DEBUG 102198157Srrsconst char * 103198157Srrs_umem_debug_init(void) 104198157Srrs{ 105198157Srrs return ("default,verbose"); /* $UMEM_DEBUG setting */ 106198157Srrs} 107198157Srrs 108198157Srrsconst char * 109198157Srrs_umem_logging_init(void) 110198157Srrs{ 111198157Srrs return ("fail,contents"); /* $UMEM_LOGGING setting */ 112198157Srrs} 113198157Srrs#endif 114198157Srrs 115198157Srrstypedef enum { 116198157Srrs HELP_ADD, 117198157Srrs HELP_ATTACH, 118198157Srrs HELP_CLEAR, 119198157Srrs HELP_CREATE, 120198157Srrs HELP_DESTROY, 121198157Srrs HELP_DETACH, 122198157Srrs HELP_EXPORT, 123198157Srrs HELP_HISTORY, 124198157Srrs HELP_IMPORT, 125198157Srrs HELP_IOSTAT, 126198157Srrs HELP_LABELCLEAR, 127198157Srrs HELP_LIST, 128198157Srrs HELP_OFFLINE, 129198157Srrs HELP_ONLINE, 130198157Srrs HELP_REPLACE, 131198157Srrs HELP_REMOVE, 132198157Srrs HELP_SCRUB, 133198157Srrs HELP_STATUS, 134198157Srrs HELP_UPGRADE, 135198157Srrs HELP_GET, 136198157Srrs HELP_SET, 137198157Srrs HELP_SPLIT, 138198157Srrs HELP_REGUID, 139198157Srrs HELP_REOPEN 140198157Srrs} zpool_help_t; 141198157Srrs 142198157Srrs 143198157Srrstypedef struct zpool_command { 144198157Srrs const char *name; 145198157Srrs int (*func)(int, char **); 146198157Srrs zpool_help_t usage; 147198157Srrs} zpool_command_t; 148198157Srrs 149198157Srrs/* 150198157Srrs * Master command table. Each ZFS command has a name, associated function, and 151198157Srrs * usage message. The usage messages need to be internationalized, so we have 152198157Srrs * to have a function to return the usage message based on a command index. 153198157Srrs * 154198157Srrs * These commands are organized according to how they are displayed in the usage 155198157Srrs * message. An empty command (one with a NULL name) indicates an empty line in 156198157Srrs * the generic usage message. 157198157Srrs */ 158198157Srrsstatic zpool_command_t command_table[] = { 159198157Srrs { "create", zpool_do_create, HELP_CREATE }, 160198157Srrs { "destroy", zpool_do_destroy, HELP_DESTROY }, 161198157Srrs { NULL }, 162198157Srrs { "add", zpool_do_add, HELP_ADD }, 163198157Srrs { "remove", zpool_do_remove, HELP_REMOVE }, 164198157Srrs { NULL }, 165198157Srrs { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR }, 166198157Srrs { NULL }, 167198157Srrs { "list", zpool_do_list, HELP_LIST }, 168198157Srrs { "iostat", zpool_do_iostat, HELP_IOSTAT }, 169198157Srrs { "status", zpool_do_status, HELP_STATUS }, 170198157Srrs { NULL }, 171198157Srrs { "online", zpool_do_online, HELP_ONLINE }, 172198157Srrs { "offline", zpool_do_offline, HELP_OFFLINE }, 173198157Srrs { "clear", zpool_do_clear, HELP_CLEAR }, 174198157Srrs { "reopen", zpool_do_reopen, HELP_REOPEN }, 175198157Srrs { NULL }, 176198157Srrs { "attach", zpool_do_attach, HELP_ATTACH }, 177198157Srrs { "detach", zpool_do_detach, HELP_DETACH }, 178198157Srrs { "replace", zpool_do_replace, HELP_REPLACE }, 179198157Srrs { "split", zpool_do_split, HELP_SPLIT }, 180198157Srrs { NULL }, 181198157Srrs { "scrub", zpool_do_scrub, HELP_SCRUB }, 182198157Srrs { NULL }, 183198157Srrs { "import", zpool_do_import, HELP_IMPORT }, 184198157Srrs { "export", zpool_do_export, HELP_EXPORT }, 185198157Srrs { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, 186198157Srrs { "reguid", zpool_do_reguid, HELP_REGUID }, 187198157Srrs { NULL }, 188198157Srrs { "history", zpool_do_history, HELP_HISTORY }, 189198157Srrs { "get", zpool_do_get, HELP_GET }, 190198157Srrs { "set", zpool_do_set, HELP_SET }, 191198157Srrs}; 192198157Srrs 193198157Srrs#define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 194198157Srrs 195198157Srrsstatic zpool_command_t *current_command; 196198157Srrsstatic char history_str[HIS_MAX_RECORD_LEN]; 197198157Srrsstatic boolean_t log_history = B_TRUE; 198198157Srrsstatic uint_t timestamp_fmt = NODATE; 199198157Srrs 200198157Srrsstatic const char * 201198157Srrsget_usage(zpool_help_t idx) { 202198157Srrs switch (idx) { 203198157Srrs case HELP_ADD: 204198157Srrs return (gettext("\tadd [-fn] <pool> <vdev> ...\n")); 205198157Srrs case HELP_ATTACH: 206198157Srrs return (gettext("\tattach [-f] <pool> <device> " 207198157Srrs "<new-device>\n")); 208198157Srrs case HELP_CLEAR: 209198157Srrs return (gettext("\tclear [-nF] <pool> [device]\n")); 210198157Srrs case HELP_CREATE: 211198157Srrs return (gettext("\tcreate [-fnd] [-o property=value] ... \n" 212198157Srrs "\t [-O file-system-property=value] ... \n" 213198157Srrs "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n")); 214198157Srrs case HELP_DESTROY: 215198157Srrs return (gettext("\tdestroy [-f] <pool>\n")); 216198157Srrs case HELP_DETACH: 217198157Srrs return (gettext("\tdetach <pool> <device>\n")); 218198157Srrs case HELP_EXPORT: 219198157Srrs return (gettext("\texport [-f] <pool> ...\n")); 220198157Srrs case HELP_HISTORY: 221198157Srrs return (gettext("\thistory [-il] [<pool>] ...\n")); 222198157Srrs case HELP_IMPORT: 223198157Srrs return (gettext("\timport [-d dir] [-D]\n" 224198157Srrs "\timport [-d dir | -c cachefile] [-F [-n]] <pool | id>\n" 225198157Srrs "\timport [-o mntopts] [-o property=value] ... \n" 226198157Srrs "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] " 227198157Srrs "[-R root] [-F [-n]] -a\n" 228198157Srrs "\timport [-o mntopts] [-o property=value] ... \n" 229198157Srrs "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] " 230198157Srrs "[-R root] [-F [-n]]\n" 231198157Srrs "\t <pool | id> [newpool]\n")); 232198157Srrs case HELP_IOSTAT: 233198157Srrs return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval " 234198157Srrs "[count]]\n")); 235198157Srrs case HELP_LABELCLEAR: 236198157Srrs return (gettext("\tlabelclear [-f] <vdev>\n")); 237198157Srrs case HELP_LIST: 238198157Srrs return (gettext("\tlist [-Hv] [-o property[,...]] " 239198157Srrs "[-T d|u] [pool] ... [interval [count]]\n")); 240198157Srrs case HELP_OFFLINE: 241198157Srrs return (gettext("\toffline [-t] <pool> <device> ...\n")); 242198157Srrs case HELP_ONLINE: 243198157Srrs return (gettext("\tonline [-e] <pool> <device> ...\n")); 244198157Srrs case HELP_REPLACE: 245198157Srrs return (gettext("\treplace [-f] <pool> <device> " 246198157Srrs "[new-device]\n")); 247198157Srrs case HELP_REMOVE: 248198157Srrs return (gettext("\tremove <pool> <device> ...\n")); 249198157Srrs case HELP_REOPEN: 250198157Srrs return (""); /* Undocumented command */ 251198157Srrs case HELP_SCRUB: 252198157Srrs return (gettext("\tscrub [-s] <pool> ...\n")); 253198157Srrs case HELP_STATUS: 254198157Srrs return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval " 255198157Srrs "[count]]\n")); 256198157Srrs case HELP_UPGRADE: 257198157Srrs return (gettext("\tupgrade [-v]\n" 258198157Srrs "\tupgrade [-V version] <-a | pool ...>\n")); 259198157Srrs case HELP_GET: 260198157Srrs return (gettext("\tget <\"all\" | property[,...]> " 261198157Srrs "<pool> ...\n")); 262198157Srrs case HELP_SET: 263198157Srrs return (gettext("\tset <property=value> <pool> \n")); 264198157Srrs case HELP_SPLIT: 265198157Srrs return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n" 266198157Srrs "\t [-o property=value] <pool> <newpool> " 267198157Srrs "[<device> ...]\n")); 268198157Srrs case HELP_REGUID: 269198157Srrs return (gettext("\treguid <pool>\n")); 270198157Srrs } 271198157Srrs 272198157Srrs abort(); 273198157Srrs /* NOTREACHED */ 274198157Srrs} 275198157Srrs 276198157Srrs 277198157Srrs/* 278198157Srrs * Callback routine that will print out a pool property value. 279198157Srrs */ 280198157Srrsstatic int 281198157Srrsprint_prop_cb(int prop, void *cb) 282198157Srrs{ 283198157Srrs FILE *fp = cb; 284198157Srrs 285198157Srrs (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop)); 286198157Srrs 287198157Srrs if (zpool_prop_readonly(prop)) 288198157Srrs (void) fprintf(fp, " NO "); 289198157Srrs else 290198157Srrs (void) fprintf(fp, " YES "); 291198157Srrs 292198157Srrs if (zpool_prop_values(prop) == NULL) 293198157Srrs (void) fprintf(fp, "-\n"); 294198157Srrs else 295198157Srrs (void) fprintf(fp, "%s\n", zpool_prop_values(prop)); 296198157Srrs 297198157Srrs return (ZPROP_CONT); 298198157Srrs} 299198157Srrs 300198157Srrs/* 301198157Srrs * Display usage message. If we're inside a command, display only the usage for 302198157Srrs * that command. Otherwise, iterate over the entire command table and display 303198157Srrs * a complete usage message. 304198157Srrs */ 305198157Srrsvoid 306198157Srrsusage(boolean_t requested) 307198157Srrs{ 308198157Srrs FILE *fp = requested ? stdout : stderr; 309198157Srrs 310198157Srrs if (current_command == NULL) { 311198157Srrs int i; 312198157Srrs 313198157Srrs (void) fprintf(fp, gettext("usage: zpool command args ...\n")); 314198157Srrs (void) fprintf(fp, 315198157Srrs gettext("where 'command' is one of the following:\n\n")); 316198157Srrs 317198157Srrs for (i = 0; i < NCOMMAND; i++) { 318198157Srrs if (command_table[i].name == NULL) 319198157Srrs (void) fprintf(fp, "\n"); 320198157Srrs else 321198157Srrs (void) fprintf(fp, "%s", 322198157Srrs get_usage(command_table[i].usage)); 323198157Srrs } 324198157Srrs } else { 325198157Srrs (void) fprintf(fp, gettext("usage:\n")); 326198157Srrs (void) fprintf(fp, "%s", get_usage(current_command->usage)); 327198157Srrs } 328198157Srrs 329198157Srrs if (current_command != NULL && 330198157Srrs ((strcmp(current_command->name, "set") == 0) || 331198157Srrs (strcmp(current_command->name, "get") == 0) || 332198157Srrs (strcmp(current_command->name, "list") == 0))) { 333198157Srrs 334198157Srrs (void) fprintf(fp, 335198157Srrs gettext("\nthe following properties are supported:\n")); 336198157Srrs 337198157Srrs (void) fprintf(fp, "\n\t%-15s %s %s\n\n", 338198157Srrs "PROPERTY", "EDIT", "VALUES"); 339198157Srrs 340198157Srrs /* Iterate over all properties */ 341198157Srrs (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, 342198157Srrs ZFS_TYPE_POOL); 343198157Srrs 344198157Srrs (void) fprintf(fp, "\t%-15s ", "feature@..."); 345198157Srrs (void) fprintf(fp, "YES disabled | enabled | active\n"); 346198157Srrs 347198157Srrs (void) fprintf(fp, gettext("\nThe feature@ properties must be " 348198157Srrs "appended with a feature name.\nSee zpool-features(7).\n")); 349198157Srrs } 350198157Srrs 351198157Srrs /* 352198157Srrs * See comments at end of main(). 353198157Srrs */ 354198157Srrs if (getenv("ZFS_ABORT") != NULL) { 355198157Srrs (void) printf("dumping core by request\n"); 356198157Srrs abort(); 357198157Srrs } 358198157Srrs 359198157Srrs exit(requested ? 0 : 2); 360198157Srrs} 361198157Srrs 362198157Srrsvoid 363198157Srrsprint_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, 364198157Srrs boolean_t print_logs) 365198157Srrs{ 366198157Srrs nvlist_t **child; 367198157Srrs uint_t c, children; 368198157Srrs char *vname; 369198157Srrs 370198157Srrs if (name != NULL) 371198157Srrs (void) printf("\t%*s%s\n", indent, "", name); 372198157Srrs 373198157Srrs if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 374198157Srrs &child, &children) != 0) 375198157Srrs return; 376198157Srrs 377198157Srrs for (c = 0; c < children; c++) { 378198157Srrs uint64_t is_log = B_FALSE; 379198157Srrs 380198157Srrs (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 381198157Srrs &is_log); 382198157Srrs if ((is_log && !print_logs) || (!is_log && print_logs)) 383198157Srrs continue; 384198157Srrs 385198157Srrs vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 386198157Srrs print_vdev_tree(zhp, vname, child[c], indent + 2, 387198157Srrs B_FALSE); 388198157Srrs free(vname); 389198157Srrs } 390198157Srrs} 391198157Srrs 392198157Srrsstatic boolean_t 393198157Srrsprop_list_contains_feature(nvlist_t *proplist) 394198157Srrs{ 395198157Srrs nvpair_t *nvp; 396198157Srrs for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp; 397198157Srrs nvp = nvlist_next_nvpair(proplist, nvp)) { 398198157Srrs if (zpool_prop_feature(nvpair_name(nvp))) 399198157Srrs return (B_TRUE); 400198157Srrs } 401198157Srrs return (B_FALSE); 402198157Srrs} 403198157Srrs 404198157Srrs/* 405198157Srrs * Add a property pair (name, string-value) into a property nvlist. 406198157Srrs */ 407198157Srrsstatic int 408198157Srrsadd_prop_list(const char *propname, char *propval, nvlist_t **props, 409198157Srrs boolean_t poolprop) 410198157Srrs{ 411198157Srrs zpool_prop_t prop = ZPROP_INVAL; 412198157Srrs zfs_prop_t fprop; 413198157Srrs nvlist_t *proplist; 414198157Srrs const char *normnm; 415198157Srrs char *strval; 416198157Srrs 417198157Srrs if (*props == NULL && 418198157Srrs nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) { 419198157Srrs (void) fprintf(stderr, 420198157Srrs gettext("internal error: out of memory\n")); 421198157Srrs return (1); 422198157Srrs } 423198157Srrs 424198157Srrs proplist = *props; 425198157Srrs 426198157Srrs if (poolprop) { 427198157Srrs const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION); 428198157Srrs 429198157Srrs if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL && 430198157Srrs !zpool_prop_feature(propname)) { 431198157Srrs (void) fprintf(stderr, gettext("property '%s' is " 432198157Srrs "not a valid pool property\n"), propname); 433198157Srrs return (2); 434198157Srrs } 435198157Srrs 436198157Srrs /* 437198157Srrs * feature@ properties and version should not be specified 438198157Srrs * at the same time. 439198157Srrs */ 440198157Srrs if ((prop == ZPROP_INVAL && zpool_prop_feature(propname) && 441198157Srrs nvlist_exists(proplist, vname)) || 442198157Srrs (prop == ZPOOL_PROP_VERSION && 443198157Srrs prop_list_contains_feature(proplist))) { 444198157Srrs (void) fprintf(stderr, gettext("'feature@' and " 445198157Srrs "'version' properties cannot be specified " 446198157Srrs "together\n")); 447198157Srrs return (2); 448198157Srrs } 449198157Srrs 450198157Srrs 451198157Srrs if (zpool_prop_feature(propname)) 452198157Srrs normnm = propname; 453198157Srrs else 454198157Srrs normnm = zpool_prop_to_name(prop); 455198157Srrs } else { 456198157Srrs if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) { 457198157Srrs normnm = zfs_prop_to_name(fprop); 458198157Srrs } else { 459198157Srrs normnm = propname; 460198157Srrs } 461198157Srrs } 462198157Srrs 463198157Srrs if (nvlist_lookup_string(proplist, normnm, &strval) == 0 && 464198157Srrs prop != ZPOOL_PROP_CACHEFILE) { 465198157Srrs (void) fprintf(stderr, gettext("property '%s' " 466198157Srrs "specified multiple times\n"), propname); 467198157Srrs return (2); 468198157Srrs } 469198157Srrs 470198157Srrs if (nvlist_add_string(proplist, normnm, propval) != 0) { 471198157Srrs (void) fprintf(stderr, gettext("internal " 472198157Srrs "error: out of memory\n")); 473198157Srrs return (1); 474198157Srrs } 475198157Srrs 476198157Srrs return (0); 477198157Srrs} 478198157Srrs 479198157Srrs/* 480198157Srrs * zpool add [-fn] <pool> <vdev> ... 481198157Srrs * 482198157Srrs * -f Force addition of devices, even if they appear in use 483198157Srrs * -n Do not add the devices, but display the resulting layout if 484198157Srrs * they were to be added. 485198157Srrs * 486198157Srrs * Adds the given vdevs to 'pool'. As with create, the bulk of this work is 487198157Srrs * handled by get_vdev_spec(), which constructs the nvlist needed to pass to 488198157Srrs * libzfs. 489198157Srrs */ 490198157Srrsint 491198157Srrszpool_do_add(int argc, char **argv) 492198157Srrs{ 493198157Srrs boolean_t force = B_FALSE; 494198157Srrs boolean_t dryrun = B_FALSE; 495198157Srrs int c; 496198157Srrs nvlist_t *nvroot; 497198157Srrs char *poolname; 498198157Srrs int ret; 499198157Srrs zpool_handle_t *zhp; 500198157Srrs nvlist_t *config; 501198157Srrs 502198157Srrs /* check options */ 503198157Srrs while ((c = getopt(argc, argv, "fn")) != -1) { 504198157Srrs switch (c) { 505198157Srrs case 'f': 506198157Srrs force = B_TRUE; 507198157Srrs break; 508198157Srrs case 'n': 509198157Srrs dryrun = B_TRUE; 510198157Srrs break; 511198157Srrs case '?': 512198157Srrs (void) fprintf(stderr, gettext("invalid option '%c'\n"), 513198157Srrs optopt); 514198157Srrs usage(B_FALSE); 515198157Srrs } 516198157Srrs } 517198157Srrs 518198157Srrs argc -= optind; 519198157Srrs argv += optind; 520198157Srrs 521198157Srrs /* get pool name and check number of arguments */ 522198157Srrs if (argc < 1) { 523198157Srrs (void) fprintf(stderr, gettext("missing pool name argument\n")); 524198157Srrs usage(B_FALSE); 525198157Srrs } 526198157Srrs if (argc < 2) { 527198157Srrs (void) fprintf(stderr, gettext("missing vdev specification\n")); 528198157Srrs usage(B_FALSE); 529198157Srrs } 530198157Srrs 531198157Srrs poolname = argv[0]; 532198157Srrs 533198157Srrs argc--; 534198157Srrs argv++; 535198157Srrs 536198157Srrs if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 537198157Srrs return (1); 538198157Srrs 539198157Srrs if ((config = zpool_get_config(zhp, NULL)) == NULL) { 540198157Srrs (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 541198157Srrs poolname); 542198157Srrs zpool_close(zhp); 543198157Srrs return (1); 544198157Srrs } 545198157Srrs 546198157Srrs /* pass off to get_vdev_spec for processing */ 547198157Srrs nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun, 548198157Srrs argc, argv); 549198157Srrs if (nvroot == NULL) { 550198157Srrs zpool_close(zhp); 551198157Srrs return (1); 552198157Srrs } 553198157Srrs 554198157Srrs if (dryrun) { 555198157Srrs nvlist_t *poolnvroot; 556198157Srrs 557198157Srrs verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 558198157Srrs &poolnvroot) == 0); 559198157Srrs 560198157Srrs (void) printf(gettext("would update '%s' to the following " 561198157Srrs "configuration:\n"), zpool_get_name(zhp)); 562198157Srrs 563198157Srrs /* print original main pool and new tree */ 564198157Srrs print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE); 565198157Srrs print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE); 566198157Srrs 567198157Srrs /* Do the same for the logs */ 568198157Srrs if (num_logs(poolnvroot) > 0) { 569198157Srrs print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE); 570198157Srrs print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE); 571198157Srrs } else if (num_logs(nvroot) > 0) { 572198157Srrs print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE); 573198157Srrs } 574198157Srrs 575198157Srrs ret = 0; 576198157Srrs } else { 577198157Srrs ret = (zpool_add(zhp, nvroot) != 0); 578198157Srrs } 579198157Srrs 580198157Srrs nvlist_free(nvroot); 581198157Srrs zpool_close(zhp); 582198157Srrs 583198157Srrs return (ret); 584198157Srrs} 585198157Srrs 586198157Srrs/* 587198157Srrs * zpool remove <pool> <vdev> ... 588198157Srrs * 589198157Srrs * Removes the given vdev from the pool. Currently, this supports removing 590198157Srrs * spares, cache, and log devices from the pool. 591198157Srrs */ 592198157Srrsint 593198157Srrszpool_do_remove(int argc, char **argv) 594198157Srrs{ 595198157Srrs char *poolname; 596198157Srrs int i, ret = 0; 597198157Srrs zpool_handle_t *zhp; 598198157Srrs 599198157Srrs argc--; 600198157Srrs argv++; 601198157Srrs 602198157Srrs /* get pool name and check number of arguments */ 603198157Srrs if (argc < 1) { 604198157Srrs (void) fprintf(stderr, gettext("missing pool name argument\n")); 605198157Srrs usage(B_FALSE); 606198157Srrs } 607198157Srrs if (argc < 2) { 608198157Srrs (void) fprintf(stderr, gettext("missing device\n")); 609198157Srrs usage(B_FALSE); 610198157Srrs } 611198157Srrs 612198157Srrs poolname = argv[0]; 613198157Srrs 614198157Srrs if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 615198157Srrs return (1); 616198157Srrs 617198157Srrs for (i = 1; i < argc; i++) { 618198157Srrs if (zpool_vdev_remove(zhp, argv[i]) != 0) 619198157Srrs ret = 1; 620198157Srrs } 621198157Srrs 622198157Srrs return (ret); 623198157Srrs} 624198157Srrs 625198157Srrs/* 626198157Srrs * zpool labelclear <vdev> 627198157Srrs * 628198157Srrs * Verifies that the vdev is not active and zeros out the label information 629198157Srrs * on the device. 630198157Srrs */ 631198157Srrsint 632198157Srrszpool_do_labelclear(int argc, char **argv) 633198157Srrs{ 634198157Srrs char *vdev, *name; 635198157Srrs int c, fd = -1, ret = 0; 636198157Srrs pool_state_t state; 637198157Srrs boolean_t inuse = B_FALSE; 638198157Srrs boolean_t force = B_FALSE; 639198157Srrs 640198157Srrs /* check options */ 641198157Srrs while ((c = getopt(argc, argv, "f")) != -1) { 642198157Srrs switch (c) { 643198157Srrs case 'f': 644198157Srrs force = B_TRUE; 645198157Srrs break; 646198157Srrs default: 647198157Srrs (void) fprintf(stderr, gettext("invalid option '%c'\n"), 648198157Srrs optopt); 649198157Srrs usage(B_FALSE); 650198157Srrs } 651198157Srrs } 652198157Srrs 653198157Srrs argc -= optind; 654198157Srrs argv += optind; 655198157Srrs 656198157Srrs /* get vdev name */ 657198157Srrs if (argc < 1) { 658198157Srrs (void) fprintf(stderr, gettext("missing vdev device name\n")); 659198157Srrs usage(B_FALSE); 660198157Srrs } 661198157Srrs 662198157Srrs vdev = argv[0]; 663198157Srrs if ((fd = open(vdev, O_RDWR)) < 0) { 664198157Srrs (void) fprintf(stderr, gettext("Unable to open %s\n"), vdev); 665198157Srrs return (B_FALSE); 666198157Srrs } 667198157Srrs 668198157Srrs name = NULL; 669198157Srrs if (zpool_in_use(g_zfs, fd, &state, &name, &inuse) != 0) { 670198157Srrs if (force) 671198157Srrs goto wipe_label; 672198157Srrs 673198157Srrs (void) fprintf(stderr, 674198157Srrs gettext("Unable to determine pool state for %s\n" 675198157Srrs "Use -f to force the clearing any label data\n"), vdev); 676198157Srrs 677198157Srrs return (1); 678198157Srrs } 679198157Srrs 680198157Srrs if (inuse) { 681198157Srrs switch (state) { 682198157Srrs default: 683198157Srrs case POOL_STATE_ACTIVE: 684198157Srrs case POOL_STATE_SPARE: 685198157Srrs case POOL_STATE_L2CACHE: 686198157Srrs (void) fprintf(stderr, 687198157Srrsgettext("labelclear operation failed.\n" 688198157Srrs "\tVdev %s is a member (%s), of pool \"%s\".\n" 689198157Srrs "\tTo remove label information from this device, export or destroy\n" 690198157Srrs "\tthe pool, or remove %s from the configuration of this pool\n" 691198157Srrs "\tand retry the labelclear operation\n"), 692198157Srrs vdev, zpool_pool_state_to_name(state), name, vdev); 693198157Srrs ret = 1; 694198157Srrs goto errout; 695198157Srrs 696198157Srrs case POOL_STATE_EXPORTED: 697198157Srrs if (force) 698198157Srrs break; 699198157Srrs 700198157Srrs (void) fprintf(stderr, 701198157Srrsgettext("labelclear operation failed.\n" 702198157Srrs "\tVdev %s is a member of the exported pool \"%s\".\n" 703198157Srrs "\tUse \"zpool labelclear -f %s\" to force the removal of label\n" 704198157Srrs "\tinformation.\n"), 705198157Srrs vdev, name, vdev); 706198157Srrs ret = 1; 707198157Srrs goto errout; 708198157Srrs 709198157Srrs case POOL_STATE_POTENTIALLY_ACTIVE: 710198157Srrs if (force) 711198157Srrs break; 712198157Srrs 713198157Srrs (void) fprintf(stderr, 714198157Srrsgettext("labelclear operation failed.\n" 715198157Srrs "\tVdev %s is a member of the pool \"%s\".\n" 716198157Srrs "\tThis pool is unknown to this system, but may be active on\n" 717198157Srrs "\tanother system. Use \'zpool labelclear -f %s\' to force the\n" 718198157Srrs "\tremoval of label information.\n"), 719198157Srrs vdev, name, vdev); 720198157Srrs ret = 1; 721198157Srrs goto errout; 722198157Srrs 723198157Srrs case POOL_STATE_DESTROYED: 724198157Srrs /* inuse should never be set for a destoryed pool... */ 725198157Srrs break; 726198157Srrs } 727198157Srrs } 728198157Srrs 729198157Srrswipe_label: 730198157Srrs if (zpool_clear_label(fd) != 0) { 731198157Srrs (void) fprintf(stderr, 732198157Srrs gettext("Label clear failed on vdev %s\n"), vdev); 733198157Srrs ret = 1; 734198157Srrs } 735198157Srrs 736198157Srrserrout: 737198157Srrs close(fd); 738198157Srrs if (name != NULL) 739198157Srrs free(name); 740198157Srrs 741198157Srrs return (ret); 742198157Srrs} 743198157Srrs 744198157Srrs/* 745198157Srrs * zpool create [-fnd] [-o property=value] ... 746198157Srrs * [-O file-system-property=value] ... 747198157Srrs * [-R root] [-m mountpoint] <pool> <dev> ... 748198157Srrs * 749198157Srrs * -f Force creation, even if devices appear in use 750198157Srrs * -n Do not create the pool, but display the resulting layout if it 751198157Srrs * were to be created. 752198157Srrs * -R Create a pool under an alternate root 753198157Srrs * -m Set default mountpoint for the root dataset. By default it's 754198157Srrs * '/<pool>' 755198157Srrs * -o Set property=value. 756198157Srrs * -d Don't automatically enable all supported pool features 757198157Srrs * (individual features can be enabled with -o). 758198157Srrs * -O Set fsproperty=value in the pool's root file system 759198157Srrs * 760198157Srrs * Creates the named pool according to the given vdev specification. The 761198157Srrs * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once 762198157Srrs * we get the nvlist back from get_vdev_spec(), we either print out the contents 763198157Srrs * (if '-n' was specified), or pass it to libzfs to do the creation. 764198157Srrs */ 765198157Srrsint 766198157Srrszpool_do_create(int argc, char **argv) 767198157Srrs{ 768198157Srrs boolean_t force = B_FALSE; 769198157Srrs boolean_t dryrun = B_FALSE; 770198157Srrs boolean_t enable_all_pool_feat = B_TRUE; 771198157Srrs int c; 772198157Srrs nvlist_t *nvroot = NULL; 773198157Srrs char *poolname; 774198157Srrs int ret = 1; 775198157Srrs char *altroot = NULL; 776198157Srrs char *mountpoint = NULL; 777198157Srrs nvlist_t *fsprops = NULL; 778198157Srrs nvlist_t *props = NULL; 779198157Srrs char *propval; 780198157Srrs 781198157Srrs /* check options */ 782198157Srrs while ((c = getopt(argc, argv, ":fndR:m:o:O:")) != -1) { 783198157Srrs switch (c) { 784198157Srrs case 'f': 785198157Srrs force = B_TRUE; 786198157Srrs break; 787198157Srrs case 'n': 788198157Srrs dryrun = B_TRUE; 789198157Srrs break; 790198157Srrs case 'd': 791198157Srrs enable_all_pool_feat = B_FALSE; 792198157Srrs break; 793198157Srrs case 'R': 794198157Srrs altroot = optarg; 795198157Srrs if (add_prop_list(zpool_prop_to_name( 796198157Srrs ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 797198157Srrs goto errout; 798198157Srrs if (nvlist_lookup_string(props, 799198157Srrs zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 800198157Srrs &propval) == 0) 801198157Srrs break; 802198157Srrs if (add_prop_list(zpool_prop_to_name( 803198157Srrs ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 804198157Srrs goto errout; 805198157Srrs break; 806198157Srrs case 'm': 807198157Srrs /* Equivalent to -O mountpoint=optarg */ 808198157Srrs mountpoint = optarg; 809198157Srrs break; 810198157Srrs case 'o': 811198157Srrs if ((propval = strchr(optarg, '=')) == NULL) { 812198157Srrs (void) fprintf(stderr, gettext("missing " 813198157Srrs "'=' for -o option\n")); 814198157Srrs goto errout; 815198157Srrs } 816198157Srrs *propval = '\0'; 817198157Srrs propval++; 818198157Srrs 819198157Srrs if (add_prop_list(optarg, propval, &props, B_TRUE)) 820198157Srrs goto errout; 821198157Srrs 822198157Srrs /* 823198157Srrs * If the user is creating a pool that doesn't support 824198157Srrs * feature flags, don't enable any features. 825198157Srrs */ 826198157Srrs if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) { 827198157Srrs char *end; 828198157Srrs u_longlong_t ver; 829198157Srrs 830198157Srrs ver = strtoull(propval, &end, 10); 831198157Srrs if (*end == '\0' && 832198157Srrs ver < SPA_VERSION_FEATURES) { 833198157Srrs enable_all_pool_feat = B_FALSE; 834198157Srrs } 835198157Srrs } 836198157Srrs break; 837198157Srrs case 'O': 838198157Srrs if ((propval = strchr(optarg, '=')) == NULL) { 839198157Srrs (void) fprintf(stderr, gettext("missing " 840198157Srrs "'=' for -O option\n")); 841198157Srrs goto errout; 842198157Srrs } 843198157Srrs *propval = '\0'; 844198157Srrs propval++; 845198157Srrs 846198157Srrs /* 847198157Srrs * Mountpoints are checked and then added later. 848198157Srrs * Uniquely among properties, they can be specified 849198157Srrs * more than once, to avoid conflict with -m. 850198157Srrs */ 851198157Srrs if (0 == strcmp(optarg, 852198157Srrs zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) { 853198157Srrs mountpoint = propval; 854198157Srrs } else if (add_prop_list(optarg, propval, &fsprops, 855198157Srrs B_FALSE)) { 856198157Srrs goto errout; 857198157Srrs } 858198157Srrs break; 859198157Srrs case ':': 860198157Srrs (void) fprintf(stderr, gettext("missing argument for " 861198157Srrs "'%c' option\n"), optopt); 862198157Srrs goto badusage; 863198157Srrs case '?': 864198157Srrs (void) fprintf(stderr, gettext("invalid option '%c'\n"), 865198157Srrs optopt); 866198157Srrs goto badusage; 867198157Srrs } 868198157Srrs } 869198157Srrs 870198157Srrs argc -= optind; 871198157Srrs argv += optind; 872198157Srrs 873198157Srrs /* get pool name and check number of arguments */ 874198157Srrs if (argc < 1) { 875198157Srrs (void) fprintf(stderr, gettext("missing pool name argument\n")); 876198157Srrs goto badusage; 877198157Srrs } 878198157Srrs if (argc < 2) { 879198157Srrs (void) fprintf(stderr, gettext("missing vdev specification\n")); 880198157Srrs goto badusage; 881198157Srrs } 882198157Srrs 883198157Srrs poolname = argv[0]; 884198157Srrs 885198157Srrs /* 886198157Srrs * As a special case, check for use of '/' in the name, and direct the 887198157Srrs * user to use 'zfs create' instead. 888198157Srrs */ 889198157Srrs if (strchr(poolname, '/') != NULL) { 890198157Srrs (void) fprintf(stderr, gettext("cannot create '%s': invalid " 891198157Srrs "character '/' in pool name\n"), poolname); 892198157Srrs (void) fprintf(stderr, gettext("use 'zfs create' to " 893198157Srrs "create a dataset\n")); 894198157Srrs goto errout; 895198157Srrs } 896198157Srrs 897198157Srrs /* pass off to get_vdev_spec for bulk processing */ 898198157Srrs nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun, 899198157Srrs argc - 1, argv + 1); 900198157Srrs if (nvroot == NULL) 901198157Srrs goto errout; 902198157Srrs 903198157Srrs /* make_root_vdev() allows 0 toplevel children if there are spares */ 904198157Srrs if (!zfs_allocatable_devs(nvroot)) { 905198157Srrs (void) fprintf(stderr, gettext("invalid vdev " 906198157Srrs "specification: at least one toplevel vdev must be " 907198157Srrs "specified\n")); 908198157Srrs goto errout; 909198157Srrs } 910198157Srrs 911198157Srrs if (altroot != NULL && altroot[0] != '/') { 912198157Srrs (void) fprintf(stderr, gettext("invalid alternate root '%s': " 913198157Srrs "must be an absolute path\n"), altroot); 914198157Srrs goto errout; 915198157Srrs } 916198157Srrs 917198157Srrs /* 918198157Srrs * Check the validity of the mountpoint and direct the user to use the 919198157Srrs * '-m' mountpoint option if it looks like its in use. 920198157Srrs * Ignore the checks if the '-f' option is given. 921198157Srrs */ 922198157Srrs if (!force && (mountpoint == NULL || 923198157Srrs (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 && 924198157Srrs strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0))) { 925198157Srrs char buf[MAXPATHLEN]; 926198157Srrs DIR *dirp; 927198157Srrs 928198157Srrs if (mountpoint && mountpoint[0] != '/') { 929198157Srrs (void) fprintf(stderr, gettext("invalid mountpoint " 930198157Srrs "'%s': must be an absolute path, 'legacy', or " 931198157Srrs "'none'\n"), mountpoint); 932198157Srrs goto errout; 933198157Srrs } 934198157Srrs 935198157Srrs if (mountpoint == NULL) { 936198157Srrs if (altroot != NULL) 937198157Srrs (void) snprintf(buf, sizeof (buf), "%s/%s", 938198157Srrs altroot, poolname); 939198157Srrs else 940198157Srrs (void) snprintf(buf, sizeof (buf), "/%s", 941198157Srrs poolname); 942198157Srrs } else { 943198157Srrs if (altroot != NULL) 944198608Srrs (void) snprintf(buf, sizeof (buf), "%s%s", 945198608Srrs altroot, mountpoint); 946198608Srrs else 947198626Srrs (void) snprintf(buf, sizeof (buf), "%s", 948198608Srrs mountpoint); 949198608Srrs } 950198608Srrs 951198608Srrs if ((dirp = opendir(buf)) == NULL && errno != ENOENT) { 952198626Srrs (void) fprintf(stderr, gettext("mountpoint '%s' : " 953198608Srrs "%s\n"), buf, strerror(errno)); 954198608Srrs (void) fprintf(stderr, gettext("use '-m' " 955198608Srrs "option to provide a different default\n")); 956198608Srrs goto errout; 957198626Srrs } else if (dirp) { 958198608Srrs int count = 0; 959198608Srrs 960198608Srrs while (count < 3 && readdir(dirp) != NULL) 961198608Srrs count++; 962198626Srrs (void) closedir(dirp); 963198608Srrs 964198608Srrs if (count > 2) { 965198608Srrs (void) fprintf(stderr, gettext("mountpoint " 966198608Srrs "'%s' exists and is not empty\n"), buf); 967198608Srrs (void) fprintf(stderr, gettext("use '-m' " 968198608Srrs "option to provide a " 969198608Srrs "different default\n")); 970198608Srrs goto errout; 971198608Srrs } 972198608Srrs } 973198608Srrs } 974198608Srrs 975198608Srrs /* 976212759Sjchandra * Now that the mountpoint's validity has been checked, ensure that 977212759Sjchandra * the property is set appropriately prior to creating the pool. 978212759Sjchandra */ 979212759Sjchandra if (mountpoint != NULL) { 980212759Sjchandra ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT), 981212759Sjchandra mountpoint, &fsprops, B_FALSE); 982198608Srrs if (ret != 0) 983198608Srrs goto errout; 984198608Srrs } 985198608Srrs 986198608Srrs ret = 1; 987198608Srrs if (dryrun) { 988198608Srrs /* 989198608Srrs * For a dry run invocation, print out a basic message and run 990198608Srrs * through all the vdevs in the list and print out in an 991198608Srrs * appropriate hierarchy. 992198608Srrs */ 993198608Srrs (void) printf(gettext("would create '%s' with the " 994198608Srrs "following layout:\n\n"), poolname); 995198608Srrs 996198626Srrs print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE); 997198608Srrs if (num_logs(nvroot) > 0) 998198608Srrs print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE); 999198608Srrs 1000198626Srrs ret = 0; 1001198608Srrs } else { 1002198626Srrs /* 1003198626Srrs * Hand off to libzfs. 1004198626Srrs */ 1005198626Srrs if (enable_all_pool_feat) { 1006198608Srrs int i; 1007198626Srrs for (i = 0; i < SPA_FEATURES; i++) { 1008198626Srrs char propname[MAXPATHLEN]; 1009198608Srrs zfeature_info_t *feat = &spa_feature_table[i]; 1010198626Srrs 1011198626Srrs (void) snprintf(propname, sizeof (propname), 1012198626Srrs "feature@%s", feat->fi_uname); 1013198626Srrs 1014198626Srrs /* 1015198608Srrs * Skip feature if user specified it manually 1016198626Srrs * on the command line. 1017198608Srrs */ 1018198626Srrs if (nvlist_exists(props, propname)) 1019198626Srrs continue; 1020198626Srrs 1021198608Srrs ret = add_prop_list(propname, 1022198626Srrs ZFS_FEATURE_ENABLED, &props, B_TRUE); 1023198626Srrs if (ret != 0) 1024198626Srrs goto errout; 1025198626Srrs } 1026198626Srrs } 1027198626Srrs 1028198626Srrs ret = 1; 1029198608Srrs if (zpool_create(g_zfs, poolname, 1030198608Srrs nvroot, props, fsprops) == 0) { 1031198608Srrs zfs_handle_t *pool = zfs_open(g_zfs, poolname, 1032198626Srrs ZFS_TYPE_FILESYSTEM); 1033198626Srrs if (pool != NULL) { 1034198626Srrs if (zfs_mount(pool, NULL, 0) == 0) 1035198626Srrs ret = zfs_shareall(pool); 1036198626Srrs zfs_close(pool); 1037198626Srrs } 1038198626Srrs } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { 1039198626Srrs (void) fprintf(stderr, gettext("pool name may have " 1040198626Srrs "been omitted\n")); 1041198608Srrs } 1042198626Srrs } 1043198626Srrs 1044198626Srrserrout: 1045198608Srrs nvlist_free(nvroot); 1046198626Srrs nvlist_free(fsprops); 1047198626Srrs nvlist_free(props); 1048198626Srrs return (ret); 1049198608Srrsbadusage: 1050198626Srrs nvlist_free(fsprops); 1051198626Srrs nvlist_free(props); 1052198626Srrs usage(B_FALSE); 1053198626Srrs return (2); 1054198626Srrs} 1055198626Srrs 1056198626Srrs/* 1057198626Srrs * zpool destroy <pool> 1058198608Srrs * 1059198608Srrs * -f Forcefully unmount any datasets 1060198608Srrs * 1061198608Srrs * Destroy the given pool. Automatically unmounts any datasets in the pool. 1062198608Srrs */ 1063198157Srrsint 1064198626Srrszpool_do_destroy(int argc, char **argv) 1065198157Srrs{ 1066198157Srrs boolean_t force = B_FALSE; 1067198157Srrs int c; 1068198626Srrs char *pool; 1069198626Srrs zpool_handle_t *zhp; 1070198157Srrs int ret; 1071198157Srrs 1072198157Srrs /* check options */ 1073198626Srrs while ((c = getopt(argc, argv, "f")) != -1) { 1074198626Srrs switch (c) { 1075198626Srrs case 'f': 1076198157Srrs force = B_TRUE; 1077198157Srrs break; 1078198157Srrs case '?': 1079198626Srrs (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1080198626Srrs optopt); 1081198626Srrs usage(B_FALSE); 1082198626Srrs } 1083198157Srrs } 1084198157Srrs 1085198157Srrs argc -= optind; 1086198157Srrs argv += optind; 1087198157Srrs 1088198157Srrs /* check arguments */ 1089198157Srrs if (argc < 1) { 1090198157Srrs (void) fprintf(stderr, gettext("missing pool argument\n")); 1091198157Srrs usage(B_FALSE); 1092198157Srrs } 1093198157Srrs if (argc > 1) { 1094198157Srrs (void) fprintf(stderr, gettext("too many arguments\n")); 1095198157Srrs usage(B_FALSE); 1096198157Srrs } 1097198157Srrs 1098198157Srrs pool = argv[0]; 1099 1100 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 1101 /* 1102 * As a special case, check for use of '/' in the name, and 1103 * direct the user to use 'zfs destroy' instead. 1104 */ 1105 if (strchr(pool, '/') != NULL) 1106 (void) fprintf(stderr, gettext("use 'zfs destroy' to " 1107 "destroy a dataset\n")); 1108 return (1); 1109 } 1110 1111 if (zpool_disable_datasets(zhp, force) != 0) { 1112 (void) fprintf(stderr, gettext("could not destroy '%s': " 1113 "could not unmount datasets\n"), zpool_get_name(zhp)); 1114 return (1); 1115 } 1116 1117 /* The history must be logged as part of the export */ 1118 log_history = B_FALSE; 1119 1120 ret = (zpool_destroy(zhp, history_str) != 0); 1121 1122 zpool_close(zhp); 1123 1124 return (ret); 1125} 1126 1127/* 1128 * zpool export [-f] <pool> ... 1129 * 1130 * -f Forcefully unmount datasets 1131 * 1132 * Export the given pools. By default, the command will attempt to cleanly 1133 * unmount any active datasets within the pool. If the '-f' flag is specified, 1134 * then the datasets will be forcefully unmounted. 1135 */ 1136int 1137zpool_do_export(int argc, char **argv) 1138{ 1139 boolean_t force = B_FALSE; 1140 boolean_t hardforce = B_FALSE; 1141 int c; 1142 zpool_handle_t *zhp; 1143 int ret; 1144 int i; 1145 1146 /* check options */ 1147 while ((c = getopt(argc, argv, "fF")) != -1) { 1148 switch (c) { 1149 case 'f': 1150 force = B_TRUE; 1151 break; 1152 case 'F': 1153 hardforce = B_TRUE; 1154 break; 1155 case '?': 1156 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1157 optopt); 1158 usage(B_FALSE); 1159 } 1160 } 1161 1162 argc -= optind; 1163 argv += optind; 1164 1165 /* check arguments */ 1166 if (argc < 1) { 1167 (void) fprintf(stderr, gettext("missing pool argument\n")); 1168 usage(B_FALSE); 1169 } 1170 1171 ret = 0; 1172 for (i = 0; i < argc; i++) { 1173 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) { 1174 ret = 1; 1175 continue; 1176 } 1177 1178 if (zpool_disable_datasets(zhp, force) != 0) { 1179 ret = 1; 1180 zpool_close(zhp); 1181 continue; 1182 } 1183 1184 /* The history must be logged as part of the export */ 1185 log_history = B_FALSE; 1186 1187 if (hardforce) { 1188 if (zpool_export_force(zhp, history_str) != 0) 1189 ret = 1; 1190 } else if (zpool_export(zhp, force, history_str) != 0) { 1191 ret = 1; 1192 } 1193 1194 zpool_close(zhp); 1195 } 1196 1197 return (ret); 1198} 1199 1200/* 1201 * Given a vdev configuration, determine the maximum width needed for the device 1202 * name column. 1203 */ 1204static int 1205max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max) 1206{ 1207 char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE); 1208 nvlist_t **child; 1209 uint_t c, children; 1210 int ret; 1211 1212 if (strlen(name) + depth > max) 1213 max = strlen(name) + depth; 1214 1215 free(name); 1216 1217 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1218 &child, &children) == 0) { 1219 for (c = 0; c < children; c++) 1220 if ((ret = max_width(zhp, child[c], depth + 2, 1221 max)) > max) 1222 max = ret; 1223 } 1224 1225 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1226 &child, &children) == 0) { 1227 for (c = 0; c < children; c++) 1228 if ((ret = max_width(zhp, child[c], depth + 2, 1229 max)) > max) 1230 max = ret; 1231 } 1232 1233 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1234 &child, &children) == 0) { 1235 for (c = 0; c < children; c++) 1236 if ((ret = max_width(zhp, child[c], depth + 2, 1237 max)) > max) 1238 max = ret; 1239 } 1240 1241 1242 return (max); 1243} 1244 1245typedef struct spare_cbdata { 1246 uint64_t cb_guid; 1247 zpool_handle_t *cb_zhp; 1248} spare_cbdata_t; 1249 1250static boolean_t 1251find_vdev(nvlist_t *nv, uint64_t search) 1252{ 1253 uint64_t guid; 1254 nvlist_t **child; 1255 uint_t c, children; 1256 1257 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && 1258 search == guid) 1259 return (B_TRUE); 1260 1261 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1262 &child, &children) == 0) { 1263 for (c = 0; c < children; c++) 1264 if (find_vdev(child[c], search)) 1265 return (B_TRUE); 1266 } 1267 1268 return (B_FALSE); 1269} 1270 1271static int 1272find_spare(zpool_handle_t *zhp, void *data) 1273{ 1274 spare_cbdata_t *cbp = data; 1275 nvlist_t *config, *nvroot; 1276 1277 config = zpool_get_config(zhp, NULL); 1278 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1279 &nvroot) == 0); 1280 1281 if (find_vdev(nvroot, cbp->cb_guid)) { 1282 cbp->cb_zhp = zhp; 1283 return (1); 1284 } 1285 1286 zpool_close(zhp); 1287 return (0); 1288} 1289 1290/* 1291 * Print out configuration state as requested by status_callback. 1292 */ 1293void 1294print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 1295 int namewidth, int depth, boolean_t isspare) 1296{ 1297 nvlist_t **child; 1298 uint_t c, vsc, children; 1299 pool_scan_stat_t *ps = NULL; 1300 vdev_stat_t *vs; 1301 char rbuf[6], wbuf[6], cbuf[6]; 1302 char *vname; 1303 uint64_t notpresent; 1304 uint64_t ashift; 1305 spare_cbdata_t cb; 1306 const char *state; 1307 1308 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1309 &child, &children) != 0) 1310 children = 0; 1311 1312 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 1313 (uint64_t **)&vs, &vsc) == 0); 1314 1315 state = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1316 if (isspare) { 1317 /* 1318 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for 1319 * online drives. 1320 */ 1321 if (vs->vs_aux == VDEV_AUX_SPARED) 1322 state = "INUSE"; 1323 else if (vs->vs_state == VDEV_STATE_HEALTHY) 1324 state = "AVAIL"; 1325 } 1326 1327 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth, 1328 name, state); 1329 1330 if (!isspare) { 1331 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf)); 1332 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf)); 1333 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf)); 1334 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf); 1335 } 1336 1337 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, 1338 ¬present) == 0 || 1339 vs->vs_state <= VDEV_STATE_CANT_OPEN) { 1340 char *path; 1341 if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) 1342 (void) printf(" was %s", path); 1343 } else if (vs->vs_aux != 0) { 1344 (void) printf(" "); 1345 1346 switch (vs->vs_aux) { 1347 case VDEV_AUX_OPEN_FAILED: 1348 (void) printf(gettext("cannot open")); 1349 break; 1350 1351 case VDEV_AUX_BAD_GUID_SUM: 1352 (void) printf(gettext("missing device")); 1353 break; 1354 1355 case VDEV_AUX_NO_REPLICAS: 1356 (void) printf(gettext("insufficient replicas")); 1357 break; 1358 1359 case VDEV_AUX_VERSION_NEWER: 1360 (void) printf(gettext("newer version")); 1361 break; 1362 1363 case VDEV_AUX_UNSUP_FEAT: 1364 (void) printf(gettext("unsupported feature(s)")); 1365 break; 1366 1367 case VDEV_AUX_ASHIFT_TOO_BIG: 1368 (void) printf(gettext("unsupported minimum blocksize")); 1369 break; 1370 1371 case VDEV_AUX_SPARED: 1372 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, 1373 &cb.cb_guid) == 0); 1374 if (zpool_iter(g_zfs, find_spare, &cb) == 1) { 1375 if (strcmp(zpool_get_name(cb.cb_zhp), 1376 zpool_get_name(zhp)) == 0) 1377 (void) printf(gettext("currently in " 1378 "use")); 1379 else 1380 (void) printf(gettext("in use by " 1381 "pool '%s'"), 1382 zpool_get_name(cb.cb_zhp)); 1383 zpool_close(cb.cb_zhp); 1384 } else { 1385 (void) printf(gettext("currently in use")); 1386 } 1387 break; 1388 1389 case VDEV_AUX_ERR_EXCEEDED: 1390 (void) printf(gettext("too many errors")); 1391 break; 1392 1393 case VDEV_AUX_IO_FAILURE: 1394 (void) printf(gettext("experienced I/O failures")); 1395 break; 1396 1397 case VDEV_AUX_BAD_LOG: 1398 (void) printf(gettext("bad intent log")); 1399 break; 1400 1401 case VDEV_AUX_EXTERNAL: 1402 (void) printf(gettext("external device fault")); 1403 break; 1404 1405 case VDEV_AUX_SPLIT_POOL: 1406 (void) printf(gettext("split into new pool")); 1407 break; 1408 1409 default: 1410 (void) printf(gettext("corrupted data")); 1411 break; 1412 } 1413 } else if (children == 0 && !isspare && 1414 VDEV_STAT_VALID(vs_physical_ashift, vsc) && 1415 vs->vs_configured_ashift < vs->vs_physical_ashift) { 1416 (void) printf( 1417 gettext(" block size: %dB configured, %dB native"), 1418 1 << vs->vs_configured_ashift, 1 << vs->vs_physical_ashift); 1419 } 1420 1421 (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS, 1422 (uint64_t **)&ps, &c); 1423 1424 if (ps && ps->pss_state == DSS_SCANNING && 1425 vs->vs_scan_processed != 0 && children == 0) { 1426 (void) printf(gettext(" (%s)"), 1427 (ps->pss_func == POOL_SCAN_RESILVER) ? 1428 "resilvering" : "repairing"); 1429 } 1430 1431 (void) printf("\n"); 1432 1433 for (c = 0; c < children; c++) { 1434 uint64_t islog = B_FALSE, ishole = B_FALSE; 1435 1436 /* Don't print logs or holes here */ 1437 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1438 &islog); 1439 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE, 1440 &ishole); 1441 if (islog || ishole) 1442 continue; 1443 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE); 1444 print_status_config(zhp, vname, child[c], 1445 namewidth, depth + 2, isspare); 1446 free(vname); 1447 } 1448} 1449 1450 1451/* 1452 * Print the configuration of an exported pool. Iterate over all vdevs in the 1453 * pool, printing out the name and status for each one. 1454 */ 1455void 1456print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) 1457{ 1458 nvlist_t **child; 1459 uint_t c, children; 1460 vdev_stat_t *vs; 1461 char *type, *vname; 1462 1463 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); 1464 if (strcmp(type, VDEV_TYPE_MISSING) == 0 || 1465 strcmp(type, VDEV_TYPE_HOLE) == 0) 1466 return; 1467 1468 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 1469 (uint64_t **)&vs, &c) == 0); 1470 1471 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name); 1472 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux)); 1473 1474 if (vs->vs_aux != 0) { 1475 (void) printf(" "); 1476 1477 switch (vs->vs_aux) { 1478 case VDEV_AUX_OPEN_FAILED: 1479 (void) printf(gettext("cannot open")); 1480 break; 1481 1482 case VDEV_AUX_BAD_GUID_SUM: 1483 (void) printf(gettext("missing device")); 1484 break; 1485 1486 case VDEV_AUX_NO_REPLICAS: 1487 (void) printf(gettext("insufficient replicas")); 1488 break; 1489 1490 case VDEV_AUX_VERSION_NEWER: 1491 (void) printf(gettext("newer version")); 1492 break; 1493 1494 case VDEV_AUX_UNSUP_FEAT: 1495 (void) printf(gettext("unsupported feature(s)")); 1496 break; 1497 1498 case VDEV_AUX_ERR_EXCEEDED: 1499 (void) printf(gettext("too many errors")); 1500 break; 1501 1502 default: 1503 (void) printf(gettext("corrupted data")); 1504 break; 1505 } 1506 } 1507 (void) printf("\n"); 1508 1509 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 1510 &child, &children) != 0) 1511 return; 1512 1513 for (c = 0; c < children; c++) { 1514 uint64_t is_log = B_FALSE; 1515 1516 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1517 &is_log); 1518 if (is_log) 1519 continue; 1520 1521 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE); 1522 print_import_config(vname, child[c], namewidth, depth + 2); 1523 free(vname); 1524 } 1525 1526 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 1527 &child, &children) == 0) { 1528 (void) printf(gettext("\tcache\n")); 1529 for (c = 0; c < children; c++) { 1530 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE); 1531 (void) printf("\t %s\n", vname); 1532 free(vname); 1533 } 1534 } 1535 1536 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, 1537 &child, &children) == 0) { 1538 (void) printf(gettext("\tspares\n")); 1539 for (c = 0; c < children; c++) { 1540 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE); 1541 (void) printf("\t %s\n", vname); 1542 free(vname); 1543 } 1544 } 1545} 1546 1547/* 1548 * Print log vdevs. 1549 * Logs are recorded as top level vdevs in the main pool child array 1550 * but with "is_log" set to 1. We use either print_status_config() or 1551 * print_import_config() to print the top level logs then any log 1552 * children (eg mirrored slogs) are printed recursively - which 1553 * works because only the top level vdev is marked "is_log" 1554 */ 1555static void 1556print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose) 1557{ 1558 uint_t c, children; 1559 nvlist_t **child; 1560 1561 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, 1562 &children) != 0) 1563 return; 1564 1565 (void) printf(gettext("\tlogs\n")); 1566 1567 for (c = 0; c < children; c++) { 1568 uint64_t is_log = B_FALSE; 1569 char *name; 1570 1571 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG, 1572 &is_log); 1573 if (!is_log) 1574 continue; 1575 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE); 1576 if (verbose) 1577 print_status_config(zhp, name, child[c], namewidth, 1578 2, B_FALSE); 1579 else 1580 print_import_config(name, child[c], namewidth, 2); 1581 free(name); 1582 } 1583} 1584 1585/* 1586 * Display the status for the given pool. 1587 */ 1588static void 1589show_import(nvlist_t *config) 1590{ 1591 uint64_t pool_state; 1592 vdev_stat_t *vs; 1593 char *name; 1594 uint64_t guid; 1595 char *msgid; 1596 nvlist_t *nvroot; 1597 int reason; 1598 const char *health; 1599 uint_t vsc; 1600 int namewidth; 1601 char *comment; 1602 1603 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1604 &name) == 0); 1605 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, 1606 &guid) == 0); 1607 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 1608 &pool_state) == 0); 1609 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 1610 &nvroot) == 0); 1611 1612 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 1613 (uint64_t **)&vs, &vsc) == 0); 1614 health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 1615 1616 reason = zpool_import_status(config, &msgid); 1617 1618 (void) printf(gettext(" pool: %s\n"), name); 1619 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); 1620 (void) printf(gettext(" state: %s"), health); 1621 if (pool_state == POOL_STATE_DESTROYED) 1622 (void) printf(gettext(" (DESTROYED)")); 1623 (void) printf("\n"); 1624 1625 switch (reason) { 1626 case ZPOOL_STATUS_MISSING_DEV_R: 1627 case ZPOOL_STATUS_MISSING_DEV_NR: 1628 case ZPOOL_STATUS_BAD_GUID_SUM: 1629 (void) printf(gettext(" status: One or more devices are " 1630 "missing from the system.\n")); 1631 break; 1632 1633 case ZPOOL_STATUS_CORRUPT_LABEL_R: 1634 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 1635 (void) printf(gettext(" status: One or more devices contains " 1636 "corrupted data.\n")); 1637 break; 1638 1639 case ZPOOL_STATUS_CORRUPT_DATA: 1640 (void) printf( 1641 gettext(" status: The pool data is corrupted.\n")); 1642 break; 1643 1644 case ZPOOL_STATUS_OFFLINE_DEV: 1645 (void) printf(gettext(" status: One or more devices " 1646 "are offlined.\n")); 1647 break; 1648 1649 case ZPOOL_STATUS_CORRUPT_POOL: 1650 (void) printf(gettext(" status: The pool metadata is " 1651 "corrupted.\n")); 1652 break; 1653 1654 case ZPOOL_STATUS_VERSION_OLDER: 1655 (void) printf(gettext(" status: The pool is formatted using a " 1656 "legacy on-disk version.\n")); 1657 break; 1658 1659 case ZPOOL_STATUS_VERSION_NEWER: 1660 (void) printf(gettext(" status: The pool is formatted using an " 1661 "incompatible version.\n")); 1662 break; 1663 1664 case ZPOOL_STATUS_FEAT_DISABLED: 1665 (void) printf(gettext(" status: Some supported features are " 1666 "not enabled on the pool.\n")); 1667 break; 1668 1669 case ZPOOL_STATUS_UNSUP_FEAT_READ: 1670 (void) printf(gettext("status: The pool uses the following " 1671 "feature(s) not supported on this sytem:\n")); 1672 zpool_print_unsup_feat(config); 1673 break; 1674 1675 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 1676 (void) printf(gettext("status: The pool can only be accessed " 1677 "in read-only mode on this system. It\n\tcannot be " 1678 "accessed in read-write mode because it uses the " 1679 "following\n\tfeature(s) not supported on this system:\n")); 1680 zpool_print_unsup_feat(config); 1681 break; 1682 1683 case ZPOOL_STATUS_HOSTID_MISMATCH: 1684 (void) printf(gettext(" status: The pool was last accessed by " 1685 "another system.\n")); 1686 break; 1687 1688 case ZPOOL_STATUS_FAULTED_DEV_R: 1689 case ZPOOL_STATUS_FAULTED_DEV_NR: 1690 (void) printf(gettext(" status: One or more devices are " 1691 "faulted.\n")); 1692 break; 1693 1694 case ZPOOL_STATUS_BAD_LOG: 1695 (void) printf(gettext(" status: An intent log record cannot be " 1696 "read.\n")); 1697 break; 1698 1699 case ZPOOL_STATUS_RESILVERING: 1700 (void) printf(gettext(" status: One or more devices were being " 1701 "resilvered.\n")); 1702 break; 1703 1704 default: 1705 /* 1706 * No other status can be seen when importing pools. 1707 */ 1708 assert(reason == ZPOOL_STATUS_OK); 1709 } 1710 1711 /* 1712 * Print out an action according to the overall state of the pool. 1713 */ 1714 if (vs->vs_state == VDEV_STATE_HEALTHY) { 1715 if (reason == ZPOOL_STATUS_VERSION_OLDER || 1716 reason == ZPOOL_STATUS_FEAT_DISABLED) { 1717 (void) printf(gettext(" action: The pool can be " 1718 "imported using its name or numeric identifier, " 1719 "though\n\tsome features will not be available " 1720 "without an explicit 'zpool upgrade'.\n")); 1721 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) { 1722 (void) printf(gettext(" action: The pool can be " 1723 "imported using its name or numeric " 1724 "identifier and\n\tthe '-f' flag.\n")); 1725 } else { 1726 (void) printf(gettext(" action: The pool can be " 1727 "imported using its name or numeric " 1728 "identifier.\n")); 1729 } 1730 } else if (vs->vs_state == VDEV_STATE_DEGRADED) { 1731 (void) printf(gettext(" action: The pool can be imported " 1732 "despite missing or damaged devices. The\n\tfault " 1733 "tolerance of the pool may be compromised if imported.\n")); 1734 } else { 1735 switch (reason) { 1736 case ZPOOL_STATUS_VERSION_NEWER: 1737 (void) printf(gettext(" action: The pool cannot be " 1738 "imported. Access the pool on a system running " 1739 "newer\n\tsoftware, or recreate the pool from " 1740 "backup.\n")); 1741 break; 1742 case ZPOOL_STATUS_UNSUP_FEAT_READ: 1743 (void) printf(gettext("action: The pool cannot be " 1744 "imported. Access the pool on a system that " 1745 "supports\n\tthe required feature(s), or recreate " 1746 "the pool from backup.\n")); 1747 break; 1748 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 1749 (void) printf(gettext("action: The pool cannot be " 1750 "imported in read-write mode. Import the pool " 1751 "with\n" 1752 "\t\"-o readonly=on\", access the pool on a system " 1753 "that supports the\n\trequired feature(s), or " 1754 "recreate the pool from backup.\n")); 1755 break; 1756 case ZPOOL_STATUS_MISSING_DEV_R: 1757 case ZPOOL_STATUS_MISSING_DEV_NR: 1758 case ZPOOL_STATUS_BAD_GUID_SUM: 1759 (void) printf(gettext(" action: The pool cannot be " 1760 "imported. Attach the missing\n\tdevices and try " 1761 "again.\n")); 1762 break; 1763 default: 1764 (void) printf(gettext(" action: The pool cannot be " 1765 "imported due to damaged devices or data.\n")); 1766 } 1767 } 1768 1769 /* Print the comment attached to the pool. */ 1770 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0) 1771 (void) printf(gettext("comment: %s\n"), comment); 1772 1773 /* 1774 * If the state is "closed" or "can't open", and the aux state 1775 * is "corrupt data": 1776 */ 1777 if (((vs->vs_state == VDEV_STATE_CLOSED) || 1778 (vs->vs_state == VDEV_STATE_CANT_OPEN)) && 1779 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) { 1780 if (pool_state == POOL_STATE_DESTROYED) 1781 (void) printf(gettext("\tThe pool was destroyed, " 1782 "but can be imported using the '-Df' flags.\n")); 1783 else if (pool_state != POOL_STATE_EXPORTED) 1784 (void) printf(gettext("\tThe pool may be active on " 1785 "another system, but can be imported using\n\t" 1786 "the '-f' flag.\n")); 1787 } 1788 1789 if (msgid != NULL) 1790 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 1791 msgid); 1792 1793 (void) printf(gettext(" config:\n\n")); 1794 1795 namewidth = max_width(NULL, nvroot, 0, 0); 1796 if (namewidth < 10) 1797 namewidth = 10; 1798 1799 print_import_config(name, nvroot, namewidth, 0); 1800 if (num_logs(nvroot) > 0) 1801 print_logs(NULL, nvroot, namewidth, B_FALSE); 1802 1803 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { 1804 (void) printf(gettext("\n\tAdditional devices are known to " 1805 "be part of this pool, though their\n\texact " 1806 "configuration cannot be determined.\n")); 1807 } 1808} 1809 1810/* 1811 * Perform the import for the given configuration. This passes the heavy 1812 * lifting off to zpool_import_props(), and then mounts the datasets contained 1813 * within the pool. 1814 */ 1815static int 1816do_import(nvlist_t *config, const char *newname, const char *mntopts, 1817 nvlist_t *props, int flags) 1818{ 1819 zpool_handle_t *zhp; 1820 char *name; 1821 uint64_t state; 1822 uint64_t version; 1823 1824 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, 1825 &name) == 0); 1826 1827 verify(nvlist_lookup_uint64(config, 1828 ZPOOL_CONFIG_POOL_STATE, &state) == 0); 1829 verify(nvlist_lookup_uint64(config, 1830 ZPOOL_CONFIG_VERSION, &version) == 0); 1831 if (!SPA_VERSION_IS_SUPPORTED(version)) { 1832 (void) fprintf(stderr, gettext("cannot import '%s': pool " 1833 "is formatted using an unsupported ZFS version\n"), name); 1834 return (1); 1835 } else if (state != POOL_STATE_EXPORTED && 1836 !(flags & ZFS_IMPORT_ANY_HOST)) { 1837 uint64_t hostid; 1838 1839 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, 1840 &hostid) == 0) { 1841 if ((unsigned long)hostid != gethostid()) { 1842 char *hostname; 1843 uint64_t timestamp; 1844 time_t t; 1845 1846 verify(nvlist_lookup_string(config, 1847 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0); 1848 verify(nvlist_lookup_uint64(config, 1849 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0); 1850 t = timestamp; 1851 (void) fprintf(stderr, gettext("cannot import " 1852 "'%s': pool may be in use from other " 1853 "system, it was last accessed by %s " 1854 "(hostid: 0x%lx) on %s"), name, hostname, 1855 (unsigned long)hostid, 1856 asctime(localtime(&t))); 1857 (void) fprintf(stderr, gettext("use '-f' to " 1858 "import anyway\n")); 1859 return (1); 1860 } 1861 } else { 1862 (void) fprintf(stderr, gettext("cannot import '%s': " 1863 "pool may be in use from other system\n"), name); 1864 (void) fprintf(stderr, gettext("use '-f' to import " 1865 "anyway\n")); 1866 return (1); 1867 } 1868 } 1869 1870 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0) 1871 return (1); 1872 1873 if (newname != NULL) 1874 name = (char *)newname; 1875 1876 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL) 1877 return (1); 1878 1879 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 1880 !(flags & ZFS_IMPORT_ONLY) && 1881 zpool_enable_datasets(zhp, mntopts, 0) != 0) { 1882 zpool_close(zhp); 1883 return (1); 1884 } 1885 1886 zpool_close(zhp); 1887 return (0); 1888} 1889 1890/* 1891 * zpool import [-d dir] [-D] 1892 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 1893 * [-d dir | -c cachefile] [-f] -a 1894 * import [-o mntopts] [-o prop=value] ... [-R root] [-D] 1895 * [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool] 1896 * 1897 * -c Read pool information from a cachefile instead of searching 1898 * devices. 1899 * 1900 * -d Scan in a specific directory, other than /dev/dsk. More than 1901 * one directory can be specified using multiple '-d' options. 1902 * 1903 * -D Scan for previously destroyed pools or import all or only 1904 * specified destroyed pools. 1905 * 1906 * -R Temporarily import the pool, with all mountpoints relative to 1907 * the given root. The pool will remain exported when the machine 1908 * is rebooted. 1909 * 1910 * -V Import even in the presence of faulted vdevs. This is an 1911 * intentionally undocumented option for testing purposes, and 1912 * treats the pool configuration as complete, leaving any bad 1913 * vdevs in the FAULTED state. In other words, it does verbatim 1914 * import. 1915 * 1916 * -f Force import, even if it appears that the pool is active. 1917 * 1918 * -F Attempt rewind if necessary. 1919 * 1920 * -n See if rewind would work, but don't actually rewind. 1921 * 1922 * -N Import the pool but don't mount datasets. 1923 * 1924 * -T Specify a starting txg to use for import. This option is 1925 * intentionally undocumented option for testing purposes. 1926 * 1927 * -a Import all pools found. 1928 * 1929 * -o Set property=value and/or temporary mount options (without '='). 1930 * 1931 * The import command scans for pools to import, and import pools based on pool 1932 * name and GUID. The pool can also be renamed as part of the import process. 1933 */ 1934int 1935zpool_do_import(int argc, char **argv) 1936{ 1937 char **searchdirs = NULL; 1938 int nsearch = 0; 1939 int c; 1940 int err = 0; 1941 nvlist_t *pools = NULL; 1942 boolean_t do_all = B_FALSE; 1943 boolean_t do_destroyed = B_FALSE; 1944 char *mntopts = NULL; 1945 nvpair_t *elem; 1946 nvlist_t *config; 1947 uint64_t searchguid = 0; 1948 char *searchname = NULL; 1949 char *propval; 1950 nvlist_t *found_config; 1951 nvlist_t *policy = NULL; 1952 nvlist_t *props = NULL; 1953 boolean_t first; 1954 int flags = ZFS_IMPORT_NORMAL; 1955 uint32_t rewind_policy = ZPOOL_NO_REWIND; 1956 boolean_t dryrun = B_FALSE; 1957 boolean_t do_rewind = B_FALSE; 1958 boolean_t xtreme_rewind = B_FALSE; 1959 uint64_t pool_state, txg = -1ULL; 1960 char *cachefile = NULL; 1961 importargs_t idata = { 0 }; 1962 char *endptr; 1963 1964 /* check options */ 1965 while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:rR:T:VX")) != -1) { 1966 switch (c) { 1967 case 'a': 1968 do_all = B_TRUE; 1969 break; 1970 case 'c': 1971 cachefile = optarg; 1972 break; 1973 case 'd': 1974 if (searchdirs == NULL) { 1975 searchdirs = safe_malloc(sizeof (char *)); 1976 } else { 1977 char **tmp = safe_malloc((nsearch + 1) * 1978 sizeof (char *)); 1979 bcopy(searchdirs, tmp, nsearch * 1980 sizeof (char *)); 1981 free(searchdirs); 1982 searchdirs = tmp; 1983 } 1984 searchdirs[nsearch++] = optarg; 1985 break; 1986 case 'D': 1987 do_destroyed = B_TRUE; 1988 break; 1989 case 'f': 1990 flags |= ZFS_IMPORT_ANY_HOST; 1991 break; 1992 case 'F': 1993 do_rewind = B_TRUE; 1994 break; 1995 case 'm': 1996 flags |= ZFS_IMPORT_MISSING_LOG; 1997 break; 1998 case 'n': 1999 dryrun = B_TRUE; 2000 break; 2001 case 'N': 2002 flags |= ZFS_IMPORT_ONLY; 2003 break; 2004 case 'o': 2005 if ((propval = strchr(optarg, '=')) != NULL) { 2006 *propval = '\0'; 2007 propval++; 2008 if (add_prop_list(optarg, propval, 2009 &props, B_TRUE)) 2010 goto error; 2011 } else { 2012 mntopts = optarg; 2013 } 2014 break; 2015 case 'R': 2016 if (add_prop_list(zpool_prop_to_name( 2017 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE)) 2018 goto error; 2019 if (nvlist_lookup_string(props, 2020 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE), 2021 &propval) == 0) 2022 break; 2023 if (add_prop_list(zpool_prop_to_name( 2024 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE)) 2025 goto error; 2026 break; 2027 case 'T': 2028 errno = 0; 2029 txg = strtoull(optarg, &endptr, 10); 2030 if (errno != 0 || *endptr != '\0') { 2031 (void) fprintf(stderr, 2032 gettext("invalid txg value\n")); 2033 usage(B_FALSE); 2034 } 2035 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND; 2036 break; 2037 case 'V': 2038 flags |= ZFS_IMPORT_VERBATIM; 2039 break; 2040 case 'X': 2041 xtreme_rewind = B_TRUE; 2042 break; 2043 case ':': 2044 (void) fprintf(stderr, gettext("missing argument for " 2045 "'%c' option\n"), optopt); 2046 usage(B_FALSE); 2047 break; 2048 case '?': 2049 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2050 optopt); 2051 usage(B_FALSE); 2052 } 2053 } 2054 2055 argc -= optind; 2056 argv += optind; 2057 2058 if (cachefile && nsearch != 0) { 2059 (void) fprintf(stderr, gettext("-c is incompatible with -d\n")); 2060 usage(B_FALSE); 2061 } 2062 2063 if ((dryrun || xtreme_rewind) && !do_rewind) { 2064 (void) fprintf(stderr, 2065 gettext("-n or -X only meaningful with -F\n")); 2066 usage(B_FALSE); 2067 } 2068 if (dryrun) 2069 rewind_policy = ZPOOL_TRY_REWIND; 2070 else if (do_rewind) 2071 rewind_policy = ZPOOL_DO_REWIND; 2072 if (xtreme_rewind) 2073 rewind_policy |= ZPOOL_EXTREME_REWIND; 2074 2075 /* In the future, we can capture further policy and include it here */ 2076 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 2077 nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 || 2078 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0) 2079 goto error; 2080 2081 if (searchdirs == NULL) { 2082 searchdirs = safe_malloc(sizeof (char *)); 2083 searchdirs[0] = "/dev"; 2084 nsearch = 1; 2085 } 2086 2087 /* check argument count */ 2088 if (do_all) { 2089 if (argc != 0) { 2090 (void) fprintf(stderr, gettext("too many arguments\n")); 2091 usage(B_FALSE); 2092 } 2093 } else { 2094 if (argc > 2) { 2095 (void) fprintf(stderr, gettext("too many arguments\n")); 2096 usage(B_FALSE); 2097 } 2098 2099 /* 2100 * Check for the SYS_CONFIG privilege. We do this explicitly 2101 * here because otherwise any attempt to discover pools will 2102 * silently fail. 2103 */ 2104 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { 2105 (void) fprintf(stderr, gettext("cannot " 2106 "discover pools: permission denied\n")); 2107 free(searchdirs); 2108 nvlist_free(policy); 2109 return (1); 2110 } 2111 } 2112 2113 /* 2114 * Depending on the arguments given, we do one of the following: 2115 * 2116 * <none> Iterate through all pools and display information about 2117 * each one. 2118 * 2119 * -a Iterate through all pools and try to import each one. 2120 * 2121 * <id> Find the pool that corresponds to the given GUID/pool 2122 * name and import that one. 2123 * 2124 * -D Above options applies only to destroyed pools. 2125 */ 2126 if (argc != 0) { 2127 char *endptr; 2128 2129 errno = 0; 2130 searchguid = strtoull(argv[0], &endptr, 10); 2131 if (errno != 0 || *endptr != '\0') 2132 searchname = argv[0]; 2133 found_config = NULL; 2134 2135 /* 2136 * User specified a name or guid. Ensure it's unique. 2137 */ 2138 idata.unique = B_TRUE; 2139 } 2140 2141 2142 idata.path = searchdirs; 2143 idata.paths = nsearch; 2144 idata.poolname = searchname; 2145 idata.guid = searchguid; 2146 idata.cachefile = cachefile; 2147 2148 pools = zpool_search_import(g_zfs, &idata); 2149 2150 if (pools != NULL && idata.exists && 2151 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) { 2152 (void) fprintf(stderr, gettext("cannot import '%s': " 2153 "a pool with that name already exists\n"), 2154 argv[0]); 2155 (void) fprintf(stderr, gettext("use the form '%s " 2156 "<pool | id> <newpool>' to give it a new name\n"), 2157 "zpool import"); 2158 err = 1; 2159 } else if (pools == NULL && idata.exists) { 2160 (void) fprintf(stderr, gettext("cannot import '%s': " 2161 "a pool with that name is already created/imported,\n"), 2162 argv[0]); 2163 (void) fprintf(stderr, gettext("and no additional pools " 2164 "with that name were found\n")); 2165 err = 1; 2166 } else if (pools == NULL) { 2167 if (argc != 0) { 2168 (void) fprintf(stderr, gettext("cannot import '%s': " 2169 "no such pool available\n"), argv[0]); 2170 } 2171 err = 1; 2172 } 2173 2174 if (err == 1) { 2175 free(searchdirs); 2176 nvlist_free(policy); 2177 return (1); 2178 } 2179 2180 /* 2181 * At this point we have a list of import candidate configs. Even if 2182 * we were searching by pool name or guid, we still need to 2183 * post-process the list to deal with pool state and possible 2184 * duplicate names. 2185 */ 2186 err = 0; 2187 elem = NULL; 2188 first = B_TRUE; 2189 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { 2190 2191 verify(nvpair_value_nvlist(elem, &config) == 0); 2192 2193 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, 2194 &pool_state) == 0); 2195 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED) 2196 continue; 2197 if (do_destroyed && pool_state != POOL_STATE_DESTROYED) 2198 continue; 2199 2200 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY, 2201 policy) == 0); 2202 2203 if (argc == 0) { 2204 if (first) 2205 first = B_FALSE; 2206 else if (!do_all) 2207 (void) printf("\n"); 2208 2209 if (do_all) { 2210 err |= do_import(config, NULL, mntopts, 2211 props, flags); 2212 } else { 2213 show_import(config); 2214 } 2215 } else if (searchname != NULL) { 2216 char *name; 2217 2218 /* 2219 * We are searching for a pool based on name. 2220 */ 2221 verify(nvlist_lookup_string(config, 2222 ZPOOL_CONFIG_POOL_NAME, &name) == 0); 2223 2224 if (strcmp(name, searchname) == 0) { 2225 if (found_config != NULL) { 2226 (void) fprintf(stderr, gettext( 2227 "cannot import '%s': more than " 2228 "one matching pool\n"), searchname); 2229 (void) fprintf(stderr, gettext( 2230 "import by numeric ID instead\n")); 2231 err = B_TRUE; 2232 } 2233 found_config = config; 2234 } 2235 } else { 2236 uint64_t guid; 2237 2238 /* 2239 * Search for a pool by guid. 2240 */ 2241 verify(nvlist_lookup_uint64(config, 2242 ZPOOL_CONFIG_POOL_GUID, &guid) == 0); 2243 2244 if (guid == searchguid) 2245 found_config = config; 2246 } 2247 } 2248 2249 /* 2250 * If we were searching for a specific pool, verify that we found a 2251 * pool, and then do the import. 2252 */ 2253 if (argc != 0 && err == 0) { 2254 if (found_config == NULL) { 2255 (void) fprintf(stderr, gettext("cannot import '%s': " 2256 "no such pool available\n"), argv[0]); 2257 err = B_TRUE; 2258 } else { 2259 err |= do_import(found_config, argc == 1 ? NULL : 2260 argv[1], mntopts, props, flags); 2261 } 2262 } 2263 2264 /* 2265 * If we were just looking for pools, report an error if none were 2266 * found. 2267 */ 2268 if (argc == 0 && first) 2269 (void) fprintf(stderr, 2270 gettext("no pools available to import\n")); 2271 2272error: 2273 nvlist_free(props); 2274 nvlist_free(pools); 2275 nvlist_free(policy); 2276 free(searchdirs); 2277 2278 return (err ? 1 : 0); 2279} 2280 2281typedef struct iostat_cbdata { 2282 boolean_t cb_verbose; 2283 int cb_namewidth; 2284 int cb_iteration; 2285 zpool_list_t *cb_list; 2286} iostat_cbdata_t; 2287 2288static void 2289print_iostat_separator(iostat_cbdata_t *cb) 2290{ 2291 int i = 0; 2292 2293 for (i = 0; i < cb->cb_namewidth; i++) 2294 (void) printf("-"); 2295 (void) printf(" ----- ----- ----- ----- ----- -----\n"); 2296} 2297 2298static void 2299print_iostat_header(iostat_cbdata_t *cb) 2300{ 2301 (void) printf("%*s capacity operations bandwidth\n", 2302 cb->cb_namewidth, ""); 2303 (void) printf("%-*s alloc free read write read write\n", 2304 cb->cb_namewidth, "pool"); 2305 print_iostat_separator(cb); 2306} 2307 2308/* 2309 * Display a single statistic. 2310 */ 2311static void 2312print_one_stat(uint64_t value) 2313{ 2314 char buf[64]; 2315 2316 zfs_nicenum(value, buf, sizeof (buf)); 2317 (void) printf(" %5s", buf); 2318} 2319 2320/* 2321 * Print out all the statistics for the given vdev. This can either be the 2322 * toplevel configuration, or called recursively. If 'name' is NULL, then this 2323 * is a verbose output, and we don't want to display the toplevel pool stats. 2324 */ 2325void 2326print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, 2327 nvlist_t *newnv, iostat_cbdata_t *cb, int depth) 2328{ 2329 nvlist_t **oldchild, **newchild; 2330 uint_t c, children; 2331 vdev_stat_t *oldvs, *newvs; 2332 vdev_stat_t zerovs = { 0 }; 2333 uint64_t tdelta; 2334 double scale; 2335 char *vname; 2336 2337 if (oldnv != NULL) { 2338 verify(nvlist_lookup_uint64_array(oldnv, 2339 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0); 2340 } else { 2341 oldvs = &zerovs; 2342 } 2343 2344 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS, 2345 (uint64_t **)&newvs, &c) == 0); 2346 2347 if (strlen(name) + depth > cb->cb_namewidth) 2348 (void) printf("%*s%s", depth, "", name); 2349 else 2350 (void) printf("%*s%s%*s", depth, "", name, 2351 (int)(cb->cb_namewidth - strlen(name) - depth), ""); 2352 2353 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp; 2354 2355 if (tdelta == 0) 2356 scale = 1.0; 2357 else 2358 scale = (double)NANOSEC / tdelta; 2359 2360 /* only toplevel vdevs have capacity stats */ 2361 if (newvs->vs_space == 0) { 2362 (void) printf(" - -"); 2363 } else { 2364 print_one_stat(newvs->vs_alloc); 2365 print_one_stat(newvs->vs_space - newvs->vs_alloc); 2366 } 2367 2368 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] - 2369 oldvs->vs_ops[ZIO_TYPE_READ]))); 2370 2371 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] - 2372 oldvs->vs_ops[ZIO_TYPE_WRITE]))); 2373 2374 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] - 2375 oldvs->vs_bytes[ZIO_TYPE_READ]))); 2376 2377 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] - 2378 oldvs->vs_bytes[ZIO_TYPE_WRITE]))); 2379 2380 (void) printf("\n"); 2381 2382 if (!cb->cb_verbose) 2383 return; 2384 2385 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN, 2386 &newchild, &children) != 0) 2387 return; 2388 2389 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN, 2390 &oldchild, &c) != 0) 2391 return; 2392 2393 for (c = 0; c < children; c++) { 2394 uint64_t ishole = B_FALSE, islog = B_FALSE; 2395 2396 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE, 2397 &ishole); 2398 2399 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG, 2400 &islog); 2401 2402 if (ishole || islog) 2403 continue; 2404 2405 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE); 2406 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 2407 newchild[c], cb, depth + 2); 2408 free(vname); 2409 } 2410 2411 /* 2412 * Log device section 2413 */ 2414 2415 if (num_logs(newnv) > 0) { 2416 (void) printf("%-*s - - - - - " 2417 "-\n", cb->cb_namewidth, "logs"); 2418 2419 for (c = 0; c < children; c++) { 2420 uint64_t islog = B_FALSE; 2421 (void) nvlist_lookup_uint64(newchild[c], 2422 ZPOOL_CONFIG_IS_LOG, &islog); 2423 2424 if (islog) { 2425 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 2426 B_FALSE); 2427 print_vdev_stats(zhp, vname, oldnv ? 2428 oldchild[c] : NULL, newchild[c], 2429 cb, depth + 2); 2430 free(vname); 2431 } 2432 } 2433 2434 } 2435 2436 /* 2437 * Include level 2 ARC devices in iostat output 2438 */ 2439 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, 2440 &newchild, &children) != 0) 2441 return; 2442 2443 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, 2444 &oldchild, &c) != 0) 2445 return; 2446 2447 if (children > 0) { 2448 (void) printf("%-*s - - - - - " 2449 "-\n", cb->cb_namewidth, "cache"); 2450 for (c = 0; c < children; c++) { 2451 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], 2452 B_FALSE); 2453 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, 2454 newchild[c], cb, depth + 2); 2455 free(vname); 2456 } 2457 } 2458} 2459 2460static int 2461refresh_iostat(zpool_handle_t *zhp, void *data) 2462{ 2463 iostat_cbdata_t *cb = data; 2464 boolean_t missing; 2465 2466 /* 2467 * If the pool has disappeared, remove it from the list and continue. 2468 */ 2469 if (zpool_refresh_stats(zhp, &missing) != 0) 2470 return (-1); 2471 2472 if (missing) 2473 pool_list_remove(cb->cb_list, zhp); 2474 2475 return (0); 2476} 2477 2478/* 2479 * Callback to print out the iostats for the given pool. 2480 */ 2481int 2482print_iostat(zpool_handle_t *zhp, void *data) 2483{ 2484 iostat_cbdata_t *cb = data; 2485 nvlist_t *oldconfig, *newconfig; 2486 nvlist_t *oldnvroot, *newnvroot; 2487 2488 newconfig = zpool_get_config(zhp, &oldconfig); 2489 2490 if (cb->cb_iteration == 1) 2491 oldconfig = NULL; 2492 2493 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE, 2494 &newnvroot) == 0); 2495 2496 if (oldconfig == NULL) 2497 oldnvroot = NULL; 2498 else 2499 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE, 2500 &oldnvroot) == 0); 2501 2502 /* 2503 * Print out the statistics for the pool. 2504 */ 2505 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); 2506 2507 if (cb->cb_verbose) 2508 print_iostat_separator(cb); 2509 2510 return (0); 2511} 2512 2513int 2514get_namewidth(zpool_handle_t *zhp, void *data) 2515{ 2516 iostat_cbdata_t *cb = data; 2517 nvlist_t *config, *nvroot; 2518 2519 if ((config = zpool_get_config(zhp, NULL)) != NULL) { 2520 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2521 &nvroot) == 0); 2522 if (!cb->cb_verbose) 2523 cb->cb_namewidth = strlen(zpool_get_name(zhp)); 2524 else 2525 cb->cb_namewidth = max_width(zhp, nvroot, 0, 2526 cb->cb_namewidth); 2527 } 2528 2529 /* 2530 * The width must fall into the range [10,38]. The upper limit is the 2531 * maximum we can have and still fit in 80 columns. 2532 */ 2533 if (cb->cb_namewidth < 10) 2534 cb->cb_namewidth = 10; 2535 if (cb->cb_namewidth > 38) 2536 cb->cb_namewidth = 38; 2537 2538 return (0); 2539} 2540 2541/* 2542 * Parse the input string, get the 'interval' and 'count' value if there is one. 2543 */ 2544static void 2545get_interval_count(int *argcp, char **argv, unsigned long *iv, 2546 unsigned long *cnt) 2547{ 2548 unsigned long interval = 0, count = 0; 2549 int argc = *argcp, errno; 2550 2551 /* 2552 * Determine if the last argument is an integer or a pool name 2553 */ 2554 if (argc > 0 && isdigit(argv[argc - 1][0])) { 2555 char *end; 2556 2557 errno = 0; 2558 interval = strtoul(argv[argc - 1], &end, 10); 2559 2560 if (*end == '\0' && errno == 0) { 2561 if (interval == 0) { 2562 (void) fprintf(stderr, gettext("interval " 2563 "cannot be zero\n")); 2564 usage(B_FALSE); 2565 } 2566 /* 2567 * Ignore the last parameter 2568 */ 2569 argc--; 2570 } else { 2571 /* 2572 * If this is not a valid number, just plow on. The 2573 * user will get a more informative error message later 2574 * on. 2575 */ 2576 interval = 0; 2577 } 2578 } 2579 2580 /* 2581 * If the last argument is also an integer, then we have both a count 2582 * and an interval. 2583 */ 2584 if (argc > 0 && isdigit(argv[argc - 1][0])) { 2585 char *end; 2586 2587 errno = 0; 2588 count = interval; 2589 interval = strtoul(argv[argc - 1], &end, 10); 2590 2591 if (*end == '\0' && errno == 0) { 2592 if (interval == 0) { 2593 (void) fprintf(stderr, gettext("interval " 2594 "cannot be zero\n")); 2595 usage(B_FALSE); 2596 } 2597 2598 /* 2599 * Ignore the last parameter 2600 */ 2601 argc--; 2602 } else { 2603 interval = 0; 2604 } 2605 } 2606 2607 *iv = interval; 2608 *cnt = count; 2609 *argcp = argc; 2610} 2611 2612static void 2613get_timestamp_arg(char c) 2614{ 2615 if (c == 'u') 2616 timestamp_fmt = UDATE; 2617 else if (c == 'd') 2618 timestamp_fmt = DDATE; 2619 else 2620 usage(B_FALSE); 2621} 2622 2623/* 2624 * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]] 2625 * 2626 * -v Display statistics for individual vdevs 2627 * -T Display a timestamp in date(1) or Unix format 2628 * 2629 * This command can be tricky because we want to be able to deal with pool 2630 * creation/destruction as well as vdev configuration changes. The bulk of this 2631 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely 2632 * on pool_list_update() to detect the addition of new pools. Configuration 2633 * changes are all handled within libzfs. 2634 */ 2635int 2636zpool_do_iostat(int argc, char **argv) 2637{ 2638 int c; 2639 int ret; 2640 int npools; 2641 unsigned long interval = 0, count = 0; 2642 zpool_list_t *list; 2643 boolean_t verbose = B_FALSE; 2644 iostat_cbdata_t cb; 2645 2646 /* check options */ 2647 while ((c = getopt(argc, argv, "T:v")) != -1) { 2648 switch (c) { 2649 case 'T': 2650 get_timestamp_arg(*optarg); 2651 break; 2652 case 'v': 2653 verbose = B_TRUE; 2654 break; 2655 case '?': 2656 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2657 optopt); 2658 usage(B_FALSE); 2659 } 2660 } 2661 2662 argc -= optind; 2663 argv += optind; 2664 2665 get_interval_count(&argc, argv, &interval, &count); 2666 2667 /* 2668 * Construct the list of all interesting pools. 2669 */ 2670 ret = 0; 2671 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL) 2672 return (1); 2673 2674 if (pool_list_count(list) == 0 && argc != 0) { 2675 pool_list_free(list); 2676 return (1); 2677 } 2678 2679 if (pool_list_count(list) == 0 && interval == 0) { 2680 pool_list_free(list); 2681 (void) fprintf(stderr, gettext("no pools available\n")); 2682 return (1); 2683 } 2684 2685 /* 2686 * Enter the main iostat loop. 2687 */ 2688 cb.cb_list = list; 2689 cb.cb_verbose = verbose; 2690 cb.cb_iteration = 0; 2691 cb.cb_namewidth = 0; 2692 2693 for (;;) { 2694 pool_list_update(list); 2695 2696 if ((npools = pool_list_count(list)) == 0) 2697 break; 2698 2699 /* 2700 * Refresh all statistics. This is done as an explicit step 2701 * before calculating the maximum name width, so that any 2702 * configuration changes are properly accounted for. 2703 */ 2704 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb); 2705 2706 /* 2707 * Iterate over all pools to determine the maximum width 2708 * for the pool / device name column across all pools. 2709 */ 2710 cb.cb_namewidth = 0; 2711 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 2712 2713 if (timestamp_fmt != NODATE) 2714 print_timestamp(timestamp_fmt); 2715 2716 /* 2717 * If it's the first time, or verbose mode, print the header. 2718 */ 2719 if (++cb.cb_iteration == 1 || verbose) 2720 print_iostat_header(&cb); 2721 2722 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb); 2723 2724 /* 2725 * If there's more than one pool, and we're not in verbose mode 2726 * (which prints a separator for us), then print a separator. 2727 */ 2728 if (npools > 1 && !verbose) 2729 print_iostat_separator(&cb); 2730 2731 if (verbose) 2732 (void) printf("\n"); 2733 2734 /* 2735 * Flush the output so that redirection to a file isn't buffered 2736 * indefinitely. 2737 */ 2738 (void) fflush(stdout); 2739 2740 if (interval == 0) 2741 break; 2742 2743 if (count != 0 && --count == 0) 2744 break; 2745 2746 (void) sleep(interval); 2747 } 2748 2749 pool_list_free(list); 2750 2751 return (ret); 2752} 2753 2754typedef struct list_cbdata { 2755 boolean_t cb_verbose; 2756 int cb_namewidth; 2757 boolean_t cb_scripted; 2758 zprop_list_t *cb_proplist; 2759} list_cbdata_t; 2760 2761/* 2762 * Given a list of columns to display, output appropriate headers for each one. 2763 */ 2764static void 2765print_header(list_cbdata_t *cb) 2766{ 2767 zprop_list_t *pl = cb->cb_proplist; 2768 char headerbuf[ZPOOL_MAXPROPLEN]; 2769 const char *header; 2770 boolean_t first = B_TRUE; 2771 boolean_t right_justify; 2772 size_t width = 0; 2773 2774 for (; pl != NULL; pl = pl->pl_next) { 2775 width = pl->pl_width; 2776 if (first && cb->cb_verbose) { 2777 /* 2778 * Reset the width to accommodate the verbose listing 2779 * of devices. 2780 */ 2781 width = cb->cb_namewidth; 2782 } 2783 2784 if (!first) 2785 (void) printf(" "); 2786 else 2787 first = B_FALSE; 2788 2789 right_justify = B_FALSE; 2790 if (pl->pl_prop != ZPROP_INVAL) { 2791 header = zpool_prop_column_name(pl->pl_prop); 2792 right_justify = zpool_prop_align_right(pl->pl_prop); 2793 } else { 2794 int i; 2795 2796 for (i = 0; pl->pl_user_prop[i] != '\0'; i++) 2797 headerbuf[i] = toupper(pl->pl_user_prop[i]); 2798 headerbuf[i] = '\0'; 2799 header = headerbuf; 2800 } 2801 2802 if (pl->pl_next == NULL && !right_justify) 2803 (void) printf("%s", header); 2804 else if (right_justify) 2805 (void) printf("%*s", width, header); 2806 else 2807 (void) printf("%-*s", width, header); 2808 2809 } 2810 2811 (void) printf("\n"); 2812} 2813 2814/* 2815 * Given a pool and a list of properties, print out all the properties according 2816 * to the described layout. 2817 */ 2818static void 2819print_pool(zpool_handle_t *zhp, list_cbdata_t *cb) 2820{ 2821 zprop_list_t *pl = cb->cb_proplist; 2822 boolean_t first = B_TRUE; 2823 char property[ZPOOL_MAXPROPLEN]; 2824 char *propstr; 2825 boolean_t right_justify; 2826 size_t width; 2827 2828 for (; pl != NULL; pl = pl->pl_next) { 2829 2830 width = pl->pl_width; 2831 if (first && cb->cb_verbose) { 2832 /* 2833 * Reset the width to accommodate the verbose listing 2834 * of devices. 2835 */ 2836 width = cb->cb_namewidth; 2837 } 2838 2839 if (!first) { 2840 if (cb->cb_scripted) 2841 (void) printf("\t"); 2842 else 2843 (void) printf(" "); 2844 } else { 2845 first = B_FALSE; 2846 } 2847 2848 right_justify = B_FALSE; 2849 if (pl->pl_prop != ZPROP_INVAL) { 2850 if (pl->pl_prop == ZPOOL_PROP_EXPANDSZ && 2851 zpool_get_prop_int(zhp, pl->pl_prop, NULL) == 0) 2852 propstr = "-"; 2853 else if (zpool_get_prop(zhp, pl->pl_prop, property, 2854 sizeof (property), NULL) != 0) 2855 propstr = "-"; 2856 else 2857 propstr = property; 2858 2859 right_justify = zpool_prop_align_right(pl->pl_prop); 2860 } else if ((zpool_prop_feature(pl->pl_user_prop) || 2861 zpool_prop_unsupported(pl->pl_user_prop)) && 2862 zpool_prop_get_feature(zhp, pl->pl_user_prop, property, 2863 sizeof (property)) == 0) { 2864 propstr = property; 2865 } else { 2866 propstr = "-"; 2867 } 2868 2869 2870 /* 2871 * If this is being called in scripted mode, or if this is the 2872 * last column and it is left-justified, don't include a width 2873 * format specifier. 2874 */ 2875 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify)) 2876 (void) printf("%s", propstr); 2877 else if (right_justify) 2878 (void) printf("%*s", width, propstr); 2879 else 2880 (void) printf("%-*s", width, propstr); 2881 } 2882 2883 (void) printf("\n"); 2884} 2885 2886static void 2887print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted) 2888{ 2889 char propval[64]; 2890 boolean_t fixed; 2891 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL); 2892 2893 zfs_nicenum(value, propval, sizeof (propval)); 2894 2895 if (prop == ZPOOL_PROP_EXPANDSZ && value == 0) 2896 (void) strlcpy(propval, "-", sizeof (propval)); 2897 2898 if (scripted) 2899 (void) printf("\t%s", propval); 2900 else 2901 (void) printf(" %*s", width, propval); 2902} 2903 2904void 2905print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, 2906 list_cbdata_t *cb, int depth) 2907{ 2908 nvlist_t **child; 2909 vdev_stat_t *vs; 2910 uint_t c, children; 2911 char *vname; 2912 boolean_t scripted = cb->cb_scripted; 2913 2914 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, 2915 (uint64_t **)&vs, &c) == 0); 2916 2917 if (name != NULL) { 2918 if (scripted) 2919 (void) printf("\t%s", name); 2920 else if (strlen(name) + depth > cb->cb_namewidth) 2921 (void) printf("%*s%s", depth, "", name); 2922 else 2923 (void) printf("%*s%s%*s", depth, "", name, 2924 (int)(cb->cb_namewidth - strlen(name) - depth), ""); 2925 2926 /* only toplevel vdevs have capacity stats */ 2927 if (vs->vs_space == 0) { 2928 if (scripted) 2929 (void) printf("\t-\t-\t-"); 2930 else 2931 (void) printf(" - - -"); 2932 } else { 2933 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, 2934 scripted); 2935 print_one_column(ZPOOL_PROP_CAPACITY, vs->vs_alloc, 2936 scripted); 2937 print_one_column(ZPOOL_PROP_FREE, 2938 vs->vs_space - vs->vs_alloc, scripted); 2939 } 2940 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, 2941 scripted); 2942 (void) printf("\n"); 2943 } 2944 2945 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 2946 &child, &children) != 0) 2947 return; 2948 2949 for (c = 0; c < children; c++) { 2950 uint64_t ishole = B_FALSE; 2951 2952 if (nvlist_lookup_uint64(child[c], 2953 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole) 2954 continue; 2955 2956 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); 2957 print_list_stats(zhp, vname, child[c], cb, depth + 2); 2958 free(vname); 2959 } 2960 2961 /* 2962 * Include level 2 ARC devices in iostat output 2963 */ 2964 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, 2965 &child, &children) != 0) 2966 return; 2967 2968 if (children > 0) { 2969 (void) printf("%-*s - - - - - " 2970 "-\n", cb->cb_namewidth, "cache"); 2971 for (c = 0; c < children; c++) { 2972 vname = zpool_vdev_name(g_zfs, zhp, child[c], 2973 B_FALSE); 2974 print_list_stats(zhp, vname, child[c], cb, depth + 2); 2975 free(vname); 2976 } 2977 } 2978} 2979 2980 2981/* 2982 * Generic callback function to list a pool. 2983 */ 2984int 2985list_callback(zpool_handle_t *zhp, void *data) 2986{ 2987 list_cbdata_t *cbp = data; 2988 nvlist_t *config; 2989 nvlist_t *nvroot; 2990 2991 config = zpool_get_config(zhp, NULL); 2992 2993 print_pool(zhp, cbp); 2994 if (!cbp->cb_verbose) 2995 return (0); 2996 2997 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 2998 &nvroot) == 0); 2999 print_list_stats(zhp, NULL, nvroot, cbp, 0); 3000 3001 return (0); 3002} 3003 3004/* 3005 * zpool list [-H] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]] 3006 * 3007 * -H Scripted mode. Don't display headers, and separate properties 3008 * by a single tab. 3009 * -o List of properties to display. Defaults to 3010 * "name,size,allocated,free,capacity,health,altroot" 3011 * -T Display a timestamp in date(1) or Unix format 3012 * 3013 * List all pools in the system, whether or not they're healthy. Output space 3014 * statistics for each one, as well as health status summary. 3015 */ 3016int 3017zpool_do_list(int argc, char **argv) 3018{ 3019 int c; 3020 int ret; 3021 list_cbdata_t cb = { 0 }; 3022 static char default_props[] = 3023 "name,size,allocated,free,capacity,dedupratio," 3024 "health,altroot"; 3025 char *props = default_props; 3026 unsigned long interval = 0, count = 0; 3027 zpool_list_t *list; 3028 boolean_t first = B_TRUE; 3029 3030 /* check options */ 3031 while ((c = getopt(argc, argv, ":Ho:T:v")) != -1) { 3032 switch (c) { 3033 case 'H': 3034 cb.cb_scripted = B_TRUE; 3035 break; 3036 case 'o': 3037 props = optarg; 3038 break; 3039 case 'T': 3040 get_timestamp_arg(*optarg); 3041 break; 3042 case 'v': 3043 cb.cb_verbose = B_TRUE; 3044 break; 3045 case ':': 3046 (void) fprintf(stderr, gettext("missing argument for " 3047 "'%c' option\n"), optopt); 3048 usage(B_FALSE); 3049 break; 3050 case '?': 3051 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3052 optopt); 3053 usage(B_FALSE); 3054 } 3055 } 3056 3057 argc -= optind; 3058 argv += optind; 3059 3060 get_interval_count(&argc, argv, &interval, &count); 3061 3062 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) 3063 usage(B_FALSE); 3064 3065 if ((list = pool_list_get(argc, argv, &cb.cb_proplist, &ret)) == NULL) 3066 return (1); 3067 3068 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) { 3069 (void) printf(gettext("no pools available\n")); 3070 zprop_free_list(cb.cb_proplist); 3071 return (0); 3072 } 3073 3074 for (;;) { 3075 pool_list_update(list); 3076 3077 if (pool_list_count(list) == 0) 3078 break; 3079 3080 cb.cb_namewidth = 0; 3081 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); 3082 3083 if (timestamp_fmt != NODATE) 3084 print_timestamp(timestamp_fmt); 3085 3086 if (!cb.cb_scripted && (first || cb.cb_verbose)) { 3087 print_header(&cb); 3088 first = B_FALSE; 3089 } 3090 ret = pool_list_iter(list, B_TRUE, list_callback, &cb); 3091 3092 if (interval == 0) 3093 break; 3094 3095 if (count != 0 && --count == 0) 3096 break; 3097 3098 (void) sleep(interval); 3099 } 3100 3101 zprop_free_list(cb.cb_proplist); 3102 return (ret); 3103} 3104 3105static nvlist_t * 3106zpool_get_vdev_by_name(nvlist_t *nv, char *name) 3107{ 3108 nvlist_t **child; 3109 uint_t c, children; 3110 nvlist_t *match; 3111 char *path; 3112 3113 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, 3114 &child, &children) != 0) { 3115 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); 3116 if (strncmp(name, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) 3117 name += sizeof(_PATH_DEV) - 1; 3118 if (strncmp(path, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) 3119 path += sizeof(_PATH_DEV) - 1; 3120 if (strcmp(name, path) == 0) 3121 return (nv); 3122 return (NULL); 3123 } 3124 3125 for (c = 0; c < children; c++) 3126 if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL) 3127 return (match); 3128 3129 return (NULL); 3130} 3131 3132static int 3133zpool_do_attach_or_replace(int argc, char **argv, int replacing) 3134{ 3135 boolean_t force = B_FALSE; 3136 int c; 3137 nvlist_t *nvroot; 3138 char *poolname, *old_disk, *new_disk; 3139 zpool_handle_t *zhp; 3140 int ret; 3141 3142 /* check options */ 3143 while ((c = getopt(argc, argv, "f")) != -1) { 3144 switch (c) { 3145 case 'f': 3146 force = B_TRUE; 3147 break; 3148 case '?': 3149 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3150 optopt); 3151 usage(B_FALSE); 3152 } 3153 } 3154 3155 argc -= optind; 3156 argv += optind; 3157 3158 /* get pool name and check number of arguments */ 3159 if (argc < 1) { 3160 (void) fprintf(stderr, gettext("missing pool name argument\n")); 3161 usage(B_FALSE); 3162 } 3163 3164 poolname = argv[0]; 3165 3166 if (argc < 2) { 3167 (void) fprintf(stderr, 3168 gettext("missing <device> specification\n")); 3169 usage(B_FALSE); 3170 } 3171 3172 old_disk = argv[1]; 3173 3174 if (argc < 3) { 3175 if (!replacing) { 3176 (void) fprintf(stderr, 3177 gettext("missing <new_device> specification\n")); 3178 usage(B_FALSE); 3179 } 3180 new_disk = old_disk; 3181 argc -= 1; 3182 argv += 1; 3183 } else { 3184 new_disk = argv[2]; 3185 argc -= 2; 3186 argv += 2; 3187 } 3188 3189 if (argc > 1) { 3190 (void) fprintf(stderr, gettext("too many arguments\n")); 3191 usage(B_FALSE); 3192 } 3193 3194 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3195 return (1); 3196 3197 if (zpool_get_config(zhp, NULL) == NULL) { 3198 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), 3199 poolname); 3200 zpool_close(zhp); 3201 return (1); 3202 } 3203 3204 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE, 3205 argc, argv); 3206 if (nvroot == NULL) { 3207 zpool_close(zhp); 3208 return (1); 3209 } 3210 3211 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); 3212 3213 nvlist_free(nvroot); 3214 zpool_close(zhp); 3215 3216 return (ret); 3217} 3218 3219/* 3220 * zpool replace [-f] <pool> <device> <new_device> 3221 * 3222 * -f Force attach, even if <new_device> appears to be in use. 3223 * 3224 * Replace <device> with <new_device>. 3225 */ 3226/* ARGSUSED */ 3227int 3228zpool_do_replace(int argc, char **argv) 3229{ 3230 return (zpool_do_attach_or_replace(argc, argv, B_TRUE)); 3231} 3232 3233/* 3234 * zpool attach [-f] <pool> <device> <new_device> 3235 * 3236 * -f Force attach, even if <new_device> appears to be in use. 3237 * 3238 * Attach <new_device> to the mirror containing <device>. If <device> is not 3239 * part of a mirror, then <device> will be transformed into a mirror of 3240 * <device> and <new_device>. In either case, <new_device> will begin life 3241 * with a DTL of [0, now], and will immediately begin to resilver itself. 3242 */ 3243int 3244zpool_do_attach(int argc, char **argv) 3245{ 3246 return (zpool_do_attach_or_replace(argc, argv, B_FALSE)); 3247} 3248 3249/* 3250 * zpool detach [-f] <pool> <device> 3251 * 3252 * -f Force detach of <device>, even if DTLs argue against it 3253 * (not supported yet) 3254 * 3255 * Detach a device from a mirror. The operation will be refused if <device> 3256 * is the last device in the mirror, or if the DTLs indicate that this device 3257 * has the only valid copy of some data. 3258 */ 3259/* ARGSUSED */ 3260int 3261zpool_do_detach(int argc, char **argv) 3262{ 3263 int c; 3264 char *poolname, *path; 3265 zpool_handle_t *zhp; 3266 int ret; 3267 3268 /* check options */ 3269 while ((c = getopt(argc, argv, "f")) != -1) { 3270 switch (c) { 3271 case 'f': 3272 case '?': 3273 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3274 optopt); 3275 usage(B_FALSE); 3276 } 3277 } 3278 3279 argc -= optind; 3280 argv += optind; 3281 3282 /* get pool name and check number of arguments */ 3283 if (argc < 1) { 3284 (void) fprintf(stderr, gettext("missing pool name argument\n")); 3285 usage(B_FALSE); 3286 } 3287 3288 if (argc < 2) { 3289 (void) fprintf(stderr, 3290 gettext("missing <device> specification\n")); 3291 usage(B_FALSE); 3292 } 3293 3294 poolname = argv[0]; 3295 path = argv[1]; 3296 3297 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3298 return (1); 3299 3300 ret = zpool_vdev_detach(zhp, path); 3301 3302 zpool_close(zhp); 3303 3304 return (ret); 3305} 3306 3307/* 3308 * zpool split [-n] [-o prop=val] ... 3309 * [-o mntopt] ... 3310 * [-R altroot] <pool> <newpool> [<device> ...] 3311 * 3312 * -n Do not split the pool, but display the resulting layout if 3313 * it were to be split. 3314 * -o Set property=value, or set mount options. 3315 * -R Mount the split-off pool under an alternate root. 3316 * 3317 * Splits the named pool and gives it the new pool name. Devices to be split 3318 * off may be listed, provided that no more than one device is specified 3319 * per top-level vdev mirror. The newly split pool is left in an exported 3320 * state unless -R is specified. 3321 * 3322 * Restrictions: the top-level of the pool pool must only be made up of 3323 * mirrors; all devices in the pool must be healthy; no device may be 3324 * undergoing a resilvering operation. 3325 */ 3326int 3327zpool_do_split(int argc, char **argv) 3328{ 3329 char *srcpool, *newpool, *propval; 3330 char *mntopts = NULL; 3331 splitflags_t flags; 3332 int c, ret = 0; 3333 zpool_handle_t *zhp; 3334 nvlist_t *config, *props = NULL; 3335 3336 flags.dryrun = B_FALSE; 3337 flags.import = B_FALSE; 3338 3339 /* check options */ 3340 while ((c = getopt(argc, argv, ":R:no:")) != -1) { 3341 switch (c) { 3342 case 'R': 3343 flags.import = B_TRUE; 3344 if (add_prop_list( 3345 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg, 3346 &props, B_TRUE) != 0) { 3347 if (props) 3348 nvlist_free(props); 3349 usage(B_FALSE); 3350 } 3351 break; 3352 case 'n': 3353 flags.dryrun = B_TRUE; 3354 break; 3355 case 'o': 3356 if ((propval = strchr(optarg, '=')) != NULL) { 3357 *propval = '\0'; 3358 propval++; 3359 if (add_prop_list(optarg, propval, 3360 &props, B_TRUE) != 0) { 3361 if (props) 3362 nvlist_free(props); 3363 usage(B_FALSE); 3364 } 3365 } else { 3366 mntopts = optarg; 3367 } 3368 break; 3369 case ':': 3370 (void) fprintf(stderr, gettext("missing argument for " 3371 "'%c' option\n"), optopt); 3372 usage(B_FALSE); 3373 break; 3374 case '?': 3375 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3376 optopt); 3377 usage(B_FALSE); 3378 break; 3379 } 3380 } 3381 3382 if (!flags.import && mntopts != NULL) { 3383 (void) fprintf(stderr, gettext("setting mntopts is only " 3384 "valid when importing the pool\n")); 3385 usage(B_FALSE); 3386 } 3387 3388 argc -= optind; 3389 argv += optind; 3390 3391 if (argc < 1) { 3392 (void) fprintf(stderr, gettext("Missing pool name\n")); 3393 usage(B_FALSE); 3394 } 3395 if (argc < 2) { 3396 (void) fprintf(stderr, gettext("Missing new pool name\n")); 3397 usage(B_FALSE); 3398 } 3399 3400 srcpool = argv[0]; 3401 newpool = argv[1]; 3402 3403 argc -= 2; 3404 argv += 2; 3405 3406 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) 3407 return (1); 3408 3409 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv); 3410 if (config == NULL) { 3411 ret = 1; 3412 } else { 3413 if (flags.dryrun) { 3414 (void) printf(gettext("would create '%s' with the " 3415 "following layout:\n\n"), newpool); 3416 print_vdev_tree(NULL, newpool, config, 0, B_FALSE); 3417 } 3418 nvlist_free(config); 3419 } 3420 3421 zpool_close(zhp); 3422 3423 if (ret != 0 || flags.dryrun || !flags.import) 3424 return (ret); 3425 3426 /* 3427 * The split was successful. Now we need to open the new 3428 * pool and import it. 3429 */ 3430 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) 3431 return (1); 3432 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && 3433 zpool_enable_datasets(zhp, mntopts, 0) != 0) { 3434 ret = 1; 3435 (void) fprintf(stderr, gettext("Split was successful, but " 3436 "the datasets could not all be mounted\n")); 3437 (void) fprintf(stderr, gettext("Try doing '%s' with a " 3438 "different altroot\n"), "zpool import"); 3439 } 3440 zpool_close(zhp); 3441 3442 return (ret); 3443} 3444 3445 3446 3447/* 3448 * zpool online <pool> <device> ... 3449 */ 3450int 3451zpool_do_online(int argc, char **argv) 3452{ 3453 int c, i; 3454 char *poolname; 3455 zpool_handle_t *zhp; 3456 int ret = 0; 3457 vdev_state_t newstate; 3458 int flags = 0; 3459 3460 /* check options */ 3461 while ((c = getopt(argc, argv, "et")) != -1) { 3462 switch (c) { 3463 case 'e': 3464 flags |= ZFS_ONLINE_EXPAND; 3465 break; 3466 case 't': 3467 case '?': 3468 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3469 optopt); 3470 usage(B_FALSE); 3471 } 3472 } 3473 3474 argc -= optind; 3475 argv += optind; 3476 3477 /* get pool name and check number of arguments */ 3478 if (argc < 1) { 3479 (void) fprintf(stderr, gettext("missing pool name\n")); 3480 usage(B_FALSE); 3481 } 3482 if (argc < 2) { 3483 (void) fprintf(stderr, gettext("missing device name\n")); 3484 usage(B_FALSE); 3485 } 3486 3487 poolname = argv[0]; 3488 3489 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3490 return (1); 3491 3492 for (i = 1; i < argc; i++) { 3493 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) { 3494 if (newstate != VDEV_STATE_HEALTHY) { 3495 (void) printf(gettext("warning: device '%s' " 3496 "onlined, but remains in faulted state\n"), 3497 argv[i]); 3498 if (newstate == VDEV_STATE_FAULTED) 3499 (void) printf(gettext("use 'zpool " 3500 "clear' to restore a faulted " 3501 "device\n")); 3502 else 3503 (void) printf(gettext("use 'zpool " 3504 "replace' to replace devices " 3505 "that are no longer present\n")); 3506 } 3507 } else { 3508 ret = 1; 3509 } 3510 } 3511 3512 zpool_close(zhp); 3513 3514 return (ret); 3515} 3516 3517/* 3518 * zpool offline [-ft] <pool> <device> ... 3519 * 3520 * -f Force the device into the offline state, even if doing 3521 * so would appear to compromise pool availability. 3522 * (not supported yet) 3523 * 3524 * -t Only take the device off-line temporarily. The offline 3525 * state will not be persistent across reboots. 3526 */ 3527/* ARGSUSED */ 3528int 3529zpool_do_offline(int argc, char **argv) 3530{ 3531 int c, i; 3532 char *poolname; 3533 zpool_handle_t *zhp; 3534 int ret = 0; 3535 boolean_t istmp = B_FALSE; 3536 3537 /* check options */ 3538 while ((c = getopt(argc, argv, "ft")) != -1) { 3539 switch (c) { 3540 case 't': 3541 istmp = B_TRUE; 3542 break; 3543 case 'f': 3544 case '?': 3545 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3546 optopt); 3547 usage(B_FALSE); 3548 } 3549 } 3550 3551 argc -= optind; 3552 argv += optind; 3553 3554 /* get pool name and check number of arguments */ 3555 if (argc < 1) { 3556 (void) fprintf(stderr, gettext("missing pool name\n")); 3557 usage(B_FALSE); 3558 } 3559 if (argc < 2) { 3560 (void) fprintf(stderr, gettext("missing device name\n")); 3561 usage(B_FALSE); 3562 } 3563 3564 poolname = argv[0]; 3565 3566 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3567 return (1); 3568 3569 for (i = 1; i < argc; i++) { 3570 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0) 3571 ret = 1; 3572 } 3573 3574 zpool_close(zhp); 3575 3576 return (ret); 3577} 3578 3579/* 3580 * zpool clear <pool> [device] 3581 * 3582 * Clear all errors associated with a pool or a particular device. 3583 */ 3584int 3585zpool_do_clear(int argc, char **argv) 3586{ 3587 int c; 3588 int ret = 0; 3589 boolean_t dryrun = B_FALSE; 3590 boolean_t do_rewind = B_FALSE; 3591 boolean_t xtreme_rewind = B_FALSE; 3592 uint32_t rewind_policy = ZPOOL_NO_REWIND; 3593 nvlist_t *policy = NULL; 3594 zpool_handle_t *zhp; 3595 char *pool, *device; 3596 3597 /* check options */ 3598 while ((c = getopt(argc, argv, "FnX")) != -1) { 3599 switch (c) { 3600 case 'F': 3601 do_rewind = B_TRUE; 3602 break; 3603 case 'n': 3604 dryrun = B_TRUE; 3605 break; 3606 case 'X': 3607 xtreme_rewind = B_TRUE; 3608 break; 3609 case '?': 3610 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3611 optopt); 3612 usage(B_FALSE); 3613 } 3614 } 3615 3616 argc -= optind; 3617 argv += optind; 3618 3619 if (argc < 1) { 3620 (void) fprintf(stderr, gettext("missing pool name\n")); 3621 usage(B_FALSE); 3622 } 3623 3624 if (argc > 2) { 3625 (void) fprintf(stderr, gettext("too many arguments\n")); 3626 usage(B_FALSE); 3627 } 3628 3629 if ((dryrun || xtreme_rewind) && !do_rewind) { 3630 (void) fprintf(stderr, 3631 gettext("-n or -X only meaningful with -F\n")); 3632 usage(B_FALSE); 3633 } 3634 if (dryrun) 3635 rewind_policy = ZPOOL_TRY_REWIND; 3636 else if (do_rewind) 3637 rewind_policy = ZPOOL_DO_REWIND; 3638 if (xtreme_rewind) 3639 rewind_policy |= ZPOOL_EXTREME_REWIND; 3640 3641 /* In future, further rewind policy choices can be passed along here */ 3642 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || 3643 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0) 3644 return (1); 3645 3646 pool = argv[0]; 3647 device = argc == 2 ? argv[1] : NULL; 3648 3649 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) { 3650 nvlist_free(policy); 3651 return (1); 3652 } 3653 3654 if (zpool_clear(zhp, device, policy) != 0) 3655 ret = 1; 3656 3657 zpool_close(zhp); 3658 3659 nvlist_free(policy); 3660 3661 return (ret); 3662} 3663 3664/* 3665 * zpool reguid <pool> 3666 */ 3667int 3668zpool_do_reguid(int argc, char **argv) 3669{ 3670 int c; 3671 char *poolname; 3672 zpool_handle_t *zhp; 3673 int ret = 0; 3674 3675 /* check options */ 3676 while ((c = getopt(argc, argv, "")) != -1) { 3677 switch (c) { 3678 case '?': 3679 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3680 optopt); 3681 usage(B_FALSE); 3682 } 3683 } 3684 3685 argc -= optind; 3686 argv += optind; 3687 3688 /* get pool name and check number of arguments */ 3689 if (argc < 1) { 3690 (void) fprintf(stderr, gettext("missing pool name\n")); 3691 usage(B_FALSE); 3692 } 3693 3694 if (argc > 1) { 3695 (void) fprintf(stderr, gettext("too many arguments\n")); 3696 usage(B_FALSE); 3697 } 3698 3699 poolname = argv[0]; 3700 if ((zhp = zpool_open(g_zfs, poolname)) == NULL) 3701 return (1); 3702 3703 ret = zpool_reguid(zhp); 3704 3705 zpool_close(zhp); 3706 return (ret); 3707} 3708 3709 3710/* 3711 * zpool reopen <pool> 3712 * 3713 * Reopen the pool so that the kernel can update the sizes of all vdevs. 3714 * 3715 * NOTE: This command is currently undocumented. If the command is ever 3716 * exposed then the appropriate usage() messages will need to be made. 3717 */ 3718int 3719zpool_do_reopen(int argc, char **argv) 3720{ 3721 int ret = 0; 3722 zpool_handle_t *zhp; 3723 char *pool; 3724 3725 argc--; 3726 argv++; 3727 3728 if (argc != 1) 3729 return (2); 3730 3731 pool = argv[0]; 3732 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) 3733 return (1); 3734 3735 ret = zpool_reopen(zhp); 3736 zpool_close(zhp); 3737 return (ret); 3738} 3739 3740typedef struct scrub_cbdata { 3741 int cb_type; 3742 int cb_argc; 3743 char **cb_argv; 3744} scrub_cbdata_t; 3745 3746int 3747scrub_callback(zpool_handle_t *zhp, void *data) 3748{ 3749 scrub_cbdata_t *cb = data; 3750 int err; 3751 3752 /* 3753 * Ignore faulted pools. 3754 */ 3755 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) { 3756 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is " 3757 "currently unavailable\n"), zpool_get_name(zhp)); 3758 return (1); 3759 } 3760 3761 err = zpool_scan(zhp, cb->cb_type); 3762 3763 return (err != 0); 3764} 3765 3766/* 3767 * zpool scrub [-s] <pool> ... 3768 * 3769 * -s Stop. Stops any in-progress scrub. 3770 */ 3771int 3772zpool_do_scrub(int argc, char **argv) 3773{ 3774 int c; 3775 scrub_cbdata_t cb; 3776 3777 cb.cb_type = POOL_SCAN_SCRUB; 3778 3779 /* check options */ 3780 while ((c = getopt(argc, argv, "s")) != -1) { 3781 switch (c) { 3782 case 's': 3783 cb.cb_type = POOL_SCAN_NONE; 3784 break; 3785 case '?': 3786 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3787 optopt); 3788 usage(B_FALSE); 3789 } 3790 } 3791 3792 cb.cb_argc = argc; 3793 cb.cb_argv = argv; 3794 argc -= optind; 3795 argv += optind; 3796 3797 if (argc < 1) { 3798 (void) fprintf(stderr, gettext("missing pool name argument\n")); 3799 usage(B_FALSE); 3800 } 3801 3802 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb)); 3803} 3804 3805typedef struct status_cbdata { 3806 int cb_count; 3807 boolean_t cb_allpools; 3808 boolean_t cb_verbose; 3809 boolean_t cb_explain; 3810 boolean_t cb_first; 3811 boolean_t cb_dedup_stats; 3812} status_cbdata_t; 3813 3814/* 3815 * Print out detailed scrub status. 3816 */ 3817void 3818print_scan_status(pool_scan_stat_t *ps) 3819{ 3820 time_t start, end; 3821 uint64_t elapsed, mins_left, hours_left; 3822 uint64_t pass_exam, examined, total; 3823 uint_t rate; 3824 double fraction_done; 3825 char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7]; 3826 3827 (void) printf(gettext(" scan: ")); 3828 3829 /* If there's never been a scan, there's not much to say. */ 3830 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE || 3831 ps->pss_func >= POOL_SCAN_FUNCS) { 3832 (void) printf(gettext("none requested\n")); 3833 return; 3834 } 3835 3836 start = ps->pss_start_time; 3837 end = ps->pss_end_time; 3838 zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf)); 3839 3840 assert(ps->pss_func == POOL_SCAN_SCRUB || 3841 ps->pss_func == POOL_SCAN_RESILVER); 3842 /* 3843 * Scan is finished or canceled. 3844 */ 3845 if (ps->pss_state == DSS_FINISHED) { 3846 uint64_t minutes_taken = (end - start) / 60; 3847 char *fmt; 3848 3849 if (ps->pss_func == POOL_SCAN_SCRUB) { 3850 fmt = gettext("scrub repaired %s in %lluh%um with " 3851 "%llu errors on %s"); 3852 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 3853 fmt = gettext("resilvered %s in %lluh%um with " 3854 "%llu errors on %s"); 3855 } 3856 /* LINTED */ 3857 (void) printf(fmt, processed_buf, 3858 (u_longlong_t)(minutes_taken / 60), 3859 (uint_t)(minutes_taken % 60), 3860 (u_longlong_t)ps->pss_errors, 3861 ctime((time_t *)&end)); 3862 return; 3863 } else if (ps->pss_state == DSS_CANCELED) { 3864 if (ps->pss_func == POOL_SCAN_SCRUB) { 3865 (void) printf(gettext("scrub canceled on %s"), 3866 ctime(&end)); 3867 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 3868 (void) printf(gettext("resilver canceled on %s"), 3869 ctime(&end)); 3870 } 3871 return; 3872 } 3873 3874 assert(ps->pss_state == DSS_SCANNING); 3875 3876 /* 3877 * Scan is in progress. 3878 */ 3879 if (ps->pss_func == POOL_SCAN_SCRUB) { 3880 (void) printf(gettext("scrub in progress since %s"), 3881 ctime(&start)); 3882 } else if (ps->pss_func == POOL_SCAN_RESILVER) { 3883 (void) printf(gettext("resilver in progress since %s"), 3884 ctime(&start)); 3885 } 3886 3887 examined = ps->pss_examined ? ps->pss_examined : 1; 3888 total = ps->pss_to_examine; 3889 fraction_done = (double)examined / total; 3890 3891 /* elapsed time for this pass */ 3892 elapsed = time(NULL) - ps->pss_pass_start; 3893 elapsed = elapsed ? elapsed : 1; 3894 pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1; 3895 rate = pass_exam / elapsed; 3896 rate = rate ? rate : 1; 3897 mins_left = ((total - examined) / rate) / 60; 3898 hours_left = mins_left / 60; 3899 3900 zfs_nicenum(examined, examined_buf, sizeof (examined_buf)); 3901 zfs_nicenum(total, total_buf, sizeof (total_buf)); 3902 zfs_nicenum(rate, rate_buf, sizeof (rate_buf)); 3903 3904 /* 3905 * do not print estimated time if hours_left is more than 30 days 3906 */ 3907 (void) printf(gettext(" %s scanned out of %s at %s/s"), 3908 examined_buf, total_buf, rate_buf); 3909 if (hours_left < (30 * 24)) { 3910 (void) printf(gettext(", %lluh%um to go\n"), 3911 (u_longlong_t)hours_left, (uint_t)(mins_left % 60)); 3912 } else { 3913 (void) printf(gettext( 3914 ", (scan is slow, no estimated time)\n")); 3915 } 3916 3917 if (ps->pss_func == POOL_SCAN_RESILVER) { 3918 (void) printf(gettext(" %s resilvered, %.2f%% done\n"), 3919 processed_buf, 100 * fraction_done); 3920 } else if (ps->pss_func == POOL_SCAN_SCRUB) { 3921 (void) printf(gettext(" %s repaired, %.2f%% done\n"), 3922 processed_buf, 100 * fraction_done); 3923 } 3924} 3925 3926static void 3927print_error_log(zpool_handle_t *zhp) 3928{ 3929 nvlist_t *nverrlist = NULL; 3930 nvpair_t *elem; 3931 char *pathname; 3932 size_t len = MAXPATHLEN * 2; 3933 3934 if (zpool_get_errlog(zhp, &nverrlist) != 0) { 3935 (void) printf("errors: List of errors unavailable " 3936 "(insufficient privileges)\n"); 3937 return; 3938 } 3939 3940 (void) printf("errors: Permanent errors have been " 3941 "detected in the following files:\n\n"); 3942 3943 pathname = safe_malloc(len); 3944 elem = NULL; 3945 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { 3946 nvlist_t *nv; 3947 uint64_t dsobj, obj; 3948 3949 verify(nvpair_value_nvlist(elem, &nv) == 0); 3950 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, 3951 &dsobj) == 0); 3952 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, 3953 &obj) == 0); 3954 zpool_obj_to_path(zhp, dsobj, obj, pathname, len); 3955 (void) printf("%7s %s\n", "", pathname); 3956 } 3957 free(pathname); 3958 nvlist_free(nverrlist); 3959} 3960 3961static void 3962print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares, 3963 int namewidth) 3964{ 3965 uint_t i; 3966 char *name; 3967 3968 if (nspares == 0) 3969 return; 3970 3971 (void) printf(gettext("\tspares\n")); 3972 3973 for (i = 0; i < nspares; i++) { 3974 name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE); 3975 print_status_config(zhp, name, spares[i], 3976 namewidth, 2, B_TRUE); 3977 free(name); 3978 } 3979} 3980 3981static void 3982print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache, 3983 int namewidth) 3984{ 3985 uint_t i; 3986 char *name; 3987 3988 if (nl2cache == 0) 3989 return; 3990 3991 (void) printf(gettext("\tcache\n")); 3992 3993 for (i = 0; i < nl2cache; i++) { 3994 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE); 3995 print_status_config(zhp, name, l2cache[i], 3996 namewidth, 2, B_FALSE); 3997 free(name); 3998 } 3999} 4000 4001static void 4002print_dedup_stats(nvlist_t *config) 4003{ 4004 ddt_histogram_t *ddh; 4005 ddt_stat_t *dds; 4006 ddt_object_t *ddo; 4007 uint_t c; 4008 4009 /* 4010 * If the pool was faulted then we may not have been able to 4011 * obtain the config. Otherwise, if we have anything in the dedup 4012 * table continue processing the stats. 4013 */ 4014 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS, 4015 (uint64_t **)&ddo, &c) != 0) 4016 return; 4017 4018 (void) printf("\n"); 4019 (void) printf(gettext(" dedup: ")); 4020 if (ddo->ddo_count == 0) { 4021 (void) printf(gettext("no DDT entries\n")); 4022 return; 4023 } 4024 4025 (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n", 4026 (u_longlong_t)ddo->ddo_count, 4027 (u_longlong_t)ddo->ddo_dspace, 4028 (u_longlong_t)ddo->ddo_mspace); 4029 4030 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS, 4031 (uint64_t **)&dds, &c) == 0); 4032 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM, 4033 (uint64_t **)&ddh, &c) == 0); 4034 zpool_dump_ddt(dds, ddh); 4035} 4036 4037/* 4038 * Display a summary of pool status. Displays a summary such as: 4039 * 4040 * pool: tank 4041 * status: DEGRADED 4042 * reason: One or more devices ... 4043 * see: http://illumos.org/msg/ZFS-xxxx-01 4044 * config: 4045 * mirror DEGRADED 4046 * c1t0d0 OK 4047 * c2t0d0 UNAVAIL 4048 * 4049 * When given the '-v' option, we print out the complete config. If the '-e' 4050 * option is specified, then we print out error rate information as well. 4051 */ 4052int 4053status_callback(zpool_handle_t *zhp, void *data) 4054{ 4055 status_cbdata_t *cbp = data; 4056 nvlist_t *config, *nvroot; 4057 char *msgid; 4058 int reason; 4059 const char *health; 4060 uint_t c; 4061 vdev_stat_t *vs; 4062 4063 config = zpool_get_config(zhp, NULL); 4064 reason = zpool_get_status(zhp, &msgid); 4065 4066 cbp->cb_count++; 4067 4068 /* 4069 * If we were given 'zpool status -x', only report those pools with 4070 * problems. 4071 */ 4072 if (cbp->cb_explain && 4073 (reason == ZPOOL_STATUS_OK || 4074 reason == ZPOOL_STATUS_VERSION_OLDER || 4075 reason == ZPOOL_STATUS_FEAT_DISABLED)) { 4076 if (!cbp->cb_allpools) { 4077 (void) printf(gettext("pool '%s' is healthy\n"), 4078 zpool_get_name(zhp)); 4079 if (cbp->cb_first) 4080 cbp->cb_first = B_FALSE; 4081 } 4082 return (0); 4083 } 4084 4085 if (cbp->cb_first) 4086 cbp->cb_first = B_FALSE; 4087 else 4088 (void) printf("\n"); 4089 4090 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, 4091 &nvroot) == 0); 4092 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, 4093 (uint64_t **)&vs, &c) == 0); 4094 health = zpool_state_to_name(vs->vs_state, vs->vs_aux); 4095 4096 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp)); 4097 (void) printf(gettext(" state: %s\n"), health); 4098 4099 switch (reason) { 4100 case ZPOOL_STATUS_MISSING_DEV_R: 4101 (void) printf(gettext("status: One or more devices could not " 4102 "be opened. Sufficient replicas exist for\n\tthe pool to " 4103 "continue functioning in a degraded state.\n")); 4104 (void) printf(gettext("action: Attach the missing device and " 4105 "online it using 'zpool online'.\n")); 4106 break; 4107 4108 case ZPOOL_STATUS_MISSING_DEV_NR: 4109 (void) printf(gettext("status: One or more devices could not " 4110 "be opened. There are insufficient\n\treplicas for the " 4111 "pool to continue functioning.\n")); 4112 (void) printf(gettext("action: Attach the missing device and " 4113 "online it using 'zpool online'.\n")); 4114 break; 4115 4116 case ZPOOL_STATUS_CORRUPT_LABEL_R: 4117 (void) printf(gettext("status: One or more devices could not " 4118 "be used because the label is missing or\n\tinvalid. " 4119 "Sufficient replicas exist for the pool to continue\n\t" 4120 "functioning in a degraded state.\n")); 4121 (void) printf(gettext("action: Replace the device using " 4122 "'zpool replace'.\n")); 4123 break; 4124 4125 case ZPOOL_STATUS_CORRUPT_LABEL_NR: 4126 (void) printf(gettext("status: One or more devices could not " 4127 "be used because the label is missing \n\tor invalid. " 4128 "There are insufficient replicas for the pool to " 4129 "continue\n\tfunctioning.\n")); 4130 zpool_explain_recover(zpool_get_handle(zhp), 4131 zpool_get_name(zhp), reason, config); 4132 break; 4133 4134 case ZPOOL_STATUS_FAILING_DEV: 4135 (void) printf(gettext("status: One or more devices has " 4136 "experienced an unrecoverable error. An\n\tattempt was " 4137 "made to correct the error. Applications are " 4138 "unaffected.\n")); 4139 (void) printf(gettext("action: Determine if the device needs " 4140 "to be replaced, and clear the errors\n\tusing " 4141 "'zpool clear' or replace the device with 'zpool " 4142 "replace'.\n")); 4143 break; 4144 4145 case ZPOOL_STATUS_OFFLINE_DEV: 4146 (void) printf(gettext("status: One or more devices has " 4147 "been taken offline by the administrator.\n\tSufficient " 4148 "replicas exist for the pool to continue functioning in " 4149 "a\n\tdegraded state.\n")); 4150 (void) printf(gettext("action: Online the device using " 4151 "'zpool online' or replace the device with\n\t'zpool " 4152 "replace'.\n")); 4153 break; 4154 4155 case ZPOOL_STATUS_REMOVED_DEV: 4156 (void) printf(gettext("status: One or more devices has " 4157 "been removed by the administrator.\n\tSufficient " 4158 "replicas exist for the pool to continue functioning in " 4159 "a\n\tdegraded state.\n")); 4160 (void) printf(gettext("action: Online the device using " 4161 "'zpool online' or replace the device with\n\t'zpool " 4162 "replace'.\n")); 4163 break; 4164 4165 case ZPOOL_STATUS_RESILVERING: 4166 (void) printf(gettext("status: One or more devices is " 4167 "currently being resilvered. The pool will\n\tcontinue " 4168 "to function, possibly in a degraded state.\n")); 4169 (void) printf(gettext("action: Wait for the resilver to " 4170 "complete.\n")); 4171 break; 4172 4173 case ZPOOL_STATUS_CORRUPT_DATA: 4174 (void) printf(gettext("status: One or more devices has " 4175 "experienced an error resulting in data\n\tcorruption. " 4176 "Applications may be affected.\n")); 4177 (void) printf(gettext("action: Restore the file in question " 4178 "if possible. Otherwise restore the\n\tentire pool from " 4179 "backup.\n")); 4180 break; 4181 4182 case ZPOOL_STATUS_CORRUPT_POOL: 4183 (void) printf(gettext("status: The pool metadata is corrupted " 4184 "and the pool cannot be opened.\n")); 4185 zpool_explain_recover(zpool_get_handle(zhp), 4186 zpool_get_name(zhp), reason, config); 4187 break; 4188 4189 case ZPOOL_STATUS_VERSION_OLDER: 4190 (void) printf(gettext("status: The pool is formatted using a " 4191 "legacy on-disk format. The pool can\n\tstill be used, " 4192 "but some features are unavailable.\n")); 4193 (void) printf(gettext("action: Upgrade the pool using 'zpool " 4194 "upgrade'. Once this is done, the\n\tpool will no longer " 4195 "be accessible on software that does not support feature\n" 4196 "\tflags.\n")); 4197 break; 4198 4199 case ZPOOL_STATUS_VERSION_NEWER: 4200 (void) printf(gettext("status: The pool has been upgraded to a " 4201 "newer, incompatible on-disk version.\n\tThe pool cannot " 4202 "be accessed on this system.\n")); 4203 (void) printf(gettext("action: Access the pool from a system " 4204 "running more recent software, or\n\trestore the pool from " 4205 "backup.\n")); 4206 break; 4207 4208 case ZPOOL_STATUS_FEAT_DISABLED: 4209 (void) printf(gettext("status: Some supported features are not " 4210 "enabled on the pool. The pool can\n\tstill be used, but " 4211 "some features are unavailable.\n")); 4212 (void) printf(gettext("action: Enable all features using " 4213 "'zpool upgrade'. Once this is done,\n\tthe pool may no " 4214 "longer be accessible by software that does not support\n\t" 4215 "the features. See zpool-features(7) for details.\n")); 4216 break; 4217 4218 case ZPOOL_STATUS_UNSUP_FEAT_READ: 4219 (void) printf(gettext("status: The pool cannot be accessed on " 4220 "this system because it uses the\n\tfollowing feature(s) " 4221 "not supported on this system:\n")); 4222 zpool_print_unsup_feat(config); 4223 (void) printf("\n"); 4224 (void) printf(gettext("action: Access the pool from a system " 4225 "that supports the required feature(s),\n\tor restore the " 4226 "pool from backup.\n")); 4227 break; 4228 4229 case ZPOOL_STATUS_UNSUP_FEAT_WRITE: 4230 (void) printf(gettext("status: The pool can only be accessed " 4231 "in read-only mode on this system. It\n\tcannot be " 4232 "accessed in read-write mode because it uses the " 4233 "following\n\tfeature(s) not supported on this system:\n")); 4234 zpool_print_unsup_feat(config); 4235 (void) printf("\n"); 4236 (void) printf(gettext("action: The pool cannot be accessed in " 4237 "read-write mode. Import the pool with\n" 4238 "\t\"-o readonly=on\", access the pool from a system that " 4239 "supports the\n\trequired feature(s), or restore the " 4240 "pool from backup.\n")); 4241 break; 4242 4243 case ZPOOL_STATUS_FAULTED_DEV_R: 4244 (void) printf(gettext("status: One or more devices are " 4245 "faulted in response to persistent errors.\n\tSufficient " 4246 "replicas exist for the pool to continue functioning " 4247 "in a\n\tdegraded state.\n")); 4248 (void) printf(gettext("action: Replace the faulted device, " 4249 "or use 'zpool clear' to mark the device\n\trepaired.\n")); 4250 break; 4251 4252 case ZPOOL_STATUS_FAULTED_DEV_NR: 4253 (void) printf(gettext("status: One or more devices are " 4254 "faulted in response to persistent errors. There are " 4255 "insufficient replicas for the pool to\n\tcontinue " 4256 "functioning.\n")); 4257 (void) printf(gettext("action: Destroy and re-create the pool " 4258 "from a backup source. Manually marking the device\n" 4259 "\trepaired using 'zpool clear' may allow some data " 4260 "to be recovered.\n")); 4261 break; 4262 4263 case ZPOOL_STATUS_IO_FAILURE_WAIT: 4264 case ZPOOL_STATUS_IO_FAILURE_CONTINUE: 4265 (void) printf(gettext("status: One or more devices are " 4266 "faulted in response to IO failures.\n")); 4267 (void) printf(gettext("action: Make sure the affected devices " 4268 "are connected, then run 'zpool clear'.\n")); 4269 break; 4270 4271 case ZPOOL_STATUS_BAD_LOG: 4272 (void) printf(gettext("status: An intent log record " 4273 "could not be read.\n" 4274 "\tWaiting for adminstrator intervention to fix the " 4275 "faulted pool.\n")); 4276 (void) printf(gettext("action: Either restore the affected " 4277 "device(s) and run 'zpool online',\n" 4278 "\tor ignore the intent log records by running " 4279 "'zpool clear'.\n")); 4280 break; 4281 4282 case ZPOOL_STATUS_NON_NATIVE_ASHIFT: 4283 (void) printf(gettext("status: One or more devices are " 4284 "configured to use a non-native block size.\n" 4285 "\tExpect reduced performance.\n")); 4286 (void) printf(gettext("action: Replace affected devices with " 4287 "devices that support the\n\tconfigured block size, or " 4288 "migrate data to a properly configured\n\tpool.\n")); 4289 break; 4290 4291 default: 4292 /* 4293 * The remaining errors can't actually be generated, yet. 4294 */ 4295 assert(reason == ZPOOL_STATUS_OK); 4296 } 4297 4298 if (msgid != NULL) 4299 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), 4300 msgid); 4301 4302 if (config != NULL) { 4303 int namewidth; 4304 uint64_t nerr; 4305 nvlist_t **spares, **l2cache; 4306 uint_t nspares, nl2cache; 4307 pool_scan_stat_t *ps = NULL; 4308 4309 (void) nvlist_lookup_uint64_array(nvroot, 4310 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c); 4311 print_scan_status(ps); 4312 4313 namewidth = max_width(zhp, nvroot, 0, 0); 4314 if (namewidth < 10) 4315 namewidth = 10; 4316 4317 (void) printf(gettext("config:\n\n")); 4318 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth, 4319 "NAME", "STATE", "READ", "WRITE", "CKSUM"); 4320 print_status_config(zhp, zpool_get_name(zhp), nvroot, 4321 namewidth, 0, B_FALSE); 4322 4323 if (num_logs(nvroot) > 0) 4324 print_logs(zhp, nvroot, namewidth, B_TRUE); 4325 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, 4326 &l2cache, &nl2cache) == 0) 4327 print_l2cache(zhp, l2cache, nl2cache, namewidth); 4328 4329 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, 4330 &spares, &nspares) == 0) 4331 print_spares(zhp, spares, nspares, namewidth); 4332 4333 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, 4334 &nerr) == 0) { 4335 nvlist_t *nverrlist = NULL; 4336 4337 /* 4338 * If the approximate error count is small, get a 4339 * precise count by fetching the entire log and 4340 * uniquifying the results. 4341 */ 4342 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose && 4343 zpool_get_errlog(zhp, &nverrlist) == 0) { 4344 nvpair_t *elem; 4345 4346 elem = NULL; 4347 nerr = 0; 4348 while ((elem = nvlist_next_nvpair(nverrlist, 4349 elem)) != NULL) { 4350 nerr++; 4351 } 4352 } 4353 nvlist_free(nverrlist); 4354 4355 (void) printf("\n"); 4356 4357 if (nerr == 0) 4358 (void) printf(gettext("errors: No known data " 4359 "errors\n")); 4360 else if (!cbp->cb_verbose) 4361 (void) printf(gettext("errors: %llu data " 4362 "errors, use '-v' for a list\n"), 4363 (u_longlong_t)nerr); 4364 else 4365 print_error_log(zhp); 4366 } 4367 4368 if (cbp->cb_dedup_stats) 4369 print_dedup_stats(config); 4370 } else { 4371 (void) printf(gettext("config: The configuration cannot be " 4372 "determined.\n")); 4373 } 4374 4375 return (0); 4376} 4377 4378/* 4379 * zpool status [-vx] [-T d|u] [pool] ... [interval [count]] 4380 * 4381 * -v Display complete error logs 4382 * -x Display only pools with potential problems 4383 * -D Display dedup status (undocumented) 4384 * -T Display a timestamp in date(1) or Unix format 4385 * 4386 * Describes the health status of all pools or some subset. 4387 */ 4388int 4389zpool_do_status(int argc, char **argv) 4390{ 4391 int c; 4392 int ret; 4393 unsigned long interval = 0, count = 0; 4394 status_cbdata_t cb = { 0 }; 4395 4396 /* check options */ 4397 while ((c = getopt(argc, argv, "vxDT:")) != -1) { 4398 switch (c) { 4399 case 'v': 4400 cb.cb_verbose = B_TRUE; 4401 break; 4402 case 'x': 4403 cb.cb_explain = B_TRUE; 4404 break; 4405 case 'D': 4406 cb.cb_dedup_stats = B_TRUE; 4407 break; 4408 case 'T': 4409 get_timestamp_arg(*optarg); 4410 break; 4411 case '?': 4412 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4413 optopt); 4414 usage(B_FALSE); 4415 } 4416 } 4417 4418 argc -= optind; 4419 argv += optind; 4420 4421 get_interval_count(&argc, argv, &interval, &count); 4422 4423 if (argc == 0) 4424 cb.cb_allpools = B_TRUE; 4425 4426 cb.cb_first = B_TRUE; 4427 4428 for (;;) { 4429 if (timestamp_fmt != NODATE) 4430 print_timestamp(timestamp_fmt); 4431 4432 ret = for_each_pool(argc, argv, B_TRUE, NULL, 4433 status_callback, &cb); 4434 4435 if (argc == 0 && cb.cb_count == 0) 4436 (void) printf(gettext("no pools available\n")); 4437 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools) 4438 (void) printf(gettext("all pools are healthy\n")); 4439 4440 if (ret != 0) 4441 return (ret); 4442 4443 if (interval == 0) 4444 break; 4445 4446 if (count != 0 && --count == 0) 4447 break; 4448 4449 (void) sleep(interval); 4450 } 4451 4452 return (0); 4453} 4454 4455typedef struct upgrade_cbdata { 4456 int cb_first; 4457 char cb_poolname[ZPOOL_MAXNAMELEN]; 4458 int cb_argc; 4459 uint64_t cb_version; 4460 char **cb_argv; 4461} upgrade_cbdata_t; 4462 4463#ifdef __FreeBSD__ 4464static int 4465is_root_pool(zpool_handle_t *zhp) 4466{ 4467 static struct statfs sfs; 4468 static char *poolname = NULL; 4469 static boolean_t stated = B_FALSE; 4470 char *slash; 4471 4472 if (!stated) { 4473 stated = B_TRUE; 4474 if (statfs("/", &sfs) == -1) { 4475 (void) fprintf(stderr, 4476 "Unable to stat root file system: %s.\n", 4477 strerror(errno)); 4478 return (0); 4479 } 4480 if (strcmp(sfs.f_fstypename, "zfs") != 0) 4481 return (0); 4482 poolname = sfs.f_mntfromname; 4483 if ((slash = strchr(poolname, '/')) != NULL) 4484 *slash = '\0'; 4485 } 4486 return (poolname != NULL && strcmp(poolname, zpool_get_name(zhp)) == 0); 4487} 4488 4489static void 4490root_pool_upgrade_check(zpool_handle_t *zhp, char *poolname, int size) { 4491 4492 if (poolname[0] == '\0' && is_root_pool(zhp)) 4493 (void) strlcpy(poolname, zpool_get_name(zhp), size); 4494} 4495#endif /* FreeBSD */ 4496 4497static int 4498upgrade_version(zpool_handle_t *zhp, uint64_t version) 4499{ 4500 int ret; 4501 nvlist_t *config; 4502 uint64_t oldversion; 4503 4504 config = zpool_get_config(zhp, NULL); 4505 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 4506 &oldversion) == 0); 4507 4508 assert(SPA_VERSION_IS_SUPPORTED(oldversion)); 4509 assert(oldversion < version); 4510 4511 ret = zpool_upgrade(zhp, version); 4512 if (ret != 0) 4513 return (ret); 4514 4515 if (version >= SPA_VERSION_FEATURES) { 4516 (void) printf(gettext("Successfully upgraded " 4517 "'%s' from version %llu to feature flags.\n"), 4518 zpool_get_name(zhp), oldversion); 4519 } else { 4520 (void) printf(gettext("Successfully upgraded " 4521 "'%s' from version %llu to version %llu.\n"), 4522 zpool_get_name(zhp), oldversion, version); 4523 } 4524 4525 return (0); 4526} 4527 4528static int 4529upgrade_enable_all(zpool_handle_t *zhp, int *countp) 4530{ 4531 int i, ret, count; 4532 boolean_t firstff = B_TRUE; 4533 nvlist_t *enabled = zpool_get_features(zhp); 4534 4535 count = 0; 4536 for (i = 0; i < SPA_FEATURES; i++) { 4537 const char *fname = spa_feature_table[i].fi_uname; 4538 const char *fguid = spa_feature_table[i].fi_guid; 4539 if (!nvlist_exists(enabled, fguid)) { 4540 char *propname; 4541 verify(-1 != asprintf(&propname, "feature@%s", fname)); 4542 ret = zpool_set_prop(zhp, propname, 4543 ZFS_FEATURE_ENABLED); 4544 if (ret != 0) { 4545 free(propname); 4546 return (ret); 4547 } 4548 count++; 4549 4550 if (firstff) { 4551 (void) printf(gettext("Enabled the " 4552 "following features on '%s':\n"), 4553 zpool_get_name(zhp)); 4554 firstff = B_FALSE; 4555 } 4556 (void) printf(gettext(" %s\n"), fname); 4557 free(propname); 4558 } 4559 } 4560 4561 if (countp != NULL) 4562 *countp = count; 4563 return (0); 4564} 4565 4566static int 4567upgrade_cb(zpool_handle_t *zhp, void *arg) 4568{ 4569 upgrade_cbdata_t *cbp = arg; 4570 nvlist_t *config; 4571 uint64_t version; 4572 boolean_t printnl = B_FALSE; 4573 int ret; 4574 4575 config = zpool_get_config(zhp, NULL); 4576 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 4577 &version) == 0); 4578 4579 assert(SPA_VERSION_IS_SUPPORTED(version)); 4580 4581 if (version < cbp->cb_version) { 4582 cbp->cb_first = B_FALSE; 4583 ret = upgrade_version(zhp, cbp->cb_version); 4584 if (ret != 0) 4585 return (ret); 4586#ifdef __FreeBSD__ 4587 root_pool_upgrade_check(zhp, cbp->cb_poolname, 4588 sizeof(cbp->cb_poolname)); 4589#endif /* ___FreeBSD__ */ 4590 printnl = B_TRUE; 4591 4592#ifdef illumos 4593 /* 4594 * If they did "zpool upgrade -a", then we could 4595 * be doing ioctls to different pools. We need 4596 * to log this history once to each pool, and bypass 4597 * the normal history logging that happens in main(). 4598 */ 4599 (void) zpool_log_history(g_zfs, history_str); 4600 log_history = B_FALSE; 4601#endif 4602 } 4603 4604 if (cbp->cb_version >= SPA_VERSION_FEATURES) { 4605 int count; 4606 ret = upgrade_enable_all(zhp, &count); 4607 if (ret != 0) 4608 return (ret); 4609 4610 if (count > 0) { 4611 cbp->cb_first = B_FALSE; 4612 printnl = B_TRUE; 4613 /* 4614 * If they did "zpool upgrade -a", then we could 4615 * be doing ioctls to different pools. We need 4616 * to log this history once to each pool, and bypass 4617 * the normal history logging that happens in main(). 4618 */ 4619 (void) zpool_log_history(g_zfs, history_str); 4620 log_history = B_FALSE; 4621 } 4622 } 4623 4624 if (printnl) { 4625 (void) printf(gettext("\n")); 4626 } 4627 4628 return (0); 4629} 4630 4631static int 4632upgrade_list_older_cb(zpool_handle_t *zhp, void *arg) 4633{ 4634 upgrade_cbdata_t *cbp = arg; 4635 nvlist_t *config; 4636 uint64_t version; 4637 4638 config = zpool_get_config(zhp, NULL); 4639 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 4640 &version) == 0); 4641 4642 assert(SPA_VERSION_IS_SUPPORTED(version)); 4643 4644 if (version < SPA_VERSION_FEATURES) { 4645 if (cbp->cb_first) { 4646 (void) printf(gettext("The following pools are " 4647 "formatted with legacy version numbers and can\n" 4648 "be upgraded to use feature flags. After " 4649 "being upgraded, these pools\nwill no " 4650 "longer be accessible by software that does not " 4651 "support feature\nflags.\n\n")); 4652 (void) printf(gettext("VER POOL\n")); 4653 (void) printf(gettext("--- ------------\n")); 4654 cbp->cb_first = B_FALSE; 4655 } 4656 4657 (void) printf("%2llu %s\n", (u_longlong_t)version, 4658 zpool_get_name(zhp)); 4659 } 4660 4661 return (0); 4662} 4663 4664static int 4665upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg) 4666{ 4667 upgrade_cbdata_t *cbp = arg; 4668 nvlist_t *config; 4669 uint64_t version; 4670 4671 config = zpool_get_config(zhp, NULL); 4672 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, 4673 &version) == 0); 4674 4675 if (version >= SPA_VERSION_FEATURES) { 4676 int i; 4677 boolean_t poolfirst = B_TRUE; 4678 nvlist_t *enabled = zpool_get_features(zhp); 4679 4680 for (i = 0; i < SPA_FEATURES; i++) { 4681 const char *fguid = spa_feature_table[i].fi_guid; 4682 const char *fname = spa_feature_table[i].fi_uname; 4683 if (!nvlist_exists(enabled, fguid)) { 4684 if (cbp->cb_first) { 4685 (void) printf(gettext("\nSome " 4686 "supported features are not " 4687 "enabled on the following pools. " 4688 "Once a\nfeature is enabled the " 4689 "pool may become incompatible with " 4690 "software\nthat does not support " 4691 "the feature. See " 4692 "zpool-features(7) for " 4693 "details.\n\n")); 4694 (void) printf(gettext("POOL " 4695 "FEATURE\n")); 4696 (void) printf(gettext("------" 4697 "---------\n")); 4698 cbp->cb_first = B_FALSE; 4699 } 4700 4701 if (poolfirst) { 4702 (void) printf(gettext("%s\n"), 4703 zpool_get_name(zhp)); 4704 poolfirst = B_FALSE; 4705 } 4706 4707 (void) printf(gettext(" %s\n"), fname); 4708 } 4709 } 4710 } 4711 4712 return (0); 4713} 4714 4715/* ARGSUSED */ 4716static int 4717upgrade_one(zpool_handle_t *zhp, void *data) 4718{ 4719 boolean_t printnl = B_FALSE; 4720 upgrade_cbdata_t *cbp = data; 4721 uint64_t cur_version; 4722 int ret; 4723 4724 if (strcmp("log", zpool_get_name(zhp)) == 0) { 4725 (void) printf(gettext("'log' is now a reserved word\n" 4726 "Pool 'log' must be renamed using export and import" 4727 " to upgrade.\n")); 4728 return (1); 4729 } 4730 4731 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL); 4732 if (cur_version > cbp->cb_version) { 4733 (void) printf(gettext("Pool '%s' is already formatted " 4734 "using more current version '%llu'.\n\n"), 4735 zpool_get_name(zhp), cur_version); 4736 return (0); 4737 } 4738 4739 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) { 4740 (void) printf(gettext("Pool '%s' is already formatted " 4741 "using version %llu.\n\n"), zpool_get_name(zhp), 4742 cbp->cb_version); 4743 return (0); 4744 } 4745 4746 if (cur_version != cbp->cb_version) { 4747 printnl = B_TRUE; 4748 ret = upgrade_version(zhp, cbp->cb_version); 4749 if (ret != 0) 4750 return (ret); 4751#ifdef __FreeBSD__ 4752 root_pool_upgrade_check(zhp, cbp->cb_poolname, 4753 sizeof(cbp->cb_poolname)); 4754#endif /* ___FreeBSD__ */ 4755 } 4756 4757 if (cbp->cb_version >= SPA_VERSION_FEATURES) { 4758 int count = 0; 4759 ret = upgrade_enable_all(zhp, &count); 4760 if (ret != 0) 4761 return (ret); 4762 4763 if (count != 0) { 4764 printnl = B_TRUE; 4765#ifdef __FreeBSD__ 4766 root_pool_upgrade_check(zhp, cbp->cb_poolname, 4767 sizeof(cbp->cb_poolname)); 4768#endif /* __FreeBSD __*/ 4769 } else if (cur_version == SPA_VERSION) { 4770 (void) printf(gettext("Pool '%s' already has all " 4771 "supported features enabled.\n"), 4772 zpool_get_name(zhp)); 4773 } 4774 } 4775 4776 if (printnl) { 4777 (void) printf(gettext("\n")); 4778 } 4779 4780 return (0); 4781} 4782 4783/* 4784 * zpool upgrade 4785 * zpool upgrade -v 4786 * zpool upgrade [-V version] <-a | pool ...> 4787 * 4788 * With no arguments, display downrev'd ZFS pool available for upgrade. 4789 * Individual pools can be upgraded by specifying the pool, and '-a' will 4790 * upgrade all pools. 4791 */ 4792int 4793zpool_do_upgrade(int argc, char **argv) 4794{ 4795 int c; 4796 upgrade_cbdata_t cb = { 0 }; 4797 int ret = 0; 4798 boolean_t showversions = B_FALSE; 4799 boolean_t upgradeall = B_FALSE; 4800 char *end; 4801 4802 4803 /* check options */ 4804 while ((c = getopt(argc, argv, ":avV:")) != -1) { 4805 switch (c) { 4806 case 'a': 4807 upgradeall = B_TRUE; 4808 break; 4809 case 'v': 4810 showversions = B_TRUE; 4811 break; 4812 case 'V': 4813 cb.cb_version = strtoll(optarg, &end, 10); 4814 if (*end != '\0' || 4815 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) { 4816 (void) fprintf(stderr, 4817 gettext("invalid version '%s'\n"), optarg); 4818 usage(B_FALSE); 4819 } 4820 break; 4821 case ':': 4822 (void) fprintf(stderr, gettext("missing argument for " 4823 "'%c' option\n"), optopt); 4824 usage(B_FALSE); 4825 break; 4826 case '?': 4827 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 4828 optopt); 4829 usage(B_FALSE); 4830 } 4831 } 4832 4833 cb.cb_argc = argc; 4834 cb.cb_argv = argv; 4835 argc -= optind; 4836 argv += optind; 4837 4838 if (cb.cb_version == 0) { 4839 cb.cb_version = SPA_VERSION; 4840 } else if (!upgradeall && argc == 0) { 4841 (void) fprintf(stderr, gettext("-V option is " 4842 "incompatible with other arguments\n")); 4843 usage(B_FALSE); 4844 } 4845 4846 if (showversions) { 4847 if (upgradeall || argc != 0) { 4848 (void) fprintf(stderr, gettext("-v option is " 4849 "incompatible with other arguments\n")); 4850 usage(B_FALSE); 4851 } 4852 } else if (upgradeall) { 4853 if (argc != 0) { 4854 (void) fprintf(stderr, gettext("-a option should not " 4855 "be used along with a pool name\n")); 4856 usage(B_FALSE); 4857 } 4858 } 4859 4860 (void) printf(gettext("This system supports ZFS pool feature " 4861 "flags.\n\n")); 4862 if (showversions) { 4863 int i; 4864 4865 (void) printf(gettext("The following features are " 4866 "supported:\n\n")); 4867 (void) printf(gettext("FEAT DESCRIPTION\n")); 4868 (void) printf("----------------------------------------------" 4869 "---------------\n"); 4870 for (i = 0; i < SPA_FEATURES; i++) { 4871 zfeature_info_t *fi = &spa_feature_table[i]; 4872 const char *ro = fi->fi_can_readonly ? 4873 " (read-only compatible)" : ""; 4874 4875 (void) printf("%-37s%s\n", fi->fi_uname, ro); 4876 (void) printf(" %s\n", fi->fi_desc); 4877 } 4878 (void) printf("\n"); 4879 4880 (void) printf(gettext("The following legacy versions are also " 4881 "supported:\n\n")); 4882 (void) printf(gettext("VER DESCRIPTION\n")); 4883 (void) printf("--- -----------------------------------------" 4884 "---------------\n"); 4885 (void) printf(gettext(" 1 Initial ZFS version\n")); 4886 (void) printf(gettext(" 2 Ditto blocks " 4887 "(replicated metadata)\n")); 4888 (void) printf(gettext(" 3 Hot spares and double parity " 4889 "RAID-Z\n")); 4890 (void) printf(gettext(" 4 zpool history\n")); 4891 (void) printf(gettext(" 5 Compression using the gzip " 4892 "algorithm\n")); 4893 (void) printf(gettext(" 6 bootfs pool property\n")); 4894 (void) printf(gettext(" 7 Separate intent log devices\n")); 4895 (void) printf(gettext(" 8 Delegated administration\n")); 4896 (void) printf(gettext(" 9 refquota and refreservation " 4897 "properties\n")); 4898 (void) printf(gettext(" 10 Cache devices\n")); 4899 (void) printf(gettext(" 11 Improved scrub performance\n")); 4900 (void) printf(gettext(" 12 Snapshot properties\n")); 4901 (void) printf(gettext(" 13 snapused property\n")); 4902 (void) printf(gettext(" 14 passthrough-x aclinherit\n")); 4903 (void) printf(gettext(" 15 user/group space accounting\n")); 4904 (void) printf(gettext(" 16 stmf property support\n")); 4905 (void) printf(gettext(" 17 Triple-parity RAID-Z\n")); 4906 (void) printf(gettext(" 18 Snapshot user holds\n")); 4907 (void) printf(gettext(" 19 Log device removal\n")); 4908 (void) printf(gettext(" 20 Compression using zle " 4909 "(zero-length encoding)\n")); 4910 (void) printf(gettext(" 21 Deduplication\n")); 4911 (void) printf(gettext(" 22 Received properties\n")); 4912 (void) printf(gettext(" 23 Slim ZIL\n")); 4913 (void) printf(gettext(" 24 System attributes\n")); 4914 (void) printf(gettext(" 25 Improved scrub stats\n")); 4915 (void) printf(gettext(" 26 Improved snapshot deletion " 4916 "performance\n")); 4917 (void) printf(gettext(" 27 Improved snapshot creation " 4918 "performance\n")); 4919 (void) printf(gettext(" 28 Multiple vdev replacements\n")); 4920 (void) printf(gettext("\nFor more information on a particular " 4921 "version, including supported releases,\n")); 4922 (void) printf(gettext("see the ZFS Administration Guide.\n\n")); 4923 } else if (argc == 0 && upgradeall) { 4924 cb.cb_first = B_TRUE; 4925 ret = zpool_iter(g_zfs, upgrade_cb, &cb); 4926 if (ret == 0 && cb.cb_first) { 4927 if (cb.cb_version == SPA_VERSION) { 4928 (void) printf(gettext("All pools are already " 4929 "formatted using feature flags.\n\n")); 4930 (void) printf(gettext("Every feature flags " 4931 "pool already has all supported features " 4932 "enabled.\n")); 4933 } else { 4934 (void) printf(gettext("All pools are already " 4935 "formatted with version %llu or higher.\n"), 4936 cb.cb_version); 4937 } 4938 } 4939 } else if (argc == 0) { 4940 cb.cb_first = B_TRUE; 4941 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb); 4942 assert(ret == 0); 4943 4944 if (cb.cb_first) { 4945 (void) printf(gettext("All pools are formatted " 4946 "using feature flags.\n\n")); 4947 } else { 4948 (void) printf(gettext("\nUse 'zpool upgrade -v' " 4949 "for a list of available legacy versions.\n")); 4950 } 4951 4952 cb.cb_first = B_TRUE; 4953 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb); 4954 assert(ret == 0); 4955 4956 if (cb.cb_first) { 4957 (void) printf(gettext("Every feature flags pool has " 4958 "all supported features enabled.\n")); 4959 } else { 4960 (void) printf(gettext("\n")); 4961 } 4962 } else { 4963 ret = for_each_pool(argc, argv, B_FALSE, NULL, 4964 upgrade_one, &cb); 4965 } 4966 4967 if (cb.cb_poolname[0] != '\0') { 4968 (void) printf( 4969 "If you boot from pool '%s', don't forget to update boot code.\n" 4970 "Assuming you use GPT partitioning and da0 is your boot disk\n" 4971 "the following command will do it:\n" 4972 "\n" 4973 "\tgpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0\n\n", 4974 cb.cb_poolname); 4975 } 4976 4977 return (ret); 4978} 4979 4980typedef struct hist_cbdata { 4981 boolean_t first; 4982 boolean_t longfmt; 4983 boolean_t internal; 4984} hist_cbdata_t; 4985 4986/* 4987 * Print out the command history for a specific pool. 4988 */ 4989static int 4990get_history_one(zpool_handle_t *zhp, void *data) 4991{ 4992 nvlist_t *nvhis; 4993 nvlist_t **records; 4994 uint_t numrecords; 4995 int ret, i; 4996 hist_cbdata_t *cb = (hist_cbdata_t *)data; 4997 4998 cb->first = B_FALSE; 4999 5000 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); 5001 5002 if ((ret = zpool_get_history(zhp, &nvhis)) != 0) 5003 return (ret); 5004 5005 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, 5006 &records, &numrecords) == 0); 5007 for (i = 0; i < numrecords; i++) { 5008 nvlist_t *rec = records[i]; 5009 char tbuf[30] = ""; 5010 5011 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) { 5012 time_t tsec; 5013 struct tm t; 5014 5015 tsec = fnvlist_lookup_uint64(records[i], 5016 ZPOOL_HIST_TIME); 5017 (void) localtime_r(&tsec, &t); 5018 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); 5019 } 5020 5021 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) { 5022 (void) printf("%s %s", tbuf, 5023 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD)); 5024 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) { 5025 int ievent = 5026 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT); 5027 if (!cb->internal) 5028 continue; 5029 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) { 5030 (void) printf("%s unrecognized record:\n", 5031 tbuf); 5032 dump_nvlist(rec, 4); 5033 continue; 5034 } 5035 (void) printf("%s [internal %s txg:%lld] %s", tbuf, 5036 zfs_history_event_names[ievent], 5037 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 5038 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR)); 5039 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) { 5040 if (!cb->internal) 5041 continue; 5042 (void) printf("%s [txg:%lld] %s", tbuf, 5043 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), 5044 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME)); 5045 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) { 5046 (void) printf(" %s (%llu)", 5047 fnvlist_lookup_string(rec, 5048 ZPOOL_HIST_DSNAME), 5049 fnvlist_lookup_uint64(rec, 5050 ZPOOL_HIST_DSID)); 5051 } 5052 (void) printf(" %s", fnvlist_lookup_string(rec, 5053 ZPOOL_HIST_INT_STR)); 5054 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) { 5055 if (!cb->internal) 5056 continue; 5057 (void) printf("%s ioctl %s\n", tbuf, 5058 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL)); 5059 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) { 5060 (void) printf(" input:\n"); 5061 dump_nvlist(fnvlist_lookup_nvlist(rec, 5062 ZPOOL_HIST_INPUT_NVL), 8); 5063 } 5064 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) { 5065 (void) printf(" output:\n"); 5066 dump_nvlist(fnvlist_lookup_nvlist(rec, 5067 ZPOOL_HIST_OUTPUT_NVL), 8); 5068 } 5069 } else { 5070 if (!cb->internal) 5071 continue; 5072 (void) printf("%s unrecognized record:\n", tbuf); 5073 dump_nvlist(rec, 4); 5074 } 5075 5076 if (!cb->longfmt) { 5077 (void) printf("\n"); 5078 continue; 5079 } 5080 (void) printf(" ["); 5081 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) { 5082 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO); 5083 struct passwd *pwd = getpwuid(who); 5084 (void) printf("user %d ", (int)who); 5085 if (pwd != NULL) 5086 (void) printf("(%s) ", pwd->pw_name); 5087 } 5088 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) { 5089 (void) printf("on %s", 5090 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST)); 5091 } 5092 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) { 5093 (void) printf(":%s", 5094 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE)); 5095 } 5096 (void) printf("]"); 5097 (void) printf("\n"); 5098 } 5099 (void) printf("\n"); 5100 nvlist_free(nvhis); 5101 5102 return (ret); 5103} 5104 5105/* 5106 * zpool history <pool> 5107 * 5108 * Displays the history of commands that modified pools. 5109 */ 5110int 5111zpool_do_history(int argc, char **argv) 5112{ 5113 hist_cbdata_t cbdata = { 0 }; 5114 int ret; 5115 int c; 5116 5117 cbdata.first = B_TRUE; 5118 /* check options */ 5119 while ((c = getopt(argc, argv, "li")) != -1) { 5120 switch (c) { 5121 case 'l': 5122 cbdata.longfmt = B_TRUE; 5123 break; 5124 case 'i': 5125 cbdata.internal = B_TRUE; 5126 break; 5127 case '?': 5128 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5129 optopt); 5130 usage(B_FALSE); 5131 } 5132 } 5133 argc -= optind; 5134 argv += optind; 5135 5136 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one, 5137 &cbdata); 5138 5139 if (argc == 0 && cbdata.first == B_TRUE) { 5140 (void) printf(gettext("no pools available\n")); 5141 return (0); 5142 } 5143 5144 return (ret); 5145} 5146 5147static int 5148get_callback(zpool_handle_t *zhp, void *data) 5149{ 5150 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data; 5151 char value[MAXNAMELEN]; 5152 zprop_source_t srctype; 5153 zprop_list_t *pl; 5154 5155 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 5156 5157 /* 5158 * Skip the special fake placeholder. This will also skip 5159 * over the name property when 'all' is specified. 5160 */ 5161 if (pl->pl_prop == ZPOOL_PROP_NAME && 5162 pl == cbp->cb_proplist) 5163 continue; 5164 5165 if (pl->pl_prop == ZPROP_INVAL && 5166 (zpool_prop_feature(pl->pl_user_prop) || 5167 zpool_prop_unsupported(pl->pl_user_prop))) { 5168 srctype = ZPROP_SRC_LOCAL; 5169 5170 if (zpool_prop_get_feature(zhp, pl->pl_user_prop, 5171 value, sizeof (value)) == 0) { 5172 zprop_print_one_property(zpool_get_name(zhp), 5173 cbp, pl->pl_user_prop, value, srctype, 5174 NULL, NULL); 5175 } 5176 } else { 5177 if (zpool_get_prop(zhp, pl->pl_prop, value, 5178 sizeof (value), &srctype) != 0) 5179 continue; 5180 5181 zprop_print_one_property(zpool_get_name(zhp), cbp, 5182 zpool_prop_to_name(pl->pl_prop), value, srctype, 5183 NULL, NULL); 5184 } 5185 } 5186 return (0); 5187} 5188 5189int 5190zpool_do_get(int argc, char **argv) 5191{ 5192 zprop_get_cbdata_t cb = { 0 }; 5193 zprop_list_t fake_name = { 0 }; 5194 int ret; 5195 5196 if (argc < 2) { 5197 (void) fprintf(stderr, gettext("missing property " 5198 "argument\n")); 5199 usage(B_FALSE); 5200 } 5201 5202 cb.cb_first = B_TRUE; 5203 cb.cb_sources = ZPROP_SRC_ALL; 5204 cb.cb_columns[0] = GET_COL_NAME; 5205 cb.cb_columns[1] = GET_COL_PROPERTY; 5206 cb.cb_columns[2] = GET_COL_VALUE; 5207 cb.cb_columns[3] = GET_COL_SOURCE; 5208 cb.cb_type = ZFS_TYPE_POOL; 5209 5210 if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist, 5211 ZFS_TYPE_POOL) != 0) 5212 usage(B_FALSE); 5213 5214 if (cb.cb_proplist != NULL) { 5215 fake_name.pl_prop = ZPOOL_PROP_NAME; 5216 fake_name.pl_width = strlen(gettext("NAME")); 5217 fake_name.pl_next = cb.cb_proplist; 5218 cb.cb_proplist = &fake_name; 5219 } 5220 5221 ret = for_each_pool(argc - 2, argv + 2, B_TRUE, &cb.cb_proplist, 5222 get_callback, &cb); 5223 5224 if (cb.cb_proplist == &fake_name) 5225 zprop_free_list(fake_name.pl_next); 5226 else 5227 zprop_free_list(cb.cb_proplist); 5228 5229 return (ret); 5230} 5231 5232typedef struct set_cbdata { 5233 char *cb_propname; 5234 char *cb_value; 5235 boolean_t cb_any_successful; 5236} set_cbdata_t; 5237 5238int 5239set_callback(zpool_handle_t *zhp, void *data) 5240{ 5241 int error; 5242 set_cbdata_t *cb = (set_cbdata_t *)data; 5243 5244 error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value); 5245 5246 if (!error) 5247 cb->cb_any_successful = B_TRUE; 5248 5249 return (error); 5250} 5251 5252int 5253zpool_do_set(int argc, char **argv) 5254{ 5255 set_cbdata_t cb = { 0 }; 5256 int error; 5257 5258 if (argc > 1 && argv[1][0] == '-') { 5259 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 5260 argv[1][1]); 5261 usage(B_FALSE); 5262 } 5263 5264 if (argc < 2) { 5265 (void) fprintf(stderr, gettext("missing property=value " 5266 "argument\n")); 5267 usage(B_FALSE); 5268 } 5269 5270 if (argc < 3) { 5271 (void) fprintf(stderr, gettext("missing pool name\n")); 5272 usage(B_FALSE); 5273 } 5274 5275 if (argc > 3) { 5276 (void) fprintf(stderr, gettext("too many pool names\n")); 5277 usage(B_FALSE); 5278 } 5279 5280 cb.cb_propname = argv[1]; 5281 cb.cb_value = strchr(cb.cb_propname, '='); 5282 if (cb.cb_value == NULL) { 5283 (void) fprintf(stderr, gettext("missing value in " 5284 "property=value argument\n")); 5285 usage(B_FALSE); 5286 } 5287 5288 *(cb.cb_value) = '\0'; 5289 cb.cb_value++; 5290 5291 error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, 5292 set_callback, &cb); 5293 5294 return (error); 5295} 5296 5297static int 5298find_command_idx(char *command, int *idx) 5299{ 5300 int i; 5301 5302 for (i = 0; i < NCOMMAND; i++) { 5303 if (command_table[i].name == NULL) 5304 continue; 5305 5306 if (strcmp(command, command_table[i].name) == 0) { 5307 *idx = i; 5308 return (0); 5309 } 5310 } 5311 return (1); 5312} 5313 5314int 5315main(int argc, char **argv) 5316{ 5317 int ret; 5318 int i; 5319 char *cmdname; 5320 5321 (void) setlocale(LC_ALL, ""); 5322 (void) textdomain(TEXT_DOMAIN); 5323 5324 if ((g_zfs = libzfs_init()) == NULL) { 5325 (void) fprintf(stderr, gettext("internal error: failed to " 5326 "initialize ZFS library\n")); 5327 return (1); 5328 } 5329 5330 libzfs_print_on_error(g_zfs, B_TRUE); 5331 5332 opterr = 0; 5333 5334 /* 5335 * Make sure the user has specified some command. 5336 */ 5337 if (argc < 2) { 5338 (void) fprintf(stderr, gettext("missing command\n")); 5339 usage(B_FALSE); 5340 } 5341 5342 cmdname = argv[1]; 5343 5344 /* 5345 * Special case '-?' 5346 */ 5347 if (strcmp(cmdname, "-?") == 0) 5348 usage(B_TRUE); 5349 5350 zfs_save_arguments(argc, argv, history_str, sizeof (history_str)); 5351 5352 /* 5353 * Run the appropriate command. 5354 */ 5355 if (find_command_idx(cmdname, &i) == 0) { 5356 current_command = &command_table[i]; 5357 ret = command_table[i].func(argc - 1, argv + 1); 5358 } else if (strchr(cmdname, '=')) { 5359 verify(find_command_idx("set", &i) == 0); 5360 current_command = &command_table[i]; 5361 ret = command_table[i].func(argc, argv); 5362 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) { 5363 /* 5364 * 'freeze' is a vile debugging abomination, so we treat 5365 * it as such. 5366 */ 5367 zfs_cmd_t zc = { 0 }; 5368 (void) strlcpy(zc.zc_name, argv[2], sizeof (zc.zc_name)); 5369 return (!!zfs_ioctl(g_zfs, ZFS_IOC_POOL_FREEZE, &zc)); 5370 } else { 5371 (void) fprintf(stderr, gettext("unrecognized " 5372 "command '%s'\n"), cmdname); 5373 usage(B_FALSE); 5374 } 5375 5376 if (ret == 0 && log_history) 5377 (void) zpool_log_history(g_zfs, history_str); 5378 5379 libzfs_fini(g_zfs); 5380 5381 /* 5382 * The 'ZFS_ABORT' environment variable causes us to dump core on exit 5383 * for the purposes of running ::findleaks. 5384 */ 5385 if (getenv("ZFS_ABORT") != NULL) { 5386 (void) printf("dumping core by request\n"); 5387 abort(); 5388 } 5389 5390 return (ret); 5391} 5392