Author: avg
Date: Thu Oct 26 16:20:47 2017
New Revision: 325013
URL: https://svnweb.freebsd.org/changeset/base/325013

Log:
  640 number_to_scaled_string is duplicated in several commands
  
  illumos/illumos-gate@0a0551200ecbcd4f1b17560acaeeb7b6c8b0090e
  
https://github.com/illumos/illumos-gate/commit/0a0551200ecbcd4f1b17560acaeeb7b6c8b0090e
  
  https://www.illumos.org/issues/640
    du(1), df(1m), ls(1), and swap(1m) all include a copy (it appears literally
    copied) of the 'number_to_scaled_string' function in their source. This 
should
    be moved to a shared library and all 4 commands should use this instead.
  
  Reviewed by: Sebastian Wiedenroth <wi...@frubar.net>
  Reviewed by: Robert Mustacchi <r...@joyent.com>
  Reviewed by: Yuri Pankov <yur...@gmx.com>
  Approved by: Dan McDonald <dan...@joyent.com>
  Author: Jason King <jason.brian.k...@gmail.com>

Added:
  vendor/illumos/dist/lib/libcmdutils/
  vendor/illumos/dist/lib/libcmdutils/common/
  vendor/illumos/dist/lib/libcmdutils/common/nicenum.c   (contents, props 
changed)
Modified:
  vendor/illumos/dist/cmd/zdb/zdb.c
  vendor/illumos/dist/cmd/ztest/ztest.c
  vendor/illumos/dist/lib/libzfs/common/libzfs_util.c
  vendor/illumos/dist/lib/libzpool/common/sys/zfs_context.h
  vendor/illumos/dist/lib/libzpool/common/util.c

Modified: vendor/illumos/dist/cmd/zdb/zdb.c
==============================================================================
--- vendor/illumos/dist/cmd/zdb/zdb.c   Thu Oct 26 16:02:38 2017        
(r325012)
+++ vendor/illumos/dist/cmd/zdb/zdb.c   Thu Oct 26 16:20:47 2017        
(r325013)
@@ -63,6 +63,7 @@
 #include <sys/abd.h>
 #include <sys/blkptr.h>
 #include <zfs_comutil.h>
+#include <libcmdutils.h>
 #undef verify
 #include <libzfs.h>
 
@@ -277,12 +278,12 @@ dump_history_offsets(objset_t *os, uint64_t object, vo
 }
 
 static void
-zdb_nicenum(uint64_t num, char *buf)
+zdb_nicenum(uint64_t num, char *buf, size_t buflen)
 {
        if (dump_opt['P'])
-               (void) sprintf(buf, "%llu", (longlong_t)num);
+               (void) snprintf(buf, buflen, "%llu", (longlong_t)num);
        else
-               nicenum(num, buf);
+               nicenum(num, buf, sizeof (buf));
 }
 
 static const char histo_stars[] = "****************************************";
