aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/cmd/zpool/zpool_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/cmd/zpool/zpool_main.c')
-rw-r--r--sys/contrib/openzfs/cmd/zpool/zpool_main.c390
1 files changed, 232 insertions, 158 deletions
diff --git a/sys/contrib/openzfs/cmd/zpool/zpool_main.c b/sys/contrib/openzfs/cmd/zpool/zpool_main.c
index f2c2c3f41a7c..1feec55c0e8b 100644
--- a/sys/contrib/openzfs/cmd/zpool/zpool_main.c
+++ b/sys/contrib/openzfs/cmd/zpool/zpool_main.c
@@ -33,8 +33,8 @@
* Copyright (c) 2017, Intel Corporation.
* Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com>
* Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
- * Copyright (c) 2021, 2023, Klara Inc.
- * Copyright [2021] Hewlett Packard Enterprise Development LP
+ * Copyright (c) 2021, 2023, 2025, Klara, Inc.
+ * Copyright (c) 2021, 2025 Hewlett Packard Enterprise Development LP.
*/
#include <assert.h>
@@ -456,7 +456,7 @@ get_usage(zpool_help_t idx)
"<pool> <vdev> ...\n"));
case HELP_ATTACH:
return (gettext("\tattach [-fsw] [-o property=value] "
- "<pool> <device> <new-device>\n"));
+ "<pool> <vdev> <new-device>\n"));
case HELP_CLEAR:
return (gettext("\tclear [[--power]|[-nF]] <pool> [device]\n"));
case HELP_CREATE:
@@ -510,22 +510,22 @@ get_usage(zpool_help_t idx)
case HELP_REOPEN:
return (gettext("\treopen [-n] <pool>\n"));
case HELP_INITIALIZE:
- return (gettext("\tinitialize [-c | -s | -u] [-w] <pool> "
- "[<device> ...]\n"));
+ return (gettext("\tinitialize [-c | -s | -u] [-w] <-a | <pool> "
+ "[<device> ...]>\n"));
case HELP_SCRUB:
- return (gettext("\tscrub [-e | -s | -p | -C] [-w] "
- "<pool> ...\n"));
+ return (gettext("\tscrub [-e | -s | -p | -C | -E | -S] [-w] "
+ "<-a | <pool> [<pool> ...]>\n"));
case HELP_RESILVER:
return (gettext("\tresilver <pool> ...\n"));
case HELP_TRIM:
- return (gettext("\ttrim [-dw] [-r <rate>] [-c | -s] <pool> "
- "[<device> ...]\n"));
+ return (gettext("\ttrim [-dw] [-r <rate>] [-c | -s] "
+ "<-a | <pool> [<device> ...]>\n"));
case HELP_STATUS:
- return (gettext("\tstatus [--power] [-j [--json-int, "
- "--json-flat-vdevs, ...\n"
- "\t --json-pool-key-guid]] [-c [script1,script2,...]] "
- "[-dDegiLpPstvx] ...\n"
- "\t [-T d|u] [pool] [interval [count]]\n"));
+ return (gettext("\tstatus [-DdegiLPpstvx] "
+ "[-c script1[,script2,...]] ...\n"
+ "\t [-j|--json [--json-flat-vdevs] [--json-int] "
+ "[--json-pool-key-guid]] ...\n"
+ "\t [-T d|u] [--power] [pool] [interval [count]]\n"));
case HELP_UPGRADE:
return (gettext("\tupgrade\n"
"\tupgrade -v\n"
@@ -560,33 +560,6 @@ get_usage(zpool_help_t idx)
}
}
-static void
-zpool_collect_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *res)
-{
- uint_t children = 0;
- nvlist_t **child;
- uint_t i;
-
- (void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
- &child, &children);
-
- if (children == 0) {
- char *path = zpool_vdev_name(g_zfs, zhp, nvroot,
- VDEV_NAME_PATH);
-
- if (strcmp(path, VDEV_TYPE_INDIRECT) != 0 &&
- strcmp(path, VDEV_TYPE_HOLE) != 0)
- fnvlist_add_boolean(res, path);
-
- free(path);
- return;
- }
-
- for (i = 0; i < children; i++) {
- zpool_collect_leaves(zhp, child[i], res);
- }
-}
-
/*
* Callback routine that will print out a pool property value.
*/
@@ -779,10 +752,11 @@ usage(boolean_t requested)
}
/*
- * zpool initialize [-c | -s | -u] [-w] <pool> [<vdev> ...]
+ * zpool initialize [-c | -s | -u] [-w] <-a | pool> [<vdev> ...]
* Initialize all unused blocks in the specified vdevs, or all vdevs in the pool
* if none specified.
*
+ * -a Use all pools.
* -c Cancel. Ends active initializing.
* -s Suspend. Initializing can then be restarted with no flags.
* -u Uninitialize. Clears initialization state.
@@ -794,22 +768,26 @@ zpool_do_initialize(int argc, char **argv)
int c;
char *poolname;
zpool_handle_t *zhp;
- nvlist_t *vdevs;
int err = 0;
boolean_t wait = B_FALSE;
+ boolean_t initialize_all = B_FALSE;
struct option long_options[] = {
{"cancel", no_argument, NULL, 'c'},
{"suspend", no_argument, NULL, 's'},
{"uninit", no_argument, NULL, 'u'},
{"wait", no_argument, NULL, 'w'},
+ {"all", no_argument, NULL, 'a'},
{0, 0, 0, 0}
};
pool_initialize_func_t cmd_type = POOL_INITIALIZE_START;
- while ((c = getopt_long(argc, argv, "csuw", long_options,
+ while ((c = getopt_long(argc, argv, "acsuw", long_options,
NULL)) != -1) {
switch (c) {
+ case 'a':
+ initialize_all = B_TRUE;
+ break;
case 'c':
if (cmd_type != POOL_INITIALIZE_START &&
cmd_type != POOL_INITIALIZE_CANCEL) {
@@ -856,7 +834,18 @@ zpool_do_initialize(int argc, char **argv)
argc -= optind;
argv += optind;
- if (argc < 1) {
+ initialize_cbdata_t cbdata = {
+ .wait = wait,
+ .cmd_type = cmd_type
+ };
+
+ if (initialize_all && argc > 0) {
+ (void) fprintf(stderr, gettext("-a cannot be combined with "
+ "individual pools or vdevs\n"));
+ usage(B_FALSE);
+ }
+
+ if (argc < 1 && !initialize_all) {
(void) fprintf(stderr, gettext("missing pool name argument\n"));
usage(B_FALSE);
return (-1);
@@ -868,30 +857,35 @@ zpool_do_initialize(int argc, char **argv)
usage(B_FALSE);
}
- poolname = argv[0];
- zhp = zpool_open(g_zfs, poolname);
- if (zhp == NULL)
- return (-1);
-
- vdevs = fnvlist_alloc();
- if (argc == 1) {
- /* no individual leaf vdevs specified, so add them all */
- nvlist_t *config = zpool_get_config(zhp, NULL);
- nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
- ZPOOL_CONFIG_VDEV_TREE);
- zpool_collect_leaves(zhp, nvroot, vdevs);
+ if (argc == 0 && initialize_all) {
+ /* Initilize each pool recursively */
+ err = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
+ B_FALSE, zpool_initialize_one, &cbdata);
+ return (err);
+ } else if (argc == 1) {
+ /* no individual leaf vdevs specified, initialize the pool */
+ poolname = argv[0];
+ zhp = zpool_open(g_zfs, poolname);
+ if (zhp == NULL)
+ return (-1);
+ err = zpool_initialize_one(zhp, &cbdata);
} else {
+ /* individual leaf vdevs specified, initialize them */
+ poolname = argv[0];
+ zhp = zpool_open(g_zfs, poolname);
+ if (zhp == NULL)
+ return (-1);
+ nvlist_t *vdevs = fnvlist_alloc();
for (int i = 1; i < argc; i++) {
fnvlist_add_boolean(vdevs, argv[i]);
}
+ if (wait)
+ err = zpool_initialize_wait(zhp, cmd_type, vdevs);
+ else
+ err = zpool_initialize(zhp, cmd_type, vdevs);
+ fnvlist_free(vdevs);
}
- if (wait)
- err = zpool_initialize_wait(zhp, cmd_type, vdevs);
- else
- err = zpool_initialize(zhp, cmd_type, vdevs);
-
- fnvlist_free(vdevs);
zpool_close(zhp);
return (err);
@@ -1788,7 +1782,7 @@ zpool_do_labelclear(int argc, char **argv)
{
char vdev[MAXPATHLEN];
char *name = NULL;
- int c, fd = -1, ret = 0;
+ int c, fd, ret = 0;
nvlist_t *config;
pool_state_t state;
boolean_t inuse = B_FALSE;
@@ -5767,24 +5761,6 @@ children:
return (ret);
}
-static int
-refresh_iostat(zpool_handle_t *zhp, void *data)
-{
- iostat_cbdata_t *cb = data;
- boolean_t missing;
-
- /*
- * If the pool has disappeared, remove it from the list and continue.
- */
- if (zpool_refresh_stats(zhp, &missing) != 0)
- return (-1);
-
- if (missing)
- pool_list_remove(cb->cb_list, zhp);
-
- return (0);
-}
-
/*
* Callback to print out the iostats for the given pool.
*/
@@ -6157,7 +6133,6 @@ static void
get_interval_count_filter_guids(int *argc, char **argv, float *interval,
unsigned long *count, iostat_cbdata_t *cb)
{
- char **tmpargv = argv;
int argc_for_interval = 0;
/* Is the last arg an interval value? Or a guid? */
@@ -6181,7 +6156,7 @@ get_interval_count_filter_guids(int *argc, char **argv, float *interval,
}
/* Point to our list of possible intervals */
- tmpargv = &argv[*argc - argc_for_interval];
+ char **tmpargv = &argv[*argc - argc_for_interval];
*argc = *argc - argc_for_interval;
get_interval_count(&argc_for_interval, tmpargv,
@@ -6366,18 +6341,16 @@ get_namewidth_iostat(zpool_handle_t *zhp, void *data)
* This command can be tricky because we want to be able to deal with pool
* creation/destruction as well as vdev configuration changes. The bulk of this
* processing is handled by the pool_list_* routines in zpool_iter.c. We rely
- * on pool_list_update() to detect the addition of new pools. Configuration
- * changes are all handled within libzfs.
+ * on pool_list_refresh() to detect the addition and removal of pools.
+ * Configuration changes are all handled within libzfs.
*/
int
zpool_do_iostat(int argc, char **argv)
{
int c;
int ret;
- int npools;
float interval = 0;
unsigned long count = 0;
- int winheight = 24;
zpool_list_t *list;
boolean_t verbose = B_FALSE;
boolean_t latency = B_FALSE, l_histo = B_FALSE, rq_histo = B_FALSE;
@@ -6626,10 +6599,24 @@ zpool_do_iostat(int argc, char **argv)
return (1);
}
+ int last_npools = 0;
for (;;) {
- if ((npools = pool_list_count(list)) == 0)
+ /*
+ * Refresh all pools in list, adding or removing pools as
+ * necessary.
+ */
+ int npools = pool_list_refresh(list);
+ if (npools == 0) {
(void) fprintf(stderr, gettext("no pools available\n"));
- else {
+ } else {
+ /*
+ * If the list of pools has changed since last time
+ * around, reset the iteration count to force the
+ * header to be redisplayed.
+ */
+ if (last_npools != npools)
+ cb.cb_iteration = 0;
+
/*
* If this is the first iteration and -y was supplied
* we skip any printing.
@@ -6638,15 +6625,6 @@ zpool_do_iostat(int argc, char **argv)
cb.cb_iteration == 0);
/*
- * Refresh all statistics. This is done as an
- * explicit step before calculating the maximum name
- * width, so that any * configuration changes are
- * properly accounted for.
- */
- (void) pool_list_iter(list, B_FALSE, refresh_iostat,
- &cb);
-
- /*
* Iterate over all pools to determine the maximum width
* for the pool / device name column across all pools.
*/
@@ -6673,7 +6651,7 @@ zpool_do_iostat(int argc, char **argv)
* even when terminal window has its height
* changed.
*/
- winheight = terminal_height();
+ int winheight = terminal_height();
/*
* Are we connected to TTY? If not, headers_once
* should be true, to avoid breaking scripts.
@@ -6699,6 +6677,7 @@ zpool_do_iostat(int argc, char **argv)
if (skip) {
(void) fflush(stdout);
(void) fsleep(interval);
+ last_npools = npools;
continue;
}
@@ -6736,6 +6715,8 @@ zpool_do_iostat(int argc, char **argv)
(void) fflush(stdout);
(void) fsleep(interval);
+
+ last_npools = npools;
}
pool_list_free(list);
@@ -7652,7 +7633,7 @@ zpool_do_replace(int argc, char **argv)
}
/*
- * zpool attach [-fsw] [-o property=value] <pool> <device>|<vdev> <new_device>
+ * zpool attach [-fsw] [-o property=value] <pool> <vdev> <new_device>
*
* -f Force attach, even if <new_device> appears to be in use.
* -s Use sequential instead of healing reconstruction for resilver.
@@ -7660,9 +7641,9 @@ zpool_do_replace(int argc, char **argv)
* -w Wait for resilvering (mirror) or expansion (raidz) to complete
* before returning.
*
- * Attach <new_device> to a <device> or <vdev>, where the vdev can be of type
- * mirror or raidz. If <device> is not part of a mirror, then <device> will
- * be transformed into a mirror of <device> and <new_device>. When a mirror
+ * Attach <new_device> to a <vdev>, where the vdev can be of type
+ * device, mirror or raidz. If <vdev> is not part of a mirror, then <vdev> will
+ * be transformed into a mirror of <vdev> and <new_device>. When a mirror
* is involved, <new_device> will begin life with a DTL of [0, now], and will
* immediately begin to resilver itself. For the raidz case, a expansion will
* commence and reflow the raidz data across all the disks including the
@@ -8368,6 +8349,8 @@ zpool_do_reopen(int argc, char **argv)
typedef struct scrub_cbdata {
int cb_type;
pool_scrub_cmd_t cb_scrub_cmd;
+ time_t cb_date_start;
+ time_t cb_date_end;
} scrub_cbdata_t;
static boolean_t
@@ -8411,8 +8394,8 @@ scrub_callback(zpool_handle_t *zhp, void *data)
return (1);
}
- err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
-
+ err = zpool_scan_range(zhp, cb->cb_type, cb->cb_scrub_cmd,
+ cb->cb_date_start, cb->cb_date_end);
if (err == 0 && zpool_has_checkpoint(zhp) &&
cb->cb_type == POOL_SCAN_SCRUB) {
(void) printf(gettext("warning: will not scrub state that "
@@ -8430,10 +8413,35 @@ wait_callback(zpool_handle_t *zhp, void *data)
return (zpool_wait(zhp, *act));
}
+static time_t
+date_string_to_sec(const char *timestr, boolean_t rounding)
+{
+ struct tm tm = {0};
+ int adjustment = rounding ? 1 : 0;
+
+ /* Allow mktime to determine timezone. */
+ tm.tm_isdst = -1;
+
+ if (strptime(timestr, "%Y-%m-%d %H:%M", &tm) == NULL) {
+ if (strptime(timestr, "%Y-%m-%d", &tm) == NULL) {
+ fprintf(stderr, gettext("Failed to parse the date.\n"));
+ usage(B_FALSE);
+ }
+ adjustment *= 24 * 60 * 60;
+ } else {
+ adjustment *= 60;
+ }
+
+ return (mktime(&tm) + adjustment);
+}
+
/*
- * zpool scrub [-e | -s | -p | -C] [-w] <pool> ...
+ * zpool scrub [-e | -s | -p | -C | -E | -S] [-w] [-a | <pool> ...]
*
+ * -a Scrub all pools.
* -e Only scrub blocks in the error log.
+ * -E End date of scrub.
+ * -S Start date of scrub.
* -s Stop. Stops any in-progress scrub.
* -p Pause. Pause in-progress scrub.
* -w Wait. Blocks until scrub has completed.
@@ -8449,21 +8457,36 @@ zpool_do_scrub(int argc, char **argv)
cb.cb_type = POOL_SCAN_SCRUB;
cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
+ cb.cb_date_start = cb.cb_date_end = 0;
boolean_t is_error_scrub = B_FALSE;
boolean_t is_pause = B_FALSE;
boolean_t is_stop = B_FALSE;
boolean_t is_txg_continue = B_FALSE;
+ boolean_t scrub_all = B_FALSE;
/* check options */
- while ((c = getopt(argc, argv, "spweC")) != -1) {
+ while ((c = getopt(argc, argv, "aspweCE:S:")) != -1) {
switch (c) {
+ case 'a':
+ scrub_all = B_TRUE;
+ break;
case 'e':
is_error_scrub = B_TRUE;
break;
+ case 'E':
+ /*
+ * Round the date. It's better to scrub more data than
+ * less. This also makes the date inclusive.
+ */
+ cb.cb_date_end = date_string_to_sec(optarg, B_TRUE);
+ break;
case 's':
is_stop = B_TRUE;
break;
+ case 'S':
+ cb.cb_date_start = date_string_to_sec(optarg, B_FALSE);
+ break;
case 'p':
is_pause = B_TRUE;
break;
@@ -8511,6 +8534,19 @@ zpool_do_scrub(int argc, char **argv)
}
}
+ if ((cb.cb_date_start != 0 || cb.cb_date_end != 0) &&
+ cb.cb_scrub_cmd != POOL_SCRUB_NORMAL) {
+ (void) fprintf(stderr, gettext("invalid option combination: "
+ "start/end date is available only with normal scrub\n"));
+ usage(B_FALSE);
+ }
+ if (cb.cb_date_start != 0 && cb.cb_date_end != 0 &&
+ cb.cb_date_start > cb.cb_date_end) {
+ (void) fprintf(stderr, gettext("invalid arguments: "
+ "end date has to be later than start date\n"));
+ usage(B_FALSE);
+ }
+
if (wait && (cb.cb_type == POOL_SCAN_NONE ||
cb.cb_scrub_cmd == POOL_SCRUB_PAUSE)) {
(void) fprintf(stderr, gettext("invalid option combination: "
@@ -8521,7 +8557,7 @@ zpool_do_scrub(int argc, char **argv)
argc -= optind;
argv += optind;
- if (argc < 1) {
+ if (argc < 1 && !scrub_all) {
(void) fprintf(stderr, gettext("missing pool name argument\n"));
usage(B_FALSE);
}
@@ -8551,6 +8587,7 @@ zpool_do_resilver(int argc, char **argv)
cb.cb_type = POOL_SCAN_RESILVER;
cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
+ cb.cb_date_start = cb.cb_date_end = 0;
/* check options */
while ((c = getopt(argc, argv, "")) != -1) {
@@ -8575,8 +8612,9 @@ zpool_do_resilver(int argc, char **argv)
}
/*
- * zpool trim [-d] [-r <rate>] [-c | -s] <pool> [<device> ...]
+ * zpool trim [-d] [-r <rate>] [-c | -s] <-a | pool> [<device> ...]
*
+ * -a Trim all pools.
* -c Cancel. Ends any in-progress trim.
* -d Secure trim. Requires kernel and device support.
* -r <rate> Sets the TRIM rate in bytes (per second). Supports
@@ -8593,6 +8631,7 @@ zpool_do_trim(int argc, char **argv)
{"rate", required_argument, NULL, 'r'},
{"suspend", no_argument, NULL, 's'},
{"wait", no_argument, NULL, 'w'},
+ {"all", no_argument, NULL, 'a'},
{0, 0, 0, 0}
};
@@ -8600,11 +8639,16 @@ zpool_do_trim(int argc, char **argv)
uint64_t rate = 0;
boolean_t secure = B_FALSE;
boolean_t wait = B_FALSE;
+ boolean_t trimall = B_FALSE;
+ int error;
int c;
- while ((c = getopt_long(argc, argv, "cdr:sw", long_options, NULL))
+ while ((c = getopt_long(argc, argv, "acdr:sw", long_options, NULL))
!= -1) {
switch (c) {
+ case 'a':
+ trimall = B_TRUE;
+ break;
case 'c':
if (cmd_type != POOL_TRIM_START &&
cmd_type != POOL_TRIM_CANCEL) {
@@ -8663,7 +8707,18 @@ zpool_do_trim(int argc, char **argv)
argc -= optind;
argv += optind;
- if (argc < 1) {
+ trimflags_t trim_flags = {
+ .secure = secure,
+ .rate = rate,
+ .wait = wait,
+ };
+
+ trim_cbdata_t cbdata = {
+ .trim_flags = trim_flags,
+ .cmd_type = cmd_type
+ };
+
+ if (argc < 1 && !trimall) {
(void) fprintf(stderr, gettext("missing pool name argument\n"));
usage(B_FALSE);
return (-1);
@@ -8671,41 +8726,46 @@ zpool_do_trim(int argc, char **argv)
if (wait && (cmd_type != POOL_TRIM_START)) {
(void) fprintf(stderr, gettext("-w cannot be used with -c or "
- "-s\n"));
+ "-s options\n"));
usage(B_FALSE);
}
- char *poolname = argv[0];
- zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
- if (zhp == NULL)
- return (-1);
-
- trimflags_t trim_flags = {
- .secure = secure,
- .rate = rate,
- .wait = wait,
- };
+ if (trimall && argc > 0) {
+ (void) fprintf(stderr, gettext("-a cannot be combined with "
+ "individual zpools or vdevs\n"));
+ usage(B_FALSE);
+ }
- nvlist_t *vdevs = fnvlist_alloc();
- if (argc == 1) {
+ if (argc == 0 && trimall) {
+ cbdata.trim_flags.fullpool = B_TRUE;
+ /* Trim each pool recursively */
+ error = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
+ B_FALSE, zpool_trim_one, &cbdata);
+ } else if (argc == 1) {
+ char *poolname = argv[0];
+ zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
+ if (zhp == NULL)
+ return (-1);
/* no individual leaf vdevs specified, so add them all */
- nvlist_t *config = zpool_get_config(zhp, NULL);
- nvlist_t *nvroot = fnvlist_lookup_nvlist(config,
- ZPOOL_CONFIG_VDEV_TREE);
- zpool_collect_leaves(zhp, nvroot, vdevs);
- trim_flags.fullpool = B_TRUE;
+ error = zpool_trim_one(zhp, &cbdata);
+ zpool_close(zhp);
} else {
- trim_flags.fullpool = B_FALSE;
+ char *poolname = argv[0];
+ zpool_handle_t *zhp = zpool_open(g_zfs, poolname);
+ if (zhp == NULL)
+ return (-1);
+ /* leaf vdevs specified, trim only those */
+ cbdata.trim_flags.fullpool = B_FALSE;
+ nvlist_t *vdevs = fnvlist_alloc();
for (int i = 1; i < argc; i++) {
fnvlist_add_boolean(vdevs, argv[i]);
}
+ error = zpool_trim(zhp, cbdata.cmd_type, vdevs,
+ &cbdata.trim_flags);
+ fnvlist_free(vdevs);
+ zpool_close(zhp);
}
- int error = zpool_trim(zhp, cmd_type, vdevs, &trim_flags);
-
- fnvlist_free(vdevs);
- zpool_close(zhp);
-
return (error);
}
@@ -10432,10 +10492,9 @@ print_status_reason(zpool_handle_t *zhp, status_cbdata_t *cbp,
break;
case ZPOOL_STATUS_REMOVED_DEV:
- snprintf(status, ST_SIZE, gettext("One or more devices has "
- "been removed by the administrator.\n\tSufficient "
- "replicas exist for the pool to continue functioning in "
- "a\n\tdegraded state.\n"));
+ snprintf(status, ST_SIZE, gettext("One or more devices have "
+ "been removed.\n\tSufficient replicas exist for the pool "
+ "to continue functioning in a\n\tdegraded state.\n"));
snprintf(action, AC_SIZE, gettext("Online the device "
"using zpool online' or replace the device with\n\t'zpool "
"replace'.\n"));
@@ -10707,7 +10766,6 @@ status_callback_json(zpool_handle_t *zhp, void *data)
uint_t c;
vdev_stat_t *vs;
nvlist_t *item, *d, *load_info, *vds;
- item = d = NULL;
/* If dedup stats were requested, also fetch dedupcached. */
if (cbp->cb_dedup_stats > 1)
@@ -10980,28 +11038,30 @@ status_callback(zpool_handle_t *zhp, void *data)
}
/*
- * zpool status [-c [script1,script2,...]] [-dDegiLpPstvx] [--power] ...
- * [-T d|u] [pool] [interval [count]]
+ * zpool status [-dDegiLpPstvx] [-c [script1,script2,...]] ...
+ * [-j|--json [--json-flat-vdevs] [--json-int] ...
+ * [--json-pool-key-guid]] [--power] [-T d|u] ...
+ * [pool] [interval [count]]
*
* -c CMD For each vdev, run command CMD
- * -d Display Direct I/O write verify errors
* -D Display dedup status (undocumented)
+ * -d Display Direct I/O write verify errors
* -e Display only unhealthy vdevs
* -g Display guid for individual vdev name.
* -i Display vdev initialization status.
+ * -j [...] Display output in JSON format
+ * --json-flat-vdevs Display vdevs in flat hierarchy
+ * --json-int Display numbers in integer format instead of string
+ * --json-pool-key-guid Use pool GUID as key for pool objects
* -L Follow links when resolving vdev path name.
- * -p Display values in parsable (exact) format.
* -P Display full path for vdev name.
+ * -p Display values in parsable (exact) format.
+ * --power Display vdev enclosure slot power status
* -s Display slow IOs column.
- * -t Display vdev TRIM status.
* -T Display a timestamp in date(1) or Unix format
+ * -t Display vdev TRIM status.
* -v Display complete error logs
* -x Display only pools with potential problems
- * -j Display output in JSON format
- * --power Display vdev enclosure slot power status
- * --json-int Display numbers in inteeger format instead of string
- * --json-flat-vdevs Display vdevs in flat hierarchy
- * --json-pool-key-guid Use pool GUID as key for pool objects
*
* Describes the health status of all pools or some subset.
*/
@@ -11329,7 +11389,8 @@ upgrade_enable_all(zpool_handle_t *zhp, int *countp)
const char *fname = spa_feature_table[i].fi_uname;
const char *fguid = spa_feature_table[i].fi_guid;
- if (!spa_feature_table[i].fi_zfs_mod_supported)
+ if (!spa_feature_table[i].fi_zfs_mod_supported ||
+ (spa_feature_table[i].fi_flags & ZFEATURE_FLAG_NO_UPGRADE))
continue;
if (!nvlist_exists(enabled, fguid) && requested_features[i]) {
@@ -11484,7 +11545,11 @@ upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
"Note that the pool "
"'compatibility' feature can be "
"used to inhibit\nfeature "
- "upgrades.\n\n"));
+ "upgrades.\n\n"
+ "Features marked with (*) are not "
+ "applied automatically on upgrade, "
+ "and\nmust be applied explicitly "
+ "with zpool-set(7).\n\n"));
(void) printf(gettext("POOL "
"FEATURE\n"));
(void) printf(gettext("------"
@@ -11498,7 +11563,9 @@ upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
poolfirst = B_FALSE;
}
- (void) printf(gettext(" %s\n"), fname);
+ (void) printf(gettext(" %s%s\n"), fname,
+ spa_feature_table[i].fi_flags &
+ ZFEATURE_FLAG_NO_UPGRADE ? "(*)" : "");
}
/*
* If they did "zpool upgrade -a", then we could
@@ -12069,6 +12136,11 @@ zpool_do_events_nvprint(nvlist_t *nvl, int depth)
sizeof (flagstr));
printf(gettext("0x%x [%s]"), i32, flagstr);
} else if (strcmp(name,
+ FM_EREPORT_PAYLOAD_ZFS_ZIO_TYPE) == 0) {
+ zfs_valstr_zio_type(i32, flagstr,
+ sizeof (flagstr));
+ printf(gettext("0x%x [%s]"), i32, flagstr);
+ } else if (strcmp(name,
FM_EREPORT_PAYLOAD_ZFS_ZIO_PRIORITY) == 0) {
zfs_valstr_zio_priority(i32, flagstr,
sizeof (flagstr));
@@ -12294,7 +12366,7 @@ zpool_do_events_next(ev_opts_t *opts)
nvlist_free(nvl);
}
- VERIFY(0 == close(zevent_fd));
+ VERIFY0(close(zevent_fd));
return (ret);
}
@@ -12747,11 +12819,13 @@ found:
if (strcmp(argv[1], "root") == 0)
vdev = strdup("root-0");
- else
- vdev = strdup(argv[1]);
/* ... and the rest are vdev names */
- cb.cb_vdevs.cb_names = &vdev;
+ if (vdev == NULL)
+ cb.cb_vdevs.cb_names = argv + 1;
+ else
+ cb.cb_vdevs.cb_names = &vdev;
+
cb.cb_vdevs.cb_names_count = argc - 1;
cb.cb_type = ZFS_TYPE_VDEV;
argc = 1; /* One pool to process */