]> git.proxmox.com Git - mirror_zfs.git/blobdiff - lib/libzfs/libzfs_util.c
Add -lhHpw options to "zpool iostat" for avg latency, histograms, & queues
[mirror_zfs.git] / lib / libzfs / libzfs_util.c
index 57c2ac85386a13bcc53e1c20fc8285c949d70e28..926ed4ed8aa9647980a998e93878585da56450fb 100644 (file)
@@ -596,27 +596,49 @@ zfs_strdup(libzfs_handle_t *hdl, const char *str)
  * Convert a number to an appropriately human-readable output.
  */
 void
-zfs_nicenum(uint64_t num, char *buf, size_t buflen)
+zfs_nicenum_format(uint64_t num, char *buf, size_t buflen,
+    enum zfs_nicenum_format format)
 {
        uint64_t n = num;
        int index = 0;
-       char u;
+       const char *u;
+       const char *units[3][7] = {
+           [ZFS_NICENUM_1024] = {"", "K", "M", "G", "T", "P", "E"},
+           [ZFS_NICENUM_TIME] = {"ns", "us", "ms", "s", "?", "?", "?"}
+       };
+
+       const int units_len[] = {[ZFS_NICENUM_1024] = 6,
+           [ZFS_NICENUM_TIME] = 4};
+
+       const int k_unit[] = {  [ZFS_NICENUM_1024] = 1024,
+           [ZFS_NICENUM_TIME] = 1000};
 
-       while (n >= 1024 && index < 6) {
-               n /= 1024;
+       double val;
+
+       if (format == ZFS_NICENUM_RAW) {
+               snprintf(buf, buflen, "%llu", (u_longlong_t) num);
+               return;
+       }
+
+
+       while (n >= k_unit[format] && index < units_len[format]) {
+               n /= k_unit[format];
                index++;
        }
 
-       u = " KMGTPE"[index];
+       u = units[format][index];
 
-       if (index == 0) {
-               (void) snprintf(buf, buflen, "%llu", (u_longlong_t) n);
-       } else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
+       /* Don't print 0ns times */
+       if ((format == ZFS_NICENUM_TIME) && (num == 0)) {
+               (void) snprintf(buf, buflen, "-");
+       } else if ((index == 0) || ((num %
+           (uint64_t) powl(k_unit[format], index)) == 0)) {
                /*
                 * If this is an even multiple of the base, always display
                 * without any decimal precision.
                 */
-               (void) snprintf(buf, buflen, "%llu%c", (u_longlong_t) n, u);
+               (void) snprintf(buf, buflen, "%llu%s", (u_longlong_t) n, u);
+
        } else {
                /*
                 * We want to choose a precision that reflects the best choice
@@ -629,13 +651,61 @@ zfs_nicenum(uint64_t num, char *buf, size_t buflen)
                 */
                int i;
                for (i = 2; i >= 0; i--) {
-                       if (snprintf(buf, buflen, "%.*f%c", i,
-                           (double)num / (1ULL << 10 * index), u) <= 5)
-                               break;
+                       val = (double) num /
+                           (uint64_t) powl(k_unit[format], index);
+
+                       /*
+                        * Don't print floating point values for time.  Note,
+                        * we use floor() instead of round() here, since
+                        * round can result in undesirable results.  For
+                        * example, if "num" is in the range of
+                        * 999500-999999, it will print out "1000us".  This
+                        * doesn't happen if we use floor().
+                        */
+                       if (format == ZFS_NICENUM_TIME) {
+                               if (snprintf(buf, buflen, "%d%s",
+                                   (unsigned int) floor(val), u) <= 5)
+                                       break;
+
+                       } else {
+                               if (snprintf(buf, buflen, "%.*f%s", i,
+                                   val, u) <= 5)
+                                       break;
+                       }
                }
        }
 }
 
+/*
+ * Convert a number to an appropriately human-readable output.
+ */
+void
+zfs_nicenum(uint64_t num, char *buf, size_t buflen)
+{
+       zfs_nicenum_format(num, buf, buflen, ZFS_NICENUM_1024);
+}
+
+/*
+ * Convert a time to an appropriately human-readable output.
+ * @num:       Time in nanoseconds
+ */
+void
+zfs_nicetime(uint64_t num, char *buf, size_t buflen)
+{
+       zfs_nicenum_format(num, buf, buflen, ZFS_NICENUM_TIME);
+}
+
+/*
+ * Print out a raw number with correct column spacing
+ */
+void
+zfs_niceraw(uint64_t num, char *buf, size_t buflen)
+{
+       zfs_nicenum_format(num, buf, buflen, ZFS_NICENUM_RAW);
+}
+
+
+
 void
 libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
 {