summaryrefslogtreecommitdiff
path: root/usr/src/cmd/zpool/zpool_main.c
diff options
context:
space:
mode:
authorJohn Sonnenschein <johns@joyent.com>2012-05-17 18:26:57 +0000
committerJohn Sonnenschein <johns@joyent.com>2012-05-17 18:26:57 +0000
commit04b244dd661c24b510ac22936decfc0972d202d3 (patch)
tree3ebfef98afc303fddf3415d6fba64e8682f495e8 /usr/src/cmd/zpool/zpool_main.c
parenteac250589e41f1b705e1b7427b02b3379aac9f9e (diff)
parenta69187741b83640a90dd8586195456dd50c016a8 (diff)
downloadillumos-joyent-20120517.tar.gz
Merge git.joyent.com:illumos-joyent20120517
Diffstat (limited to 'usr/src/cmd/zpool/zpool_main.c')
-rw-r--r--usr/src/cmd/zpool/zpool_main.c245
1 files changed, 211 insertions, 34 deletions
diff --git a/usr/src/cmd/zpool/zpool_main.c b/usr/src/cmd/zpool/zpool_main.c
index 7de30d1f77..6df035d97d 100644
--- a/usr/src/cmd/zpool/zpool_main.c
+++ b/usr/src/cmd/zpool/zpool_main.c
@@ -23,7 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Joyent, Inc. 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.
*/
@@ -44,6 +44,7 @@
#include <priv.h>
#include <pwd.h>
#include <zone.h>
+#include <zfs_prop.h>
#include <sys/fs/zfs.h>
#include <sys/stat.h>
@@ -67,6 +68,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 **);
@@ -128,7 +130,8 @@ typedef enum {
HELP_GET,
HELP_SET,
HELP_SPLIT,
- HELP_REGUID
+ HELP_REGUID,
+ HELP_REOPEN
} zpool_help_t;
@@ -161,6 +164,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 },
@@ -233,6 +237,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:
@@ -1982,10 +1988,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
@@ -2455,8 +2461,9 @@ zpool_do_iostat(int argc, char **argv)
}
typedef struct list_cbdata {
+ boolean_t cb_verbose;
+ boolean_t cb_namewidth;
boolean_t cb_scripted;
- boolean_t cb_first;
boolean_t cb_literal;
zprop_list_t *cb_proplist;
} list_cbdata_t;
@@ -2465,16 +2472,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
@@ -2486,9 +2504,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");
@@ -2499,18 +2518,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,
- boolean_t literal)
+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(" ");
@@ -2520,8 +2549,11 @@ 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,
- sizeof (property), NULL, literal) != 0)
+ 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, cb->cb_literal) != 0)
propstr = "-";
else
propstr = property;
@@ -2531,14 +2563,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);
@@ -2549,6 +2580,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.
*/
@@ -2556,14 +2682,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, cbp->cb_literal);
+ 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);
}
@@ -2588,12 +2718,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,expandsize,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, ":Hpo:T:")) != -1) {
+ while ((c = getopt(argc, argv, ":Hpo:T:v")) != -1) {
switch (c) {
case 'H':
cb.cb_scripted = B_TRUE;
@@ -2607,6 +2740,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);
@@ -2627,21 +2763,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;
@@ -3261,6 +3408,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;
@@ -3532,7 +3709,7 @@ print_dedup_stats(nvlist_t *config)
/*
* If the pool was faulted then we may not have been able to
- * obtain the config. Otherwise, if have anything in the dedup
+ * obtain the config. Otherwise, if we have anything in the dedup
* table continue processing the stats.
*/
if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,