From a769fb53a17e7f8b6375b25cd23f3ff491b631cb Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 27 Dec 2018 13:12:53 -0800 Subject: [PATCH] Add 'zpool status -i' option Only display the full details of the vdev initialization state in 'zpool status' output when requested with the -i option. By default display '(initializing)' after vdevs when they are being actively initialized. This is consistent with the established precident of appending '(resilvering), etc' and fits within the default 80 column terminal width making it easy to read. Additionally, updated the 'zpool initialize' documentation to make it clear the options are mutually exclusive, but allow duplicate options like all other zfs/zpool commands. Reviewed by: Matt Ahrens Reviewed-by: loli10K Reviewed-by: Tim Chase Reviewed-by: George Wilson Signed-off-by: Brian Behlendorf Closes #8230 --- cmd/zpool/zpool_main.c | 97 +++++++++++-------- man/man8/zpool.8 | 10 +- .../zpool_initialize/zpool_initialize.kshlib | 2 +- 3 files changed, 65 insertions(+), 44 deletions(-) diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index 4e6a699c4f..b96aaf3b7d 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -364,14 +364,15 @@ get_usage(zpool_help_t idx) case HELP_REOPEN: return (gettext("\treopen [-n] \n")); case HELP_INITIALIZE: - return (gettext("\tinitialize [-cs] [ ...]\n")); + return (gettext("\tinitialize [-c | -s] " + "[ ...]\n")); case HELP_SCRUB: return (gettext("\tscrub [-s | -p] ...\n")); case HELP_RESILVER: return (gettext("\tresilver ...\n")); case HELP_STATUS: return (gettext("\tstatus [-c [script1,script2,...]] " - "[-gLpPsvxD] [-T d|u] [pool] ... \n" + "[-igLpPsvxD] [-T d|u] [pool] ... \n" "\t [interval [count]]\n")); case HELP_UPGRADE: return (gettext("\tupgrade\n" @@ -506,7 +507,7 @@ usage(boolean_t requested) } /* - * zpool initialize [-cs] [ ...] + * zpool initialize [-c | -s] [ ...] * Initialize all unused blocks in the specified vdevs, or all vdevs in the pool * if none specified. * @@ -532,7 +533,8 @@ zpool_do_initialize(int argc, char **argv) while ((c = getopt_long(argc, argv, "cs", long_options, NULL)) != -1) { switch (c) { case 'c': - if (cmd_type != POOL_INITIALIZE_DO) { + if (cmd_type != POOL_INITIALIZE_DO && + cmd_type != POOL_INITIALIZE_CANCEL) { (void) fprintf(stderr, gettext("-c cannot be " "combined with other options\n")); usage(B_FALSE); @@ -540,7 +542,8 @@ zpool_do_initialize(int argc, char **argv) cmd_type = POOL_INITIALIZE_CANCEL; break; case 's': - if (cmd_type != POOL_INITIALIZE_DO) { + if (cmd_type != POOL_INITIALIZE_DO && + cmd_type != POOL_INITIALIZE_SUSPEND) { (void) fprintf(stderr, gettext("-s cannot be " "combined with other options\n")); usage(B_FALSE); @@ -1792,6 +1795,7 @@ typedef struct status_cbdata { boolean_t cb_dedup_stats; boolean_t cb_print_status; boolean_t cb_print_slow_ios; + boolean_t cb_print_vdev_init; vdev_cmd_data_list_t *vcdl; } status_cbdata_t; @@ -2040,41 +2044,52 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name, } } - if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE || - vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED || - vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) && - !vs->vs_scan_removing) { - char zbuf[1024]; - char tbuf[256]; - struct tm zaction_ts; + /* Optionally display vdev initialization status for leaves */ + if (cb->cb_print_vdev_init && children == 0) { + if ((vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE || + vs->vs_initialize_state == VDEV_INITIALIZE_SUSPENDED || + vs->vs_initialize_state == VDEV_INITIALIZE_COMPLETE) && + !vs->vs_scan_removing) { + char zbuf[1024]; + char tbuf[256]; + struct tm zaction_ts; - time_t t = vs->vs_initialize_action_time; - int initialize_pct = 100; - if (vs->vs_initialize_state != VDEV_INITIALIZE_COMPLETE) { - initialize_pct = (vs->vs_initialize_bytes_done * 100 / - (vs->vs_initialize_bytes_est + 1)); + time_t t = vs->vs_initialize_action_time; + int initialize_pct = 100; + if (vs->vs_initialize_state != + VDEV_INITIALIZE_COMPLETE) { + initialize_pct = (vs->vs_initialize_bytes_done * + 100 / (vs->vs_initialize_bytes_est + 1)); + } + + (void) localtime_r(&t, &zaction_ts); + (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts); + + switch (vs->vs_initialize_state) { + case VDEV_INITIALIZE_SUSPENDED: + (void) snprintf(zbuf, sizeof (zbuf), + ", suspended, started at %s", tbuf); + break; + case VDEV_INITIALIZE_ACTIVE: + (void) snprintf(zbuf, sizeof (zbuf), + ", started at %s", tbuf); + break; + case VDEV_INITIALIZE_COMPLETE: + (void) snprintf(zbuf, sizeof (zbuf), + ", completed at %s", tbuf); + break; + } + + (void) printf(gettext(" (%d%% initialized%s)"), + initialize_pct, zbuf); + } else { + (void) printf(gettext(" (uninitialized)")); } - - (void) localtime_r(&t, &zaction_ts); - (void) strftime(tbuf, sizeof (tbuf), "%c", &zaction_ts); - - switch (vs->vs_initialize_state) { - case VDEV_INITIALIZE_SUSPENDED: - (void) snprintf(zbuf, sizeof (zbuf), - ", suspended, started at %s", tbuf); - break; - case VDEV_INITIALIZE_ACTIVE: - (void) snprintf(zbuf, sizeof (zbuf), - ", started at %s", tbuf); - break; - case VDEV_INITIALIZE_COMPLETE: - (void) snprintf(zbuf, sizeof (zbuf), - ", completed at %s", tbuf); - break; + } else { + if (vs->vs_initialize_state == VDEV_INITIALIZE_ACTIVE && + children == 0) { + (void) printf(gettext(" (initializing)")); } - - (void) printf(gettext(" (%d%% initialized%s)"), - initialize_pct, zbuf); } (void) printf("\n"); @@ -7477,10 +7492,11 @@ status_callback(zpool_handle_t *zhp, void *data) } /* - * zpool status [-c [script1,script2,...]] [-gLpPsvx] [-T d|u] [pool] ... + * zpool status [-c [script1,script2,...]] [-igLpPsvx] [-T d|u] [pool] ... * [interval [count]] * * -c CMD For each vdev, run command CMD + * -i Display vdev initialization status. * -g Display guid for individual vdev name. * -L Follow links when resolving vdev path name. * -p Display values in parsable (exact) format. @@ -7504,7 +7520,7 @@ zpool_do_status(int argc, char **argv) char *cmd = NULL; /* check options */ - while ((c = getopt(argc, argv, "c:gLpPsvxDT:")) != -1) { + while ((c = getopt(argc, argv, "c:igLpPsvxDT:")) != -1) { switch (c) { case 'c': if (cmd != NULL) { @@ -7530,6 +7546,9 @@ zpool_do_status(int argc, char **argv) } cmd = optarg; break; + case 'i': + cb.cb_print_vdev_init = B_TRUE; + break; case 'g': cb.cb_name_flags |= VDEV_NAME_GUID; break; diff --git a/man/man8/zpool.8 b/man/man8/zpool.8 index a05d4d1f32..8f35ca0ee7 100644 --- a/man/man8/zpool.8 +++ b/man/man8/zpool.8 @@ -116,7 +116,7 @@ .Op Ar newpool Oo Fl t Oc .Nm .Cm initialize -.Op Fl cs +.Op Fl c | Fl s .Ar pool .Op Ar device Ns ... .Nm @@ -187,7 +187,7 @@ .Nm .Cm status .Oo Fl c Ar SCRIPT Oc -.Op Fl DgLpPsvx +.Op Fl DigLpPsvx .Op Fl T Sy u Ns | Ns Sy d .Oo Ar pool Oc Ns ... .Op Ar interval Op Ar count @@ -1603,7 +1603,7 @@ Will also set -o cachefile=none when not explicitly specified. .It Xo .Nm .Cm initialize -.Op Fl cs +.Op Fl c | Fl s .Ar pool .Op Ar device Ns ... .Xc @@ -2199,7 +2199,7 @@ and automatically import it. .Nm .Cm status .Op Fl c Op Ar SCRIPT1 Ns Oo , Ns Ar SCRIPT2 Oc Ns ... -.Op Fl DgLpPsvx +.Op Fl DigLpPsvx .Op Fl T Sy u Ns | Ns Sy d .Oo Ar pool Oc Ns ... .Op Ar interval Op Ar count @@ -2226,6 +2226,8 @@ output. See the option of .Nm zpool Cm iostat for complete details. +.It Fl i +Display vdev initialization status. .It Fl g Display vdev GUIDs instead of the normal device names. These GUIDs can be used in place of device names for the zpool diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib index 0f4e7f0fa9..8b0727483c 100644 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib @@ -21,7 +21,7 @@ function initialize_prog_line # pool disk { typeset pool="$1" typeset disk="$2" - zpool status "$pool" | grep "$disk" | grep "initialized" + zpool status -i "$pool" | grep "$disk" | grep "[[:digit:]]* initialized" } function initialize_progress # pool disk