diff options
Diffstat (limited to 'cmd/zpool/zpool_main.c')
-rw-r--r-- | cmd/zpool/zpool_main.c | 775 |
1 files changed, 162 insertions, 613 deletions
diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index 3ecdbec9684d..8aa985b1a552 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -21,9 +21,6 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. - * Copyright (c) 2012 by Frederik Wessels. All rights reserved. */ #include <assert.h> @@ -43,7 +40,6 @@ #include <priv.h> #include <pwd.h> #include <zone.h> -#include <zfs_prop.h> #include <sys/fs/zfs.h> #include <sys/stat.h> @@ -51,7 +47,6 @@ #include "zpool_util.h" #include "zfs_comutil.h" -#include "zfeature_common.h" #include "statcommon.h" @@ -68,9 +63,6 @@ static int zpool_do_status(int, char **); static int zpool_do_online(int, char **); static int zpool_do_offline(int, char **); static int zpool_do_clear(int, char **); -static int zpool_do_reopen(int, char **); - -static int zpool_do_reguid(int, char **); static int zpool_do_attach(int, char **); static int zpool_do_detach(int, char **); @@ -129,9 +121,7 @@ typedef enum { HELP_UPGRADE, HELP_GET, HELP_SET, - HELP_SPLIT, - HELP_REGUID, - HELP_REOPEN + HELP_SPLIT } zpool_help_t; @@ -164,7 +154,6 @@ static zpool_command_t command_table[] = { { "online", zpool_do_online, HELP_ONLINE }, { "offline", zpool_do_offline, HELP_OFFLINE }, { "clear", zpool_do_clear, HELP_CLEAR }, - { "reopen", zpool_do_reopen, HELP_REOPEN }, { NULL }, { "attach", zpool_do_attach, HELP_ATTACH }, { "detach", zpool_do_detach, HELP_DETACH }, @@ -176,7 +165,6 @@ static zpool_command_t command_table[] = { { "import", zpool_do_import, HELP_IMPORT }, { "export", zpool_do_export, HELP_EXPORT }, { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, - { "reguid", zpool_do_reguid, HELP_REGUID }, { NULL }, { "history", zpool_do_history, HELP_HISTORY }, { "get", zpool_do_get, HELP_GET }, @@ -185,9 +173,9 @@ static zpool_command_t command_table[] = { #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) -static zpool_command_t *current_command; +zpool_command_t *current_command; static char history_str[HIS_MAX_RECORD_LEN]; -static boolean_t log_history = B_TRUE; + static uint_t timestamp_fmt = NODATE; static const char * @@ -201,7 +189,7 @@ get_usage(zpool_help_t idx) { case HELP_CLEAR: return (gettext("\tclear [-nF] <pool> [device]\n")); case HELP_CREATE: - return (gettext("\tcreate [-fnd] [-o property=value] ... \n" + return (gettext("\tcreate [-fn] [-o property=value] ... \n" "\t [-O file-system-property=value] ... \n" "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n")); case HELP_DESTROY: @@ -237,8 +225,6 @@ get_usage(zpool_help_t idx) { "[new-device]\n")); case HELP_REMOVE: return (gettext("\tremove <pool> <device> ...\n")); - case HELP_REOPEN: - return (""); /* Undocumented command */ case HELP_SCRUB: return (gettext("\tscrub [-s] <pool> ...\n")); case HELP_STATUS: @@ -257,8 +243,6 @@ get_usage(zpool_help_t idx) { return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n" "\t [-o property=value] <pool> <newpool> " "[<device> ...]\n")); - case HELP_REGUID: - return (gettext("\treguid <pool>\n")); } abort(); @@ -332,12 +316,6 @@ usage(boolean_t requested) /* Iterate over all properties */ (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE, ZFS_TYPE_POOL); - - (void) fprintf(fp, "\t%-15s ", "feature@..."); - (void) fprintf(fp, "YES disabled | enabled | active\n"); - - (void) fprintf(fp, gettext("\nThe feature@ properties must be " - "appended with a feature name.\nSee zpool-features(5).\n")); } /* @@ -404,16 +382,12 @@ add_prop_list(const char *propname, char *propval, nvlist_t **props, proplist = *props; if (poolprop) { - if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL && - !zpool_prop_feature(propname)) { + if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) { (void) fprintf(stderr, gettext("property '%s' is " "not a valid pool property\n"), propname); return (2); } - if (zpool_prop_feature(propname)) - normnm = propname; - else - normnm = zpool_prop_to_name(prop); + normnm = zpool_prop_to_name(prop); } else { if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) { normnm = zfs_prop_to_name(fprop); @@ -585,7 +559,7 @@ zpool_do_remove(int argc, char **argv) } /* - * zpool create [-fnd] [-o property=value] ... + * zpool create [-fn] [-o property=value] ... * [-O file-system-property=value] ... * [-R root] [-m mountpoint] <pool> <dev> ... * @@ -594,10 +568,8 @@ zpool_do_remove(int argc, char **argv) * were to be created. * -R Create a pool under an alternate root * -m Set default mountpoint for the root dataset. By default it's - * '/<pool>' + * '/<pool>' * -o Set property=value. - * -d Don't automatically enable all supported pool features - * (individual features can be enabled with -o). * -O Set fsproperty=value in the pool's root file system * * Creates the named pool according to the given vdev specification. The @@ -610,7 +582,6 @@ zpool_do_create(int argc, char **argv) { boolean_t force = B_FALSE; boolean_t dryrun = B_FALSE; - boolean_t enable_all_pool_feat = B_TRUE; int c; nvlist_t *nvroot = NULL; char *poolname; @@ -622,7 +593,7 @@ zpool_do_create(int argc, char **argv) char *propval; /* check options */ - while ((c = getopt(argc, argv, ":fndR:m:o:O:")) != -1) { + while ((c = getopt(argc, argv, ":fnR:m:o:O:")) != -1) { switch (c) { case 'f': force = B_TRUE; @@ -630,9 +601,6 @@ zpool_do_create(int argc, char **argv) case 'n': dryrun = B_TRUE; break; - case 'd': - enable_all_pool_feat = B_FALSE; - break; case 'R': altroot = optarg; if (add_prop_list(zpool_prop_to_name( @@ -660,21 +628,6 @@ zpool_do_create(int argc, char **argv) if (add_prop_list(optarg, propval, &props, B_TRUE)) goto errout; - - /* - * If the user is creating a pool that doesn't support - * feature flags, don't enable any features. - */ - if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) { - char *end; - u_longlong_t ver; - - ver = strtoull(propval, &end, 10); - if (*end == '\0' && - ver < SPA_VERSION_FEATURES) { - enable_all_pool_feat = B_FALSE; - } - } break; case 'O': if ((propval = strchr(optarg, '=')) == NULL) { @@ -740,6 +693,7 @@ zpool_do_create(int argc, char **argv) goto errout; } + if (altroot != NULL && altroot[0] != '/') { (void) fprintf(stderr, gettext("invalid alternate root '%s': " "must be an absolute path\n"), altroot); @@ -821,27 +775,6 @@ zpool_do_create(int argc, char **argv) /* * Hand off to libzfs. */ - if (enable_all_pool_feat) { - int i; - for (i = 0; i < SPA_FEATURES; i++) { - char propname[MAXPATHLEN]; - zfeature_info_t *feat = &spa_feature_table[i]; - - (void) snprintf(propname, sizeof (propname), - "feature@%s", feat->fi_uname); - - /* - * Skip feature if user specified it manually - * on the command line. - */ - if (nvlist_exists(props, propname)) - continue; - - if (add_prop_list(propname, ZFS_FEATURE_ENABLED, - &props, B_TRUE) != 0) - goto errout; - } - } if (zpool_create(g_zfs, poolname, nvroot, props, fsprops) == 0) { zfs_handle_t *pool = zfs_open(g_zfs, poolname, @@ -935,10 +868,7 @@ zpool_do_destroy(int argc, char **argv) return (1); } - /* The history must be logged as part of the export */ - log_history = B_FALSE; - - ret = (zpool_destroy(zhp, history_str) != 0); + ret = (zpool_destroy(zhp) != 0); zpool_close(zhp); @@ -1002,13 +932,10 @@ zpool_do_export(int argc, char **argv) continue; } - /* The history must be logged as part of the export */ - log_history = B_FALSE; - if (hardforce) { - if (zpool_export_force(zhp, history_str) != 0) + if (zpool_export_force(zhp) != 0) ret = 1; - } else if (zpool_export(zhp, force, history_str) != 0) { + } else if (zpool_export(zhp, force) != 0) { ret = 1; } @@ -1179,10 +1106,6 @@ print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, (void) printf(gettext("newer version")); break; - case VDEV_AUX_UNSUP_FEAT: - (void) printf(gettext("unsupported feature(s)")); - break; - case VDEV_AUX_SPARED: verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &cb.cb_guid) == 0); @@ -1300,10 +1223,6 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) (void) printf(gettext("newer version")); break; - case VDEV_AUX_UNSUP_FEAT: - (void) printf(gettext("unsupported feature(s)")); - break; - case VDEV_AUX_ERR_EXCEEDED: (void) printf(gettext("too many errors")); break; @@ -1407,7 +1326,6 @@ show_import(nvlist_t *config) const char *health; uint_t vsc; int namewidth; - char *comment; verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, &name) == 0); @@ -1424,9 +1342,9 @@ show_import(nvlist_t *config) reason = zpool_import_status(config, &msgid); - (void) printf(gettext(" pool: %s\n"), name); - (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); - (void) printf(gettext(" state: %s"), health); + (void) printf(gettext(" pool: %s\n"), name); + (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid); + (void) printf(gettext(" state: %s"), health); if (pool_state == POOL_STATE_DESTROYED) (void) printf(gettext(" (DESTROYED)")); (void) printf("\n"); @@ -1435,73 +1353,58 @@ show_import(nvlist_t *config) case ZPOOL_STATUS_MISSING_DEV_R: case ZPOOL_STATUS_MISSING_DEV_NR: case ZPOOL_STATUS_BAD_GUID_SUM: - (void) printf(gettext(" status: One or more devices are " - "missing from the system.\n")); + (void) printf(gettext("status: One or more devices are missing " + "from the system.\n")); break; case ZPOOL_STATUS_CORRUPT_LABEL_R: case ZPOOL_STATUS_CORRUPT_LABEL_NR: - (void) printf(gettext(" status: One or more devices contains " + (void) printf(gettext("status: One or more devices contains " "corrupted data.\n")); break; case ZPOOL_STATUS_CORRUPT_DATA: - (void) printf( - gettext(" status: The pool data is corrupted.\n")); + (void) printf(gettext("status: The pool data is corrupted.\n")); break; case ZPOOL_STATUS_OFFLINE_DEV: - (void) printf(gettext(" status: One or more devices " + (void) printf(gettext("status: One or more devices " "are offlined.\n")); break; case ZPOOL_STATUS_CORRUPT_POOL: - (void) printf(gettext(" status: The pool metadata is " + (void) printf(gettext("status: The pool metadata is " "corrupted.\n")); break; case ZPOOL_STATUS_VERSION_OLDER: - (void) printf(gettext(" status: The pool is formatted using an " + (void) printf(gettext("status: The pool is formatted using an " "older on-disk version.\n")); break; case ZPOOL_STATUS_VERSION_NEWER: - (void) printf(gettext(" status: The pool is formatted using an " + (void) printf(gettext("status: The pool is formatted using an " "incompatible version.\n")); break; - case ZPOOL_STATUS_UNSUP_FEAT_READ: - (void) printf(gettext("status: The pool uses the following " - "feature(s) not supported on this sytem:\n")); - zpool_print_unsup_feat(config); - break; - - case ZPOOL_STATUS_UNSUP_FEAT_WRITE: - (void) printf(gettext("status: The pool can only be accessed " - "in read-only mode on this system. It\n\tcannot be " - "accessed in read-write mode because it uses the " - "following\n\tfeature(s) not supported on this system:\n")); - zpool_print_unsup_feat(config); - break; - case ZPOOL_STATUS_HOSTID_MISMATCH: - (void) printf(gettext(" status: The pool was last accessed by " + (void) printf(gettext("status: The pool was last accessed by " "another system.\n")); break; case ZPOOL_STATUS_FAULTED_DEV_R: case ZPOOL_STATUS_FAULTED_DEV_NR: - (void) printf(gettext(" status: One or more devices are " + (void) printf(gettext("status: One or more devices are " "faulted.\n")); break; case ZPOOL_STATUS_BAD_LOG: - (void) printf(gettext(" status: An intent log record cannot be " + (void) printf(gettext("status: An intent log record cannot be " "read.\n")); break; case ZPOOL_STATUS_RESILVERING: - (void) printf(gettext(" status: One or more devices were being " + (void) printf(gettext("status: One or more devices were being " "resilvered.\n")); break; @@ -1517,61 +1420,43 @@ show_import(nvlist_t *config) */ if (vs->vs_state == VDEV_STATE_HEALTHY) { if (reason == ZPOOL_STATUS_VERSION_OLDER) - (void) printf(gettext(" action: The pool can be " + (void) printf(gettext("action: The pool can be " "imported using its name or numeric identifier, " "though\n\tsome features will not be available " "without an explicit 'zpool upgrade'.\n")); else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) - (void) printf(gettext(" action: The pool can be " + (void) printf(gettext("action: The pool can be " "imported using its name or numeric " "identifier and\n\tthe '-f' flag.\n")); else - (void) printf(gettext(" action: The pool can be " + (void) printf(gettext("action: The pool can be " "imported using its name or numeric " "identifier.\n")); } else if (vs->vs_state == VDEV_STATE_DEGRADED) { - (void) printf(gettext(" action: The pool can be imported " + (void) printf(gettext("action: The pool can be imported " "despite missing or damaged devices. The\n\tfault " "tolerance of the pool may be compromised if imported.\n")); } else { switch (reason) { case ZPOOL_STATUS_VERSION_NEWER: - (void) printf(gettext(" action: The pool cannot be " + (void) printf(gettext("action: The pool cannot be " "imported. Access the pool on a system running " "newer\n\tsoftware, or recreate the pool from " "backup.\n")); break; - case ZPOOL_STATUS_UNSUP_FEAT_READ: - (void) printf(gettext("action: The pool cannot be " - "imported. Access the pool on a system that " - "supports\n\tthe required feature(s), or recreate " - "the pool from backup.\n")); - break; - case ZPOOL_STATUS_UNSUP_FEAT_WRITE: - (void) printf(gettext("action: The pool cannot be " - "imported in read-write mode. Import the pool " - "with\n" - "\t\"-o readonly=on\", access the pool on a system " - "that supports the\n\trequired feature(s), or " - "recreate the pool from backup.\n")); - break; case ZPOOL_STATUS_MISSING_DEV_R: case ZPOOL_STATUS_MISSING_DEV_NR: case ZPOOL_STATUS_BAD_GUID_SUM: - (void) printf(gettext(" action: The pool cannot be " + (void) printf(gettext("action: The pool cannot be " "imported. Attach the missing\n\tdevices and try " "again.\n")); break; default: - (void) printf(gettext(" action: The pool cannot be " + (void) printf(gettext("action: The pool cannot be " "imported due to damaged devices or data.\n")); } } - /* Print the comment attached to the pool. */ - if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0) - (void) printf(gettext("comment: %s\n"), comment); - /* * If the state is "closed" or "can't open", and the aux state * is "corrupt data": @@ -1589,10 +1474,10 @@ show_import(nvlist_t *config) } if (msgid != NULL) - (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), + (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), msgid); - (void) printf(gettext(" config:\n\n")); + (void) printf(gettext("config:\n\n")); namewidth = max_width(NULL, nvroot, 0, 0); if (namewidth < 10) @@ -1630,9 +1515,9 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts, ZPOOL_CONFIG_POOL_STATE, &state) == 0); verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, &version) == 0); - if (!SPA_VERSION_IS_SUPPORTED(version)) { + if (version > SPA_VERSION) { (void) fprintf(stderr, gettext("cannot import '%s': pool " - "is formatted using an unsupported ZFS version\n"), name); + "is formatted using a newer ZFS version\n"), name); return (1); } else if (state != POOL_STATE_EXPORTED && !(flags & ZFS_IMPORT_ANY_HOST)) { @@ -2081,10 +1966,10 @@ error: } typedef struct iostat_cbdata { - boolean_t cb_verbose; - int cb_namewidth; - int cb_iteration; zpool_list_t *cb_list; + int cb_verbose; + int cb_iteration; + int cb_namewidth; } iostat_cbdata_t; static void @@ -2193,15 +2078,10 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, return; for (c = 0; c < children; c++) { - uint64_t ishole = B_FALSE, islog = B_FALSE; - - (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE, - &ishole); - - (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG, - &islog); + uint64_t ishole = B_FALSE; - if (ishole || islog) + if (nvlist_lookup_uint64(newchild[c], + ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole) continue; vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE); @@ -2211,31 +2091,6 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, } /* - * Log device section - */ - - if (num_logs(newnv) > 0) { - (void) printf("%-*s - - - - - " - "-\n", cb->cb_namewidth, "logs"); - - for (c = 0; c < children; c++) { - uint64_t islog = B_FALSE; - (void) nvlist_lookup_uint64(newchild[c], - ZPOOL_CONFIG_IS_LOG, &islog); - - if (islog) { - vname = zpool_vdev_name(g_zfs, zhp, newchild[c], - B_FALSE); - print_vdev_stats(zhp, vname, oldnv ? - oldchild[c] : NULL, newchild[c], - cb, depth + 2); - free(vname); - } - } - - } - - /* * Include level 2 ARC devices in iostat output */ if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE, @@ -2324,8 +2179,7 @@ get_namewidth(zpool_handle_t *zhp, void *data) if (!cb->cb_verbose) cb->cb_namewidth = strlen(zpool_get_name(zhp)); else - cb->cb_namewidth = max_width(zhp, nvroot, 0, - cb->cb_namewidth); + cb->cb_namewidth = max_width(zhp, nvroot, 0, 0); } /* @@ -2554,9 +2408,8 @@ zpool_do_iostat(int argc, char **argv) } typedef struct list_cbdata { - boolean_t cb_verbose; - int cb_namewidth; boolean_t cb_scripted; + boolean_t cb_first; zprop_list_t *cb_proplist; } list_cbdata_t; @@ -2564,50 +2417,30 @@ typedef struct list_cbdata { * Given a list of columns to display, output appropriate headers for each one. */ static void -print_header(list_cbdata_t *cb) +print_header(zprop_list_t *pl) { - zprop_list_t *pl = cb->cb_proplist; - char headerbuf[ZPOOL_MAXPROPLEN]; const char *header; boolean_t first = B_TRUE; boolean_t right_justify; - size_t width = 0; for (; pl != NULL; pl = pl->pl_next) { - width = pl->pl_width; - if (first && cb->cb_verbose) { - /* - * Reset the width to accommodate the verbose listing - * of devices. - */ - width = cb->cb_namewidth; - } + if (pl->pl_prop == ZPROP_INVAL) + continue; if (!first) (void) printf(" "); else first = B_FALSE; - right_justify = B_FALSE; - if (pl->pl_prop != ZPROP_INVAL) { - header = zpool_prop_column_name(pl->pl_prop); - right_justify = zpool_prop_align_right(pl->pl_prop); - } else { - int i; - - for (i = 0; pl->pl_user_prop[i] != '\0'; i++) - headerbuf[i] = toupper(pl->pl_user_prop[i]); - headerbuf[i] = '\0'; - header = headerbuf; - } + header = zpool_prop_column_name(pl->pl_prop); + right_justify = zpool_prop_align_right(pl->pl_prop); if (pl->pl_next == NULL && !right_justify) (void) printf("%s", header); else if (right_justify) - (void) printf("%*s", width, header); + (void) printf("%*s", pl->pl_width, header); else - (void) printf("%-*s", width, header); - + (void) printf("%-*s", pl->pl_width, header); } (void) printf("\n"); @@ -2618,28 +2451,17 @@ print_header(list_cbdata_t *cb) * to the described layout. */ static void -print_pool(zpool_handle_t *zhp, list_cbdata_t *cb) +print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted) { - zprop_list_t *pl = cb->cb_proplist; boolean_t first = B_TRUE; char property[ZPOOL_MAXPROPLEN]; char *propstr; boolean_t right_justify; - size_t width; + int width; for (; pl != NULL; pl = pl->pl_next) { - - width = pl->pl_width; - if (first && cb->cb_verbose) { - /* - * Reset the width to accommodate the verbose listing - * of devices. - */ - width = cb->cb_namewidth; - } - if (!first) { - if (cb->cb_scripted) + if (scripted) (void) printf("\t"); else (void) printf(" "); @@ -2649,32 +2471,25 @@ print_pool(zpool_handle_t *zhp, list_cbdata_t *cb) right_justify = B_FALSE; if (pl->pl_prop != ZPROP_INVAL) { - if (pl->pl_prop == ZPOOL_PROP_EXPANDSZ && - zpool_get_prop_int(zhp, pl->pl_prop, NULL) == 0) - propstr = "-"; - else if (zpool_get_prop(zhp, pl->pl_prop, property, + if (zpool_get_prop(zhp, pl->pl_prop, property, sizeof (property), NULL) != 0) propstr = "-"; else propstr = property; right_justify = zpool_prop_align_right(pl->pl_prop); - } else if ((zpool_prop_feature(pl->pl_user_prop) || - zpool_prop_unsupported(pl->pl_user_prop)) && - zpool_prop_get_feature(zhp, pl->pl_user_prop, property, - sizeof (property)) == 0) { - propstr = property; } else { propstr = "-"; } + width = pl->pl_width; /* * If this is being called in scripted mode, or if this is the * last column and it is left-justified, don't include a width * format specifier. */ - if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify)) + if (scripted || (pl->pl_next == NULL && !right_justify)) (void) printf("%s", propstr); else if (right_justify) (void) printf("%*s", width, propstr); @@ -2685,101 +2500,6 @@ print_pool(zpool_handle_t *zhp, list_cbdata_t *cb) (void) printf("\n"); } -static void -print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted) -{ - char propval[64]; - boolean_t fixed; - size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL); - - zfs_nicenum(value, propval, sizeof (propval)); - - if (prop == ZPOOL_PROP_EXPANDSZ && value == 0) - (void) strlcpy(propval, "-", sizeof (propval)); - - if (scripted) - (void) printf("\t%s", propval); - else - (void) printf(" %*s", width, propval); -} - -void -print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, - list_cbdata_t *cb, int depth) -{ - nvlist_t **child; - vdev_stat_t *vs; - uint_t c, children; - char *vname; - boolean_t scripted = cb->cb_scripted; - - verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, - (uint64_t **)&vs, &c) == 0); - - if (name != NULL) { - if (scripted) - (void) printf("\t%s", name); - else if (strlen(name) + depth > cb->cb_namewidth) - (void) printf("%*s%s", depth, "", name); - else - (void) printf("%*s%s%*s", depth, "", name, - (int)(cb->cb_namewidth - strlen(name) - depth), ""); - - /* only toplevel vdevs have capacity stats */ - if (vs->vs_space == 0) { - if (scripted) - (void) printf("\t-\t-\t-"); - else - (void) printf(" - - -"); - } else { - print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, - scripted); - print_one_column(ZPOOL_PROP_CAPACITY, vs->vs_alloc, - scripted); - print_one_column(ZPOOL_PROP_FREE, - vs->vs_space - vs->vs_alloc, scripted); - } - print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, - scripted); - (void) printf("\n"); - } - - if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, - &child, &children) != 0) - return; - - for (c = 0; c < children; c++) { - uint64_t ishole = B_FALSE; - - if (nvlist_lookup_uint64(child[c], - ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole) - continue; - - vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); - print_list_stats(zhp, vname, child[c], cb, depth + 2); - free(vname); - } - - /* - * Include level 2 ARC devices in iostat output - */ - if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, - &child, &children) != 0) - return; - - if (children > 0) { - (void) printf("%-*s - - - - - " - "-\n", cb->cb_namewidth, "cache"); - for (c = 0; c < children; c++) { - vname = zpool_vdev_name(g_zfs, zhp, child[c], - B_FALSE); - print_list_stats(zhp, vname, child[c], cb, depth + 2); - free(vname); - } - } -} - - /* * Generic callback function to list a pool. */ @@ -2787,18 +2507,14 @@ int list_callback(zpool_handle_t *zhp, void *data) { list_cbdata_t *cbp = data; - nvlist_t *config; - nvlist_t *nvroot; - config = zpool_get_config(zhp, NULL); - - print_pool(zhp, cbp); - if (!cbp->cb_verbose) - return (0); + if (cbp->cb_first) { + if (!cbp->cb_scripted) + print_header(cbp->cb_proplist); + cbp->cb_first = B_FALSE; + } - verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, - &nvroot) == 0); - print_list_stats(zhp, NULL, nvroot, cbp, 0); + print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted); return (0); } @@ -2822,15 +2538,12 @@ zpool_do_list(int argc, char **argv) int ret; list_cbdata_t cb = { 0 }; static char default_props[] = - "name,size,allocated,free,expandsize,capacity,dedupratio," - "health,altroot"; + "name,size,allocated,free,capacity,dedupratio,health,altroot"; char *props = default_props; unsigned long interval = 0, count = 0; - zpool_list_t *list; - boolean_t first = B_TRUE; /* check options */ - while ((c = getopt(argc, argv, ":Ho:T:v")) != -1) { + while ((c = getopt(argc, argv, ":Ho:T:")) != -1) { switch (c) { case 'H': cb.cb_scripted = B_TRUE; @@ -2841,9 +2554,6 @@ zpool_do_list(int argc, char **argv) case 'T': get_timestamp_arg(*optarg); break; - case 'v': - cb.cb_verbose = B_TRUE; - break; case ':': (void) fprintf(stderr, gettext("missing argument for " "'%c' option\n"), optopt); @@ -2864,32 +2574,21 @@ zpool_do_list(int argc, char **argv) if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0) usage(B_FALSE); - if ((list = pool_list_get(argc, argv, &cb.cb_proplist, &ret)) == NULL) - return (1); - - if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) { - (void) printf(gettext("no pools available\n")); - zprop_free_list(cb.cb_proplist); - return (0); - } + cb.cb_first = B_TRUE; for (;;) { - pool_list_update(list); - - if (pool_list_count(list) == 0) - break; - - cb.cb_namewidth = 0; - (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb); if (timestamp_fmt != NODATE) print_timestamp(timestamp_fmt); - if (!cb.cb_scripted && (first || cb.cb_verbose)) { - print_header(&cb); - first = B_FALSE; + ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist, + list_callback, &cb); + + if (argc == 0 && cb.cb_first && !cb.cb_scripted) { + (void) printf(gettext("no pools available\n")); + zprop_free_list(cb.cb_proplist); + return (0); } - ret = pool_list_iter(list, B_TRUE, list_callback, &cb); if (interval == 0) break; @@ -3463,82 +3162,6 @@ zpool_do_clear(int argc, char **argv) return (ret); } -/* - * zpool reguid <pool> - */ -int -zpool_do_reguid(int argc, char **argv) -{ - int c; - char *poolname; - zpool_handle_t *zhp; - int ret = 0; - - /* check options */ - while ((c = getopt(argc, argv, "")) != -1) { - switch (c) { - case '?': - (void) fprintf(stderr, gettext("invalid option '%c'\n"), - optopt); - usage(B_FALSE); - } - } - - argc -= optind; - argv += optind; - - /* get pool name and check number of arguments */ - if (argc < 1) { - (void) fprintf(stderr, gettext("missing pool name\n")); - usage(B_FALSE); - } - - if (argc > 1) { - (void) fprintf(stderr, gettext("too many arguments\n")); - usage(B_FALSE); - } - - poolname = argv[0]; - if ((zhp = zpool_open(g_zfs, poolname)) == NULL) - return (1); - - ret = zpool_reguid(zhp); - - zpool_close(zhp); - return (ret); -} - - -/* - * zpool reopen <pool> - * - * Reopen the pool so that the kernel can update the sizes of all vdevs. - * - * NOTE: This command is currently undocumented. If the command is ever - * exposed then the appropriate usage() messages will need to be made. - */ -int -zpool_do_reopen(int argc, char **argv) -{ - int ret = 0; - zpool_handle_t *zhp; - char *pool; - - argc--; - argv++; - - if (argc != 1) - return (2); - - pool = argv[0]; - if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) - return (1); - - ret = zpool_reopen(zhp); - zpool_close(zhp); - return (ret); -} - typedef struct scrub_cbdata { int cb_type; int cb_argc; @@ -3626,7 +3249,7 @@ print_scan_status(pool_scan_stat_t *ps) double fraction_done; char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7]; - (void) printf(gettext(" scan: ")); + (void) printf(gettext(" scan: ")); /* If there's never been a scan, there's not much to say. */ if (ps == NULL || ps->pss_func == POOL_SCAN_NONE || @@ -3810,20 +3433,14 @@ print_dedup_stats(nvlist_t *config) /* * If the pool was faulted then we may not have been able to - * obtain the config. Otherwise, if we have anything in the dedup + * obtain the config. Otherwise, if have anything in the dedup * table continue processing the stats. */ if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS, - (uint64_t **)&ddo, &c) != 0) + (uint64_t **)&ddo, &c) != 0 || ddo->ddo_count == 0) return; (void) printf("\n"); - (void) printf(gettext(" dedup: ")); - if (ddo->ddo_count == 0) { - (void) printf(gettext("no DDT entries\n")); - return; - } - (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n", (u_longlong_t)ddo->ddo_count, (u_longlong_t)ddo->ddo_dspace, @@ -3842,7 +3459,7 @@ print_dedup_stats(nvlist_t *config) * pool: tank * status: DEGRADED * reason: One or more devices ... - * see: http://illumos.org/msg/ZFS-xxxx-01 + * see: http://www.sun.com/msg/ZFS-xxxx-01 * config: * mirror DEGRADED * c1t0d0 OK @@ -4003,31 +3620,6 @@ status_callback(zpool_handle_t *zhp, void *data) "backup.\n")); break; - case ZPOOL_STATUS_UNSUP_FEAT_READ: - (void) printf(gettext("status: The pool cannot be accessed on " - "this system because it uses the\n\tfollowing feature(s) " - "not supported on this system:\n")); - zpool_print_unsup_feat(config); - (void) printf("\n"); - (void) printf(gettext("action: Access the pool from a system " - "that supports the required feature(s),\n\tor restore the " - "pool from backup.\n")); - break; - - case ZPOOL_STATUS_UNSUP_FEAT_WRITE: - (void) printf(gettext("status: The pool can only be accessed " - "in read-only mode on this system. It\n\tcannot be " - "accessed in read-write mode because it uses the " - "following\n\tfeature(s) not supported on this system:\n")); - zpool_print_unsup_feat(config); - (void) printf("\n"); - (void) printf(gettext("action: The pool cannot be accessed in " - "read-write mode. Import the pool with\n" - "\t\"-o readonly=on\", access the pool from a system that " - "supports the\n\trequired feature(s), or restore the " - "pool from backup.\n")); - break; - case ZPOOL_STATUS_FAULTED_DEV_R: (void) printf(gettext("status: One or more devices are " "faulted in response to persistent errors.\n\tSufficient " @@ -4075,7 +3667,7 @@ status_callback(zpool_handle_t *zhp, void *data) } if (msgid != NULL) - (void) printf(gettext(" see: http://illumos.org/msg/%s\n"), + (void) printf(gettext(" see: http://www.sun.com/msg/%s\n"), msgid); if (config != NULL) { @@ -4252,8 +3844,7 @@ upgrade_cb(zpool_handle_t *zhp, void *arg) verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, &version) == 0); - if (!cbp->cb_newer && SPA_VERSION_IS_SUPPORTED(version) && - version != SPA_VERSION) { + if (!cbp->cb_newer && version < SPA_VERSION) { if (!cbp->cb_all) { if (cbp->cb_first) { (void) printf(gettext("The following pools are " @@ -4275,23 +3866,14 @@ upgrade_cb(zpool_handle_t *zhp, void *arg) (void) printf(gettext("Successfully upgraded " "'%s'\n\n"), zpool_get_name(zhp)); } - /* - * If they did "zpool upgrade -a", then we could - * be doing ioctls to different pools. We need - * to log this history once to each pool, and bypass - * the normal history logging that happens in main(). - */ - (void) zpool_log_history(g_zfs, history_str); - log_history = B_FALSE; } - } else if (cbp->cb_newer && !SPA_VERSION_IS_SUPPORTED(version)) { + } else if (cbp->cb_newer && version > SPA_VERSION) { assert(!cbp->cb_all); if (cbp->cb_first) { (void) printf(gettext("The following pools are " - "formatted using an unsupported software version " - "and\ncannot be accessed on the current " - "system.\n\n")); + "formatted using a newer software version and\n" + "cannot be accessed on the current system.\n\n")); (void) printf(gettext("VER POOL\n")); (void) printf(gettext("--- ------------\n")); cbp->cb_first = B_FALSE; @@ -4375,8 +3957,8 @@ zpool_do_upgrade(int argc, char **argv) break; case 'V': cb.cb_version = strtoll(optarg, &end, 10); - if (*end != '\0' || - !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) { + if (*end != '\0' || cb.cb_version > SPA_VERSION || + cb.cb_version < SPA_VERSION_1) { (void) fprintf(stderr, gettext("invalid version '%s'\n"), optarg); usage(B_FALSE); @@ -4421,8 +4003,8 @@ zpool_do_upgrade(int argc, char **argv) } } - (void) printf(gettext("This system supports ZFS pool feature " - "flags.\n\n")); + (void) printf(gettext("This system is currently running " + "ZFS pool version %llu.\n\n"), SPA_VERSION); cb.cb_first = B_TRUE; if (showversions) { (void) printf(gettext("The following versions are " @@ -4505,8 +4087,8 @@ zpool_do_upgrade(int argc, char **argv) typedef struct hist_cbdata { boolean_t first; - boolean_t longfmt; - boolean_t internal; + int longfmt; + int internal; } hist_cbdata_t; /* @@ -4518,8 +4100,21 @@ get_history_one(zpool_handle_t *zhp, void *data) nvlist_t *nvhis; nvlist_t **records; uint_t numrecords; + char *cmdstr; + char *pathstr; + uint64_t dst_time; + time_t tsec; + struct tm t; + char tbuf[30]; int ret, i; + uint64_t who; + struct passwd *pwd; + char *hostname; + char *zonename; + char internalstr[MAXPATHLEN]; hist_cbdata_t *cb = (hist_cbdata_t *)data; + uint64_t txg; + uint64_t ievent; cb->first = B_FALSE; @@ -4531,94 +4126,64 @@ get_history_one(zpool_handle_t *zhp, void *data) verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, &records, &numrecords) == 0); for (i = 0; i < numrecords; i++) { - nvlist_t *rec = records[i]; - char tbuf[30] = ""; - - if (nvlist_exists(rec, ZPOOL_HIST_TIME)) { - time_t tsec; - struct tm t; - - tsec = fnvlist_lookup_uint64(records[i], - ZPOOL_HIST_TIME); - (void) localtime_r(&tsec, &t); - (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); - } + if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME, + &dst_time) != 0) + continue; - if (nvlist_exists(rec, ZPOOL_HIST_CMD)) { - (void) printf("%s %s", tbuf, - fnvlist_lookup_string(rec, ZPOOL_HIST_CMD)); - } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) { - int ievent = - fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT); - if (!cb->internal) - continue; - if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) { - (void) printf("%s unrecognized record:\n", - tbuf); - dump_nvlist(rec, 4); - continue; - } - (void) printf("%s [internal %s txg:%lld] %s", tbuf, - zfs_history_event_names[ievent], - fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), - fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR)); - } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) { - if (!cb->internal) + /* is it an internal event or a standard event? */ + if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD, + &cmdstr) != 0) { + if (cb->internal == 0) continue; - (void) printf("%s [txg:%lld] %s", tbuf, - fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), - fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME)); - if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) { - (void) printf(" %s (%llu)", - fnvlist_lookup_string(rec, - ZPOOL_HIST_DSNAME), - fnvlist_lookup_uint64(rec, - ZPOOL_HIST_DSID)); - } - (void) printf(" %s", fnvlist_lookup_string(rec, - ZPOOL_HIST_INT_STR)); - } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) { - if (!cb->internal) + + if (nvlist_lookup_uint64(records[i], + ZPOOL_HIST_INT_EVENT, &ievent) != 0) continue; - (void) printf("%s ioctl %s\n", tbuf, - fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL)); - if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) { - (void) printf(" input:\n"); - dump_nvlist(fnvlist_lookup_nvlist(rec, - ZPOOL_HIST_INPUT_NVL), 8); - } - if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) { - (void) printf(" output:\n"); - dump_nvlist(fnvlist_lookup_nvlist(rec, - ZPOOL_HIST_OUTPUT_NVL), 8); - } - } else { - if (!cb->internal) + verify(nvlist_lookup_uint64(records[i], + ZPOOL_HIST_TXG, &txg) == 0); + verify(nvlist_lookup_string(records[i], + ZPOOL_HIST_INT_STR, &pathstr) == 0); + if (ievent >= LOG_END) continue; - (void) printf("%s unrecognized record:\n", tbuf); - dump_nvlist(rec, 4); + (void) snprintf(internalstr, + sizeof (internalstr), + "[internal %s txg:%lld] %s", + zfs_history_event_names[ievent], txg, + pathstr); + cmdstr = internalstr; } + tsec = dst_time; + (void) localtime_r(&tsec, &t); + (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); + (void) printf("%s %s", tbuf, cmdstr); if (!cb->longfmt) { (void) printf("\n"); continue; } (void) printf(" ["); - if (nvlist_exists(rec, ZPOOL_HIST_WHO)) { - uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO); - struct passwd *pwd = getpwuid(who); - (void) printf("user %d ", (int)who); - if (pwd != NULL) - (void) printf("(%s) ", pwd->pw_name); + if (nvlist_lookup_uint64(records[i], + ZPOOL_HIST_WHO, &who) == 0) { + pwd = getpwuid((uid_t)who); + if (pwd) + (void) printf("user %s on", + pwd->pw_name); + else + (void) printf("user %d on", + (int)who); + } else { + (void) printf(gettext("no info]\n")); + continue; } - if (nvlist_exists(rec, ZPOOL_HIST_HOST)) { - (void) printf("on %s", - fnvlist_lookup_string(rec, ZPOOL_HIST_HOST)); + if (nvlist_lookup_string(records[i], + ZPOOL_HIST_HOST, &hostname) == 0) { + (void) printf(" %s", hostname); } - if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) { - (void) printf(":%s", - fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE)); + if (nvlist_lookup_string(records[i], + ZPOOL_HIST_ZONE, &zonename) == 0) { + (void) printf(":%s", zonename); } + (void) printf("]"); (void) printf("\n"); } @@ -4633,6 +4198,8 @@ get_history_one(zpool_handle_t *zhp, void *data) * * Displays the history of commands that modified pools. */ + + int zpool_do_history(int argc, char **argv) { @@ -4645,10 +4212,10 @@ zpool_do_history(int argc, char **argv) while ((c = getopt(argc, argv, "li")) != -1) { switch (c) { case 'l': - cbdata.longfmt = B_TRUE; + cbdata.longfmt = 1; break; case 'i': - cbdata.internal = B_TRUE; + cbdata.internal = 1; break; case '?': (void) fprintf(stderr, gettext("invalid option '%c'\n"), @@ -4688,26 +4255,13 @@ get_callback(zpool_handle_t *zhp, void *data) pl == cbp->cb_proplist) continue; - if (pl->pl_prop == ZPROP_INVAL && - (zpool_prop_feature(pl->pl_user_prop) || - zpool_prop_unsupported(pl->pl_user_prop))) { - srctype = ZPROP_SRC_LOCAL; - - if (zpool_prop_get_feature(zhp, pl->pl_user_prop, - value, sizeof (value)) == 0) { - zprop_print_one_property(zpool_get_name(zhp), - cbp, pl->pl_user_prop, value, srctype, - NULL, NULL); - } - } else { - if (zpool_get_prop(zhp, pl->pl_prop, value, - sizeof (value), &srctype) != 0) - continue; + if (zpool_get_prop(zhp, pl->pl_prop, + value, sizeof (value), &srctype) != 0) + continue; - zprop_print_one_property(zpool_get_name(zhp), cbp, - zpool_prop_to_name(pl->pl_prop), value, srctype, - NULL, NULL); - } + zprop_print_one_property(zpool_get_name(zhp), cbp, + zpool_prop_to_name(pl->pl_prop), value, srctype, NULL, + NULL); } return (0); } @@ -4719,11 +4273,8 @@ zpool_do_get(int argc, char **argv) zprop_list_t fake_name = { 0 }; int ret; - if (argc < 2) { - (void) fprintf(stderr, gettext("missing property " - "argument\n")); + if (argc < 3) usage(B_FALSE); - } cb.cb_first = B_TRUE; cb.cb_sources = ZPROP_SRC_ALL; @@ -4733,7 +4284,7 @@ zpool_do_get(int argc, char **argv) cb.cb_columns[3] = GET_COL_SOURCE; cb.cb_type = ZFS_TYPE_POOL; - if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist, + if (zprop_get_list(g_zfs, argv[1], &cb.cb_proplist, ZFS_TYPE_POOL) != 0) usage(B_FALSE); @@ -4873,7 +4424,8 @@ main(int argc, char **argv) if (strcmp(cmdname, "-?") == 0) usage(B_TRUE); - zfs_save_arguments(argc, argv, history_str, sizeof (history_str)); + zpool_set_history_str("zpool", argc, argv, history_str); + verify(zpool_stage_history(g_zfs, history_str) == 0); /* * Run the appropriate command. @@ -4900,9 +4452,6 @@ main(int argc, char **argv) usage(B_FALSE); } - if (ret == 0 && log_history) - (void) zpool_log_history(g_zfs, history_str); - libzfs_fini(g_zfs); /* |