diff options
author | mm <mm@FreeBSD.org> | 2012-05-27 16:00:00 +0000 |
---|---|---|
committer | mm <mm@FreeBSD.org> | 2012-05-27 16:00:00 +0000 |
commit | 38ef930079cbb1df5de9df3c1064426dba3976b1 (patch) | |
tree | 30fa7a955d657db9e029a43bcefda627cc7a28c8 /cddl | |
parent | a672aabea920d34e84bd86ff013aa294bf6a5f7b (diff) | |
download | FreeBSD-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')
-rw-r--r-- | cddl/contrib/opensolaris/cmd/zpool/zpool.8 | 4 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/cmd/zpool/zpool_main.c | 242 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h | 3 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c | 33 |
4 files changed, 242 insertions, 40 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; diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h index 129d81e..989dd80 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h @@ -24,7 +24,7 @@ * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>. * All rights reserved. - * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. * Copyright (c) 2012, Joyent, Inc. All rights reserved. * Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved. */ @@ -237,6 +237,7 @@ typedef struct splitflags { extern int zpool_scan(zpool_handle_t *, pool_scan_func_t); extern int zpool_clear(zpool_handle_t *, const char *, nvlist_t *); extern int zpool_reguid(zpool_handle_t *); +extern int zpool_reopen(zpool_handle_t *); extern int zpool_vdev_online(zpool_handle_t *, const char *, int, vdev_state_t *); diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c index 2605768..723a523 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c @@ -22,7 +22,7 @@ /* * 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. */ #include <sys/types.h> @@ -301,6 +301,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len, case ZPOOL_PROP_SIZE: case ZPOOL_PROP_ALLOCATED: case ZPOOL_PROP_FREE: + case ZPOOL_PROP_EXPANDSZ: (void) zfs_nicenum(intval, buf, len); break; @@ -390,8 +391,8 @@ pool_uses_efi(nvlist_t *config) return (B_FALSE); } -static boolean_t -pool_is_bootable(zpool_handle_t *zhp) +boolean_t +zpool_is_bootable(zpool_handle_t *zhp) { char bootfs[ZPOOL_MAXNAMELEN]; @@ -1126,7 +1127,7 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) return (zfs_error(hdl, EZFS_BADVERSION, msg)); } - if (pool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot, + if (zpool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0) { uint64_t s; @@ -2412,7 +2413,7 @@ zpool_vdev_attach(zpool_handle_t *zhp, uint_t children; nvlist_t *config_root; libzfs_handle_t *hdl = zhp->zpool_hdl; - boolean_t rootpool = pool_is_bootable(zhp); + boolean_t rootpool = zpool_is_bootable(zhp); if (replacing) (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, @@ -3054,6 +3055,26 @@ zpool_reguid(zpool_handle_t *zhp) } /* + * Reopen the pool. + */ +int +zpool_reopen(zpool_handle_t *zhp) +{ + zfs_cmd_t zc = { 0 }; + char msg[1024]; + libzfs_handle_t *hdl = zhp->zpool_hdl; + + (void) snprintf(msg, sizeof (msg), + dgettext(TEXT_DOMAIN, "cannot reopen '%s'"), + zhp->zpool_name); + + (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); + if (zfs_ioctl(hdl, ZFS_IOC_POOL_REOPEN, &zc) == 0) + return (0); + return (zpool_standard_error(hdl, errno, msg)); +} + +/* * Convert from a devid string to a path. */ static char * @@ -3703,7 +3724,7 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name) if (zhp) { nvlist_t *nvroot; - if (pool_is_bootable(zhp)) { + if (zpool_is_bootable(zhp)) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "EFI labeled devices are not supported on root " "pools.")); |