summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2017-11-16 23:27:27 +0000
committeravg <avg@FreeBSD.org>2017-11-16 23:27:27 +0000
commit589e07fe0c6d00dfb036a826bfbd255172eea36d (patch)
tree207655d98831858308de3753c4b27c2b8050c613
parent1db5dafed6025b57bd9455240e590766fe902e1f (diff)
downloadFreeBSD-src-589e07fe0c6d00dfb036a826bfbd255172eea36d.zip
FreeBSD-src-589e07fe0c6d00dfb036a826bfbd255172eea36d.tar.gz
MFC r325035: MFV r325013,r325034: 640 number_to_scaled_string is duplicated in several commands
FreeBSD note: of all libcmdutils functionality ZFS (and other illumos contrib code) currently uses only nicenum() function (which is similar to humanize_number but has some formatting differences). For this reason I decided to not port the whole library. As a result, nicenum.c from libcmdutils is compiled into libzfs and libzpool. This is a bit ugly, but works. If one day we are forced to create libillumos, then the file should be moved to that library.
-rw-r--r--cddl/contrib/opensolaris/cmd/zdb/zdb.c138
-rw-r--r--cddl/contrib/opensolaris/cmd/ztest/ztest.c21
-rw-r--r--cddl/contrib/opensolaris/lib/libcmdutils/common/nicenum.c130
-rw-r--r--cddl/contrib/opensolaris/lib/libcmdutils/libcmdutils.h235
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c38
-rw-r--r--cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h2
-rw-r--r--cddl/contrib/opensolaris/lib/libzpool/common/util.c47
-rw-r--r--cddl/lib/libzfs/Makefile4
-rw-r--r--cddl/lib/libzpool/Makefile6
-rw-r--r--cddl/usr.bin/ztest/Makefile1
-rw-r--r--cddl/usr.sbin/zdb/Makefile1
11 files changed, 502 insertions, 121 deletions
diff --git a/cddl/contrib/opensolaris/cmd/zdb/zdb.c b/cddl/contrib/opensolaris/cmd/zdb/zdb.c
index baa8a51..6ca5047 100644
--- a/cddl/contrib/opensolaris/cmd/zdb/zdb.c
+++ b/cddl/contrib/opensolaris/cmd/zdb/zdb.c
@@ -63,6 +63,7 @@
#include <sys/abd.h>
#include <sys/blkptr.h>
#include <zfs_comutil.h>
+#include <libcmdutils.h>
#undef verify
#include <libzfs.h>
@@ -276,12 +277,12 @@ dump_history_offsets(objset_t *os, uint64_t object, void *data, size_t size)
}
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));
}
const char histo_stars[] = "****************************************";
@@ -458,12 +459,17 @@ dump_bpobj(objset_t *os, uint64_t object, void *data, size_t size)
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);
@@ -756,7 +762,10 @@ 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,
@@ -773,7 +782,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",
@@ -1356,6 +1366,9 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
time_t crtime;
char nice[32];
+ /* make sure nicenum has enough space */
+ CTASSERT(sizeof (nice) >= NN_NUMBUF_SZ);
+
if (dd == NULL)
return;
@@ -1371,15 +1384,15 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
(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);
@@ -1389,7 +1402,8 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
(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);
@@ -1408,15 +1422,22 @@ dump_dsl_dataset(objset_t *os, uint64_t object, void *data, size_t size)
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",
@@ -1475,12 +1496,15 @@ dump_bptree(objset_t *os, uint64_t obj, char *name)
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);
@@ -1512,13 +1536,18 @@ dump_full_bpobj(bpobj_t *bpo, char *name, int indent)
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,
@@ -1572,6 +1601,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;
@@ -1580,9 +1614,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);
@@ -1883,6 +1917,13 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
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",
@@ -1903,11 +1944,11 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
}
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);
@@ -1970,6 +2011,8 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
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)
@@ -1977,7 +2020,7 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
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);
@@ -2008,6 +2051,9 @@ dump_dir(objset_t *os)
int print_header = 1;
int i, 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);
@@ -2026,7 +2072,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 ");
@@ -2673,6 +2719,9 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
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) "
@@ -3022,6 +3071,14 @@ dump_block_stats(spa_t *spa)
char avg[32], gang[32];
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
@@ -3055,12 +3112,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",
diff --git a/cddl/contrib/opensolaris/cmd/ztest/ztest.c b/cddl/contrib/opensolaris/cmd/ztest/ztest.c
index 658befe..64c550e 100644
--- a/cddl/contrib/opensolaris/cmd/ztest/ztest.c
+++ b/cddl/contrib/opensolaris/cmd/ztest/ztest.c
@@ -25,6 +25,7 @@
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
+ * Copyright 2017 Joyent, Inc.
*/
/*
@@ -125,6 +126,7 @@
#include <errno.h>
#include <sys/fs/zfs.h>
#include <libnvpair.h>
+#include <libcmdutils.h>
static int ztest_fd_data = -1;
static int ztest_fd_rand = -1;
@@ -556,12 +558,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"
@@ -3158,10 +3161,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);
}
@@ -6204,7 +6207,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;
@@ -6341,7 +6344,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",
diff --git a/cddl/contrib/opensolaris/lib/libcmdutils/common/nicenum.c b/cddl/contrib/opensolaris/lib/libcmdutils/common/nicenum.c
new file mode 100644
index 0000000..8e3202f
--- /dev/null
+++ b/cddl/contrib/opensolaris/lib/libcmdutils/common/nicenum.c
@@ -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);
+}
diff --git a/cddl/contrib/opensolaris/lib/libcmdutils/libcmdutils.h b/cddl/contrib/opensolaris/lib/libcmdutils/libcmdutils.h
new file mode 100644
index 0000000..fffdd9d
--- /dev/null
+++ b/cddl/contrib/opensolaris/lib/libcmdutils/libcmdutils.h
@@ -0,0 +1,235 @@
+/*
+ * 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 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Copyright (c) 2013 RackTop Systems.
+ */
+/*
+ * Copyright 2017 Joyent, Inc.
+ */
+
+/*
+ * Declarations for the functions in libcmdutils.
+ */
+
+#ifndef _LIBCMDUTILS_H
+#define _LIBCMDUTILS_H
+
+#ifdef illumos
+#if !defined(_LP64) && \
+ !((_FILE_OFFSET_BITS == 64) || defined(_LARGEFILE64_SOURCE))
+#error "libcmdutils.h can only be used in a largefile compilation environment"
+#endif
+#endif
+
+/*
+ * This is a private header file. Applications should not directly include
+ * this file.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <libintl.h>
+#include <string.h>
+#include <dirent.h>
+#ifdef illumos
+#include <attr.h>
+#endif
+#include <sys/avl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <libnvpair.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* extended system attribute support */
+#define _NOT_SATTR 0
+#define _RO_SATTR 1
+#define _RW_SATTR 2
+
+#define MAXMAPSIZE (1024*1024*8) /* map at most 8MB */
+#define SMALLFILESIZE (32*1024) /* don't use mmap on little file */
+
+/* Type used for a node containing a device id and inode number */
+
+#if defined(_LP64) || (_FILE_OFFSET_BITS == 64)
+typedef struct tree_node {
+ dev_t node_dev;
+ ino_t node_ino;
+ avl_node_t avl_link;
+} tree_node_t;
+#else
+typedef struct tree_node {
+ dev_t node_dev;
+ ino64_t node_ino;
+ avl_node_t avl_link;
+} tree_node_t;
+#endif
+
+ /* extended system attribute support */
+
+/* Determine if a file is the name of an extended system attribute file */
+extern int sysattr_type(char *);
+
+/* Determine if the underlying file system supports system attributes */
+extern int sysattr_support(char *, int);
+
+/* Copies the content of the source file to the target file */
+#if defined(_LP64) || (_FILE_OFFSET_BITS == 64)
+extern int writefile(int, int, char *, char *, char *, char *,
+ struct stat *, struct stat *);
+#else
+extern int writefile(int, int, char *, char *, char *, char *,
+ struct stat64 *, struct stat64 *);
+#endif
+
+/* Gets file descriptors of the source and target attribute files */
+extern int get_attrdirs(int, int, char *, int *, int *);
+
+/* Move extended attribute and extended system attribute */
+extern int mv_xattrs(char *, char *, char *, int, int);
+
+/* Returns non default extended system attribute list */
+extern nvlist_t *sysattr_list(char *, int, char *);
+
+
+
+ /* avltree */
+
+/*
+ * Used to compare two nodes. We are attempting to match the 1st
+ * argument (node) against the 2nd argument (a node which
+ * is already in the search tree).
+ */
+
+extern int tnode_compare(const void *, const void *);
+
+/*
+ * Used to add a single node (containing the input device id and
+ * inode number) to the specified search tree. The calling
+ * application must set the tree pointer to NULL before calling
+ * add_tnode() for the first time.
+ */
+#if defined(_LP64) || (_FILE_OFFSET_BITS == 64)
+extern int add_tnode(avl_tree_t **, dev_t, ino_t);
+#else
+extern int add_tnode(avl_tree_t **, dev_t, ino64_t);
+#endif
+
+/*
+ * Used to destroy a whole tree (all nodes) without rebalancing.
+ * The calling application is responsible for setting the tree
+ * pointer to NULL upon return.
+ */
+extern void destroy_tree(avl_tree_t *);
+
+
+
+ /* user/group id helpers */
+
+/*
+ * Used to get the next available user id in given range.
+ */
+extern int findnextuid(uid_t, uid_t, uid_t *);
+
+/*
+ * Used to get the next available group id in given range.
+ */
+extern int findnextgid(gid_t, gid_t, gid_t *);
+
+
+
+ /* dynamic string utilities */
+
+typedef struct custr custr_t;
+
+/*
+ * Allocate and free a "custr_t" dynamic string object. Returns 0 on success
+ * and -1 otherwise.
+ */
+extern int custr_alloc(custr_t **);
+extern void custr_free(custr_t *);
+
+/*
+ * Allocate a "custr_t" dynamic string object that operates on a fixed external
+ * buffer.
+ */
+extern int custr_alloc_buf(custr_t **, void *, size_t);
+
+/*
+ * Append a single character, or a NUL-terminated string of characters, to a
+ * dynamic string. Returns 0 on success and -1 otherwise. The dynamic string
+ * will be unmodified if the function returns -1.
+ */
+extern int custr_appendc(custr_t *, char);
+extern int custr_append(custr_t *, const char *);
+
+/*
+ * Append a format string and arguments as though the contents were being parsed
+ * through snprintf. Returns 0 on success and -1 otherwise. The dynamic string
+ * will be unmodified if the function returns -1.
+ */
+extern int custr_append_printf(custr_t *, const char *, ...);
+extern int custr_append_vprintf(custr_t *, const char *, va_list);
+
+/*
+ * Determine the length in bytes, not including the NUL terminator, of the
+ * dynamic string.
+ */
+extern size_t custr_len(custr_t *);
+
+/*
+ * Clear the contents of a dynamic string. Does not free the underlying
+ * memory.
+ */
+extern void custr_reset(custr_t *);
+
+/*
+ * Retrieve a const pointer to a NUL-terminated string version of the contents
+ * of the dynamic string. Storage for this string should not be freed, and
+ * the pointer will be invalidated by any mutations to the dynamic string.
+ */
+extern const char *custr_cstr(custr_t *str);
+
+#define NN_DIVISOR_1000 (1U << 0)
+
+/* Minimum size for the output of nicenum, including NULL */
+#define NN_NUMBUF_SZ (6)
+
+void nicenum(uint64_t, char *, size_t);
+void nicenum_scale(uint64_t, size_t, char *, size_t, uint32_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBCMDUTILS_H */
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c
index 621de67..5f5335d 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c
@@ -49,6 +49,7 @@
#include <sys/mnttab.h>
#include <sys/mntent.h>
#include <sys/types.h>
+#include <libcmdutils.h>
#include <libzfs.h>
#include <libzfs_core.h>
@@ -579,42 +580,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
diff --git a/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h b/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h
index 6fe41d6..019defb 100644
--- a/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h
+++ b/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h
@@ -581,7 +581,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);
diff --git a/cddl/contrib/opensolaris/lib/libzpool/common/util.c b/cddl/contrib/opensolaris/lib/libzpool/common/util.c
index 7cfc638..71894c2 100644
--- a/cddl/contrib/opensolaris/lib/libzpool/common/util.c
+++ b/cddl/contrib/opensolaris/lib/libzpool/common/util.c
@@ -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, nvlist_t *nv, int indent)
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, "",
diff --git a/cddl/lib/libzfs/Makefile b/cddl/lib/libzfs/Makefile
index a13c502..b735237 100644
--- a/cddl/lib/libzfs/Makefile
+++ b/cddl/lib/libzfs/Makefile
@@ -4,6 +4,7 @@
.PATH: ${SRCTOP}/sys/cddl/contrib/opensolaris/common/zfs
.PATH: ${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
.PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libzfs/common
+.PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libcmdutils/common
LIB= zfs
LIBADD= md pthread umem util uutil m avl bsdxml geom nvpair z zfs_core
@@ -15,6 +16,8 @@ SRCS= deviceid.c \
zmount.c \
zone.c
+SRCS+= nicenum.c
+
SRCS+= libzfs_changelist.c \
libzfs_compat.c \
libzfs_config.c \
@@ -53,5 +56,6 @@ CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libnvpair
CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libuutil/common
CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzfs/common
CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzfs_core/common
+CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libcmdutils
.include <bsd.lib.mk>
diff --git a/cddl/lib/libzpool/Makefile b/cddl/lib/libzpool/Makefile
index 7ad1bd7..4ca17c3 100644
--- a/cddl/lib/libzpool/Makefile
+++ b/cddl/lib/libzpool/Makefile
@@ -25,6 +25,8 @@ ATOMIC_SRCS= opensolaris_atomic.c
.endif
# UNICODE_SRCS
.PATH: ${SRCTOP}/sys/cddl/contrib/opensolaris/common/unicode
+# LIBCMDUTILS_SRCS
+.PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libcmdutils/common
LIB= zpool
@@ -34,10 +36,11 @@ LUA_SRCS= ${LUA_OBJS:C/.o$/.c/}
KERNEL_SRCS= kernel.c taskq.c util.c
LIST_SRCS= list.c
UNICODE_SRCS= u8_textprep.c
+LIBCMDUTILS_SRCS=nicenum.c
SRCS= ${ZFS_COMMON_SRCS} ${ZFS_SHARED_SRCS} ${LUA_SRCS} \
${KERNEL_SRCS} ${LIST_SRCS} ${ATOMIC_SRCS} \
- ${UNICODE_SRCS}
+ ${UNICODE_SRCS} ${LIBCMDUTILS_SRCS}
WARNS?= 0
CFLAGS+= -I${SRCTOP}/sys/cddl/compat/opensolaris
@@ -51,6 +54,7 @@ CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/common/zfs
CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common
CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/head
CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libnvpair
+CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libcmdutils
# XXX: pthread doesn't have mutex_owned() equivalent, so we need to look
# into libthr private structures. That's sooo evil, but it's only for
# ZFS debugging tools needs.
diff --git a/cddl/usr.bin/ztest/Makefile b/cddl/usr.bin/ztest/Makefile
index 81f120a..3675129 100644
--- a/cddl/usr.bin/ztest/Makefile
+++ b/cddl/usr.bin/ztest/Makefile
@@ -11,6 +11,7 @@ CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include
CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/lib/libumem
CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzpool/common
CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libnvpair
+CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libcmdutils
CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/common/zfs
CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common/sys
diff --git a/cddl/usr.sbin/zdb/Makefile b/cddl/usr.sbin/zdb/Makefile
index 84b64e4..8f50aaa 100644
--- a/cddl/usr.sbin/zdb/Makefile
+++ b/cddl/usr.sbin/zdb/Makefile
@@ -12,6 +12,7 @@ CSTD= c99
CFLAGS+= -I${SRCTOP}/sys/cddl/compat/opensolaris
CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include
CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/lib/libumem
+CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libcmdutils
CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libnvpair
CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libuutil/common
CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzfs/common
OpenPOWER on IntegriCloud