aboutsummaryrefslogtreecommitdiff
path: root/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
diff options
context:
space:
mode:
authorAndriy Gapon <avg@FreeBSD.org>2019-11-21 08:20:05 +0000
committerAndriy Gapon <avg@FreeBSD.org>2019-11-21 08:20:05 +0000
commit489912da7bb487a33a7f0642a983c233b22381ba (patch)
tree0fde8cde705e915892dcfb7fcefc6e73cfbc25ca /cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
parentc81e4a699bf02dfb6be1b84f8f4ee5c7544ce84d (diff)
parentf4eba6fe5e46352368dd64b7df8ed55278b1175d (diff)
downloadsrc-489912da7bb487a33a7f0642a983c233b22381ba.tar.gz
src-489912da7bb487a33a7f0642a983c233b22381ba.zip
MFV r354382,r354385: 10601 10757 Pool allocation classes
illumos/illumos-gate@663207adb1669640c01c5ec6949ce78fd806efae https://github.com/illumos/illumos-gate/commit/663207adb1669640c01c5ec6949ce78fd806efae 10601 Pool allocation classes https://www.illumos.org/issues/10601 illumos port of ZoL Pool allocation classes. Includes at least these two commits: 441709695 Pool allocation classes misplacing small file blocks cc99f275a Pool allocation classes 10757 Add -gLp to zpool subcommands for alt vdev names https://www.illumos.org/issues/10757 Port from ZoL of d2f3e292d Add -gLp to zpool subcommands for alt vdev names Note that a subsequent ZoL commit changed -p to -P a77f29f93 Change full path subcommand flag from -p to -P Portions contributed by: Jerry Jelinek <jerry.jelinek@joyent.com> Portions contributed by: HÃ¥kan Johansson <f96hajo@chalmers.se> Portions contributed by: Richard Yao <ryao@gentoo.org> Portions contributed by: Chunwei Chen <david.chen@nutanix.com> Portions contributed by: loli10K <ezomori.nozomu@gmail.com> Author: Don Brady <don.brady@delphix.com> 11541 allocation_classes feature must be enabled to add log device illumos/illumos-gate@c1064fd7ce62fe763a4475e9988ffea3b22137de https://github.com/illumos/illumos-gate/commit/c1064fd7ce62fe763a4475e9988ffea3b22137de https://www.illumos.org/issues/11541 After the allocation_classes feature was integrated, one can no longer add a log device to a pool unless that feature is enabled. There is an explicit check for this, but it is unnecessary in the case of log devices, so we should handle this better instead of forcing the feature to be enabled. Author: Jerry Jelinek <jerry.jelinek@joyent.com> FreeBSD notes. I faithfully added the new -g, -L, -P flags, but only -g does something: vdev GUIDs are displayed instead of device names. -L, resolve symlinks, and -P, display full disk paths, do nothing at the moment. The use of special vdevs is backward compatible for read-only access, so root pools should be bootable, but exercise caution. MFC after: 4 weeks
Notes
Notes: svn path=/head/; revision=354941
Diffstat (limited to 'cddl/contrib/opensolaris/cmd/zpool/zpool_main.c')
-rw-r--r--cddl/contrib/opensolaris/cmd/zpool/zpool_main.c556
1 files changed, 385 insertions, 171 deletions
diff --git a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
index d07d18247e96..d4e0a73ade67 100644
--- a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
+++ b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
@@ -28,6 +28,7 @@
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
* Copyright 2016 Nexenta Systems, Inc.
* Copyright (c) 2017 Datto Inc.
+ * Copyright (c) 2017, Intel Corporation.
*/
#include <solaris.h>
@@ -209,6 +210,8 @@ static zpool_command_t command_table[] = {
#define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
+#define VDEV_ALLOC_CLASS_LOGS "logs"
+
static zpool_command_t *current_command;
static char history_str[HIS_MAX_RECORD_LEN];
static boolean_t log_history = B_TRUE;
@@ -219,7 +222,7 @@ get_usage(zpool_help_t idx)
{
switch (idx) {
case HELP_ADD:
- return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
+ return (gettext("\tadd [-fgLnP] <pool> <vdev> ...\n"));
case HELP_ATTACH:
return (gettext("\tattach [-f] <pool> <device> "
"<new-device>\n"));
@@ -251,12 +254,12 @@ get_usage(zpool_help_t idx)
"[-R root] [-F [-n]] [-t]\n"
"\t [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
case HELP_IOSTAT:
- return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
- "[count]]\n"));
+ return (gettext("\tiostat [-gLPv] [-T d|u] [pool] ... "
+ "[interval [count]]\n"));
case HELP_LABELCLEAR:
return (gettext("\tlabelclear [-f] <vdev>\n"));
case HELP_LIST:
- return (gettext("\tlist [-Hpv] [-o property[,...]] "
+ return (gettext("\tlist [-gHLpPv] [-o property[,...]] "
"[-T d|u] [pool] ... [interval [count]]\n"));
case HELP_OFFLINE:
return (gettext("\toffline [-t] <pool> <device> ...\n"));
@@ -274,8 +277,8 @@ get_usage(zpool_help_t idx)
case HELP_SCRUB:
return (gettext("\tscrub [-s | -p] <pool> ...\n"));
case HELP_STATUS:
- return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
- "[count]]\n"));
+ return (gettext("\tstatus [-DgLPvx] [-T d|u] [pool] ... "
+ "[interval [count]]\n"));
case HELP_UPGRADE:
return (gettext("\tupgrade [-v]\n"
"\tupgrade [-V version] <-a | pool ...>\n"));
@@ -285,7 +288,7 @@ get_usage(zpool_help_t idx)
case HELP_SET:
return (gettext("\tset <property=value> <pool> \n"));
case HELP_SPLIT:
- return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
+ return (gettext("\tsplit [-gLnP] [-R altroot] [-o mntopts]\n"
"\t [-o property=value] <pool> <newpool> "
"[<device> ...]\n"));
case HELP_REGUID:
@@ -307,7 +310,7 @@ print_prop_cb(int prop, void *cb)
{
FILE *fp = cb;
- (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop));
+ (void) fprintf(fp, "\t%-19s ", zpool_prop_to_name(prop));
if (zpool_prop_readonly(prop))
(void) fprintf(fp, " NO ");
@@ -359,14 +362,14 @@ usage(boolean_t requested)
(void) fprintf(fp,
gettext("\nthe following properties are supported:\n"));
- (void) fprintf(fp, "\n\t%-15s %s %s\n\n",
+ (void) fprintf(fp, "\n\t%-19s %s %s\n\n",
"PROPERTY", "EDIT", "VALUES");
/* 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, "\t%-19s ", "feature@...");
(void) fprintf(fp, "YES disabled | enabled | active\n");
(void) fprintf(fp, gettext("\nThe feature@ properties must be "
@@ -384,32 +387,45 @@ usage(boolean_t requested)
exit(requested ? 0 : 2);
}
-void
+/*
+ * print a pool vdev config for dry runs
+ */
+static void
print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
- boolean_t print_logs)
+ const char *match, int name_flags)
{
nvlist_t **child;
uint_t c, children;
char *vname;
-
- if (name != NULL)
- (void) printf("\t%*s%s\n", indent, "", name);
+ boolean_t printed = B_FALSE;
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
- &child, &children) != 0)
+ &child, &children) != 0) {
+ if (name != NULL)
+ (void) printf("\t%*s%s\n", indent, "", name);
return;
+ }
for (c = 0; c < children; c++) {
uint64_t is_log = B_FALSE;
+ char *class = "";
(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
&is_log);
- if ((is_log && !print_logs) || (!is_log && print_logs))
+ if (is_log)
+ class = VDEV_ALLOC_BIAS_LOG;
+ (void) nvlist_lookup_string(child[c],
+ ZPOOL_CONFIG_ALLOCATION_BIAS, &class);
+ if (strcmp(match, class) != 0)
continue;
- vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
- print_vdev_tree(zhp, vname, child[c], indent + 2,
- B_FALSE);
+ if (!printed && name != NULL) {
+ (void) printf("\t%*s%s\n", indent, "", name);
+ printed = B_TRUE;
+ }
+ vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags);
+ print_vdev_tree(zhp, vname, child[c], indent + 2, "",
+ name_flags);
free(vname);
}
}
@@ -517,11 +533,14 @@ add_prop_list_default(const char *propname, char *propval, nvlist_t **props,
}
/*
- * zpool add [-fn] <pool> <vdev> ...
+ * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ...
*
* -f Force addition of devices, even if they appear in use
+ * -g Display guid for individual vdev name.
+ * -L Follow links when resolving vdev path name.
* -n Do not add the devices, but display the resulting layout if
* they were to be added.
+ * -P Display full path for vdev name.
*
* Adds the given vdevs to 'pool'. As with create, the bulk of this work is
* handled by get_vdev_spec(), which constructs the nvlist needed to pass to
@@ -532,6 +551,7 @@ zpool_do_add(int argc, char **argv)
{
boolean_t force = B_FALSE;
boolean_t dryrun = B_FALSE;
+ int name_flags = 0;
int c;
nvlist_t *nvroot;
char *poolname;
@@ -542,14 +562,23 @@ zpool_do_add(int argc, char **argv)
nvlist_t *config;
/* check options */
- while ((c = getopt(argc, argv, "fn")) != -1) {
+ while ((c = getopt(argc, argv, "fgLnP")) != -1) {
switch (c) {
case 'f':
force = B_TRUE;
break;
+ case 'g':
+ name_flags |= VDEV_NAME_GUID;
+ break;
+ case 'L':
+ name_flags |= VDEV_NAME_FOLLOW_LINKS;
+ break;
case 'n':
dryrun = B_TRUE;
break;
+ case 'P':
+ name_flags |= VDEV_NAME_PATH;
+ break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -609,16 +638,25 @@ zpool_do_add(int argc, char **argv)
"configuration:\n"), zpool_get_name(zhp));
/* print original main pool and new tree */
- print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
- print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
-
- /* Do the same for the logs */
- if (num_logs(poolnvroot) > 0) {
- print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
- print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
- } else if (num_logs(nvroot) > 0) {
- print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
- }
+ print_vdev_tree(zhp, poolname, poolnvroot, 0, "",
+ name_flags | VDEV_NAME_TYPE_ID);
+ print_vdev_tree(zhp, NULL, nvroot, 0, "", name_flags);
+
+ /* print other classes: 'dedup', 'special', and 'log' */
+ print_vdev_tree(zhp, "dedup", poolnvroot, 0,
+ VDEV_ALLOC_BIAS_DEDUP, name_flags);
+ print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_DEDUP,
+ name_flags);
+
+ print_vdev_tree(zhp, "special", poolnvroot, 0,
+ VDEV_ALLOC_BIAS_SPECIAL, name_flags);
+ print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_SPECIAL,
+ name_flags);
+
+ print_vdev_tree(zhp, "logs", poolnvroot, 0, VDEV_ALLOC_BIAS_LOG,
+ name_flags);
+ print_vdev_tree(zhp, NULL, nvroot, 0, VDEV_ALLOC_BIAS_LOG,
+ name_flags);
ret = 0;
} else {
@@ -1217,9 +1255,13 @@ zpool_do_create(int argc, char **argv)
(void) printf(gettext("would create '%s' with the "
"following layout:\n\n"), poolname);
- print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
- if (num_logs(nvroot) > 0)
- print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
+ print_vdev_tree(NULL, poolname, nvroot, 0, "", 0);
+ print_vdev_tree(NULL, "dedup", nvroot, 0,
+ VDEV_ALLOC_BIAS_DEDUP, 0);
+ print_vdev_tree(NULL, "special", nvroot, 0,
+ VDEV_ALLOC_BIAS_SPECIAL, 0);
+ print_vdev_tree(NULL, "logs", nvroot, 0,
+ VDEV_ALLOC_BIAS_LOG, 0);
ret = 0;
} else {
@@ -1426,13 +1468,15 @@ zpool_do_export(int argc, char **argv)
* name column.
*/
static int
-max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
+max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max,
+ int name_flags)
{
- char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
+ char *name;
nvlist_t **child;
uint_t c, children;
int ret;
+ name = zpool_vdev_name(g_zfs, zhp, nv, name_flags | VDEV_NAME_TYPE_ID);
if (strlen(name) + depth > max)
max = strlen(name) + depth;
@@ -1442,7 +1486,7 @@ max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
&child, &children) == 0) {
for (c = 0; c < children; c++)
if ((ret = max_width(zhp, child[c], depth + 2,
- max)) > max)
+ max, name_flags)) > max)
max = ret;
}
@@ -1450,7 +1494,7 @@ max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
&child, &children) == 0) {
for (c = 0; c < children; c++)
if ((ret = max_width(zhp, child[c], depth + 2,
- max)) > max)
+ max, name_flags)) > max)
max = ret;
}
@@ -1458,11 +1502,10 @@ max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
&child, &children) == 0) {
for (c = 0; c < children; c++)
if ((ret = max_width(zhp, child[c], depth + 2,
- max)) > max)
+ max, name_flags)) > max)
max = ret;
}
-
return (max);
}
@@ -1511,12 +1554,24 @@ find_spare(zpool_handle_t *zhp, void *data)
return (0);
}
+typedef struct status_cbdata {
+ int cb_count;
+ int cb_name_flags;
+ int cb_namewidth;
+ boolean_t cb_allpools;
+ boolean_t cb_verbose;
+ boolean_t cb_explain;
+ boolean_t cb_first;
+ boolean_t cb_dedup_stats;
+ boolean_t cb_print_status;
+} status_cbdata_t;
+
/*
* Print out configuration state as requested by status_callback.
*/
-void
-print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
- int namewidth, int depth, boolean_t isspare)
+static void
+print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
+ nvlist_t *nv, int depth, boolean_t isspare)
{
nvlist_t **child;
uint_t c, vsc, children;
@@ -1526,7 +1581,7 @@ print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
char *vname;
uint64_t notpresent;
uint64_t ashift;
- spare_cbdata_t cb;
+ spare_cbdata_t spare_cb;
const char *state;
char *type;
@@ -1554,7 +1609,7 @@ print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
state = "AVAIL";
}
- (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth,
+ (void) printf("\t%*s%-*s %-8s", depth, "", cb->cb_namewidth - depth,
name, state);
if (!isspare) {
@@ -1600,17 +1655,17 @@ print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
case VDEV_AUX_SPARED:
verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
- &cb.cb_guid) == 0);
- if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
- if (strcmp(zpool_get_name(cb.cb_zhp),
+ &spare_cb.cb_guid) == 0);
+ if (zpool_iter(g_zfs, find_spare, &spare_cb) == 1) {
+ if (strcmp(zpool_get_name(spare_cb.cb_zhp),
zpool_get_name(zhp)) == 0)
(void) printf(gettext("currently in "
"use"));
else
(void) printf(gettext("in use by "
"pool '%s'"),
- zpool_get_name(cb.cb_zhp));
- zpool_close(cb.cb_zhp);
+ zpool_get_name(spare_cb.cb_zhp));
+ zpool_close(spare_cb.cb_zhp);
} else {
(void) printf(gettext("currently in use"));
}
@@ -1715,20 +1770,25 @@ print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
&ishole);
if (islog || ishole)
continue;
- vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
- print_status_config(zhp, vname, child[c],
- namewidth, depth + 2, isspare);
+ /* Only print normal classes here */
+ if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
+ continue;
+
+ vname = zpool_vdev_name(g_zfs, zhp, child[c],
+ cb->cb_name_flags | VDEV_NAME_TYPE_ID);
+ print_status_config(zhp, cb, vname, child[c], depth + 2,
+ isspare);
free(vname);
}
}
-
/*
* Print the configuration of an exported pool. Iterate over all vdevs in the
* pool, printing out the name and status for each one.
*/
-void
-print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
+static void
+print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv,
+ int depth)
{
nvlist_t **child;
uint_t c, children;
@@ -1743,7 +1803,7 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
(uint64_t **)&vs, &c) == 0);
- (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
+ (void) printf("\t%*s%-*s", depth, "", cb->cb_namewidth - depth, name);
(void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
if (vs->vs_aux != 0) {
@@ -1800,9 +1860,12 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
&is_log);
if (is_log)
continue;
+ if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
+ continue;
- vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
- print_import_config(vname, child[c], namewidth, depth + 2);
+ vname = zpool_vdev_name(g_zfs, NULL, child[c],
+ cb->cb_name_flags | VDEV_NAME_TYPE_ID);
+ print_import_config(cb, vname, child[c], depth + 2);
free(vname);
}
@@ -1810,7 +1873,8 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
&child, &children) == 0) {
(void) printf(gettext("\tcache\n"));
for (c = 0; c < children; c++) {
- vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
+ vname = zpool_vdev_name(g_zfs, NULL, child[c],
+ cb->cb_name_flags);
(void) printf("\t %s\n", vname);
free(vname);
}
@@ -1820,7 +1884,8 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
&child, &children) == 0) {
(void) printf(gettext("\tspares\n"));
for (c = 0; c < children; c++) {
- vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
+ vname = zpool_vdev_name(g_zfs, NULL, child[c],
+ cb->cb_name_flags);
(void) printf("\t %s\n", vname);
free(vname);
}
@@ -1828,39 +1893,62 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
}
/*
- * Print log vdevs.
- * Logs are recorded as top level vdevs in the main pool child array
- * but with "is_log" set to 1. We use either print_status_config() or
- * print_import_config() to print the top level logs then any log
- * children (eg mirrored slogs) are printed recursively - which
- * works because only the top level vdev is marked "is_log"
+ * Print specialized class vdevs.
+ *
+ * These are recorded as top level vdevs in the main pool child array
+ * but with "is_log" set to 1 or an "alloc_bias" string. We use either
+ * print_status_config() or print_import_config() to print the top level
+ * class vdevs then any of their children (eg mirrored slogs) are printed
+ * recursively - which works because only the top level vdev is marked.
*/
static void
-print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose)
+print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
+ const char *class)
{
uint_t c, children;
nvlist_t **child;
+ boolean_t printed = B_FALSE;
+
+ assert(zhp != NULL || !cb->cb_verbose);
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
&children) != 0)
return;
- (void) printf(gettext("\tlogs\n"));
-
for (c = 0; c < children; c++) {
uint64_t is_log = B_FALSE;
- char *name;
+ char *bias = NULL;
+ char *type = NULL;
(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
&is_log);
- if (!is_log)
+
+ if (is_log) {
+ bias = VDEV_ALLOC_CLASS_LOGS;
+ } else {
+ (void) nvlist_lookup_string(child[c],
+ ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
+ (void) nvlist_lookup_string(child[c],
+ ZPOOL_CONFIG_TYPE, &type);
+ }
+
+ if (bias == NULL || strcmp(bias, class) != 0)
continue;
- name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
- if (verbose)
- print_status_config(zhp, name, child[c], namewidth,
- 2, B_FALSE);
+ if (!is_log && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
+ continue;
+
+ if (!printed) {
+ (void) printf("\t%s\t\n", gettext(class));
+ printed = B_TRUE;
+ }
+
+ char *name = zpool_vdev_name(g_zfs, zhp, child[c],
+ cb->cb_name_flags | VDEV_NAME_TYPE_ID);
+ if (cb->cb_print_status)
+ print_status_config(zhp, cb, name, child[c], 2,
+ B_FALSE);
else
- print_import_config(name, child[c], namewidth, 2);
+ print_import_config(cb, name, child[c], 2);
free(name);
}
}
@@ -1882,8 +1970,8 @@ show_import(nvlist_t *config)
int reason;
const char *health;
uint_t vsc;
- int namewidth;
char *comment;
+ status_cbdata_t cb = { 0 };
verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
&name) == 0);
@@ -2115,13 +2203,15 @@ show_import(nvlist_t *config)
(void) printf(gettext(" config:\n\n"));
- namewidth = max_width(NULL, nvroot, 0, 0);
- if (namewidth < 10)
- namewidth = 10;
+ cb.cb_namewidth = max_width(NULL, nvroot, 0, 0, 0);
+ if (cb.cb_namewidth < 10)
+ cb.cb_namewidth = 10;
- print_import_config(name, nvroot, namewidth, 0);
- if (num_logs(nvroot) > 0)
- print_logs(NULL, nvroot, namewidth, B_FALSE);
+ print_import_config(&cb, name, nvroot, 0);
+
+ print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_DEDUP);
+ print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
+ print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_CLASS_LOGS);
if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
(void) printf(gettext("\n\tAdditional devices are known to "
@@ -2783,8 +2873,10 @@ zpool_do_sync(int argc, char **argv)
typedef struct iostat_cbdata {
boolean_t cb_verbose;
+ int cb_name_flags;
int cb_namewidth;
int cb_iteration;
+ boolean_t cb_scripted;
zpool_list_t *cb_list;
} iostat_cbdata_t;
@@ -2820,12 +2912,20 @@ print_one_stat(uint64_t value)
(void) printf(" %5s", buf);
}
+static const char *class_name[] = {
+ VDEV_ALLOC_BIAS_DEDUP,
+ VDEV_ALLOC_BIAS_SPECIAL,
+ VDEV_ALLOC_CLASS_LOGS
+};
+
/*
* Print out all the statistics for the given vdev. This can either be the
* toplevel configuration, or called recursively. If 'name' is NULL, then this
* is a verbose output, and we don't want to display the toplevel pool stats.
+ *
+ * Returns the number of stat lines printed.
*/
-void
+static unsigned int
print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
{
@@ -2833,12 +2933,13 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
uint_t c, children;
vdev_stat_t *oldvs, *newvs;
vdev_stat_t zerovs = { 0 };
+ char *vname;
+ int ret = 0;
uint64_t tdelta;
double scale;
- char *vname;
if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
- return;
+ return (ret);
if (oldnv != NULL) {
verify(nvlist_lookup_uint64_array(oldnv,
@@ -2886,16 +2987,19 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
(void) printf("\n");
if (!cb->cb_verbose)
- return;
+ return (ret);
if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
&newchild, &children) != 0)
- return;
+ return (ret);
if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
&oldchild, &c) != 0)
- return;
+ return (ret);
+ /*
+ * print normal top-level devices
+ */
for (c = 0; c < children; c++) {
uint64_t ishole = B_FALSE, islog = B_FALSE;
@@ -2908,33 +3012,45 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
if (ishole || islog)
continue;
- vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
+ if (nvlist_exists(newchild[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
+ continue;
+
+ vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
+ cb->cb_name_flags);
print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
newchild[c], cb, depth + 2);
free(vname);
}
/*
- * Log device section
+ * print all other top-level devices
*/
-
- if (num_logs(newnv) > 0) {
- (void) printf("%-*s - - - - - "
- "-\n", cb->cb_namewidth, "logs");
-
+ for (uint_t n = 0; n < 3; n++) {
for (c = 0; c < children; c++) {
uint64_t islog = B_FALSE;
+ char *bias = NULL;
+ char *type = NULL;
+
(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);
+ bias = VDEV_ALLOC_CLASS_LOGS;
+ } else {
+ (void) nvlist_lookup_string(newchild[c],
+ ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
+ (void) nvlist_lookup_string(newchild[c],
+ ZPOOL_CONFIG_TYPE, &type);
}
+ if (bias == NULL || strcmp(bias, class_name[n]) != 0)
+ continue;
+ if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
+ continue;
+
+ vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
+ cb->cb_name_flags);
+ ret += print_vdev_stats(zhp, vname, oldnv ?
+ oldchild[c] : NULL, newchild[c], cb, depth + 2);
+ free(vname);
}
}
@@ -2944,23 +3060,25 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
*/
if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
&newchild, &children) != 0)
- return;
+ return (ret);
if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
&oldchild, &c) != 0)
- return;
+ return (ret);
if (children > 0) {
(void) printf("%-*s - - - - - "
"-\n", cb->cb_namewidth, "cache");
for (c = 0; c < children; c++) {
vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
- B_FALSE);
+ cb->cb_name_flags);
print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
newchild[c], cb, depth + 2);
free(vname);
}
}
+
+ return (ret);
}
static int
@@ -3029,7 +3147,7 @@ get_namewidth(zpool_handle_t *zhp, void *data)
cb->cb_namewidth = strlen(zpool_get_name(zhp));
else
cb->cb_namewidth = max_width(zhp, nvroot, 0,
- cb->cb_namewidth);
+ cb->cb_namewidth, cb->cb_name_flags);
}
/*
@@ -3127,8 +3245,11 @@ get_timestamp_arg(char c)
}
/*
- * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
+ * zpool iostat [-gLPv] [-T d|u] [pool] ... [interval [count]]
*
+ * -g Display guid for individual vdev name.
+ * -L Follow links when resolving vdev path name.
+ * -P Display full path for vdev name.
* -v Display statistics for individual vdevs
* -T Display a timestamp in date(1) or Unix format
*
@@ -3147,11 +3268,23 @@ zpool_do_iostat(int argc, char **argv)
unsigned long interval = 0, count = 0;
zpool_list_t *list;
boolean_t verbose = B_FALSE;
- iostat_cbdata_t cb;
+ boolean_t guid = B_FALSE;
+ boolean_t follow_links = B_FALSE;
+ boolean_t full_name = B_FALSE;
+ iostat_cbdata_t cb = { 0 };
/* check options */
- while ((c = getopt(argc, argv, "T:v")) != -1) {
+ while ((c = getopt(argc, argv, "gLPT:v")) != -1) {
switch (c) {
+ case 'g':
+ guid = B_TRUE;
+ break;
+ case 'L':
+ follow_links = B_TRUE;
+ break;
+ case 'P':
+ full_name = B_TRUE;
+ break;
case 'T':
get_timestamp_arg(*optarg);
break;
@@ -3193,6 +3326,12 @@ zpool_do_iostat(int argc, char **argv)
*/
cb.cb_list = list;
cb.cb_verbose = verbose;
+ if (guid)
+ cb.cb_name_flags |= VDEV_NAME_GUID;
+ if (follow_links)
+ cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
+ if (full_name)
+ cb.cb_name_flags |= VDEV_NAME_PATH;
cb.cb_iteration = 0;
cb.cb_namewidth = 0;
@@ -3259,12 +3398,14 @@ zpool_do_iostat(int argc, char **argv)
typedef struct list_cbdata {
boolean_t cb_verbose;
+ int cb_name_flags;
int cb_namewidth;
boolean_t cb_scripted;
zprop_list_t *cb_proplist;
boolean_t cb_literal;
} list_cbdata_t;
+
/*
* Given a list of columns to display, output appropriate headers for each one.
*/
@@ -3320,7 +3461,7 @@ print_header(list_cbdata_t *cb)
/*
* Given a pool and a list of properties, print out all the properties according
- * to the described layout.
+ * to the described layout. Used by zpool_do_list().
*/
static void
print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
@@ -3412,7 +3553,9 @@ print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
}
break;
case ZPOOL_PROP_CAPACITY:
- (void) snprintf(propval, sizeof (propval), "%llu%%", value);
+ (void) snprintf(propval, sizeof (propval),
+ value < 1000 ? "%1.2f%%" : value < 10000 ?
+ "%2.1f%%" : "%3.0f%%", value / 100.0);
break;
default:
zfs_nicenum(value, propval, sizeof (propval));
@@ -3427,6 +3570,9 @@ print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
(void) printf(" %*s", width, propval);
}
+/*
+ * print static default line per vdev
+ */
void
print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
list_cbdata_t *cb, int depth)
@@ -3437,7 +3583,6 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
char *vname;
boolean_t scripted = cb->cb_scripted;
uint64_t islog = B_FALSE;
- boolean_t haslog = B_FALSE;
char *dashes = "%-*s - - - - - -\n";
verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
@@ -3478,7 +3623,7 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
vs->vs_fragmentation, scripted,
(vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel));
cap = (vs->vs_space == 0) ? 0 :
- (vs->vs_alloc * 100 / vs->vs_space);
+ (vs->vs_alloc * 10000 / vs->vs_space);
print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel);
(void) printf("\n");
}
@@ -3487,6 +3632,7 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
&child, &children) != 0)
return;
+ /* list the normal vdevs first */
for (c = 0; c < children; c++) {
uint64_t ishole = B_FALSE;
@@ -3495,24 +3641,48 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
continue;
if (nvlist_lookup_uint64(child[c],
- ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) {
- haslog = B_TRUE;
+ ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog)
continue;
- }
- vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
+ if (nvlist_exists(child[c], ZPOOL_CONFIG_ALLOCATION_BIAS))
+ continue;
+
+ vname = zpool_vdev_name(g_zfs, zhp, child[c],
+ cb->cb_name_flags);
print_list_stats(zhp, vname, child[c], cb, depth + 2);
free(vname);
}
- if (haslog == B_TRUE) {
- /* LINTED E_SEC_PRINTF_VAR_FMT */
- (void) printf(dashes, cb->cb_namewidth, "log");
+ /* list the classes: 'logs', 'dedup', and 'special' */
+ for (uint_t n = 0; n < 3; n++) {
+ boolean_t printed = B_FALSE;
+
for (c = 0; c < children; c++) {
+ char *bias = NULL;
+ char *type = NULL;
+
if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
- &islog) != 0 || !islog)
+ &islog) == 0 && islog) {
+ bias = VDEV_ALLOC_CLASS_LOGS;
+ } else {
+ (void) nvlist_lookup_string(child[c],
+ ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
+ (void) nvlist_lookup_string(child[c],
+ ZPOOL_CONFIG_TYPE, &type);
+ }
+ if (bias == NULL || strcmp(bias, class_name[n]) != 0)
+ continue;
+ if (!islog && strcmp(type, VDEV_TYPE_INDIRECT) == 0)
continue;
- vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
+
+ if (!printed) {
+ /* LINTED E_SEC_PRINTF_VAR_FMT */
+ (void) printf(dashes, cb->cb_namewidth,
+ class_name[n]);
+ printed = B_TRUE;
+ }
+ vname = zpool_vdev_name(g_zfs, zhp, child[c],
+ cb->cb_name_flags);
print_list_stats(zhp, vname, child[c], cb, depth + 2);
free(vname);
}
@@ -3523,7 +3693,8 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
/* LINTED E_SEC_PRINTF_VAR_FMT */
(void) printf(dashes, cb->cb_namewidth, "cache");
for (c = 0; c < children; c++) {
- vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
+ vname = zpool_vdev_name(g_zfs, zhp, child[c],
+ cb->cb_name_flags);
print_list_stats(zhp, vname, child[c], cb, depth + 2);
free(vname);
}
@@ -3534,14 +3705,14 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
/* LINTED E_SEC_PRINTF_VAR_FMT */
(void) printf(dashes, cb->cb_namewidth, "spare");
for (c = 0; c < children; c++) {
- vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
+ vname = zpool_vdev_name(g_zfs, zhp, child[c],
+ cb->cb_name_flags);
print_list_stats(zhp, vname, child[c], cb, depth + 2);
free(vname);
}
}
}
-
/*
* Generic callback function to list a pool.
*/
@@ -3554,26 +3725,37 @@ list_callback(zpool_handle_t *zhp, void *data)
config = zpool_get_config(zhp, NULL);
+ if (cbp->cb_verbose) {
+ config = zpool_get_config(zhp, NULL);
+
+ verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
+ &nvroot) == 0);
+ }
+
+ if (cbp->cb_verbose)
+ cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0,
+ cbp->cb_name_flags);
+
print_pool(zhp, cbp);
- if (!cbp->cb_verbose)
- return (0);
- verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
- &nvroot) == 0);
- print_list_stats(zhp, NULL, nvroot, cbp, 0);
+ if (cbp->cb_verbose)
+ print_list_stats(zhp, NULL, nvroot, cbp, 0);
return (0);
}
/*
- * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
+ * zpool list [-gHLP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
*
+ * -g Display guid for individual vdev name.
* -H Scripted mode. Don't display headers, and separate properties
* by a single tab.
+ * -L Follow links when resolving vdev path name.
* -o List of properties to display. Defaults to
* "name,size,allocated,free,expandsize,fragmentation,capacity,"
* "dedupratio,health,altroot"
* -p Diplay values in parsable (exact) format.
+ * -P Display full path for vdev name.
* -T Display a timestamp in date(1) or Unix format
*
* List all pools in the system, whether or not they're healthy. Output space
@@ -3594,14 +3776,23 @@ zpool_do_list(int argc, char **argv)
boolean_t first = B_TRUE;
/* check options */
- while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
+ while ((c = getopt(argc, argv, ":gHLo:pPT:v")) != -1) {
switch (c) {
+ case 'g':
+ cb.cb_name_flags |= VDEV_NAME_GUID;
+ break;
case 'H':
cb.cb_scripted = B_TRUE;
break;
+ case 'L':
+ cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
+ break;
case 'o':
props = optarg;
break;
+ case 'P':
+ cb.cb_name_flags |= VDEV_NAME_PATH;
+ break;
case 'p':
cb.cb_literal = B_TRUE;
break;
@@ -3610,6 +3801,7 @@ zpool_do_list(int argc, char **argv)
break;
case 'v':
cb.cb_verbose = B_TRUE;
+ cb.cb_namewidth = 8; /* 8 until precalc is avail */
break;
case ':':
(void) fprintf(stderr, gettext("missing argument for "
@@ -3855,13 +4047,16 @@ zpool_do_detach(int argc, char **argv)
}
/*
- * zpool split [-n] [-o prop=val] ...
+ * zpool split [-gLnP] [-o prop=val] ...
* [-o mntopt] ...
* [-R altroot] <pool> <newpool> [<device> ...]
*
+ * -g Display guid for individual vdev name.
+ * -L Follow links when resolving vdev path name.
* -n Do not split the pool, but display the resulting layout if
* it were to be split.
* -o Set property=value, or set mount options.
+ * -P Display full path for vdev name.
* -R Mount the split-off pool under an alternate root.
*
* Splits the named pool and gives it the new pool name. Devices to be split
@@ -3885,10 +4080,17 @@ zpool_do_split(int argc, char **argv)
flags.dryrun = B_FALSE;
flags.import = B_FALSE;
+ flags.name_flags = 0;
/* check options */
- while ((c = getopt(argc, argv, ":R:no:")) != -1) {
+ while ((c = getopt(argc, argv, ":gLR:no:P")) != -1) {
switch (c) {
+ case 'g':
+ flags.name_flags |= VDEV_NAME_GUID;
+ break;
+ case 'L':
+ flags.name_flags |= VDEV_NAME_FOLLOW_LINKS;
+ break;
case 'R':
flags.import = B_TRUE;
if (add_prop_list(
@@ -3914,6 +4116,9 @@ zpool_do_split(int argc, char **argv)
mntopts = optarg;
}
break;
+ case 'P':
+ flags.name_flags |= VDEV_NAME_PATH;
+ break;
case ':':
(void) fprintf(stderr, gettext("missing argument for "
"'%c' option\n"), optopt);
@@ -3961,7 +4166,8 @@ zpool_do_split(int argc, char **argv)
if (flags.dryrun) {
(void) printf(gettext("would create '%s' with the "
"following layout:\n\n"), newpool);
- print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
+ print_vdev_tree(NULL, newpool, config, 0, "",
+ flags.name_flags);
}
nvlist_free(config);
}
@@ -4526,15 +4732,6 @@ zpool_do_initialize(int argc, char **argv)
return (err);
}
-typedef struct status_cbdata {
- int cb_count;
- boolean_t cb_allpools;
- boolean_t cb_verbose;
- boolean_t cb_explain;
- boolean_t cb_first;
- boolean_t cb_dedup_stats;
-} status_cbdata_t;
-
/*
* Print out detailed scrub status.
*/
@@ -4895,8 +5092,8 @@ print_error_log(zpool_handle_t *zhp)
}
static void
-print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
- int namewidth)
+print_spares(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **spares,
+ uint_t nspares)
{
uint_t i;
char *name;
@@ -4907,16 +5104,16 @@ print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
(void) printf(gettext("\tspares\n"));
for (i = 0; i < nspares; i++) {
- name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
- print_status_config(zhp, name, spares[i],
- namewidth, 2, B_TRUE);
+ name = zpool_vdev_name(g_zfs, zhp, spares[i],
+ cb->cb_name_flags);
+ print_status_config(zhp, cb, name, spares[i], 2, B_TRUE);
free(name);
}
}
static void
-print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
- int namewidth)
+print_l2cache(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **l2cache,
+ uint_t nl2cache)
{
uint_t i;
char *name;
@@ -4927,9 +5124,9 @@ print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
(void) printf(gettext("\tcache\n"));
for (i = 0; i < nl2cache; i++) {
- name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
- print_status_config(zhp, name, l2cache[i],
- namewidth, 2, B_FALSE);
+ name = zpool_vdev_name(g_zfs, zhp, l2cache[i],
+ cb->cb_name_flags);
+ print_status_config(zhp, cb, name, l2cache[i], 2, B_FALSE);
free(name);
}
}
@@ -5245,7 +5442,6 @@ status_callback(zpool_handle_t *zhp, void *data)
msgid);
if (config != NULL) {
- int namewidth;
uint64_t nerr;
nvlist_t **spares, **l2cache;
uint_t nspares, nl2cache;
@@ -5265,25 +5461,30 @@ status_callback(zpool_handle_t *zhp, void *data)
print_removal_status(zhp, prs);
print_checkpoint_status(pcs);
- namewidth = max_width(zhp, nvroot, 0, 0);
- if (namewidth < 10)
- namewidth = 10;
+ cbp->cb_namewidth = max_width(zhp, nvroot, 0, 0,
+ cbp->cb_name_flags);
+ if (cbp->cb_namewidth < 10)
+ cbp->cb_namewidth = 10;
(void) printf(gettext("config:\n\n"));
- (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth,
- "NAME", "STATE", "READ", "WRITE", "CKSUM");
- print_status_config(zhp, zpool_get_name(zhp), nvroot,
- namewidth, 0, B_FALSE);
+ (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"),
+ cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE",
+ "CKSUM");
+
+ print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0,
+ B_FALSE);
+
+ print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_DEDUP);
+ print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
+ print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_CLASS_LOGS);
- if (num_logs(nvroot) > 0)
- print_logs(zhp, nvroot, namewidth, B_TRUE);
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
&l2cache, &nl2cache) == 0)
- print_l2cache(zhp, l2cache, nl2cache, namewidth);
+ print_l2cache(zhp, cbp, l2cache, nl2cache);
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
&spares, &nspares) == 0)
- print_spares(zhp, spares, nspares, namewidth);
+ print_spares(zhp, cbp, spares, nspares);
if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
&nerr) == 0) {
@@ -5331,8 +5532,11 @@ status_callback(zpool_handle_t *zhp, void *data)
}
/*
- * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
+ * zpool status [-gLPvx] [-T d|u] [pool] ... [interval [count]]
*
+ * -g Display guid for individual vdev name.
+ * -L Follow links when resolving vdev path name.
+ * -P Display full path for vdev name.
* -v Display complete error logs
* -x Display only pools with potential problems
* -D Display dedup status (undocumented)
@@ -5349,8 +5553,17 @@ zpool_do_status(int argc, char **argv)
status_cbdata_t cb = { 0 };
/* check options */
- while ((c = getopt(argc, argv, "vxDT:")) != -1) {
+ while ((c = getopt(argc, argv, "gLPvxDT:")) != -1) {
switch (c) {
+ case 'g':
+ cb.cb_name_flags |= VDEV_NAME_GUID;
+ break;
+ case 'L':
+ cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
+ break;
+ case 'P':
+ cb.cb_name_flags |= VDEV_NAME_PATH;
+ break;
case 'v':
cb.cb_verbose = B_TRUE;
break;
@@ -5379,6 +5592,7 @@ zpool_do_status(int argc, char **argv)
cb.cb_allpools = B_TRUE;
cb.cb_first = B_TRUE;
+ cb.cb_print_status = B_TRUE;
for (;;) {
if (timestamp_fmt != NODATE)