summaryrefslogtreecommitdiffstats
path: root/cddl/contrib/opensolaris/cmd/zpool
diff options
context:
space:
mode:
authormm <mm@FreeBSD.org>2012-05-27 16:00:00 +0000
committermm <mm@FreeBSD.org>2012-05-27 16:00:00 +0000
commit38ef930079cbb1df5de9df3c1064426dba3976b1 (patch)
tree30fa7a955d657db9e029a43bcefda627cc7a28c8 /cddl/contrib/opensolaris/cmd/zpool
parenta672aabea920d34e84bd86ff013aa294bf6a5f7b (diff)
downloadFreeBSD-src-38ef930079cbb1df5de9df3c1064426dba3976b1.zip
FreeBSD-src-38ef930079cbb1df5de9df3c1064426dba3976b1.tar.gz
Import illumos changeset 13570:3411fd5f1589
1948 zpool list should show more detailed pool information Display per-vdev information with "zpool list -v". The added expandsize property has currently no value on FreeBSD. This changeset allows adding expansion support to individual vdevs in the future. References: https://www.illumos.org/issues/1948 Obtained from: illumos (issue #1948) MFC after: 2 weeks
Diffstat (limited to 'cddl/contrib/opensolaris/cmd/zpool')
-rw-r--r--cddl/contrib/opensolaris/cmd/zpool/zpool.84
-rw-r--r--cddl/contrib/opensolaris/cmd/zpool/zpool_main.c242
2 files changed, 213 insertions, 33 deletions
diff --git a/cddl/contrib/opensolaris/cmd/zpool/zpool.8 b/cddl/contrib/opensolaris/cmd/zpool/zpool.8
index ef3900e..48ff501 100644
--- a/cddl/contrib/opensolaris/cmd/zpool/zpool.8
+++ b/cddl/contrib/opensolaris/cmd/zpool/zpool.8
@@ -537,6 +537,8 @@ value of 1.76 indicates that 1.76 units of data were stored but only 1 unit of d
for a description of the deduplication feature.
.It Sy free
Number of blocks within the pool that are not allocated.
+.It Sy expandsize
+This property has currently no value on FreeBSD.
.It Sy guid
A unique identifier for the pool.
.It Sy health
@@ -1275,7 +1277,7 @@ Treat exported or foreign devices as inactive.
.It Xo
.Nm
.Cm list
-.Op Fl H
+.Op Fl Hv
.Op Fl o Ar property Ns Op , Ns Ar ...
.Op Fl T Cm d Ns | Ns Cm u
.Op Ar pool
diff --git a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
index 43cf020..3904e68 100644
--- a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
+++ b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
@@ -22,9 +22,9 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2012 by Frederik Wessels. All rights reserved.
- * Copyright (c) 2011 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
+ * Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
*/
#include <solaris.h>
@@ -46,6 +46,7 @@
#include <pwd.h>
#include <zone.h>
#include <sys/time.h>
+#include <zfs_prop.h>
#include <sys/fs/zfs.h>
#include <sys/stat.h>
@@ -70,6 +71,7 @@ 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 **);
@@ -132,7 +134,8 @@ typedef enum {
HELP_GET,
HELP_SET,
HELP_SPLIT,
- HELP_REGUID
+ HELP_REGUID,
+ HELP_REOPEN
} zpool_help_t;
@@ -167,6 +170,7 @@ 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 },
@@ -241,6 +245,8 @@ 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:
@@ -2109,10 +2115,10 @@ error:
}
typedef struct iostat_cbdata {
- zpool_list_t *cb_list;
- int cb_verbose;
- int cb_iteration;
+ boolean_t cb_verbose;
int cb_namewidth;
+ int cb_iteration;
+ zpool_list_t *cb_list;
} iostat_cbdata_t;
static void
@@ -2582,8 +2588,9 @@ 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;
@@ -2591,16 +2598,27 @@ typedef struct list_cbdata {
* Given a list of columns to display, output appropriate headers for each one.
*/
static void
-print_header(zprop_list_t *pl)
+print_header(list_cbdata_t *cb)
{
+ zprop_list_t *pl = cb->cb_proplist;
const char *header;
boolean_t first = B_TRUE;
boolean_t right_justify;
+ size_t width = 0;
for (; pl != NULL; pl = pl->pl_next) {
if (pl->pl_prop == ZPROP_INVAL)
continue;
+ 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)
(void) printf(" ");
else
@@ -2612,9 +2630,10 @@ print_header(zprop_list_t *pl)
if (pl->pl_next == NULL && !right_justify)
(void) printf("%s", header);
else if (right_justify)
- (void) printf("%*s", pl->pl_width, header);
+ (void) printf("%*s", width, header);
else
- (void) printf("%-*s", pl->pl_width, header);
+ (void) printf("%-*s", width, header);
+
}
(void) printf("\n");
@@ -2625,17 +2644,28 @@ print_header(zprop_list_t *pl)
* to the described layout.
*/
static void
-print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
+print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
{
+ zprop_list_t *pl = cb->cb_proplist;
boolean_t first = B_TRUE;
char property[ZPOOL_MAXPROPLEN];
char *propstr;
boolean_t right_justify;
- int width;
+ size_t 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 (scripted)
+ if (cb->cb_scripted)
(void) printf("\t");
else
(void) printf(" ");
@@ -2645,7 +2675,10 @@ print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
right_justify = B_FALSE;
if (pl->pl_prop != ZPROP_INVAL) {
- if (zpool_get_prop(zhp, pl->pl_prop, property,
+ 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,
sizeof (property), NULL) != 0)
propstr = "-";
else
@@ -2656,14 +2689,13 @@ print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
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 (scripted || (pl->pl_next == NULL && !right_justify))
+ if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
(void) printf("%s", propstr);
else if (right_justify)
(void) printf("%*s", width, propstr);
@@ -2674,6 +2706,101 @@ print_pool(zpool_handle_t *zhp, zprop_list_t *pl, int scripted)
(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.
*/
@@ -2681,14 +2808,18 @@ int
list_callback(zpool_handle_t *zhp, void *data)
{
list_cbdata_t *cbp = data;
+ nvlist_t *config;
+ nvlist_t *nvroot;
- if (cbp->cb_first) {
- if (!cbp->cb_scripted)
- print_header(cbp->cb_proplist);
- cbp->cb_first = B_FALSE;
- }
+ config = zpool_get_config(zhp, NULL);
- print_pool(zhp, cbp->cb_proplist, cbp->cb_scripted);
+ 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);
return (0);
}
@@ -2712,12 +2843,15 @@ zpool_do_list(int argc, char **argv)
int ret;
list_cbdata_t cb = { 0 };
static char default_props[] =
- "name,size,allocated,free,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:")) != -1) {
+ while ((c = getopt(argc, argv, ":Ho:T:v")) != -1) {
switch (c) {
case 'H':
cb.cb_scripted = B_TRUE;
@@ -2728,6 +2862,9 @@ 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);
@@ -2748,21 +2885,32 @@ zpool_do_list(int argc, char **argv)
if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
usage(B_FALSE);
- cb.cb_first = B_TRUE;
+ 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);
+ }
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);
- 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);
+ if (!cb.cb_scripted && (first || cb.cb_verbose)) {
+ print_header(&cb);
+ first = B_FALSE;
}
+ ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
if (interval == 0)
break;
@@ -3382,6 +3530,36 @@ zpool_do_reguid(int argc, char **argv)
}
+/*
+ * 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;
OpenPOWER on IntegriCloud