@@ -459,12 +460,17 @@ dump_bpobj(objset_t *os, uint64_t object, void *data, 
        bpobj_phys_t *bpop = data;
        char bytes[32], comp[32], uncomp[32];
 
+       /* make sure the output won't get truncated */
+       CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
+       CTASSERT(sizeof (comp) >= NN_NUMBUF_SZ);
+       CTASSERT(sizeof (uncomp) >= NN_NUMBUF_SZ);
+
        if (bpop == NULL)
                return;
 
-       zdb_nicenum(bpop->bpo_bytes, bytes);
-       zdb_nicenum(bpop->bpo_comp, comp);
-       zdb_nicenum(bpop->bpo_uncomp, uncomp);
+       zdb_nicenum(bpop->bpo_bytes, bytes, sizeof (bytes));
+       zdb_nicenum(bpop->bpo_comp, comp, sizeof (comp));
+       zdb_nicenum(bpop->bpo_uncomp, uncomp, sizeof (uncomp));
 
        (void) printf("\t\tnum_blkptrs = %llu\n",
            (u_longlong_t)bpop->bpo_num_blkptrs);
@@ -757,8 +763,11 @@ dump_metaslab_stats(metaslab_t *msp)
        avl_tree_t *t = &msp->ms_size_tree;
        int free_pct = range_tree_space(rt) * 100 / msp->ms_size;
 
-       zdb_nicenum(metaslab_block_maxsize(msp), maxbuf);
+       /* max sure nicenum has enough space */
+       CTASSERT(sizeof (maxbuf) >= NN_NUMBUF_SZ);
 
+       zdb_nicenum(metaslab_block_maxsize(msp), maxbuf, sizeof (maxbuf));
+
        (void) printf("\t %25s %10lu   %7s  %6s   %4s %4d%%\n",
            "segments", avl_numnodes(t), "maxsize", maxbuf,
            "freepct", free_pct);
@@ -774,7 +783,8 @@ dump_metaslab(metaslab_t *msp)
        space_map_t *sm = msp->ms_sm;
        char freebuf[32];
 
-       zdb_nicenum(msp->ms_size - space_map_allocated(sm), freebuf);
+       zdb_nicenum(msp->ms_size - space_map_allocated(sm), freebuf,
+           sizeof (freebuf));
 
        (void) printf(
            "\tmetaslab %6llu   offset %12llx   spacemap %6llu   free    %5s\n",
@@ -1334,6 +1344,9 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data
        time_t crtime;
        char nice[32];
 
+       /* make sure nicenum has enough space */
+       CTASSERT(sizeof (nice) >= NN_NUMBUF_SZ);
+
        if (dd == NULL)
                return;
 
@@ -1349,15 +1362,15 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data
            (u_longlong_t)dd->dd_origin_obj);
        (void) printf("\t\tchild_dir_zapobj = %llu\n",
            (u_longlong_t)dd->dd_child_dir_zapobj);
-       zdb_nicenum(dd->dd_used_bytes, nice);
+       zdb_nicenum(dd->dd_used_bytes, nice, sizeof (nice));
        (void) printf("\t\tused_bytes = %s\n", nice);
-       zdb_nicenum(dd->dd_compressed_bytes, nice);
+       zdb_nicenum(dd->dd_compressed_bytes, nice, sizeof (nice));
        (void) printf("\t\tcompressed_bytes = %s\n", nice);
-       zdb_nicenum(dd->dd_uncompressed_bytes, nice);
+       zdb_nicenum(dd->dd_uncompressed_bytes, nice, sizeof (nice));
        (void) printf("\t\tuncompressed_bytes = %s\n", nice);
-       zdb_nicenum(dd->dd_quota, nice);
+       zdb_nicenum(dd->dd_quota, nice, sizeof (nice));
        (void) printf("\t\tquota = %s\n", nice);
-       zdb_nicenum(dd->dd_reserved, nice);
+       zdb_nicenum(dd->dd_reserved, nice, sizeof (nice));
        (void) printf("\t\treserved = %s\n", nice);
        (void) printf("\t\tprops_zapobj = %llu\n",
            (u_longlong_t)dd->dd_props_zapobj);
@@ -1367,7 +1380,8 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data
            (u_longlong_t)dd->dd_flags);
 
 #define        DO(which) \
