OpenZFS 640 - number_to_scaled_string is duplicated in several commands

Porting Notes:
- The OpenZFS patch added nicenum_scale() and nicenum() to a
  library not used by ZFS.  Rather than pull in a new dependency
  the version of nicenum in lib/libzpool/util.c was simply
  replaced with the new one.

Reviewed by: Sebastian Wiedenroth <wiedi@frubar.net>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Yuri Pankov <yuripv@gmx.com>
Approved by: Dan McDonald <danmcd@joyent.com>
Authored by: Jason King <jason.brian.king@gmail.com>
Ported-by: Brian Behlendorf <behlendorf1@llnl.gov>

OpenZFS-issue: https://www.illumos.org/issues/640
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/0a055120
Closes #6796
This commit is contained in:
Jason King 2017-06-13 04:16:45 -05:00 committed by Brian Behlendorf
parent 47c8e7fd97
commit f3c8c9e6f0
4 changed files with 213 additions and 70 deletions

View File

@ -281,12 +281,12 @@ dump_history_offsets(objset_t *os, uint64_t object, void *data, size_t size)
} }
static void static void
zdb_nicenum(uint64_t num, char *buf) zdb_nicenum(uint64_t num, char *buf, size_t buflen)
{ {
if (dump_opt['P']) if (dump_opt['P'])
(void) sprintf(buf, "%llu", (longlong_t)num); (void) snprintf(buf, buflen, "%llu", (longlong_t)num);
else else
nicenum(num, buf); nicenum(num, buf, sizeof (buf));
} }
static const char histo_stars[] = "****************************************"; static const char histo_stars[] = "****************************************";
@ -464,12 +464,17 @@ dump_bpobj(objset_t *os, uint64_t object, void *data, size_t size)
uint64_t i; uint64_t i;
char bytes[32], comp[32], uncomp[32]; 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) if (bpop == NULL)
return; return;
zdb_nicenum(bpop->bpo_bytes, bytes); zdb_nicenum(bpop->bpo_bytes, bytes, sizeof (bytes));
zdb_nicenum(bpop->bpo_comp, comp); zdb_nicenum(bpop->bpo_comp, comp, sizeof (comp));
zdb_nicenum(bpop->bpo_uncomp, uncomp); zdb_nicenum(bpop->bpo_uncomp, uncomp, sizeof (uncomp));
(void) printf("\t\tnum_blkptrs = %llu\n", (void) printf("\t\tnum_blkptrs = %llu\n",
(u_longlong_t)bpop->bpo_num_blkptrs); (u_longlong_t)bpop->bpo_num_blkptrs);
@ -763,7 +768,10 @@ dump_metaslab_stats(metaslab_t *msp)
avl_tree_t *t = &msp->ms_size_tree; avl_tree_t *t = &msp->ms_size_tree;
int free_pct = range_tree_space(rt) * 100 / msp->ms_size; 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", (void) printf("\t %25s %10lu %7s %6s %4s %4d%%\n",
"segments", avl_numnodes(t), "maxsize", maxbuf, "segments", avl_numnodes(t), "maxsize", maxbuf,
@ -780,7 +788,8 @@ dump_metaslab(metaslab_t *msp)
space_map_t *sm = msp->ms_sm; space_map_t *sm = msp->ms_sm;
char freebuf[32]; 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( (void) printf(
"\tmetaslab %6llu offset %12llx spacemap %6llu free %5s\n", "\tmetaslab %6llu offset %12llx spacemap %6llu free %5s\n",
@ -1354,6 +1363,9 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
time_t crtime; time_t crtime;
char nice[32]; char nice[32];
/* make sure nicenum has enough space */
CTASSERT(sizeof (nice) >= NN_NUMBUF_SZ);
if (dd == NULL) if (dd == NULL)
return; return;
@ -1369,15 +1381,15 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
(u_longlong_t)dd->dd_origin_obj); (u_longlong_t)dd->dd_origin_obj);
(void) printf("\t\tchild_dir_zapobj = %llu\n", (void) printf("\t\tchild_dir_zapobj = %llu\n",
(u_longlong_t)dd->dd_child_dir_zapobj); (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); (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); (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); (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); (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\treserved = %s\n", nice);
(void) printf("\t\tprops_zapobj = %llu\n", (void) printf("\t\tprops_zapobj = %llu\n",
(u_longlong_t)dd->dd_props_zapobj); (u_longlong_t)dd->dd_props_zapobj);
@ -1387,7 +1399,8 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
(u_longlong_t)dd->dd_flags); (u_longlong_t)dd->dd_flags);
#define DO(which) \ #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) (void) printf("\t\tused_breakdown[" #which "] = %s\n", nice)
DO(HEAD); DO(HEAD);
DO(SNAP); DO(SNAP);
@ -1406,15 +1419,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 used[32], compressed[32], uncompressed[32], unique[32];
char blkbuf[BP_SPRINTF_LEN]; 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) if (ds == NULL)
return; return;
ASSERT(size == sizeof (*ds)); ASSERT(size == sizeof (*ds));
crtime = ds->ds_creation_time; crtime = ds->ds_creation_time;
zdb_nicenum(ds->ds_referenced_bytes, used); zdb_nicenum(ds->ds_referenced_bytes, used, sizeof (used));
zdb_nicenum(ds->ds_compressed_bytes, compressed); zdb_nicenum(ds->ds_compressed_bytes, compressed, sizeof (compressed));
zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed); zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed,
zdb_nicenum(ds->ds_unique_bytes, unique); sizeof (uncompressed));
zdb_nicenum(ds->ds_unique_bytes, unique, sizeof (unique));
snprintf_blkptr(blkbuf, sizeof (blkbuf), &ds->ds_bp); snprintf_blkptr(blkbuf, sizeof (blkbuf), &ds->ds_bp);
(void) printf("\t\tdir_obj = %llu\n", (void) printf("\t\tdir_obj = %llu\n",
@ -1473,12 +1493,15 @@ dump_bptree(objset_t *os, uint64_t obj, const char *name)
bptree_phys_t *bt; bptree_phys_t *bt;
dmu_buf_t *db; dmu_buf_t *db;
/* make sure nicenum has enough space */
CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
if (dump_opt['d'] < 3) if (dump_opt['d'] < 3)
return; return;
VERIFY3U(0, ==, dmu_bonus_hold(os, obj, FTAG, &db)); VERIFY3U(0, ==, dmu_bonus_hold(os, obj, FTAG, &db));
bt = db->db_data; 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", (void) printf("\n %s: %llu datasets, %s\n",
name, (unsigned long long)(bt->bt_end - bt->bt_begin), bytes); name, (unsigned long long)(bt->bt_end - bt->bt_begin), bytes);
dmu_buf_rele(db, FTAG); dmu_buf_rele(db, FTAG);
@ -1511,13 +1534,18 @@ dump_full_bpobj(bpobj_t *bpo, const char *name, int indent)
char uncomp[32]; char uncomp[32];
uint64_t i; uint64_t i;
/* 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) if (dump_opt['d'] < 3)
return; 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) { if (bpo->bpo_havesubobj && bpo->bpo_phys->bpo_subobjs != 0) {
zdb_nicenum(bpo->bpo_phys->bpo_comp, comp); zdb_nicenum(bpo->bpo_phys->bpo_comp, comp, sizeof (comp));
zdb_nicenum(bpo->bpo_phys->bpo_uncomp, uncomp); zdb_nicenum(bpo->bpo_phys->bpo_uncomp, uncomp, sizeof (uncomp));
(void) printf(" %*s: object %llu, %llu local blkptrs, " (void) printf(" %*s: object %llu, %llu local blkptrs, "
"%llu subobjs in object, %llu, %s (%s/%s comp)\n", "%llu subobjs in object, %llu, %s (%s/%s comp)\n",
indent * 8, name, indent * 8, name,
@ -1571,6 +1599,11 @@ dump_deadlist(dsl_deadlist_t *dl)
char comp[32]; char comp[32];
char uncomp[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) if (dump_opt['d'] < 3)
return; return;
@ -1579,9 +1612,9 @@ dump_deadlist(dsl_deadlist_t *dl)
return; return;
} }
zdb_nicenum(dl->dl_phys->dl_used, bytes); zdb_nicenum(dl->dl_phys->dl_used, bytes, sizeof (bytes));
zdb_nicenum(dl->dl_phys->dl_comp, comp); zdb_nicenum(dl->dl_phys->dl_comp, comp, sizeof (comp));
zdb_nicenum(dl->dl_phys->dl_uncomp, uncomp); zdb_nicenum(dl->dl_phys->dl_uncomp, uncomp, sizeof (uncomp));
(void) printf("\n Deadlist: %s (%s/%s comp)\n", (void) printf("\n Deadlist: %s (%s/%s comp)\n",
bytes, comp, uncomp); bytes, comp, uncomp);
@ -1942,6 +1975,13 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header,
char aux[50]; char aux[50];
int error; 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) { if (*print_header) {
(void) printf("\n%10s %3s %5s %5s %5s %6s %5s %6s %s\n", (void) printf("\n%10s %3s %5s %5s %5s %6s %5s %6s %s\n",
"Object", "lvl", "iblk", "dblk", "dsize", "dnsize", "Object", "lvl", "iblk", "dblk", "dsize", "dnsize",
@ -1982,12 +2022,12 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header,
if (dnode_slots_used) if (dnode_slots_used)
*dnode_slots_used = doi.doi_dnodesize / DNODE_MIN_SIZE; *dnode_slots_used = doi.doi_dnodesize / DNODE_MIN_SIZE;
zdb_nicenum(doi.doi_metadata_block_size, iblk); zdb_nicenum(doi.doi_metadata_block_size, iblk, sizeof (iblk));
zdb_nicenum(doi.doi_data_block_size, dblk); zdb_nicenum(doi.doi_data_block_size, dblk, sizeof (dblk));
zdb_nicenum(doi.doi_max_offset, lsize); zdb_nicenum(doi.doi_max_offset, lsize, sizeof (lsize));
zdb_nicenum(doi.doi_physical_blocks_512 << 9, asize); zdb_nicenum(doi.doi_physical_blocks_512 << 9, asize, sizeof (asize));
zdb_nicenum(doi.doi_bonus_size, bonus_size); zdb_nicenum(doi.doi_bonus_size, bonus_size, sizeof (bonus_size));
zdb_nicenum(doi.doi_dnodesize, dnsize); zdb_nicenum(doi.doi_dnodesize, dnsize, sizeof (dnsize));
(void) sprintf(fill, "%6.2f", 100.0 * doi.doi_fill_count * (void) sprintf(fill, "%6.2f", 100.0 * doi.doi_fill_count *
doi.doi_data_block_size / (object == 0 ? DNODES_PER_BLOCK : 1) / doi.doi_data_block_size / (object == 0 ? DNODES_PER_BLOCK : 1) /
doi.doi_max_offset); doi.doi_max_offset);
@ -2063,6 +2103,8 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header,
for (;;) { for (;;) {
char segsize[32]; char segsize[32];
/* make sure nicenum has enough space */
CTASSERT(sizeof (segsize) >= NN_NUMBUF_SZ);
error = dnode_next_offset(dn, error = dnode_next_offset(dn,
0, &start, minlvl, blkfill, 0); 0, &start, minlvl, blkfill, 0);
if (error) if (error)
@ -2070,7 +2112,7 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header,
end = start; end = start;
error = dnode_next_offset(dn, error = dnode_next_offset(dn,
DNODE_FIND_HOLE, &end, minlvl, blkfill, 0); 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)" (void) printf("\t\tsegment [%016llx, %016llx)"
" size %5s\n", (u_longlong_t)start, " size %5s\n", (u_longlong_t)start,
(u_longlong_t)end, segsize); (u_longlong_t)end, segsize);
@ -2107,6 +2149,9 @@ dump_dir(objset_t *os)
uint64_t max_slot_used = 0; uint64_t max_slot_used = 0;
uint64_t dnode_slots; uint64_t dnode_slots;
/* make sure nicenum has enough space */
CTASSERT(sizeof (numbuf) >= NN_NUMBUF_SZ);
dsl_pool_config_enter(dmu_objset_pool(os), FTAG); dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
dmu_objset_fast_stat(os, &dds); dmu_objset_fast_stat(os, &dds);
dsl_pool_config_exit(dmu_objset_pool(os), FTAG); dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
@ -2125,7 +2170,7 @@ dump_dir(objset_t *os)
ASSERT3U(usedobjs, ==, BP_GET_FILL(os->os_rootbp)); ASSERT3U(usedobjs, ==, BP_GET_FILL(os->os_rootbp));
zdb_nicenum(refdbytes, numbuf); zdb_nicenum(refdbytes, numbuf, sizeof (numbuf));
if (verbosity >= 4) { if (verbosity >= 4) {
(void) snprintf(blkbuf, sizeof (blkbuf), ", rootbp "); (void) snprintf(blkbuf, sizeof (blkbuf), ", rootbp ");
@ -3142,6 +3187,9 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
int sec_remaining = int sec_remaining =
(zcb->zcb_totalasize - bytes) / 1024 / kb_per_sec; (zcb->zcb_totalasize - bytes) / 1024 / kb_per_sec;
/* make sure nicenum has enough space */
CTASSERT(sizeof (buf) >= NN_NUMBUF_SZ);
zfs_nicebytes(bytes, buf, sizeof (buf)); zfs_nicebytes(bytes, buf, sizeof (buf));
(void) fprintf(stderr, (void) fprintf(stderr,
"\r%5s completed (%4dMB/s) " "\r%5s completed (%4dMB/s) "
@ -3497,6 +3545,14 @@ dump_block_stats(spa_t *spa)
char avg[32], gang[32]; char avg[32], gang[32];
const char *typename; 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) if (t < DMU_OT_NUMTYPES)
typename = dmu_ot[t].ot_name; typename = dmu_ot[t].ot_name;
else else
@ -3530,12 +3586,17 @@ dump_block_stats(spa_t *spa)
zcb.zcb_type[ZB_TOTAL][t].zb_asize) zcb.zcb_type[ZB_TOTAL][t].zb_asize)
continue; continue;
zdb_nicenum(zb->zb_count, csize); zdb_nicenum(zb->zb_count, csize,
zdb_nicenum(zb->zb_lsize, lsize); sizeof (csize));
zdb_nicenum(zb->zb_psize, psize); zdb_nicenum(zb->zb_lsize, lsize,
zdb_nicenum(zb->zb_asize, asize); sizeof (lsize));
zdb_nicenum(zb->zb_asize / zb->zb_count, avg); zdb_nicenum(zb->zb_psize, psize,
zdb_nicenum(zb->zb_gangs, gang); 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" (void) printf("%6s\t%5s\t%5s\t%5s\t%5s"
"\t%5.2f\t%6.2f\t", "\t%5.2f\t%6.2f\t",

View File

@ -23,6 +23,8 @@
* Copyright (c) 2011, 2016 by Delphix. All rights reserved. * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved. * Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 Joyent, Inc.
*/ */
/* /*
@ -608,12 +610,13 @@ usage(boolean_t requested)
{ {
const ztest_shared_opts_t *zo = &ztest_opts_defaults; const ztest_shared_opts_t *zo = &ztest_opts_defaults;
char nice_vdev_size[10]; char nice_vdev_size[NN_NUMBUF_SZ];
char nice_gang_bang[10]; char nice_gang_bang[NN_NUMBUF_SZ];
FILE *fp = requested ? stdout : stderr; FILE *fp = requested ? stdout : stderr;
nicenum(zo->zo_vdev_size, nice_vdev_size); nicenum(zo->zo_vdev_size, nice_vdev_size, sizeof (nice_vdev_size));
nicenum(zo->zo_metaslab_gang_bang, nice_gang_bang); nicenum(zo->zo_metaslab_gang_bang, nice_gang_bang,
sizeof (nice_gang_bang));
(void) fprintf(fp, "Usage: %s\n" (void) fprintf(fp, "Usage: %s\n"
"\t[-v vdevs (default: %llu)]\n" "\t[-v vdevs (default: %llu)]\n"
@ -3550,10 +3553,10 @@ ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id)
old_class_space, new_class_space); old_class_space, new_class_space);
if (ztest_opts.zo_verbose >= 5) { 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(old_class_space, oldnumbuf, sizeof (oldnumbuf));
nicenum(new_class_space, newnumbuf); nicenum(new_class_space, newnumbuf, sizeof (newnumbuf));
(void) printf("%s grew from %s to %s\n", (void) printf("%s grew from %s to %s\n",
spa->spa_name, oldnumbuf, newnumbuf); spa->spa_name, oldnumbuf, newnumbuf);
} }
@ -7024,7 +7027,7 @@ main(int argc, char **argv)
ztest_info_t *zi; ztest_info_t *zi;
ztest_shared_callstate_t *zc; ztest_shared_callstate_t *zc;
char timebuf[100]; char timebuf[100];
char numbuf[6]; char numbuf[NN_NUMBUF_SZ];
spa_t *spa; spa_t *spa;
char *cmd; char *cmd;
boolean_t hasalt; boolean_t hasalt;
@ -7178,7 +7181,7 @@ main(int argc, char **argv)
now = MIN(now, zs->zs_proc_stop); now = MIN(now, zs->zs_proc_stop);
print_time(zs->zs_proc_stop - now, timebuf); 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, " (void) printf("Pass %3d, %8s, %3llu ENOSPC, "
"%4.1f%% of %5s used, %3.0f%% done, %8s to go\n", "%4.1f%% of %5s used, %3.0f%% done, %8s to go\n",

View File

@ -626,6 +626,9 @@ extern void delay(clock_t ticks);
#define ptob(x) ((x) * PAGESIZE) #define ptob(x) ((x) * PAGESIZE)
#define NN_DIVISOR_1000 (1U << 0)
#define NN_NUMBUF_SZ (6)
extern uint64_t physmem; extern uint64_t physmem;
extern int highbit64(uint64_t i); extern int highbit64(uint64_t i);
@ -639,7 +642,7 @@ extern void random_init(void);
extern void random_fini(void); extern void random_fini(void);
struct spa; 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 void show_pool_stats(struct spa *);
extern int set_global_var(char *arg); extern int set_global_var(char *arg);

View File

@ -21,6 +21,7 @@
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 by Delphix. All rights reserved. * Copyright (c) 2016 by Delphix. All rights reserved.
* Copyright 2017 Jason King
*/ */
#include <assert.h> #include <assert.h>
@ -38,31 +39,104 @@
* Routines needed by more than one client of libzpool. * Routines needed by more than one client of libzpool.
*/ */
/* The largest suffix that can fit, aka an exabyte (2^60 / 10^18) */
#define INDEX_MAX (6)
/* Verify INDEX_MAX fits */
CTASSERT_GLOBAL(INDEX_MAX * 10 < sizeof (uint64_t) * 8);
void void
nicenum(uint64_t num, char *buf) nicenum_scale(uint64_t n, size_t units, char *buf, size_t buflen,
uint32_t flags)
{ {
uint64_t n = num; uint64_t divamt = 1024;
uint64_t divisor = 1;
int index = 0; int index = 0;
int rc = 0;
char u; char u;
while (n >= 1024) { if (units == 0)
n = (n + (1024 / 2)) / 1024; /* Round up or down */ 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++; index++;
} }
u = " KMGTPE"[index]; u = " KMGTPE"[index];
if (index == 0) { if (index == 0) {
(void) sprintf(buf, "%llu", (u_longlong_t)n); rc = snprintf(buf, buflen, "%llu", (u_longlong_t)n);
} else if (n < 10 && (num & (num - 1)) != 0) { } else if (n % divisor == 0) {
(void) sprintf(buf, "%.2f%c", /*
(double)num / (1ULL << 10 * index), u); * If this is an even multiple of the base, always display
} else if (n < 100 && (num & (num - 1)) != 0) { * without any decimal precision.
(void) sprintf(buf, "%.1f%c", */
(double)num / (1ULL << 10 * index), u); rc = snprintf(buf, buflen, "%llu%c",
(u_longlong_t)(n / divisor), u);
} else { } else {
(void) sprintf(buf, "%llu%c", (u_longlong_t)n, u); /*
* 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);
} }
static void static void
@ -99,15 +173,17 @@ show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
sec = MAX(1, vs->vs_timestamp / NANOSEC); sec = MAX(1, vs->vs_timestamp / NANOSEC);
nicenum(vs->vs_alloc, used); nicenum(vs->vs_alloc, used, sizeof (used));
nicenum(vs->vs_space - vs->vs_alloc, avail); nicenum(vs->vs_space - vs->vs_alloc, avail, sizeof (avail));
nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops); nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops, sizeof (rops));
nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops); nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops, sizeof (wops));
nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes); nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes,
nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes); sizeof (rbytes));
nicenum(vs->vs_read_errors, rerr); nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes,
nicenum(vs->vs_write_errors, werr); sizeof (wbytes));
nicenum(vs->vs_checksum_errors, cerr); 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", (void) printf("%*s%s%*s%*s%*s %5s %5s %5s %5s %5s %5s %5s\n",
indent, "", indent, "",