static int zpool_do_add(int, char **);
static int zpool_do_remove(int, char **);
+static int zpool_do_labelclear(int, char **);
static int zpool_do_list(int, char **);
static int zpool_do_iostat(int, char **);
HELP_HISTORY,
HELP_IMPORT,
HELP_IOSTAT,
+ HELP_LABELCLEAR,
HELP_LIST,
HELP_OFFLINE,
HELP_ONLINE,
{ "add", zpool_do_add, HELP_ADD },
{ "remove", zpool_do_remove, HELP_REMOVE },
{ NULL },
+ { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR },
+ { NULL },
{ "list", zpool_do_list, HELP_LIST },
{ "iostat", zpool_do_iostat, HELP_IOSTAT },
{ "status", zpool_do_status, HELP_STATUS },
case HELP_IOSTAT:
return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
"[count]]\n"));
+ case HELP_LABELCLEAR:
+ return (gettext("\tlabelclear [-f] <vdev>\n"));
case HELP_LIST:
- return (gettext("\tlist [-H] [-o property[,...]] "
+ return (gettext("\tlist [-Hv] [-o property[,...]] "
"[-T d|u] [pool] ... [interval [count]]\n"));
case HELP_OFFLINE:
return (gettext("\toffline [-t] <pool> <device> ...\n"));
case HELP_REMOVE:
return (gettext("\tremove <pool> <device> ...\n"));
case HELP_REOPEN:
- return (""); /* Undocumented command */
+ return (gettext("\treopen <pool>\n"));
case HELP_SCRUB:
return (gettext("\tscrub [-s] <pool> ...\n"));
case HELP_STATUS:
}
}
+static boolean_t
+prop_list_contains_feature(nvlist_t *proplist)
+{
+ nvpair_t *nvp;
+ for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
+ nvp = nvlist_next_nvpair(proplist, nvp)) {
+ if (zpool_prop_feature(nvpair_name(nvp)))
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+
/*
* Add a property pair (name, string-value) into a property nvlist.
*/
proplist = *props;
if (poolprop) {
+ const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
+
if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
!zpool_prop_feature(propname)) {
(void) fprintf(stderr, gettext("property '%s' is "
"not a valid pool property\n"), propname);
return (2);
}
+
+ /*
+ * feature@ properties and version should not be specified
+ * at the same time.
+ */
+ if ((prop == ZPROP_INVAL && zpool_prop_feature(propname) &&
+ nvlist_exists(proplist, vname)) ||
+ (prop == ZPOOL_PROP_VERSION &&
+ prop_list_contains_feature(proplist))) {
+ (void) fprintf(stderr, gettext("'feature@' and "
+ "'version' properties cannot be specified "
+ "together\n"));
+ return (2);
+ }
+
+
if (zpool_prop_feature(propname))
normnm = propname;
else
}
/*
+ * zpool labelclear <vdev>
+ *
+ * Verifies that the vdev is not active and zeros out the label information
+ * on the device.
+ */
+int
+zpool_do_labelclear(int argc, char **argv)
+{
+ char *vdev, *name;
+ int c, fd = -1, ret = 0;
+ pool_state_t state;
+ boolean_t inuse = B_FALSE;
+ boolean_t force = B_FALSE;
+
+ /* check options */
+ while ((c = getopt(argc, argv, "f")) != -1) {
+ switch (c) {
+ case 'f':
+ force = B_TRUE;
+ break;
+ default:
+ (void) fprintf(stderr, gettext("invalid option '%c'\n"),
+ optopt);
+ usage(B_FALSE);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /* get vdev name */
+ if (argc < 1) {
+ (void) fprintf(stderr, gettext("missing vdev device name\n"));
+ usage(B_FALSE);
+ }
+
+ vdev = argv[0];
+ if ((fd = open(vdev, O_RDWR)) < 0) {
+ (void) fprintf(stderr, gettext("Unable to open %s\n"), vdev);
+ return (B_FALSE);
+ }
+
+ name = NULL;
+ if (zpool_in_use(g_zfs, fd, &state, &name, &inuse) != 0) {
+ if (force)
+ goto wipe_label;
+
+ (void) fprintf(stderr,
+ gettext("Unable to determine pool state for %s\n"
+ "Use -f to force the clearing any label data\n"), vdev);
+
+ return (1);
+ }
+
+ if (inuse) {
+ switch (state) {
+ default:
+ case POOL_STATE_ACTIVE:
+ case POOL_STATE_SPARE:
+ case POOL_STATE_L2CACHE:
+ (void) fprintf(stderr,
+ gettext("labelclear operation failed.\n"
+ "\tVdev %s is a member (%s), of pool \"%s\".\n"
+ "\tTo remove label information from this device, "
+ "export or destroy\n\tthe pool, or remove %s from "
+ "the configuration of this pool\n\tand retry the "
+ "labelclear operation.\n"),
+ vdev, zpool_pool_state_to_name(state), name, vdev);
+ ret = 1;
+ goto errout;
+
+ case POOL_STATE_EXPORTED:
+ if (force)
+ break;
+
+ (void) fprintf(stderr,
+ gettext("labelclear operation failed.\n\tVdev "
+ "%s is a member of the exported pool \"%s\".\n"
+ "\tUse \"zpool labelclear -f %s\" to force the "
+ "removal of label\n\tinformation.\n"),
+ vdev, name, vdev);
+ ret = 1;
+ goto errout;
+
+ case POOL_STATE_POTENTIALLY_ACTIVE:
+ if (force)
+ break;
+
+ (void) fprintf(stderr,
+ gettext("labelclear operation failed.\n"
+ "\tVdev %s is a member of the pool \"%s\".\n"
+ "\tThis pool is unknown to this system, but may "
+ "be active on\n\tanother system. Use "
+ "\'zpool labelclear -f %s\' to force the\n"
+ "\tremoval of label information.\n"),
+ vdev, name, vdev);
+ ret = 1;
+ goto errout;
+
+ case POOL_STATE_DESTROYED:
+ /* inuse should never be set for a destroyed pool... */
+ break;
+ }
+ }
+
+wipe_label:
+ if (zpool_clear_label(fd) != 0) {
+ (void) fprintf(stderr,
+ gettext("Label clear failed on vdev %s\n"), vdev);
+ ret = 1;
+ }
+
+errout:
+ close(fd);
+ if (name != NULL)
+ free(name);
+
+ return (ret);
+}
+
+/*
* zpool create [-fnd] [-o property=value] ...
* [-O file-system-property=value] ...
* [-R root] [-m mountpoint] <pool> <dev> ...
break;
case ZPOOL_STATUS_VERSION_OLDER:
- (void) printf(gettext(" status: The pool is formatted using an "
- "older on-disk version.\n"));
+ (void) printf(gettext(" status: The pool is formatted using a "
+ "legacy on-disk version.\n"));
break;
case ZPOOL_STATUS_VERSION_NEWER:
"incompatible version.\n"));
break;
+ case ZPOOL_STATUS_FEAT_DISABLED:
+ (void) printf(gettext(" status: Some supported features are "
+ "not enabled on the pool.\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"));
* Print out an action according to the overall state of the pool.
*/
if (vs->vs_state == VDEV_STATE_HEALTHY) {
- if (reason == ZPOOL_STATUS_VERSION_OLDER)
+ if (reason == ZPOOL_STATUS_VERSION_OLDER ||
+ reason == ZPOOL_STATUS_FEAT_DISABLED) {
(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)
+ } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
(void) printf(gettext(" action: The pool can be "
"imported using its name or numeric "
"identifier and\n\tthe '-f' flag.\n"));
- else
+ } else {
(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 "
"despite missing or damaged devices. The\n\tfault "
zpool_do_list(int argc, char **argv)
{
int c;
- int ret;
+ int ret = 0;
list_cbdata_t cb = { 0 };
static char default_props[] =
"name,size,allocated,free,capacity,dedupratio,"
* 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 c;
int ret = 0;
zpool_handle_t *zhp;
char *pool;
+ /* check options */
+ while ((c = getopt(argc, argv, "")) != -1) {
+ switch (c) {
+ case '?':
+ (void) fprintf(stderr, gettext("invalid option '%c'\n"),
+ optopt);
+ usage(B_FALSE);
+ }
+ }
+
argc--;
argv++;
- if (argc != 1)
- return (2);
+ 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);
+ }
pool = argv[0];
if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
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 ||
* table continue processing the stats.
*/
if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
- (uint64_t **)&ddo, &c) != 0 || ddo->ddo_count == 0)
+ (uint64_t **)&ddo, &c) != 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,
* If we were given 'zpool status -x', only report those pools with
* problems.
*/
- if (reason == ZPOOL_STATUS_OK && cbp->cb_explain) {
+ if (cbp->cb_explain &&
+ (reason == ZPOOL_STATUS_OK ||
+ reason == ZPOOL_STATUS_VERSION_OLDER ||
+ reason == ZPOOL_STATUS_FEAT_DISABLED)) {
if (!cbp->cb_allpools) {
(void) printf(gettext("pool '%s' is healthy\n"),
zpool_get_name(zhp));
break;
case ZPOOL_STATUS_VERSION_OLDER:
- (void) printf(gettext("status: The pool is formatted using an "
- "older on-disk format. The pool can\n\tstill be used, but "
- "some features are unavailable.\n"));
+ (void) printf(gettext("status: The pool is formatted using a "
+ "legacy on-disk format. The pool can\n\tstill be used, "
+ "but some features are unavailable.\n"));
(void) printf(gettext("action: Upgrade the pool using 'zpool "
"upgrade'. Once this is done, the\n\tpool will no longer "
- "be accessible on older software versions.\n"));
+ "be accessible on software that does not support\n\t"
+ "feature flags.\n"));
break;
case ZPOOL_STATUS_VERSION_NEWER:
"backup.\n"));
break;
+ case ZPOOL_STATUS_FEAT_DISABLED:
+ (void) printf(gettext("status: Some supported features are not "
+ "enabled on the pool. The pool can\n\tstill be used, but "
+ "some features are unavailable.\n"));
+ (void) printf(gettext("action: Enable all features using "
+ "'zpool upgrade'. Once this is done,\n\tthe pool may no "
+ "longer be accessible by software that does not support\n\t"
+ "the features. See zpool-features(5) for details.\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) "
}
typedef struct upgrade_cbdata {
- int cb_all;
int cb_first;
- int cb_newer;
int cb_argc;
uint64_t cb_version;
char **cb_argv;
} upgrade_cbdata_t;
static int
+upgrade_version(zpool_handle_t *zhp, uint64_t version)
+{
+ int ret;
+ nvlist_t *config;
+ uint64_t oldversion;
+
+ config = zpool_get_config(zhp, NULL);
+ verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
+ &oldversion) == 0);
+
+ assert(SPA_VERSION_IS_SUPPORTED(oldversion));
+ assert(oldversion < version);
+
+ ret = zpool_upgrade(zhp, version);
+ if (ret != 0)
+ return (ret);
+
+ if (version >= SPA_VERSION_FEATURES) {
+ (void) printf(gettext("Successfully upgraded "
+ "'%s' from version %llu to feature flags.\n"),
+ zpool_get_name(zhp), (u_longlong_t) oldversion);
+ } else {
+ (void) printf(gettext("Successfully upgraded "
+ "'%s' from version %llu to version %llu.\n"),
+ zpool_get_name(zhp), (u_longlong_t) oldversion,
+ (u_longlong_t) version);
+ }
+
+ return (0);
+}
+
+static int
+upgrade_enable_all(zpool_handle_t *zhp, int *countp)
+{
+ int i, ret, count;
+ boolean_t firstff = B_TRUE;
+ nvlist_t *enabled = zpool_get_features(zhp);
+
+ count = 0;
+ for (i = 0; i < SPA_FEATURES; i++) {
+ const char *fname = spa_feature_table[i].fi_uname;
+ const char *fguid = spa_feature_table[i].fi_guid;
+ if (!nvlist_exists(enabled, fguid)) {
+ char *propname;
+ verify(-1 != asprintf(&propname, "feature@%s", fname));
+ ret = zpool_set_prop(zhp, propname,
+ ZFS_FEATURE_ENABLED);
+ if (ret != 0) {
+ free(propname);
+ return (ret);
+ }
+ count++;
+
+ if (firstff) {
+ (void) printf(gettext("Enabled the "
+ "following features on '%s':\n"),
+ zpool_get_name(zhp));
+ firstff = B_FALSE;
+ }
+ (void) printf(gettext(" %s\n"), fname);
+ free(propname);
+ }
+ }
+
+ if (countp != NULL)
+ *countp = count;
+ return (0);
+}
+
+static int
upgrade_cb(zpool_handle_t *zhp, void *arg)
{
upgrade_cbdata_t *cbp = arg;
nvlist_t *config;
uint64_t version;
- int ret = 0;
+ boolean_t printnl = B_FALSE;
+ int ret;
config = zpool_get_config(zhp, NULL);
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_all) {
- if (cbp->cb_first) {
- (void) printf(gettext("The following pools are "
- "out of date, and can be upgraded. After "
- "being\nupgraded, these pools will no "
- "longer be accessible by older software "
- "versions.\n\n"));
- (void) printf(gettext("VER POOL\n"));
- (void) printf(gettext("--- ------------\n"));
- cbp->cb_first = B_FALSE;
- }
+ assert(SPA_VERSION_IS_SUPPORTED(version));
- (void) printf("%2llu %s\n", (u_longlong_t)version,
- zpool_get_name(zhp));
- } else {
+ if (version < cbp->cb_version) {
+ cbp->cb_first = B_FALSE;
+ ret = upgrade_version(zhp, cbp->cb_version);
+ if (ret != 0)
+ return (ret);
+ printnl = B_TRUE;
+
+#if 0
+ /*
+ * XXX: This code can be enabled when Illumos commit
+ * 4445fffbbb1ea25fd0e9ea68b9380dd7a6709025 is merged.
+ * It reworks the history logging among other things.
+ */
+
+ /*
+ * 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;
+#endif
+ }
+
+ if (cbp->cb_version >= SPA_VERSION_FEATURES) {
+ int count;
+ ret = upgrade_enable_all(zhp, &count);
+ if (ret != 0)
+ return (ret);
+
+ if (count > 0) {
cbp->cb_first = B_FALSE;
- ret = zpool_upgrade(zhp, cbp->cb_version);
- if (!ret) {
- (void) printf(gettext("Successfully upgraded "
- "'%s'\n\n"), zpool_get_name(zhp));
- }
+ printnl = B_TRUE;
}
- } else if (cbp->cb_newer && !SPA_VERSION_IS_SUPPORTED(version)) {
- assert(!cbp->cb_all);
+ }
+
+ if (printnl) {
+ (void) printf(gettext("\n"));
+ }
+
+ return (0);
+}
+static int
+upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
+{
+ upgrade_cbdata_t *cbp = arg;
+ nvlist_t *config;
+ uint64_t version;
+
+ config = zpool_get_config(zhp, NULL);
+ verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
+ &version) == 0);
+
+ assert(SPA_VERSION_IS_SUPPORTED(version));
+
+ if (version < SPA_VERSION_FEATURES) {
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 with legacy version numbers and can\n"
+ "be upgraded to use feature flags. After "
+ "being upgraded, these pools\nwill no "
+ "longer be accessible by software that does not "
+ "support feature\nflags.\n\n"));
(void) printf(gettext("VER POOL\n"));
(void) printf(gettext("--- ------------\n"));
cbp->cb_first = B_FALSE;
zpool_get_name(zhp));
}
- zpool_close(zhp);
- return (ret);
+ return (0);
+}
+
+static int
+upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
+{
+ upgrade_cbdata_t *cbp = arg;
+ nvlist_t *config;
+ uint64_t version;
+
+ config = zpool_get_config(zhp, NULL);
+ verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
+ &version) == 0);
+
+ if (version >= SPA_VERSION_FEATURES) {
+ int i;
+ boolean_t poolfirst = B_TRUE;
+ nvlist_t *enabled = zpool_get_features(zhp);
+
+ for (i = 0; i < SPA_FEATURES; i++) {
+ const char *fguid = spa_feature_table[i].fi_guid;
+ const char *fname = spa_feature_table[i].fi_uname;
+ if (!nvlist_exists(enabled, fguid)) {
+ if (cbp->cb_first) {
+ (void) printf(gettext("\nSome "
+ "supported features are not "
+ "enabled on the following pools. "
+ "Once a\nfeature is enabled the "
+ "pool may become incompatible with "
+ "software\nthat does not support "
+ "the feature. See "
+ "zpool-features(5) for "
+ "details.\n\n"));
+ (void) printf(gettext("POOL "
+ "FEATURE\n"));
+ (void) printf(gettext("------"
+ "---------\n"));
+ cbp->cb_first = B_FALSE;
+ }
+
+ if (poolfirst) {
+ (void) printf(gettext("%s\n"),
+ zpool_get_name(zhp));
+ poolfirst = B_FALSE;
+ }
+
+ (void) printf(gettext(" %s\n"), fname);
+ }
+ }
+ }
+
+ return (0);
}
/* ARGSUSED */
static int
upgrade_one(zpool_handle_t *zhp, void *data)
{
+ boolean_t printnl = B_FALSE;
upgrade_cbdata_t *cbp = data;
uint64_t cur_version;
int ret;
cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
if (cur_version > cbp->cb_version) {
(void) printf(gettext("Pool '%s' is already formatted "
- "using more current version '%llu'.\n"),
+ "using more current version '%llu'.\n\n"),
zpool_get_name(zhp), (u_longlong_t) cur_version);
return (0);
}
- if (cur_version == cbp->cb_version) {
+
+ if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
(void) printf(gettext("Pool '%s' is already formatted "
- "using the current version.\n"), zpool_get_name(zhp));
+ "using version %llu.\n\n"), zpool_get_name(zhp),
+ (u_longlong_t) cbp->cb_version);
return (0);
}
- ret = zpool_upgrade(zhp, cbp->cb_version);
+ if (cur_version != cbp->cb_version) {
+ printnl = B_TRUE;
+ ret = upgrade_version(zhp, cbp->cb_version);
+ if (ret != 0)
+ return (ret);
+ }
- if (!ret) {
- (void) printf(gettext("Successfully upgraded '%s' "
- "from version %llu to version %llu\n\n"),
- zpool_get_name(zhp), (u_longlong_t)cur_version,
- (u_longlong_t)cbp->cb_version);
+ if (cbp->cb_version >= SPA_VERSION_FEATURES) {
+ int count = 0;
+ ret = upgrade_enable_all(zhp, &count);
+ if (ret != 0)
+ return (ret);
+
+ if (count != 0) {
+ printnl = B_TRUE;
+ } else if (cur_version == SPA_VERSION) {
+ (void) printf(gettext("Pool '%s' already has all "
+ "supported features enabled.\n"),
+ zpool_get_name(zhp));
+ }
+ }
+
+ if (printnl) {
+ (void) printf(gettext("\n"));
}
- return (ret != 0);
+ return (0);
}
/*
upgrade_cbdata_t cb = { 0 };
int ret = 0;
boolean_t showversions = B_FALSE;
+ boolean_t upgradeall = B_FALSE;
char *end;
while ((c = getopt(argc, argv, ":avV:")) != -1) {
switch (c) {
case 'a':
- cb.cb_all = B_TRUE;
+ upgradeall = B_TRUE;
break;
case 'v':
showversions = B_TRUE;
if (cb.cb_version == 0) {
cb.cb_version = SPA_VERSION;
- } else if (!cb.cb_all && argc == 0) {
+ } else if (!upgradeall && argc == 0) {
(void) fprintf(stderr, gettext("-V option is "
"incompatible with other arguments\n"));
usage(B_FALSE);
}
if (showversions) {
- if (cb.cb_all || argc != 0) {
+ if (upgradeall || argc != 0) {
(void) fprintf(stderr, gettext("-v option is "
"incompatible with other arguments\n"));
usage(B_FALSE);
}
- } else if (cb.cb_all) {
+ } else if (upgradeall) {
if (argc != 0) {
(void) fprintf(stderr, gettext("-a option should not "
"be used along with a pool name\n"));
(void) printf(gettext("This system supports ZFS pool feature "
"flags.\n\n"));
- cb.cb_first = B_TRUE;
if (showversions) {
- (void) printf(gettext("The following versions are "
+ int i;
+
+ (void) printf(gettext("The following features are "
+ "supported:\n\n"));
+ (void) printf(gettext("FEAT DESCRIPTION\n"));
+ (void) printf("----------------------------------------------"
+ "---------------\n");
+ for (i = 0; i < SPA_FEATURES; i++) {
+ zfeature_info_t *fi = &spa_feature_table[i];
+ const char *ro = fi->fi_can_readonly ?
+ " (read-only compatible)" : "";
+
+ (void) printf("%-37s%s\n", fi->fi_uname, ro);
+ (void) printf(" %s\n", fi->fi_desc);
+ }
+ (void) printf("\n");
+
+ (void) printf(gettext("The following legacy versions are also "
"supported:\n\n"));
(void) printf(gettext("VER DESCRIPTION\n"));
(void) printf("--- -----------------------------------------"
(void) printf(gettext("\nFor more information on a particular "
"version, including supported releases,\n"));
(void) printf(gettext("see the ZFS Administration Guide.\n\n"));
- } else if (argc == 0) {
- int notfound;
-
+ } else if (argc == 0 && upgradeall) {
+ cb.cb_first = B_TRUE;
ret = zpool_iter(g_zfs, upgrade_cb, &cb);
- notfound = cb.cb_first;
-
- if (!cb.cb_all && ret == 0) {
- if (!cb.cb_first)
- (void) printf("\n");
- cb.cb_first = B_TRUE;
- cb.cb_newer = B_TRUE;
- ret = zpool_iter(g_zfs, upgrade_cb, &cb);
- if (!cb.cb_first) {
- notfound = B_FALSE;
- (void) printf("\n");
+ if (ret == 0 && cb.cb_first) {
+ if (cb.cb_version == SPA_VERSION) {
+ (void) printf(gettext("All pools are already "
+ "formatted using feature flags.\n\n"));
+ (void) printf(gettext("Every feature flags "
+ "pool already has all supported features "
+ "enabled.\n"));
+ } else {
+ (void) printf(gettext("All pools are already "
+ "formatted with version %llu or higher.\n"),
+ (u_longlong_t) cb.cb_version);
}
}
+ } else if (argc == 0) {
+ cb.cb_first = B_TRUE;
+ ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
+ assert(ret == 0);
- if (ret == 0) {
- if (notfound)
- (void) printf(gettext("All pools are formatted "
- "using this version.\n"));
- else if (!cb.cb_all)
- (void) printf(gettext("Use 'zpool upgrade -v' "
- "for a list of available versions and "
- "their associated\nfeatures.\n"));
+ if (cb.cb_first) {
+ (void) printf(gettext("All pools are formatted "
+ "using feature flags.\n\n"));
+ } else {
+ (void) printf(gettext("\nUse 'zpool upgrade -v' "
+ "for a list of available legacy versions.\n"));
+ }
+
+ cb.cb_first = B_TRUE;
+ ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
+ assert(ret == 0);
+
+ if (cb.cb_first) {
+ (void) printf(gettext("Every feature flags pool has "
+ "all supported features enabled.\n"));
+ } else {
+ (void) printf(gettext("\n"));
}
} else {
ret = for_each_pool(argc, argv, B_FALSE, NULL,
zpool_do_events_nvprint(nvl, 8);
printf(gettext("\n"));
}
+ (void) fflush(stdout);
nvlist_free(nvl);
}