-       zdb_nicenum(dd->dd_used_breakdown[DD_USED_ ## which], nice); \
+       zdb_nicenum(dd->dd_used_breakdown[DD_USED_ ## which], nice, \
+           sizeof (nice)); \
        (void) printf("\t\tused_breakdown[" #which "] = %s\n", nice)
        DO(HEAD);
        DO(SNAP);
@@ -1386,15 +1400,22 @@ dump_dsl_dataset(objset_t *os, uint64_t object, void *
        char used[32], compressed[32], uncompressed[32], unique[32];
        char blkbuf[BP_SPRINTF_LEN];
 
+       /* make sure nicenum has enough space */
+       CTASSERT(sizeof (used) >= NN_NUMBUF_SZ);
+       CTASSERT(sizeof (compressed) >= NN_NUMBUF_SZ);
+       CTASSERT(sizeof (uncompressed) >= NN_NUMBUF_SZ);
+       CTASSERT(sizeof (unique) >= NN_NUMBUF_SZ);
+
        if (ds == NULL)
                return;
 
        ASSERT(size == sizeof (*ds));
        crtime = ds->ds_creation_time;
-       zdb_nicenum(ds->ds_referenced_bytes, used);
-       zdb_nicenum(ds->ds_compressed_bytes, compressed);
-       zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed);
-       zdb_nicenum(ds->ds_unique_bytes, unique);
+       zdb_nicenum(ds->ds_referenced_bytes, used, sizeof (used));
+       zdb_nicenum(ds->ds_compressed_bytes, compressed, sizeof (compressed));
+       zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed,
+           sizeof (uncompressed));
+       zdb_nicenum(ds->ds_unique_bytes, unique, sizeof (unique));
        snprintf_blkptr(blkbuf, sizeof (blkbuf), &ds->ds_bp);
 
        (void) printf("\t\tdir_obj = %llu\n",
@@ -1453,12 +1474,15 @@ dump_bptree(objset_t *os, uint64_t obj, const char *na
        bptree_phys_t *bt;
        dmu_buf_t *db;
 
+       /* make sure nicenum has enough space */
+       CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
+
        if (dump_opt['d'] < 3)
                return;
 
        VERIFY3U(0, ==, dmu_bonus_hold(os, obj, FTAG, &db));
        bt = db->db_data;
-       zdb_nicenum(bt->bt_bytes, bytes);
+       zdb_nicenum(bt->bt_bytes, bytes, sizeof (bytes));
        (void) printf("\n    %s: %llu datasets, %s\n",
            name, (unsigned long long)(bt->bt_end - bt->bt_begin), bytes);
        dmu_buf_rele(db, FTAG);
@@ -1490,13 +1514,18 @@ dump_full_bpobj(bpobj_t *bpo, const char *name, int in
        char comp[32];
        char uncomp[32];
 
+       /* make sure nicenum has enough space */
+       CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
+       CTASSERT(sizeof (comp) >= NN_NUMBUF_SZ);
+       CTASSERT(sizeof (uncomp) >= NN_NUMBUF_SZ);
+
        if (dump_opt['d'] < 3)
                return;
 
-       zdb_nicenum(bpo->bpo_phys->bpo_bytes, bytes);
+       zdb_nicenum(bpo->bpo_phys->bpo_bytes, bytes, sizeof (bytes));
        if (bpo->bpo_havesubobj && bpo->bpo_phys->bpo_subobjs != 0) {
-               zdb_nicenum(bpo->bpo_phys->bpo_comp, comp);
-               zdb_nicenum(bpo->bpo_phys->bpo_uncomp, uncomp);
+               zdb_nicenum(bpo->bpo_phys->bpo_comp, comp, sizeof (comp));
+               zdb_nicenum(bpo->bpo_phys->bpo_uncomp, uncomp, sizeof (uncomp));
                (void) printf("    %*s: object %llu, %llu local blkptrs, "
                    "%llu subobjs in object %llu, %s (%s/%s comp)\n",
                    indent * 8, name,
@@ -1550,6 +1579,11 @@ dump_deadlist(dsl_deadlist_t *dl)
        char comp[32];
        char uncomp[32];
 
+       /* make sure nicenum has enough space */
+       CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
+       CTASSERT(sizeof (comp) >= NN_NUMBUF_SZ);
+       CTASSERT(sizeof (uncomp) >= NN_NUMBUF_SZ);
+
        if (dump_opt['d'] < 3)
                return;
 
@@ -1558,9 +1592,9 @@ dump_deadlist(dsl_deadlist_t *dl)
                return;
        }
 
-       zdb_nicenum(dl->dl_phys->dl_used, bytes);
-       zdb_nicenum(dl->dl_phys->dl_comp, comp);
-       zdb_nicenum(dl->dl_phys->dl_uncomp, uncomp);
+       zdb_nicenum(dl->dl_phys->dl_used, bytes, sizeof (bytes));
+       zdb_nicenum(dl->dl_phys->dl_comp, comp, sizeof (comp));
+       zdb_nicenum(dl->dl_phys->dl_uncomp, uncomp, sizeof (uncomp));
        (void) printf("\n    Deadlist: %s (%s/%s comp)\n",
            bytes, comp, uncomp);
 
@@ -1863,6 +1897,13 @@ dump_object(objset_t *os, uint64_t object, int verbosi
        char aux[50];
        int error;
 
+       /* make sure nicenum has enough space */
+       CTASSERT(sizeof (iblk) >= NN_NUMBUF_SZ);
+       CTASSERT(sizeof (dblk) >= NN_NUMBUF_SZ);
+       CTASSERT(sizeof (lsize) >= NN_NUMBUF_SZ);
+       CTASSERT(sizeof (asize) >= NN_NUMBUF_SZ);
+       CTASSERT(sizeof (bonus_size) >= NN_NUMBUF_SZ);
+
        if (*print_header) {
                (void) printf("\n%10s  %3s  %5s  %5s  %5s  %5s  %6s  %s\n",
                    "Object", "lvl", "iblk", "dblk", "dsize", "lsize",
@@ -1883,11 +1924,11 @@ dump_object(objset_t *os, uint64_t object, int verbosi
        }
        dmu_object_info_from_dnode(dn, &doi);
 
-       zdb_nicenum(doi.doi_metadata_block_size, iblk);
-       zdb_nicenum(doi.doi_data_block_size, dblk);
-       zdb_nicenum(doi.doi_max_offset, lsize);
-       zdb_nicenum(doi.doi_physical_blocks_512 << 9, asize);
-       zdb_nicenum(doi.doi_bonus_size, bonus_size);
+       zdb_nicenum(doi.doi_metadata_block_size, iblk, sizeof (iblk));
+       zdb_nicenum(doi.doi_data_block_size, dblk, sizeof (dblk));
+       zdb_nicenum(doi.doi_max_offset, lsize, sizeof (lsize));
+       zdb_nicenum(doi.doi_physical_blocks_512 << 9, asize, sizeof (asize));
+       zdb_nicenum(doi.doi_bonus_size, bonus_size, sizeof (bonus_size));
        (void) sprintf(fill, "%6.2f", 100.0 * doi.doi_fill_count *
            doi.doi_data_block_size / (object == 0 ? DNODES_PER_BLOCK : 1) /
            doi.doi_max_offset);
@@ -1950,6 +1991,8 @@ dump_object(objset_t *os, uint64_t object, int verbosi
 
                for (;;) {
                        char segsize[32];
+                       /* make sure nicenum has enough space */
+                       CTASSERT(sizeof (segsize) >= NN_NUMBUF_SZ);
                        error = dnode_next_offset(dn,
                            0, &start, minlvl, blkfill, 0);
                        if (error)
@@ -1957,7 +2000,7 @@ dump_object(objset_t *os, uint64_t object, int verbosi
                        end = start;
                        error = dnode_next_offset(dn,
                            DNODE_FIND_HOLE, &end, minlvl, blkfill, 0);
-                       zdb_nicenum(end - start, segsize);
+                       zdb_nicenum(end - start, segsize, sizeof (segsize));
                        (void) printf("\t\tsegment [%016llx, %016llx)"
                            " size %5s\n", (u_longlong_t)start,
                            (u_longlong_t)end, segsize);
@@ -1989,6 +2032,9 @@ dump_dir(objset_t *os)
        unsigned i;
        int error;
 
+       /* make sure nicenum has enough space */
+       CTASSERT(sizeof (numbuf) >= NN_NUMBUF_SZ);
+
        dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
        dmu_objset_fast_stat(os, &dds);
        dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
@@ -2007,7 +2053,7 @@ dump_dir(objset_t *os)
 
        ASSERT3U(usedobjs, ==, BP_GET_FILL(os->os_rootbp));
 
-       zdb_nicenum(refdbytes, numbuf);
+       zdb_nicenum(refdbytes, numbuf, sizeof (numbuf));
 
        if (verbosity >= 4) {
                (void) snprintf(blkbuf, sizeof (blkbuf), ", rootbp ");
@@ -2652,6 +2698,9 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr
                int sec_remaining =
                    (zcb->zcb_totalasize - bytes) / 1024 / kb_per_sec;
 
+               /* make sure nicenum has enough space */
+               CTASSERT(sizeof (buf) >= NN_NUMBUF_SZ);
+
                zfs_nicenum(bytes, buf, sizeof (buf));
                (void) fprintf(stderr,
                    "\r%5s completed (%4dMB/s) "
@@ -3003,6 +3052,14 @@ dump_block_stats(spa_t *spa)
                        char avg[32], gang[32];
                        const char *typename;
 
+                       /* make sure nicenum has enough space */
+                       CTASSERT(sizeof (csize) >= NN_NUMBUF_SZ);
+                       CTASSERT(sizeof (lsize) >= NN_NUMBUF_SZ);
+                       CTASSERT(sizeof (psize) >= NN_NUMBUF_SZ);
+                       CTASSERT(sizeof (asize) >= NN_NUMBUF_SZ);
+                       CTASSERT(sizeof (avg) >= NN_NUMBUF_SZ);
+                       CTASSERT(sizeof (gang) >= NN_NUMBUF_SZ);
+
                        if (t < DMU_OT_NUMTYPES)
                                typename = dmu_ot[t].ot_name;
                        else
@@ -3036,12 +3093,17 @@ dump_block_stats(spa_t *spa)
                                    zcb.zcb_type[ZB_TOTAL][t].zb_asize)
                                        continue;
 
-                               zdb_nicenum(zb->zb_count, csize);
-                               zdb_nicenum(zb->zb_lsize, lsize);
-                               zdb_nicenum(zb->zb_psize, psize);
-                               zdb_nicenum(zb->zb_asize, asize);
-                               zdb_nicenum(zb->zb_asize / zb->zb_count, avg);
-                               zdb_nicenum(zb->zb_gangs, gang);
+                               zdb_nicenum(zb->zb_count, csize,
+                                   sizeof (csize));
+                               zdb_nicenum(zb->zb_lsize, lsize,
+                                   sizeof (lsize));
+                               zdb_nicenum(zb->zb_psize, psize,
+                                   sizeof (psize));
+                               zdb_nicenum(zb->zb_asize, asize,
+                                   sizeof (asize));
+                               zdb_nicenum(zb->zb_asize / zb->zb_count, avg,
+                                   sizeof (avg));
+                               zdb_nicenum(zb->zb_gangs, gang, sizeof (gang));
 
                                (void) printf("%6s\t%5s\t%5s\t%5s\t%5s"
                                    "\t%5.2f\t%6.2f\t",

Modified: vendor/illumos/dist/cmd/ztest/ztest.c
==============================================================================
--- vendor/illumos/dist/cmd/ztest/ztest.c       Thu Oct 26 16:02:38 2017        
(r325012)
+++ vendor/illumos/dist/cmd/ztest/ztest.c       Thu Oct 26 16:20:47 2017        
(r325013)
@@ -24,6 +24,7 @@
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2013 Steven Hartland. All rights reserved.
  * Copyright (c) 2014 Integros [integros.com]
+ * Copyright 2017 Joyent, Inc.
  */
 
 /*
@@ -123,6 +124,7 @@
 #include <math.h>
 #include <sys/fs/zfs.h>
 #include <libnvpair.h>
+#include <libcmdutils.h>
 
 static int ztest_fd_data = -1;
 static int ztest_fd_rand = -1;
@@ -554,12 +556,13 @@ usage(boolean_t requested)
 {
        const ztest_shared_opts_t *zo = &ztest_opts_defaults;
 
-       char nice_vdev_size[10];
-       char nice_gang_bang[10];
+       char nice_vdev_size[NN_NUMBUF_SZ];
+       char nice_gang_bang[NN_NUMBUF_SZ];
        FILE *fp = requested ? stdout : stderr;
 
-       nicenum(zo->zo_vdev_size, nice_vdev_size);
-       nicenum(zo->zo_metaslab_gang_bang, nice_gang_bang);
+       nicenum(zo->zo_vdev_size, nice_vdev_size, sizeof (nice_vdev_size));
+       nicenum(zo->zo_metaslab_gang_bang, nice_gang_bang,
+           sizeof (nice_gang_bang));
 
        (void) fprintf(fp, "Usage: %s\n"
            "\t[-v vdevs (default: %llu)]\n"
@@ -3166,10 +3169,10 @@ ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id)
                    old_class_space, new_class_space);
 
        if (ztest_opts.zo_verbose >= 5) {
-               char oldnumbuf[6], newnumbuf[6];
+               char oldnumbuf[NN_NUMBUF_SZ], newnumbuf[NN_NUMBUF_SZ];
 
-               nicenum(old_class_space, oldnumbuf);
-               nicenum(new_class_space, newnumbuf);
+               nicenum(old_class_space, oldnumbuf, sizeof (oldnumbuf));
+               nicenum(new_class_space, newnumbuf, sizeof (newnumbuf));
                (void) printf("%s grew from %s to %s\n",
                    spa->spa_name, oldnumbuf, newnumbuf);
        }
@@ -6207,7 +6210,7 @@ main(int argc, char **argv)
        ztest_info_t *zi;
        ztest_shared_callstate_t *zc;
        char timebuf[100];
-       char numbuf[6];
+       char numbuf[NN_NUMBUF_SZ];
        spa_t *spa;
        char *cmd;
        boolean_t hasalt;
@@ -6344,7 +6347,7 @@ main(int argc, char **argv)
 
                        now = MIN(now, zs->zs_proc_stop);
                        print_time(zs->zs_proc_stop - now, timebuf);
-                       nicenum(zs->zs_space, numbuf);
+                       nicenum(zs->zs_space, numbuf, sizeof (numbuf));
 
                        (void) printf("Pass %3d, %8s, %3llu ENOSPC, "
                            "%4.1f%% of %5s used, %3.0f%% done, %8s to go\n",

Added: vendor/illumos/dist/lib/libcmdutils/common/nicenum.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ vendor/illumos/dist/lib/libcmdutils/common/nicenum.c        Thu Oct 26 
16:20:47 2017        (r325013)
@@ -0,0 +1,130 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2017 Jason king
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/debug.h>
+#include "libcmdutils.h"
+
+/* The largest suffix that can fit, aka an exabyte (2^60 / 10^18) */
+#define        INDEX_MAX       (6)
+
+/* Verify INDEX_MAX fits */
+CTASSERT(INDEX_MAX * 10 < sizeof (uint64_t) * 8);
+
+void
+nicenum_scale(uint64_t n, size_t units, char *buf, size_t buflen,
+    uint32_t flags)
+{
+       uint64_t divamt = 1024;
+       uint64_t divisor = 1;
+       int index = 0;
+       int rc = 0;
+       char u;
+
+       if (units == 0)
+               units = 1;
+
+       if (n > 0) {
+               n *= units;
+               if (n < units)
+                       goto overflow;
+       }
+
+       if (flags & NN_DIVISOR_1000)
+               divamt = 1000;
+
+       /*
+        * This tries to find the suffix S(n) such that
+        * S(n) <= n < S(n+1), where S(n) = 2^(n*10) | 10^(3*n)
+        * (i.e. 1024/1000, 1,048,576/1,000,000, etc).  Stop once S(n)
+        * is the largest prefix supported (i.e. don't bother computing
+        * and checking S(n+1).  Since INDEX_MAX should be the largest
+        * suffix that fits (currently an exabyte), S(INDEX_MAX + 1) is
+        * never checked as it would overflow.
+        */
+       while (index < INDEX_MAX) {
+               uint64_t newdiv = divisor * divamt;
+
+               /* CTASSERT() guarantee these never trip */
+               VERIFY3U(newdiv, >=, divamt);
+               VERIFY3U(newdiv, >=, divisor);
+
+               if (n < newdiv)
+                       break;
+
+               divisor = newdiv;
+               index++;
+       }
+
+       u = " KMGTPE"[index];
+
+       if (index == 0) {
+               rc = snprintf(buf, buflen, "%llu", n);
+       } else if (n % divisor == 0) {
+               /*
+                * If this is an even multiple of the base, always display
+                * without any decimal precision.
+                */
+               rc = snprintf(buf, buflen, "%llu%c", n / divisor, u);
+       } else {
+               /*
+                * We want to choose a precision that reflects the best choice
+                * for fitting in 5 characters.  This can get rather tricky
+                * when we have numbers that are very close to an order of
+                * magnitude.  For example, when displaying 10239 (which is
+                * really 9.999K), we want only a single place of precision
+                * for 10.0K.  We could develop some complex heuristics for
+                * this, but it's much easier just to try each combination
+                * in turn.
+                */
+               int i;
+               for (i = 2; i >= 0; i--) {
+                       if ((rc = snprintf(buf, buflen, "%.*f%c", i,
+                           (double)n / divisor, u)) <= 5)
+                               break;
+               }
+       }
+
+       if (rc + 1 > buflen || rc < 0)
+               goto overflow;
+
+       return;
+
+overflow:
+       /* prefer a more verbose message if possible */
+       if (buflen > 10)
+               (void) strlcpy(buf, "<overflow>", buflen);
+       else
+               (void) strlcpy(buf, "??", buflen);
+}
+
+void
+nicenum(uint64_t num, char *buf, size_t buflen)
+{
+       nicenum_scale(num, 1, buf, buflen, 0);
+}

Modified: vendor/illumos/dist/lib/libzfs/common/libzfs_util.c
==============================================================================
--- vendor/illumos/dist/lib/libzfs/common/libzfs_util.c Thu Oct 26 16:02:38 
2017        (r325012)
+++ vendor/illumos/dist/lib/libzfs/common/libzfs_util.c Thu Oct 26 16:20:47 
2017        (r325013)
@@ -45,6 +45,7 @@
 #include <sys/mnttab.h>
 #include <sys/mntent.h>
 #include <sys/types.h>
+#include <libcmdutils.h>
 
 #include <libzfs.h>
 #include <libzfs_core.h>
@@ -572,42 +573,7 @@ zfs_strdup(libzfs_handle_t *hdl, const char *str)
 void
 zfs_nicenum(uint64_t num, char *buf, size_t buflen)
 {
-       uint64_t n = num;
-       int index = 0;
-       char u;
-
-       while (n >= 1024) {
-               n /= 1024;
-               index++;
-       }
-
-       u = " KMGTPE"[index];
-
-       if (index == 0) {
-               (void) snprintf(buf, buflen, "%llu", n);
-       } else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
-               /*
-                * If this is an even multiple of the base, always display
-                * without any decimal precision.
-                */
-               (void) snprintf(buf, buflen, "%llu%c", n, u);
-       } else {
-               /*
-                * We want to choose a precision that reflects the best choice
-                * for fitting in 5 characters.  This can get rather tricky when
-                * we have numbers that are very close to an order of magnitude.
-                * For example, when displaying 10239 (which is really 9.999K),
-                * we want only a single place of precision for 10.0K.  We could
-                * develop some complex heuristics for this, but it's much
-                * easier just to try each combination in turn.
-                */
-               int i;
-               for (i = 2; i >= 0; i--) {
-                       if (snprintf(buf, buflen, "%.*f%c", i,
-                           (double)num / (1ULL << 10 * index), u) <= 5)
-                               break;
-               }
-       }
+       nicenum(num, buf, buflen);
 }
 
 void

Modified: vendor/illumos/dist/lib/libzpool/common/sys/zfs_context.h
==============================================================================
--- vendor/illumos/dist/lib/libzpool/common/sys/zfs_context.h   Thu Oct 26 
16:02:38 2017        (r325012)
+++ vendor/illumos/dist/lib/libzpool/common/sys/zfs_context.h   Thu Oct 26 
16:20:47 2017        (r325013)
@@ -542,7 +542,7 @@ extern void kernel_init(int);
 extern void kernel_fini(void);
 
 struct spa;
-extern void nicenum(uint64_t num, char *buf);
+extern void nicenum(uint64_t num, char *buf, size_t);
 extern void show_pool_stats(struct spa *);
 extern int set_global_var(char *arg);
 

Modified: vendor/illumos/dist/lib/libzpool/common/util.c
==============================================================================
--- vendor/illumos/dist/lib/libzpool/common/util.c      Thu Oct 26 16:02:38 
2017        (r325012)
+++ vendor/illumos/dist/lib/libzpool/common/util.c      Thu Oct 26 16:20:47 
2017        (r325013)
@@ -38,33 +38,6 @@
  * Routines needed by more than one client of libzpool.
  */
 
-void
-nicenum(uint64_t num, char *buf)
-{
-       uint64_t n = num;
-       int index = 0;
-       char u;
-
-       while (n >= 1024) {
-               n = (n + (1024 / 2)) / 1024; /* Round up or down */
-               index++;
-       }
-
-       u = " KMGTPE"[index];
-
-       if (index == 0) {
-               (void) sprintf(buf, "%llu", (u_longlong_t)n);
-       } else if (n < 10 && (num & (num - 1)) != 0) {
-               (void) sprintf(buf, "%.2f%c",
-                   (double)num / (1ULL << 10 * index), u);
-       } else if (n < 100 && (num & (num - 1)) != 0) {
-               (void) sprintf(buf, "%.1f%c",
-                   (double)num / (1ULL << 10 * index), u);
-       } else {
-               (void) sprintf(buf, "%llu%c", (u_longlong_t)n, u);
-       }
-}
-
 static void
 show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
 {
@@ -97,15 +70,17 @@ show_vdev_stats(const char *desc, const char *ctype, n
 
                sec = MAX(1, vs->vs_timestamp / NANOSEC);
 
-               nicenum(vs->vs_alloc, used);
-               nicenum(vs->vs_space - vs->vs_alloc, avail);
-               nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops);
-               nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops);
-               nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes);
-               nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes);
-               nicenum(vs->vs_read_errors, rerr);
-               nicenum(vs->vs_write_errors, werr);
-               nicenum(vs->vs_checksum_errors, cerr);
+               nicenum(vs->vs_alloc, used, sizeof (used));
+               nicenum(vs->vs_space - vs->vs_alloc, avail, sizeof (avail));
+               nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops, sizeof (rops));
+               nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops, sizeof (wops));
+               nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes,
+                   sizeof (rbytes));
+               nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes,
+                   sizeof (wbytes));
+               nicenum(vs->vs_read_errors, rerr, sizeof (rerr));
+               nicenum(vs->vs_write_errors, werr, sizeof (werr));
+               nicenum(vs->vs_checksum_errors, cerr, sizeof (cerr));
 
                (void) printf("%*s%s%*s%*s%*s %5s %5s %5s %5s %5s %5s %5s\n",
                    indent, "",
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to