diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index 9e37eb228a6f..12b8d331c159 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -257,8 +257,8 @@ get_usage(zpool_help_t idx) { case HELP_SCRUB: return (gettext("\tscrub [-s] ...\n")); case HELP_STATUS: - return (gettext("\tstatus [-vxD] [-T d|u] [pool] ... [interval " - "[count]]\n")); + return (gettext("\tstatus [-gvxD] [-T d|u] [pool] ... [interval" + " [count]]\n")); case HELP_UPGRADE: return (gettext("\tupgrade\n" "\tupgrade -v\n" @@ -368,12 +368,40 @@ usage(boolean_t requested) exit(requested ? 0 : 2); } +/* + * Helper function to simplify setup of the nvlist passed to zpool_vdev_name(). + * The return value is NULL when all arguments are false. Passing NULL to + * zpool_vdev_name() is valid, but freeing a NULL pointer is not. If the values + * vary at runtime, check the return value before freeing the nvlist to avoid + * freeing a NULL pointer. + */ +static nvlist_t * +make_printconf_nvlist(boolean_t verbose, boolean_t print_guid) +{ + nvlist_t *display; + + if (verbose || print_guid) + display = fnvlist_alloc(); + else + return (NULL); + + if (print_guid) + fnvlist_add_boolean(display, "print_guid"); + + if (verbose) + fnvlist_add_boolean(display, "verbose"); + + return (display); + +} + void print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, - boolean_t print_logs) + boolean_t print_logs, boolean_t print_guid) { nvlist_t **child; uint_t c, children; + nvlist_t *display; char *vname; if (name != NULL) @@ -383,6 +411,7 @@ print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, &child, &children) != 0) return; + display = make_printconf_nvlist(B_FALSE, print_guid); for (c = 0; c < children; c++) { uint64_t is_log = B_FALSE; @@ -391,11 +420,14 @@ print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent, if ((is_log && !print_logs) || (!is_log && print_logs)) continue; - vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); + vname = zpool_vdev_name(g_zfs, zhp, child[c], display); print_vdev_tree(zhp, vname, child[c], indent + 2, - B_FALSE); + B_FALSE, print_guid); free(vname); } + + if (display) + fnvlist_free(display); } static boolean_t @@ -605,15 +637,17 @@ 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); + print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE, B_FALSE); + print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE, 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); + print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE, + B_FALSE); + print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE, B_FALSE); } else if (num_logs(nvroot) > 0) { - print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE); + print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE, + B_FALSE); } /* Do the same for the caches */ @@ -1081,9 +1115,10 @@ 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); + print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE, B_FALSE); if (num_logs(nvroot) > 0) - print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE); + print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE, + B_FALSE); ret = 0; } else { @@ -1290,13 +1325,17 @@ 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, + boolean_t print_guid) { - char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE); + nvlist_t *display = make_printconf_nvlist(B_TRUE, print_guid); + char *name = zpool_vdev_name(g_zfs, zhp, nv, display); nvlist_t **child; uint_t c, children; int ret; + fnvlist_free(display); + if (strlen(name) + depth > max) max = strlen(name) + depth; @@ -1306,7 +1345,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, print_guid)) > max) max = ret; } @@ -1314,7 +1353,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, print_guid)) > max) max = ret; } @@ -1322,7 +1361,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, print_guid)) > max) max = ret; } @@ -1380,9 +1419,10 @@ find_spare(zpool_handle_t *zhp, void *data) */ void print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, - int namewidth, int depth, boolean_t isspare) + int namewidth, int depth, boolean_t isspare, boolean_t print_guid) { nvlist_t **child; + nvlist_t *display; uint_t c, children; pool_scan_stat_t *ps = NULL; vdev_stat_t *vs; @@ -1506,6 +1546,7 @@ print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, (void) printf("\n"); + display = make_printconf_nvlist(B_TRUE, print_guid); for (c = 0; c < children; c++) { uint64_t islog = B_FALSE, ishole = B_FALSE; @@ -1516,11 +1557,14 @@ 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); + vname = zpool_vdev_name(g_zfs, zhp, child[c], display); print_status_config(zhp, vname, child[c], - namewidth, depth + 2, isspare); + namewidth, depth + 2, isspare, print_guid); free(vname); } + + if (display) + fnvlist_free(display); } @@ -1529,9 +1573,11 @@ print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv, * pool, printing out the name and status for each one. */ void -print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) +print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth, + boolean_t print_guid) { nvlist_t **child; + nvlist_t *display = NULL; uint_t c, children; vdev_stat_t *vs; char *type, *vname; @@ -1586,6 +1632,7 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) &child, &children) != 0) return; + display = make_printconf_nvlist(B_TRUE, print_guid); for (c = 0; c < children; c++) { uint64_t is_log = B_FALSE; @@ -1594,16 +1641,20 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) if (is_log) 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], display); + print_import_config(vname, child[c], namewidth, depth + 2, + print_guid); free(vname); } + fnvlist_free(display); + display = make_printconf_nvlist(B_FALSE, print_guid); + if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, &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], display); (void) printf("\t %s\n", vname); free(vname); } @@ -1613,11 +1664,13 @@ 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], display); (void) printf("\t %s\n", vname); free(vname); } } + if (display) + fnvlist_free(display); } /* @@ -1629,10 +1682,12 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth) * works because only the top level vdev is marked "is_log" */ static void -print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose) +print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose, + boolean_t print_guid) { uint_t c, children; nvlist_t **child; + nvlist_t *display; if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, &children) != 0) @@ -1640,6 +1695,8 @@ print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose) (void) printf(gettext("\tlogs\n")); + display = make_printconf_nvlist(B_TRUE, print_guid); + for (c = 0; c < children; c++) { uint64_t is_log = B_FALSE; char *name; @@ -1648,14 +1705,17 @@ print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose) &is_log); if (!is_log) continue; - name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE); + name = zpool_vdev_name(g_zfs, zhp, child[c], display); if (verbose) print_status_config(zhp, name, child[c], namewidth, - 2, B_FALSE); + 2, B_FALSE, print_guid); else - print_import_config(name, child[c], namewidth, 2); + print_import_config(name, child[c], namewidth, 2, + print_guid); free(name); } + + fnvlist_free(display); } /* @@ -1902,13 +1962,13 @@ show_import(nvlist_t *config) (void) printf(gettext(" config:\n\n")); - namewidth = max_width(NULL, nvroot, 0, 0); + namewidth = max_width(NULL, nvroot, 0, 0, B_FALSE); if (namewidth < 10) namewidth = 10; - print_import_config(name, nvroot, namewidth, 0); + print_import_config(name, nvroot, namewidth, 0, B_FALSE); if (num_logs(nvroot) > 0) - print_logs(NULL, nvroot, namewidth, B_FALSE); + print_logs(NULL, nvroot, namewidth, B_FALSE, B_FALSE); if (reason == ZPOOL_STATUS_BAD_GUID_SUM) { (void) printf(gettext("\n\tAdditional devices are known to " @@ -2415,6 +2475,7 @@ zpool_do_import(int argc, char **argv) typedef struct iostat_cbdata { boolean_t cb_verbose; + boolean_t cb_print_guid; int cb_namewidth; int cb_iteration; zpool_list_t *cb_list; @@ -2459,9 +2520,10 @@ print_one_stat(uint64_t value) */ void print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, - nvlist_t *newnv, iostat_cbdata_t *cb, int depth) + nvlist_t *newnv, iostat_cbdata_t *cb, int depth, boolean_t print_guid) { nvlist_t **oldchild, **newchild; + nvlist_t *display; uint_t c, children; vdev_stat_t *oldvs, *newvs; vdev_stat_t zerovs = { 0 }; @@ -2525,6 +2587,7 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, &oldchild, &c) != 0) return; + display = make_printconf_nvlist(B_FALSE, print_guid); for (c = 0; c < children; c++) { uint64_t ishole = B_FALSE, islog = B_FALSE; @@ -2537,9 +2600,9 @@ 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); + vname = zpool_vdev_name(g_zfs, zhp, newchild[c], display); print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, - newchild[c], cb, depth + 2); + newchild[c], cb, depth + 2, print_guid); free(vname); } @@ -2558,10 +2621,10 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv, if (islog) { vname = zpool_vdev_name(g_zfs, zhp, newchild[c], - B_FALSE); + display); print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, newchild[c], - cb, depth + 2); + cb, depth + 2, print_guid); free(vname); } } @@ -2573,23 +2636,26 @@ 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; + goto out; if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE, &oldchild, &c) != 0) - return; + goto out; 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); + display); print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL, - newchild[c], cb, depth + 2); + newchild[c], cb, depth + 2, print_guid); free(vname); } } +out: + if (display) + fnvlist_free(display); } static int @@ -2637,7 +2703,8 @@ print_iostat(zpool_handle_t *zhp, void *data) /* * Print out the statistics for the pool. */ - print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0); + print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0, + B_FALSE); if (cb->cb_verbose) print_iostat_separator(cb); @@ -2677,7 +2744,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_print_guid); } /* @@ -2797,6 +2864,7 @@ zpool_do_iostat(int argc, char **argv) unsigned long interval = 0, count = 0; zpool_list_t *list; boolean_t verbose = B_FALSE; + boolean_t print_guid = B_FALSE; iostat_cbdata_t cb; /* check options */ @@ -2843,6 +2911,7 @@ zpool_do_iostat(int argc, char **argv) */ cb.cb_list = list; cb.cb_verbose = verbose; + cb.cb_print_guid = print_guid; cb.cb_iteration = 0; cb.cb_namewidth = 0; @@ -2915,6 +2984,7 @@ zpool_do_iostat(int argc, char **argv) typedef struct list_cbdata { boolean_t cb_verbose; + boolean_t cb_print_guid; int cb_namewidth; boolean_t cb_scripted; zprop_list_t *cb_proplist; @@ -3086,6 +3156,7 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, list_cbdata_t *cb, int depth) { nvlist_t **child; + nvlist_t *display; vdev_stat_t *vs; uint_t c, children; char *vname; @@ -3133,6 +3204,7 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, &child, &children) != 0) return; + display = make_printconf_nvlist(B_FALSE, cb->cb_print_guid); for (c = 0; c < children; c++) { uint64_t ishole = B_FALSE; @@ -3140,7 +3212,7 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole) continue; - vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE); + vname = zpool_vdev_name(g_zfs, zhp, child[c], display); print_list_stats(zhp, vname, child[c], cb, depth + 2); free(vname); } @@ -3150,18 +3222,21 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv, */ if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, &child, &children) != 0) - return; + goto out; 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); + vname = zpool_vdev_name(g_zfs, zhp, child[c], display); print_list_stats(zhp, vname, child[c], cb, depth + 2); free(vname); } } + +out: + if (display) + fnvlist_free(display); } @@ -3587,7 +3662,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, B_FALSE, + B_FALSE); } nvlist_free(config); } @@ -3995,6 +4071,7 @@ typedef struct status_cbdata { int cb_count; boolean_t cb_allpools; boolean_t cb_verbose; + boolean_t cb_print_guid; boolean_t cb_explain; boolean_t cb_first; boolean_t cb_dedup_stats; @@ -4149,8 +4226,9 @@ print_error_log(zpool_handle_t *zhp) static void print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares, - int namewidth) + int namewidth, boolean_t print_guid) { + nvlist_t *display; uint_t i; char *name; @@ -4159,18 +4237,21 @@ print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares, (void) printf(gettext("\tspares\n")); + display = make_printconf_nvlist(B_FALSE, print_guid); for (i = 0; i < nspares; i++) { - name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE); + name = zpool_vdev_name(g_zfs, zhp, spares[i], display); print_status_config(zhp, name, spares[i], - namewidth, 2, B_TRUE); + namewidth, 2, B_TRUE, print_guid); free(name); } + fnvlist_free(display); } static void print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache, - int namewidth) + int namewidth, boolean_t print_guid) { + nvlist_t *display; uint_t i; char *name; @@ -4179,12 +4260,15 @@ print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache, (void) printf(gettext("\tcache\n")); + display = make_printconf_nvlist(B_FALSE, print_guid); for (i = 0; i < nl2cache; i++) { - name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE); + name = zpool_vdev_name(g_zfs, zhp, l2cache[i], display); print_status_config(zhp, name, l2cache[i], - namewidth, 2, B_FALSE); + namewidth, 2, B_FALSE, print_guid); free(name); } + if (display) + fnvlist_free(display); } static void @@ -4524,7 +4608,7 @@ status_callback(zpool_handle_t *zhp, void *data) ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c); print_scan_status(ps); - namewidth = max_width(zhp, nvroot, 0, 0); + namewidth = max_width(zhp, nvroot, 0, 0, cbp->cb_print_guid); if (namewidth < 10) namewidth = 10; @@ -4532,17 +4616,20 @@ status_callback(zpool_handle_t *zhp, void *data) (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); + namewidth, 0, B_FALSE, cbp->cb_print_guid); if (num_logs(nvroot) > 0) - print_logs(zhp, nvroot, namewidth, B_TRUE); + print_logs(zhp, nvroot, namewidth, B_TRUE, + cbp->cb_print_guid); if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE, &l2cache, &nl2cache) == 0) - print_l2cache(zhp, l2cache, nl2cache, namewidth); + print_l2cache(zhp, l2cache, nl2cache, namewidth, + cbp->cb_print_guid); if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0) - print_spares(zhp, spares, nspares, namewidth); + print_spares(zhp, spares, nspares, namewidth, + cbp->cb_print_guid); if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, &nerr) == 0) { @@ -4608,8 +4695,11 @@ 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, "gvxDT:")) != -1) { switch (c) { + case 'g': + cb.cb_print_guid = B_TRUE; + break; case 'v': cb.cb_verbose = B_TRUE; break; diff --git a/include/libzfs.h b/include/libzfs.h index 108b75f5eb3c..9c2ce65db36d 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -406,7 +406,7 @@ struct zfs_cmd; extern const char *zfs_history_event_names[]; extern char *zpool_vdev_name(libzfs_handle_t *, zpool_handle_t *, nvlist_t *, - boolean_t verbose); + nvlist_t *display_args); extern int zpool_upgrade(zpool_handle_t *, uint64_t); extern int zpool_get_history(zpool_handle_t *, nvlist_t **); extern int zpool_history_unpack(char *, uint64_t, uint64_t *, diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index fe26abeb7235..be16a763c665 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -1379,7 +1379,7 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) "device '%s' contains an EFI label and " "cannot be used on root pools."), zpool_vdev_name(hdl, NULL, spares[s], - B_FALSE)); + NULL)); return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg)); } } @@ -1684,6 +1684,7 @@ print_vdev_tree(libzfs_handle_t *hdl, const char *name, nvlist_t *nv, int indent) { nvlist_t **child; + nvlist_t *display; uint_t c, children; char *vname; uint64_t is_log = 0; @@ -1699,11 +1700,15 @@ print_vdev_tree(libzfs_handle_t *hdl, const char *name, nvlist_t *nv, &child, &children) != 0) return; + display = fnvlist_alloc(); + fnvlist_add_boolean(display, "verbose"); + for (c = 0; c < children; c++) { - vname = zpool_vdev_name(hdl, NULL, child[c], B_TRUE); + vname = zpool_vdev_name(hdl, NULL, child[c], display); print_vdev_tree(hdl, vname, child[c], indent + 2); free(vname); } + fnvlist_free(display); } void @@ -2688,7 +2693,7 @@ zpool_vdev_attach(zpool_handle_t *zhp, verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL), ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0); - if ((newname = zpool_vdev_name(NULL, NULL, child[0], B_FALSE)) == NULL) + if ((newname = zpool_vdev_name(NULL, NULL, child[0], NULL)) == NULL) return (-1); /* @@ -2879,11 +2884,11 @@ find_vdev_entry(zpool_handle_t *zhp, nvlist_t **mchild, uint_t mchildren, for (mc = 0; mc < mchildren; mc++) { uint_t sc; char *mpath = zpool_vdev_name(zhp->zpool_hdl, zhp, - mchild[mc], B_FALSE); + mchild[mc], NULL); for (sc = 0; sc < schildren; sc++) { char *spath = zpool_vdev_name(zhp->zpool_hdl, zhp, - schild[sc], B_FALSE); + schild[sc], NULL); boolean_t result = (strcmp(mpath, spath) == 0); free(spath); @@ -3421,17 +3426,23 @@ strip_partition(libzfs_handle_t *hdl, char *path) */ char * zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv, - boolean_t verbose) + nvlist_t *opts) { char *path, *devid, *type; uint64_t value; char buf[PATH_BUF_LEN]; char tmpbuf[PATH_BUF_LEN]; + boolean_t verbose = B_FALSE, guid = B_FALSE; vdev_stat_t *vs; uint_t vsc; - if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, - &value) == 0) { + if (opts) { + guid = (nvlist_lookup_boolean(opts, "print_guid") == 0); + verbose = (nvlist_lookup_boolean(opts, "verbose") == 0); + } + + if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &value) + == 0 || guid) { verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value) == 0); (void) snprintf(buf, sizeof (buf), "%llu", diff --git a/man/man8/zpool.8 b/man/man8/zpool.8 index 00c19305a63a..b390aa9516cf 100644 --- a/man/man8/zpool.8 +++ b/man/man8/zpool.8 @@ -150,7 +150,7 @@ zpool \- configures ZFS storage pools .LP .nf -\fBzpool status\fR [\fB-xvD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]] +\fBzpool status\fR [\fB-gxvD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]] .fi .LP @@ -1848,13 +1848,24 @@ Sets the specified property for \fInewpool\fR. See the “Properties” section .ne 2 .mk .na -\fBzpool status\fR [\fB-xvD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]] +\fBzpool status\fR [\fB-gxvD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]] .ad .sp .6 .RS 4n Displays the detailed health status for the given pools. If no \fIpool\fR is specified, then the status of each pool in the system is displayed. For more information on pool and device health, see the "Device Failure and Recovery" section. .sp If a scrub or resilver is in progress, this command reports the percentage done and the estimated time to completion. Both of these are only approximate, because the amount of data in the pool and the other workloads on the system can change. +.sp +.ne 2 +.mk +.na +\fB\fB-g\fR\fR +.ad +.RS 12n +.rt +Display vdev GUIDs instead of the normal short/long device names. These GUIDs can be used in-place of device names for the zpool detach/offline/remove/replace commands. +.RE + .sp .ne 2 .mk