Illumos #1946: incorrect formatting when listing output of multiple pools with zpool...
[zfs.git] / cmd / zpool / zpool_main.c
index b1bf5bd..bc91771 100644 (file)
@@ -21,6 +21,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 Frederik Wessels. All rights reserved.
  */
 
 #include <assert.h>
@@ -1482,7 +1485,7 @@ show_import(nvlist_t *config)
        }
 
        if (msgid != NULL)
-               (void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
+               (void) printf(gettext("   see: http://zfsonlinux.org/msg/%s\n"),
                    msgid);
 
        (void) printf(gettext("config:\n\n"));
@@ -2086,10 +2089,15 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
                return;
 
        for (c = 0; c < children; c++) {
-               uint64_t ishole = B_FALSE;
+               uint64_t ishole = B_FALSE, islog = B_FALSE;
 
-               if (nvlist_lookup_uint64(newchild[c],
-                   ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
+               (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
+                   &ishole);
+
+               (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
+                   &islog);
+
+               if (ishole || islog)
                        continue;
 
                vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
@@ -2099,6 +2107,31 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
        }
 
        /*
+        * Log device section
+        */
+
+       if (num_logs(newnv) > 0) {
+               (void) printf("%-*s      -      -      -      -      -      "
+                   "-\n", cb->cb_namewidth, "logs");
+
+               for (c = 0; c < children; c++) {
+                       uint64_t islog = B_FALSE;
+                       (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);
+                       }
+               }
+
+       }
+
+       /*
         * Include level 2 ARC devices in iostat output
         */
        if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
@@ -2175,11 +2208,30 @@ print_iostat(zpool_handle_t *zhp, void *data)
        return (0);
 }
 
+static int
+get_columns(void)
+{
+       struct winsize ws;
+       int columns = 80;
+       int error;
+
+       if (isatty(STDOUT_FILENO)) {
+               error = ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
+               if (error == 0)
+                       columns = ws.ws_col;
+       } else {
+               columns = 999;
+       }
+
+       return columns;
+}
+
 int
 get_namewidth(zpool_handle_t *zhp, void *data)
 {
        iostat_cbdata_t *cb = data;
        nvlist_t *config, *nvroot;
+       int columns;
 
        if ((config = zpool_get_config(zhp, NULL)) != NULL) {
                verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
@@ -2187,17 +2239,20 @@ get_namewidth(zpool_handle_t *zhp, void *data)
                if (!cb->cb_verbose)
                        cb->cb_namewidth = strlen(zpool_get_name(zhp));
                else
-                       cb->cb_namewidth = max_width(zhp, nvroot, 0, 0);
+                       cb->cb_namewidth = max_width(zhp, nvroot, 0,
+                           cb->cb_namewidth);
        }
 
        /*
-        * The width must fall into the range [10,38].  The upper limit is the
-        * maximum we can have and still fit in 80 columns.
+        * The width must be at least 10, but may be as large as the
+        * column width - 42 so that we can still fit in one line.
         */
+       columns = get_columns();
+
        if (cb->cb_namewidth < 10)
                cb->cb_namewidth = 10;
-       if (cb->cb_namewidth > 38)
-               cb->cb_namewidth = 38;
+       if (cb->cb_namewidth > columns - 42)
+               cb->cb_namewidth = columns - 42;
 
        return (0);
 }
@@ -2358,42 +2413,48 @@ zpool_do_iostat(int argc, char **argv)
                pool_list_update(list);
 
                if ((npools = pool_list_count(list)) == 0)
-                       break;
-
-               /*
-                * Refresh all statistics.  This is done as an explicit step
-                * before calculating the maximum name width, so that any
-                * configuration changes are properly accounted for.
-                */
-               (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
+                       (void) fprintf(stderr, gettext("no pools available\n"));
+               else {
+                       /*
+                        * Refresh all statistics.  This is done as an
+                        * explicit step before calculating the maximum name
+                        * width, so that any * configuration changes are
+                        * properly accounted for.
+                        */
+                       (void) pool_list_iter(list, B_FALSE, refresh_iostat,
+                               &cb);
 
-               /*
-                * Iterate over all pools to determine the maximum width
-                * for the pool / device name column across all pools.
-                */
-               cb.cb_namewidth = 0;
-               (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
+                       /*
+                        * Iterate over all pools to determine the maximum width
+                        * for the pool / device name column across all pools.
+                        */
+                       cb.cb_namewidth = 0;
+                       (void) pool_list_iter(list, B_FALSE, get_namewidth,
+                               &cb);
 
-               if (timestamp_fmt != NODATE)
-                       print_timestamp(timestamp_fmt);
+                       if (timestamp_fmt != NODATE)
+                               print_timestamp(timestamp_fmt);
 
-               /*
-                * If it's the first time, or verbose mode, print the header.
-                */
-               if (++cb.cb_iteration == 1 || verbose)
-                       print_iostat_header(&cb);
+                       /*
+                        * If it's the first time, or verbose mode, print the
+                        * header.
+                        */
+                       if (++cb.cb_iteration == 1 || verbose)
+                               print_iostat_header(&cb);
 
-               (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
+                       (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
 
-               /*
-                * If there's more than one pool, and we're not in verbose mode
-                * (which prints a separator for us), then print a separator.
-                */
-               if (npools > 1 && !verbose)
-                       print_iostat_separator(&cb);
+                       /*
+                        * If there's more than one pool, and we're not in
+                        * verbose mode (which prints a separator for us),
+                        * then print a separator.
+                        */
+                       if (npools > 1 && !verbose)
+                               print_iostat_separator(&cb);
 
-               if (verbose)
-                       (void) printf("\n");
+                       if (verbose)
+                               (void) printf("\n");
+               }
 
                /*
                 * Flush the output so that redirection to a file isn't buffered
@@ -2592,10 +2653,12 @@ zpool_do_list(int argc, char **argv)
                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"));
+               if (argc == 0 && cb.cb_first)
+                       (void) fprintf(stderr, gettext("no pools available\n"));
+               else if (argc && cb.cb_first) {
+                       /* cannot open the given pool */
                        zprop_free_list(cb.cb_proplist);
-                       return (0);
+                       return (1);
                }
 
                if (interval == 0)
@@ -3440,7 +3503,7 @@ print_dedup_stats(nvlist_t *config)
  *        pool: tank
  *     status: DEGRADED
  *     reason: One or more devices ...
- *         see: http://www.sun.com/msg/ZFS-xxxx-01
+ *         see: http://zfsonlinux.org/msg/ZFS-xxxx-01
  *     config:
  *             mirror          DEGRADED
  *                c1t0d0       OK
@@ -3648,7 +3711,7 @@ status_callback(zpool_handle_t *zhp, void *data)
        }
 
        if (msgid != NULL)
-               (void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
+               (void) printf(gettext("   see: http://zfsonlinux.org/msg/%s\n"),
                    msgid);
 
        if (config != NULL) {
@@ -3785,7 +3848,7 @@ zpool_do_status(int argc, char **argv)
                    status_callback, &cb);
 
                if (argc == 0 && cb.cb_count == 0)
-                       (void) printf(gettext("no pools available\n"));
+                       (void) fprintf(stderr, gettext("no pools available\n"));
                else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
                        (void) printf(gettext("all pools are healthy\n"));
 
@@ -4211,7 +4274,7 @@ zpool_do_history(int argc, char **argv)
            &cbdata);
 
        if (argc == 0 && cbdata.first == B_TRUE) {
-               (void) printf(gettext("no pools available\n"));
+               (void) fprintf(stderr, gettext("no pools available\n"));
                return (0);
        }