summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason King <jason.brian.king@gmail.com>2017-06-13 04:16:45 -0500
committerDan McDonald <danmcd@joyent.com>2017-09-04 20:42:57 -0400
commit0a0551200ecbcd4f1b17560acaeeb7b6c8b0090e (patch)
tree4e943314876a263be2f8209de2eea1a87428be80
parent30c75cb09b4d5e86a94a25a9a7ab7481510b57b0 (diff)
downloadillumos-joyent-0a0551200ecbcd4f1b17560acaeeb7b6c8b0090e.tar.gz
640 number_to_scaled_string is duplicated in several commands
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>
-rw-r--r--usr/src/cmd/beadm/Makefile2
-rw-r--r--usr/src/cmd/beadm/beadm.c30
-rw-r--r--usr/src/cmd/du/du.c82
-rw-r--r--usr/src/cmd/fs.d/Makefile1
-rw-r--r--usr/src/cmd/fs.d/df.c101
-rw-r--r--usr/src/cmd/ls/ls.c106
-rw-r--r--usr/src/cmd/stat/fsstat/Makefile2
-rw-r--r--usr/src/cmd/stat/fsstat/fsstat.c157
-rw-r--r--usr/src/cmd/swap/Makefile.com2
-rw-r--r--usr/src/cmd/swap/swap.c177
-rw-r--r--usr/src/cmd/zdb/Makefile.com3
-rw-r--r--usr/src/cmd/zdb/zdb.c138
-rw-r--r--usr/src/cmd/ztest/ztest.c21
-rw-r--r--usr/src/lib/libcmdutils/Makefile.com2
-rw-r--r--usr/src/lib/libcmdutils/common/mapfile-vers2
-rw-r--r--usr/src/lib/libcmdutils/common/nicenum.c130
-rw-r--r--usr/src/lib/libcmdutils/libcmdutils.h8
-rw-r--r--usr/src/lib/libzfs/Makefile.com2
-rw-r--r--usr/src/lib/libzfs/common/libzfs_util.c38
-rw-r--r--usr/src/lib/libzpool/common/llib-lzpool1
-rw-r--r--usr/src/lib/libzpool/common/sys/zfs_context.h2
-rw-r--r--usr/src/lib/libzpool/common/util.c47
22 files changed, 421 insertions, 633 deletions
diff --git a/usr/src/cmd/beadm/Makefile b/usr/src/cmd/beadm/Makefile
index 8ea7ac8cae..e19adc52bc 100644
--- a/usr/src/cmd/beadm/Makefile
+++ b/usr/src/cmd/beadm/Makefile
@@ -30,7 +30,7 @@ POFILE= beadm.po
include ../Makefile.cmd
-LDLIBS += -lnvpair -lbe
+LDLIBS += -lnvpair -lbe -lcmdutils
CERRWARN += -_gcc=-Wno-parentheses
$(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG
diff --git a/usr/src/cmd/beadm/beadm.c b/usr/src/cmd/beadm/beadm.c
index 00073ae717..3667c762a4 100644
--- a/usr/src/cmd/beadm/beadm.c
+++ b/usr/src/cmd/beadm/beadm.c
@@ -25,6 +25,7 @@
* Copyright 2015 Toomas Soome <tsoome@me.com>
* Copyright 2015 Gary Mills
* Copyright (c) 2015 by Delphix. All rights reserved.
+ * Copyright 2017 Jason King
*/
/*
@@ -40,6 +41,8 @@
#include <stdlib.h>
#include <wchar.h>
#include <sys/types.h>
+#include <sys/debug.h>
+#include <libcmdutils.h>
#include "libbe.h"
@@ -55,6 +58,7 @@
#define DT_BUF_LEN (128)
#define NUM_COLS (6)
+CTASSERT(DT_BUF_LEN >= NN_NUMBUF_SZ);
static int be_do_activate(int argc, char **argv);
static int be_do_create(int argc, char **argv);
@@ -249,32 +253,6 @@ init_hdr_cols(enum be_fmt be_fmt, struct hdr_info *hdr)
}
static void
-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 {
- int i;
- for (i = 2; i >= 0; i--) {
- if (snprintf(buf, buflen, "%.*f%c", i,
- (double)num / (1ULL << 10 * index), u) <= 5)
- break;
- }
- }
-}
-
-static void
count_widths(enum be_fmt be_fmt, struct hdr_info *hdr, be_node_list_t *be_nodes)
{
size_t len[NUM_COLS];
diff --git a/usr/src/cmd/du/du.c b/usr/src/cmd/du/du.c
index 3911135b50..24ca7aca50 100644
--- a/usr/src/cmd/du/du.c
+++ b/usr/src/cmd/du/du.c
@@ -22,6 +22,7 @@
* Copyright 2017 OmniTI Computer Consulting, Inc. All rights reserved.
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2017 Jason King
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -66,9 +67,6 @@ static char *name;
static size_t base_len = PATH_MAX + 1; /* # of chars for base */
static size_t name_len = PATH_MAX + 1; /* # of chars for name */
-#define NUMBER_WIDTH 64
-typedef char numbuf_t[NUMBER_WIDTH];
-
/*
* Output formats. illumos uses a tab as separator, XPG4 a space.
*/
@@ -528,75 +526,6 @@ descend(char *curname, int curfd, int *retcode, dev_t device)
return (blocks);
}
-/*
- * Convert an unsigned long long to a string representation and place the
- * result in the caller-supplied buffer.
- * The given number is in units of "unit_from" size,
- * this will first be converted to a number in 1024 or 1000 byte size,
- * depending on the scaling factor.
- * Then the number is scaled down until it is small enough to be in a good
- * human readable format i.e. in the range 0 thru scale-1.
- * If it's smaller than 10 there's room enough to provide one decimal place.
- * The value "(unsigned long long)-1" is a special case and is always
- * converted to "-1".
- * Returns a pointer to the caller-supplied buffer.
- */
-static char *
-number_to_scaled_string(
- numbuf_t buf, /* put the result here */
- unsigned long long number, /* convert this number */
- unsigned long long unit_from, /* number of bytes per input unit */
- unsigned long long scale) /* 1024 (-h) or 1000 (-H) */
-{
- unsigned long long save = 0;
- char *M = "KMGTPE"; /* Measurement: kilo, mega, giga, tera, peta, exa */
- char *uom = M; /* unit of measurement, initially 'K' (=M[0]) */
-
- if ((long long)number == (long long)-1) {
- (void) strcpy(buf, "-1");
- return (buf);
- }
-
- /*
- * Convert number from unit_from to given scale (1024 or 1000)
- * This means multiply number with unit_from and divide by scale.
- * if number is large enough, we first divide and then multiply
- * to avoid an overflow
- * (large enough here means 100 (rather arbitrary value)
- * times scale in order to reduce rounding errors)
- * otherwise, we first multiply and then divide
- * to avoid an underflow
- */
- if (number >= 100L * scale) {
- number = number / scale;
- number = number * unit_from;
- } else {
- number = number * unit_from;
- number = number / scale;
- }
-
- /*
- * Now we have number as a count of scale units.
- * Stop scaling when we reached exa bytes, then something is
- * probably wrong with our number.
- */
- while ((number >= scale) && (*uom != 'E')) {
- uom++; /* next unit of measurement */
- save = number;
- number = (number + (scale / 2)) / scale;
- }
-
- /* check if we should output a decimal place after the point */
- if (save && ((save / scale) < 10)) {
- /* sprintf() will round for us */
- float fnum = (float)save / scale;
- (void) sprintf(buf, "%4.1f%c", fnum, *uom);
- } else {
- (void) sprintf(buf, "%4llu%c", number, *uom);
- }
- return (buf);
-}
-
static void
printsize(blkcnt_t blocks, char *path)
{
@@ -605,11 +534,10 @@ printsize(blkcnt_t blocks, char *path)
bsize = Aflg ? 1 : DEV_BSIZE;
if (hflg) {
- numbuf_t numbuf;
- unsigned long long scale = 1024L;
- (void) printf(FORMAT1,
- number_to_scaled_string(numbuf, blocks, bsize, scale),
- path);
+ char buf[NN_NUMBUF_SZ] = { 0 };
+
+ nicenum_scale(blocks, bsize, buf, sizeof (buf), 0);
+ (void) printf(FORMAT1, buf, path);
} else if (kflg) {
(void) printf(FORMAT2, (long long)kb(blocks), path);
} else if (mflg) {
diff --git a/usr/src/cmd/fs.d/Makefile b/usr/src/cmd/fs.d/Makefile
index 3c36817494..2f5bd31ec7 100644
--- a/usr/src/cmd/fs.d/Makefile
+++ b/usr/src/cmd/fs.d/Makefile
@@ -87,6 +87,7 @@ CERRWARN += -_gcc=-Wno-unused-variable
CERRWARN += -_gcc=-Wno-uninitialized
CERRWARN += -_gcc=-Wno-unused-function
+$(DFPROG) := LDLIBS += -lcmdutils
$(SPPROG) := LDLIBS += -lkstat
$(ROOTETCMNTTAB) := FILEMODE = 444
diff --git a/usr/src/cmd/fs.d/df.c b/usr/src/cmd/fs.d/df.c
index 3ba4aeb832..ee7bf6e7d5 100644
--- a/usr/src/cmd/fs.d/df.c
+++ b/usr/src/cmd/fs.d/df.c
@@ -26,6 +26,9 @@
* Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+/*
+ * Copyright 2016 Jason King
+ */
#include <dlfcn.h>
#include <stdio.h>
@@ -48,7 +51,9 @@
#include <sys/mkdev.h>
#include <sys/int_limits.h>
#include <sys/zone.h>
+#include <sys/debug.h>
#include <libzfs.h>
+#include <libcmdutils.h>
#include "fslib.h"
@@ -134,6 +139,7 @@ extern char *default_fstype(char *);
/* message */
#define NUMBER_WIDTH 40
+CTASSERT(NUMBER_WIDTH >= NN_NUMBUF_SZ);
/*
* A numbuf_t is used when converting a number to a string representation
@@ -219,7 +225,6 @@ static bool_int o_option;
static bool_int tty_output;
static bool_int use_scaling;
-static int scale;
static void usage(void);
static void do_devnm(int, char **);
@@ -591,7 +596,6 @@ parse_options(int argc, char *argv[])
SET_OPTION(g);
} else if (arg == 'h') {
use_scaling = TRUE;
- scale = 1024;
} else if (arg == 'k' && ! k_option) {
SET_OPTION(k);
} else if (arg == 'l' && ! l_option) {
@@ -967,8 +971,7 @@ run_fs_specific_df(struct df_request request_list[], int entries)
*/
static int
prune_list(struct df_request request_list[],
- size_t n_requests,
- size_t *valid_requests)
+ size_t n_requests, size_t *valid_requests)
{
size_t i;
size_t n_valid = 0;
@@ -1167,73 +1170,6 @@ number_to_string(
}
/*
- * Convert an unsigned long long to a string representation and place the
- * result in the caller-supplied buffer.
- * The given number is in units of "unit_from" size,
- * this will first be converted to a number in 1024 or 1000 byte size,
- * depending on the scaling factor.
- * Then the number is scaled down until it is small enough to be in a good
- * human readable format i.e. in the range 0 thru scale-1.
- * If it's smaller than 10 there's room enough to provide one decimal place.
- * The value "(unsigned long long)-1" is a special case and is always
- * converted to "-1".
- * Returns a pointer to the caller-supplied buffer.
- */
-static char *
-number_to_scaled_string(
- numbuf_t buf, /* put the result here */
- unsigned long long number, /* convert this number */
- int unit_from,
- int scale)
-{
- unsigned long long save = 0;
- char *M = "KMGTPE"; /* Measurement: kilo, mega, giga, tera, peta, exa */
- char *uom = M; /* unit of measurement, initially 'K' (=M[0]) */
-
- if ((long long)number == (long long)-1) {
- (void) strcpy(buf, "-1");
- return (buf);
- }
-
- /*
- * Convert number from unit_from to given scale (1024 or 1000).
- * This means multiply number by unit_from and divide by scale.
- *
- * Would like to multiply by unit_from and then divide by scale,
- * but if the first multiplication would overflow, then need to
- * divide by scale and then multiply by unit_from.
- */
- if (number > (UINT64_MAX / (unsigned long long)unit_from)) {
- number = (number / (unsigned long long)scale) *
- (unsigned long long)unit_from;
- } else {
- number = (number * (unsigned long long)unit_from) /
- (unsigned long long)scale;
- }
-
- /*
- * Now we have number as a count of scale units.
- * Stop scaling when we reached exa bytes, then something is
- * probably wrong with our number.
- */
-
- while ((number >= scale) && (*uom != 'E')) {
- uom++; /* next unit of measurement */
- save = number;
- number = (number + (scale / 2)) / scale;
- }
- /* check if we should output a decimal place after the point */
- if (save && ((save / scale) < 10)) {
- /* sprintf() will round for us */
- float fnum = (float)save / scale;
- (void) sprintf(buf, "%2.1f%c", fnum, *uom);
- } else {
- (void) sprintf(buf, "%4llu%c", number, *uom);
- }
- return (buf);
-}
-
-/*
* The statvfs() implementation allows us to return only two values, the total
* number of blocks and the number of blocks free. The equation 'used = total -
* free' will not work for ZFS filesystems, due to the nature of pooled storage.
@@ -1488,16 +1424,19 @@ k_output(struct df_request *dfrp, struct statvfs64 *fsp)
adjust_total_blocks(dfrp, &total_blocks, fsp->f_frsize);
if (use_scaling) { /* comes from the -h option */
- (void) printf("%-*s %*s %*s %*s %-*s %-s\n",
- FILESYSTEM_WIDTH, file_system,
- SCALED_WIDTH, number_to_scaled_string(total_blocks_buf,
- total_blocks, fsp->f_frsize, scale),
- SCALED_WIDTH, number_to_scaled_string(used_blocks_buf,
- used_blocks, fsp->f_frsize, scale),
- AVAILABLE_WIDTH, number_to_scaled_string(available_blocks_buf,
- available_blocks, fsp->f_frsize, scale),
- CAPACITY_WIDTH, capacity_buf,
- DFR_MOUNT_POINT(dfrp));
+ nicenum_scale(total_blocks, fsp->f_frsize,
+ total_blocks_buf, sizeof (total_blocks_buf), 0);
+ nicenum_scale(used_blocks, fsp->f_frsize,
+ used_blocks_buf, sizeof (used_blocks_buf), 0);
+ nicenum_scale(available_blocks, fsp->f_frsize,
+ available_blocks_buf, sizeof (available_blocks_buf), 0);
+
+ (void) printf("%-*s %*s %*s %*s %-*s %-s\n",
+ FILESYSTEM_WIDTH, file_system,
+ SCALED_WIDTH, total_blocks_buf,
+ SCALED_WIDTH, used_blocks_buf,
+ AVAILABLE_WIDTH, available_blocks_buf,
+ CAPACITY_WIDTH, capacity_buf, DFR_MOUNT_POINT(dfrp));
return;
}
diff --git a/usr/src/cmd/ls/ls.c b/usr/src/cmd/ls/ls.c
index 1adab128a4..876ea20117 100644
--- a/usr/src/cmd/ls/ls.c
+++ b/usr/src/cmd/ls/ls.c
@@ -26,7 +26,7 @@
*/
/*
- * Copyright 2009 Jason King. All rights reserved.
+ * Copyright 2017 Jason King. All rights reserved.
* Use is subject to license terms.
*/
@@ -125,7 +125,6 @@
#undef BUFSIZ
#define BUFSIZ 4096
-#define NUMBER_WIDTH 40
#define FMTSIZE 50
struct ditem {
@@ -216,11 +215,6 @@ struct dchain {
struct dchain *dc_next; /* next directory in the chain */
};
-/*
- * A numbuf_t is used when converting a number to a string representation
- */
-typedef char numbuf_t[NUMBER_WIDTH];
-
static struct dchain *dfirst; /* start of the dir chain */
static struct dchain *cdfirst; /* start of the current dir chain */
static struct dchain *dtemp; /* temporary - used for linking */
@@ -252,9 +246,6 @@ static struct cachenode *findincache(struct cachenode **, long);
static void csi_pprintf(unsigned char *);
static void pprintf(char *, char *);
static int compar(struct lbuf **pp1, struct lbuf **pp2);
-static char *number_to_scaled_string(numbuf_t buf,
- unsigned long long number,
- long scale);
static void record_ancestry(char *, struct stat *, struct lbuf *,
int, struct ditem *);
static void ls_color_init(void);
@@ -306,7 +297,7 @@ static int atm;
static int mtm;
static int crtm;
static int alltm;
-static long hscale;
+static uint_t nicenum_flags;
static mode_t flags;
static int err = 0; /* Contains return code */
static int colorflg;
@@ -481,7 +472,7 @@ main(int argc, char *argv[])
if (strcmp(long_options[option_index].name,
"si") == 0) {
hflg++;
- hscale = 1000;
+ nicenum_flags |= NN_DIVISOR_1000;
continue;
}
@@ -751,7 +742,6 @@ main(int argc, char *argv[])
continue;
case 'h':
hflg++;
- hscale = 1024;
continue;
case 'H':
Hflg++;
@@ -1255,7 +1245,6 @@ static void
pentry(struct lbuf *ap)
{
struct lbuf *p;
- numbuf_t hbuf;
char *dmark = ""; /* Used if -p or -F option active */
char *cp;
char *str;
@@ -1308,9 +1297,13 @@ pentry(struct lbuf *ap)
curcol += printf("%3u, %2u",
(uint_t)major((dev_t)p->lsize),
(uint_t)minor((dev_t)p->lsize));
- } else if (hflg && (p->lsize >= hscale)) {
- curcol += printf("%7s",
- number_to_scaled_string(hbuf, p->lsize, hscale));
+ } else if (hflg) {
+ char numbuf[NN_NUMBUF_SZ];
+
+ nicenum_scale(p->lsize, 1, numbuf, sizeof (numbuf),
+ nicenum_flags);
+
+ curcol += printf("%7s", numbuf);
} else {
uint64_t bsize = p->lsize / block_size;
@@ -2444,85 +2437,6 @@ strcol(unsigned char *s1)
return (w);
}
-/*
- * Convert an unsigned long long to a string representation and place the
- * result in the caller-supplied buffer.
- *
- * The number provided is a size in bytes. The number is first
- * converted to an integral multiple of 'scale' bytes. This new
- * number is then scaled down until it is small enough to be in a good
- * human readable format, i.e. in the range 0 thru scale-1. If the
- * number used to derive the final number is not a multiple of scale, and
- * the final number has only a single significant digit, we compute
- * tenths of units to provide a second significant digit.
- *
- * The value "(unsigned long long)-1" is a special case and is always
- * converted to "-1".
- *
- * A pointer to the caller-supplied buffer is returned.
- */
-static char *
-number_to_scaled_string(
- numbuf_t buf, /* put the result here */
- unsigned long long number, /* convert this number */
- long scale)
-{
- unsigned long long save;
- /* Measurement: kilo, mega, giga, tera, peta, exa */
- char *uom = "KMGTPE";
-
- if ((long long)number == (long long)-1) {
- (void) strlcpy(buf, "-1", sizeof (numbuf_t));
- return (buf);
- }
-
- save = number;
- number = number / scale;
-
- /*
- * Now we have number as a count of scale units.
- * If no further scaling is necessary, we round up as appropriate.
- *
- * The largest value number could have had entering the routine is
- * 16 Exabytes, so running off the end of the uom array should
- * never happen. We check for that, though, as a guard against
- * a breakdown elsewhere in the algorithm.
- */
- if (number < (unsigned long long)scale) {
- if ((save % scale) >= (unsigned long long)(scale / 2)) {
- if (++number == (unsigned long long)scale) {
- uom++;
- number = 1;
- }
- }
- } else {
- while ((number >= (unsigned long long)scale) && (*uom != 'E')) {
- uom++; /* next unit of measurement */
- save = number;
- /*
- * If we're over half way to the next unit of
- * 'scale' bytes (which means we should round
- * up), then adding half of 'scale' prior to
- * the division will push us into that next
- * unit of scale when we perform the division
- */
- number = (number + (scale / 2)) / scale;
- }
- }
-
- /* check if we should output a decimal place after the point */
- if ((save / scale) < 10) {
- /* snprintf() will round for us */
- float fnum = (float)save / scale;
- (void) snprintf(buf, sizeof (numbuf_t), "%2.1f%c",
- fnum, *uom);
- } else {
- (void) snprintf(buf, sizeof (numbuf_t), "%4llu%c",
- number, *uom);
- }
- return (buf);
-}
-
/* Get extended system attributes and set the display */
int
diff --git a/usr/src/cmd/stat/fsstat/Makefile b/usr/src/cmd/stat/fsstat/Makefile
index 26bfdb023b..b86e2cc8f7 100644
--- a/usr/src/cmd/stat/fsstat/Makefile
+++ b/usr/src/cmd/stat/fsstat/Makefile
@@ -33,7 +33,7 @@ include $(SRC)/cmd/stat/Makefile.stat
COMMON_OBJS = common.o timestamp.o
COMMON_SRCS = $(COMMON_OBJS:%.o=$(STATCOMMONDIR)/%.c)
-LDLIBS += -lkstat
+LDLIBS += -lkstat -lcmdutils
CFLAGS += $(CCVERBOSE) -I${STATCOMMONDIR}
CERRWARN += -_gcc=-Wno-parentheses
FILEMODE= 0555
diff --git a/usr/src/cmd/stat/fsstat/fsstat.c b/usr/src/cmd/stat/fsstat/fsstat.c
index 5563f410ca..6bf07e333e 100644
--- a/usr/src/cmd/stat/fsstat/fsstat.c
+++ b/usr/src/cmd/stat/fsstat/fsstat.c
@@ -22,6 +22,7 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright (c) 2016 by Delphix. All rights reserved.
+ * Copyright 2017 Jason King
*/
#include <stdio.h>
@@ -41,12 +42,14 @@
#include <sys/fstyp.h>
#include <sys/fsid.h>
#include <sys/mnttab.h>
+#include <sys/debug.h>
#include <values.h>
#include <poll.h>
#include <ctype.h>
#include <libintl.h>
#include <locale.h>
#include <signal.h>
+#include <libcmdutils.h>
#include "statcommon.h"
@@ -73,12 +76,7 @@
#define HEADERLINES 12 /* Number of lines between display headers */
#define LBUFSZ 64 /* Generic size for local buffer */
-
-/*
- * The following are used for the nicenum() function
- */
-#define KILO_VAL 1024
-#define ONE_INDEX 3
+CTASSERT(LBUFSZ >= NN_NUMBUF_SZ);
#define NENTITY_INIT 1 /* Initial number of entities to allocate */
@@ -112,9 +110,6 @@ typedef struct entity {
#define ENTYPE_FSTYPE 1
#define ENTYPE_MNTPT 2
-/* If more sub-one units are added, make sure to adjust ONE_INDEX above */
-static char units[] = "num KMGTPE";
-
char *cmdname; /* name of this command */
int caught_cont = 0; /* have caught a SIGCONT */
@@ -131,70 +126,14 @@ usage()
exit(2);
}
-/*
- * Given a 64-bit number and a starting unit (e.g., n - nanoseconds),
- * convert the number to a 5-character representation including any
- * decimal point and single-character unit. Put that representation
- * into the array "buf" (which had better be big enough).
- */
-char *
-nicenum(uint64_t num, char unit, char *buf)
-{
- uint64_t n = num;
- int unit_index;
- int index;
- char u;
-
- /* If the user passed in a NUL/zero unit, use the blank value for 1 */
- if (unit == '\0')
- unit = ' ';
-
- unit_index = 0;
- while (units[unit_index] != unit) {
- unit_index++;
- if (unit_index > sizeof (units) - 1) {
- (void) sprintf(buf, "??");
- return (buf);
- }
- }
-
- index = 0;
- while (n >= KILO_VAL) {
- n = (n + (KILO_VAL / 2)) / KILO_VAL; /* Round up or down */
- index++;
- unit_index++;
- }
-
- if (unit_index >= sizeof (units) - 1) {
- (void) sprintf(buf, "??");
- return (buf);
- }
-
- u = units[unit_index];
-
- if (unit_index == ONE_INDEX) {
- (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);
- }
-
- return (buf);
-}
-
-
#define RAWVAL(ptr, member) ((ptr)->member.value.ui64)
#define DELTA(member) \
(newvsp->member.value.ui64 - (oldvsp ? oldvsp->member.value.ui64 : 0))
-#define PRINTSTAT(isnice, nicestring, rawstring, rawval, unit, buf) \
+#define PRINTSTAT(isnice, nicestring, rawstring, rawval, buf) \
(isnice) ? \
- (void) printf((nicestring), nicenum(rawval, unit, buf)) \
+ nicenum(rawval, buf, sizeof (buf)), \
+ (void) printf((nicestring), (buf)) \
: \
(void) printf((rawstring), (rawval))
@@ -256,17 +195,17 @@ dflt_display(char *name, vopstats_t *oldvsp, vopstats_t *newvsp, int dispflag)
" file remov chng get set ops ops ops bytes ops bytes\n");
}
- PRINTSTAT(niceflag, "%5s ", "%lld:", nnewfile, ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", nnamerm, ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", nnamechg, ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", nattrret, ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", nattrchg, ' ', buf);
- PRINTSTAT(niceflag, " %5s ", "%lld:", nlookup, ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", nreaddir, ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", ndataread, ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", readthruput, ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", ndatawrite, ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", writethruput, ' ', buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", nnewfile, buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", nnamerm, buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", nnamechg, buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", nattrret, buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", nattrchg, buf);
+ PRINTSTAT(niceflag, " %5s ", "%lld:", nlookup, buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", nreaddir, buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", ndataread, buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", readthruput, buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", ndatawrite, buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", writethruput, buf);
(void) printf("%s\n", name);
}
@@ -282,17 +221,17 @@ io_display(char *name, vopstats_t *oldvsp, vopstats_t *newvsp, int dispflag)
" ops bytes ops bytes ops bytes ops ops\n");
}
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nread), ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(read_bytes), ' ', buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nread), buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(read_bytes), buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nwrite), ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(write_bytes), ' ', buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nwrite), buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(write_bytes), buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nreaddir), ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(readdir_bytes), ' ', buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nreaddir), buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(readdir_bytes), buf);
- PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(nrwlock), ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nrwunlock), ' ', buf);
+ PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(nrwlock), buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nrwunlock), buf);
(void) printf("%s\n", name);
}
@@ -307,12 +246,12 @@ vm_display(char *name, vopstats_t *oldvsp, vopstats_t *newvsp, int dispflag)
(void) printf(" map addmap delmap getpag putpag pagio\n");
}
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nmap), ' ', buf);
- PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(naddmap), ' ', buf);
- PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(ndelmap), ' ', buf);
- PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(ngetpage), ' ', buf);
- PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(nputpage), ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(npageio), ' ', buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nmap), buf);
+ PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(naddmap), buf);
+ PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(ndelmap), buf);
+ PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(ngetpage), buf);
+ PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(nputpage), buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(npageio), buf);
(void) printf("%s\n", name);
}
@@ -326,10 +265,10 @@ attr_display(char *name, vopstats_t *oldvsp, vopstats_t *newvsp, int dispflag)
(void) printf("getattr setattr getsec setsec\n");
}
- PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(ngetattr), ' ', buf);
- PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(nsetattr), ' ', buf);
- PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(ngetsecattr), ' ', buf);
- PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(nsetsecattr), ' ', buf);
+ PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(ngetattr), buf);
+ PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(nsetattr), buf);
+ PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(ngetsecattr), buf);
+ PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(nsetsecattr), buf);
(void) printf("%s\n", name);
}
@@ -345,16 +284,16 @@ naming_display(char *name, vopstats_t *oldvsp, vopstats_t *newvsp, int dispflag)
"lookup creat remov link renam mkdir rmdir rddir symlnk rdlnk\n");
}
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nlookup), ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(ncreate), ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nremove), ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nlink), ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nrename), ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nmkdir), ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nrmdir), ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nreaddir), ' ', buf);
- PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(nsymlink), ' ', buf);
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nreadlink), ' ', buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nlookup), buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(ncreate), buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nremove), buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nlink), buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nrename), buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nmkdir), buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nrmdir), buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nreaddir), buf);
+ PRINTSTAT(niceflag, " %5s ", "%lld:", DELTA(nsymlink), buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(nreadlink), buf);
(void) printf("%s\n", name);
}
@@ -362,7 +301,7 @@ naming_display(char *name, vopstats_t *oldvsp, vopstats_t *newvsp, int dispflag)
#define PRINT_VOPSTAT_CMN(niceflag, vop) \
if (niceflag) \
(void) printf("%10s ", #vop); \
- PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(n##vop), ' ', buf);
+ PRINTSTAT(niceflag, "%5s ", "%lld:", DELTA(n##vop), buf);
#define PRINT_VOPSTAT(niceflag, vop) \
PRINT_VOPSTAT_CMN(niceflag, vop); \
@@ -372,7 +311,7 @@ naming_display(char *name, vopstats_t *oldvsp, vopstats_t *newvsp, int dispflag)
#define PRINT_VOPSTAT_IO(niceflag, vop) \
PRINT_VOPSTAT_CMN(niceflag, vop); \
PRINTSTAT(niceflag, " %5s\n", "%lld:", \
- DELTA(vop##_bytes), ' ', buf);
+ DELTA(vop##_bytes), buf);
static void
vop_display(char *name, vopstats_t *oldvsp, vopstats_t *newvsp, int dispflag)
diff --git a/usr/src/cmd/swap/Makefile.com b/usr/src/cmd/swap/Makefile.com
index 3734d8ac58..0514c15e62 100644
--- a/usr/src/cmd/swap/Makefile.com
+++ b/usr/src/cmd/swap/Makefile.com
@@ -43,7 +43,7 @@ CLEANFILES += $(OBJS)
all: $(PROG)
-LDLIBS += -ldiskmgt
+LDLIBS += -ldiskmgt -lcmdutils
$(PROG): $(OBJS)
$(LINK.c) $(OBJS) -o $@ $(LDLIBS)
$(POST_PROCESS)
diff --git a/usr/src/cmd/swap/swap.c b/usr/src/cmd/swap/swap.c
index 91cecd5cb4..6b4522745d 100644
--- a/usr/src/cmd/swap/swap.c
+++ b/usr/src/cmd/swap/swap.c
@@ -36,7 +36,9 @@
* contributors.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2017 Jason King.
+ */
/*
* Swap administrative interface
@@ -64,6 +66,8 @@
#include <libintl.h>
#include <libdiskmgt.h>
#include <sys/fs/zfs.h>
+#include <libcmdutils.h>
+#include <sys/debug.h>
#define LFLAG 0x01 /* swap -l (list swap devices) */
#define DFLAG 0x02 /* swap -d (delete swap device) */
@@ -75,6 +79,8 @@
#define KFLAG 0x80 /* swap -k (size in kilobytes) */
#define NUMBER_WIDTH 64
+/* make sure nicenum_scale() has enough space */
+CTASSERT(NUMBER_WIDTH >= NN_NUMBUF_SZ);
typedef char numbuf_t[NUMBER_WIDTH];
static char *prognamep;
@@ -85,9 +91,6 @@ static void usage(void);
static int doswap(int flag);
static int valid(char *, off_t, off_t);
static int list(int flag);
-static char *number_to_scaled_string(numbuf_t buf, unsigned long long number,
- unsigned long long unit_from, unsigned long long scale);
-
int
main(int argc, char **argv)
@@ -253,7 +256,7 @@ main(int argc, char **argv)
}
if ((ret = valid(pathname,
s_offset * 512, length * 512)) == 0) {
- ret = add(pathname, s_offset, length, flag);
+ ret = add(pathname, s_offset, length, flag);
}
}
if (!(flag & ~HFLAG & ~KFLAG)) {
@@ -271,16 +274,16 @@ usage(void)
(void) fprintf(stderr, gettext("Usage:\t%s -l\n"), prognamep);
(void) fprintf(stderr, gettext("\tsub option :\n"));
(void) fprintf(stderr, gettext("\t\t-h : displays size in human "
- "readable format\n"));
+ "readable format\n"));
(void) fprintf(stderr, gettext("\t\t-k : displays size in KB\n"));
(void) fprintf(stderr, "\t%s -s\n", prognamep);
(void) fprintf(stderr, gettext("\tsub option :\n"));
(void) fprintf(stderr, gettext("\t\t-h : displays size in human "
- "readable format rather than KB\n"));
+ "readable format rather than KB\n"));
(void) fprintf(stderr, gettext("\t%s -d <file name> [low block]\n"),
- prognamep);
+ prognamep);
(void) fprintf(stderr, gettext("\t%s -a <file name> [low block]"
- " [nbr of blocks]\n"), prognamep);
+ " [nbr of blocks]\n"), prognamep);
}
/*
@@ -305,7 +308,6 @@ doswap(int flag)
struct anoninfo ai;
pgcnt_t allocated, reserved, available;
numbuf_t numbuf;
- unsigned long long scale = 1024L;
/*
* max = total amount of swap space including physical memory
@@ -339,24 +341,25 @@ doswap(int flag)
if (flag & HFLAG) {
int factor = (int)(sysconf(_SC_PAGESIZE));
- (void) printf(gettext("total: %s allocated + "),
- number_to_scaled_string(numbuf, allocated,
- factor, scale));
- (void) printf(gettext("%s reserved = "),
- number_to_scaled_string(numbuf, reserved,
- factor, scale));
- (void) printf(gettext("%s used, "),
- number_to_scaled_string(numbuf,
- allocated + reserved, factor, scale));
- (void) printf(gettext("%s available\n"),
- number_to_scaled_string(numbuf, available,
- factor, scale));
+
+ nicenum_scale(allocated, factor, numbuf, sizeof (numbuf), 0);
+ (void) printf(gettext("total: %s allocated + "), numbuf);
+
+ nicenum_scale(reserved, factor, numbuf, sizeof (numbuf), 0);
+ (void) printf(gettext("%s reserved = "), numbuf);
+
+ nicenum_scale(allocated + reserved, factor, numbuf,
+ sizeof (numbuf), 0);
+ (void) printf(gettext("%s used, "), numbuf);
+
+ nicenum_scale(available, factor, numbuf, sizeof (numbuf), 0);
+ (void) printf(gettext("%s available\n"), numbuf);
} else {
(void) printf(gettext("total: %luk bytes allocated + %luk"
- " reserved = %luk used, %luk available\n"),
- ctok(allocated), ctok(reserved),
- ctok(reserved) + ctok(allocated),
- ctok(available));
+ " reserved = %luk used, %luk available\n"),
+ ctok(allocated), ctok(reserved),
+ ctok(reserved) + ctok(allocated),
+ ctok(available));
}
return (0);
@@ -373,7 +376,6 @@ list(int flag)
char fullpath[MAXPATHLEN+1];
int num;
numbuf_t numbuf;
- unsigned long long scale = 1024L;
if ((num = swapctl(SC_GETNSWP, NULL)) == -1) {
perror(prognamep);
@@ -387,13 +389,13 @@ list(int flag)
if ((st = malloc(num * sizeof (swapent_t) + sizeof (int)))
== NULL) {
(void) fprintf(stderr,
- gettext("Malloc failed. Please try later.\n"));
+ gettext("Malloc failed. Please try later.\n"));
perror(prognamep);
return (2);
}
if ((path = malloc(num * MAXPATHLEN)) == NULL) {
(void) fprintf(stderr,
- gettext("Malloc failed. Please try later.\n"));
+ gettext("Malloc failed. Please try later.\n"));
perror(prognamep);
return (2);
}
@@ -431,17 +433,17 @@ list(int flag)
for (i = 0; i < num; i++, swapent++) {
if (*swapent->ste_path != '/')
(void) snprintf(fullpath, sizeof (fullpath),
- "/dev/%s", swapent->ste_path);
+ "/dev/%s", swapent->ste_path);
else
(void) snprintf(fullpath, sizeof (fullpath),
- "%s", swapent->ste_path);
+ "%s", swapent->ste_path);
if (stat64(fullpath, &statbuf) < 0)
if (*swapent->ste_path != '/')
(void) printf(gettext("%-20s - "),
- swapent->ste_path);
+ swapent->ste_path);
else
(void) printf(gettext("%-20s ?,? "),
- fullpath);
+ fullpath);
else {
if (S_ISBLK(statbuf.st_mode) ||
S_ISCHR(statbuf.st_mode)) {
@@ -455,34 +457,31 @@ list(int flag)
}
{
int diskblks_per_page =
- (int)(sysconf(_SC_PAGESIZE) >> DEV_BSHIFT);
+ (int)(sysconf(_SC_PAGESIZE) >> DEV_BSHIFT);
if (flag & HFLAG) {
- (void) printf(gettext(" %8s"),
- number_to_scaled_string(numbuf,
- swapent->ste_start, DEV_BSIZE,
- scale));
- (void) printf(gettext(" %8s"),
- number_to_scaled_string(numbuf,
- swapent->ste_pages *
- diskblks_per_page,
- DEV_BSIZE, scale));
- (void) printf(gettext(" %8s"),
- number_to_scaled_string(numbuf,
- swapent->ste_free *
- diskblks_per_page,
- DEV_BSIZE, scale));
+ nicenum_scale(swapent->ste_start, DEV_BSIZE, numbuf,
+ sizeof (numbuf), 0);
+ (void) printf(gettext(" %8s"), numbuf);
+
+ nicenum_scale(swapent->ste_pages, DEV_BSIZE *
+ diskblks_per_page, numbuf, sizeof (numbuf), 0);
+ (void) printf(gettext(" %8s"), numbuf);
+
+ nicenum_scale(swapent->ste_free, DEV_BSIZE *
+ diskblks_per_page, numbuf, sizeof (numbuf), 0);
+ (void) printf(gettext(" %8s"), numbuf);
} else if (flag & KFLAG) {
(void) printf(gettext(" %7luK %7luK %7luK"),
- swapent->ste_start * DEV_BSIZE / 1024,
- swapent->ste_pages * diskblks_per_page *
- DEV_BSIZE / 1024,
- swapent->ste_free * diskblks_per_page *
- DEV_BSIZE / 1024);
+ swapent->ste_start * DEV_BSIZE / 1024,
+ swapent->ste_pages * diskblks_per_page *
+ DEV_BSIZE / 1024,
+ swapent->ste_free * diskblks_per_page *
+ DEV_BSIZE / 1024);
} else {
(void) printf(gettext(" %8lu %8lu %8lu"),
- swapent->ste_start,
- swapent->ste_pages * diskblks_per_page,
- swapent->ste_free * diskblks_per_page);
+ swapent->ste_start,
+ swapent->ste_pages * diskblks_per_page,
+ swapent->ste_free * diskblks_per_page);
}
}
if (swapent->ste_flags & ST_INDEL)
@@ -493,64 +492,6 @@ list(int flag)
return (0);
}
-/* Copied from du.c */
-static char *
-number_to_scaled_string(
- numbuf_t buf, /* put the result here */
- unsigned long long number, /* convert this number */
- unsigned long long unit_from, /* number of byes per input unit */
- unsigned long long scale) /* 1024 (-h) or 1000 (-H) */
-{
- unsigned long long save = 0;
- char *M = "KMGTPE"; /* Measurement: kilo, mega, giga, tera, peta, exa */
- char *uom = M; /* unit of measurement, initially 'K' (=M[0]) */
-
- if ((long long)number == (long long) -1) {
- (void) strcpy(buf, "-1");
- return (buf);
- }
-
- /*
- * Convert number from unit_from to given scale (1024 or 1000)
- * This means multiply number with unit_from and divide by scale.
- * if number is large enough, we first divide and then multiply
- * to avoid an overflow (large enough here means 100 (rather arbitrary
- * value) times scale in order to reduce rounding errors)
- * otherwise, we first multiply and then divide to avoid an underflow.
- */
- if (number >= 100L * scale) {
- number = number / scale;
- number = number * unit_from;
- } else {
- number = number * unit_from;
- number = number / scale;
- }
-
- /*
- * Now we have number as a count of scale units.
- * Stop scaling when we reached exa bytes, then something is
- * probably wrong with our number.
- */
- while ((number >= scale) && (*uom != 'E')) {
- uom++; /* Next unit of measurement */
- save = number;
- number = (number + (scale / 2)) / scale;
- }
-
- /* Check if we should output a decimal place after the point */
- if (save && ((save / scale) < 10)) {
- /* sprintf() will round for us */
- float fnum = (float)save / scale;
- (void) sprintf(buf, "%.1f%c", fnum, *uom);
- } else {
- (void) sprintf(buf, "%llu%c", number, *uom);
- }
- return (buf);
-}
-
-
-
-
static void
dumpadm_err(const char *warning)
{
@@ -701,7 +642,7 @@ add(char *path, off_t offset, off_t cnt, int flags)
statvfs("/etc", &fsb) == 0 && !(fsb.f_flag & ST_RDONLY)) {
(void) printf(
- gettext("operating system crash dump was previously "
+ gettext("operating system crash dump was previously "
"disabled --\ninvoking dumpadm(1M) -d swap to select "
"new dump device\n"));
@@ -726,7 +667,7 @@ valid(char *pathname, off_t offset, off_t length)
}
if (!((S_ISREG(f.st_mode) && (f.st_mode & S_ISVTX) == S_ISVTX) ||
- S_ISBLK(f.st_mode))) {
+ S_ISBLK(f.st_mode))) {
(void) fprintf(stderr,
gettext("\"%s\" is not valid for swapping.\n"
"It must be a block device or a regular file with the\n"
@@ -753,8 +694,8 @@ valid(char *pathname, off_t offset, off_t length)
if (offset < 0) {
(void) fprintf(stderr,
- gettext("%s: low block is invalid\n"),
- pathname);
+ gettext("%s: low block is invalid\n"),
+ pathname);
return (EINVAL);
}
diff --git a/usr/src/cmd/zdb/Makefile.com b/usr/src/cmd/zdb/Makefile.com
index 63b8366c80..022c984dbe 100644
--- a/usr/src/cmd/zdb/Makefile.com
+++ b/usr/src/cmd/zdb/Makefile.com
@@ -23,6 +23,7 @@
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2017 Joyent, Inc.
#
PROG:sh= cd ..; basename `pwd`
@@ -36,7 +37,7 @@ INCS += -I../../../lib/libzpool/common
INCS += -I../../../uts/common/fs/zfs
INCS += -I../../../common/zfs
-LDLIBS += -lzpool -lumem -lnvpair -lzfs -lavl
+LDLIBS += -lzpool -lumem -lnvpair -lzfs -lavl -lcmdutils
C99MODE= -xc99=%all
C99LMODE= -Xc99=%all
diff --git a/usr/src/cmd/zdb/zdb.c b/usr/src/cmd/zdb/zdb.c
index a2e0a67e11..5dcb12f5bf 100644
--- a/usr/src/cmd/zdb/zdb.c
+++ b/usr/src/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",
@@ -1331,6 +1341,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;
@@ -1346,15 +1359,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);
@@ -1364,7 +1377,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);
@@ -1383,15 +1397,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",
@@ -1450,12 +1471,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);
@@ -1487,13 +1511,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,
@@ -1547,6 +1576,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;
@@ -1555,9 +1589,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);
@@ -1860,6 +1894,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",
@@ -1880,11 +1921,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);
@@ -1947,6 +1988,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)
@@ -1954,7 +1997,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);
@@ -1985,6 +2028,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);
@@ -2003,7 +2049,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 ");
@@ -2648,6 +2694,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) "
@@ -2997,6 +3046,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
@@ -3030,12 +3087,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/usr/src/cmd/ztest/ztest.c b/usr/src/cmd/ztest/ztest.c
index f83db2d139..32ecef6b18 100644
--- a/usr/src/cmd/ztest/ztest.c
+++ b/usr/src/cmd/ztest/ztest.c
@@ -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"
@@ -3156,10 +3159,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);
}
@@ -6201,7 +6204,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;
@@ -6338,7 +6341,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/usr/src/lib/libcmdutils/Makefile.com b/usr/src/lib/libcmdutils/Makefile.com
index ffe3c9cba5..9cb35f8795 100644
--- a/usr/src/lib/libcmdutils/Makefile.com
+++ b/usr/src/lib/libcmdutils/Makefile.com
@@ -26,7 +26,7 @@
LIBRARY= libcmdutils.a
VERS= .1
CMD_OBJS= avltree.o sysattrs.o writefile.o process_xattrs.o uid.o gid.o \
- custr.o
+ custr.o nicenum.o
COM_OBJS= list.o
OBJECTS= $(CMD_OBJS) $(COM_OBJS)
diff --git a/usr/src/lib/libcmdutils/common/mapfile-vers b/usr/src/lib/libcmdutils/common/mapfile-vers
index 1f63d4eee0..0ac77eb010 100644
--- a/usr/src/lib/libcmdutils/common/mapfile-vers
+++ b/usr/src/lib/libcmdutils/common/mapfile-vers
@@ -72,6 +72,8 @@ SYMBOL_VERSION SUNWprivate_1.1 {
list_remove_head;
list_remove_tail;
list_tail;
+ nicenum;
+ nicenum_scale;
tnode_compare;
sysattr_type;
sysattr_support;
diff --git a/usr/src/lib/libcmdutils/common/nicenum.c b/usr/src/lib/libcmdutils/common/nicenum.c
new file mode 100644
index 0000000000..8e3202f792
--- /dev/null
+++ b/usr/src/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/usr/src/lib/libcmdutils/libcmdutils.h b/usr/src/lib/libcmdutils/libcmdutils.h
index 933ceb0fde..5f9957b861 100644
--- a/usr/src/lib/libcmdutils/libcmdutils.h
+++ b/usr/src/lib/libcmdutils/libcmdutils.h
@@ -216,6 +216,14 @@ extern void custr_reset(custr_t *);
*/
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
diff --git a/usr/src/lib/libzfs/Makefile.com b/usr/src/lib/libzfs/Makefile.com
index 31619b01c1..6eaf4332f2 100644
--- a/usr/src/lib/libzfs/Makefile.com
+++ b/usr/src/lib/libzfs/Makefile.com
@@ -70,7 +70,7 @@ INCS += -I../../libc/inc
C99MODE= -xc99=%all
C99LMODE= -Xc99=%all
LDLIBS += -lc -lm -ldevid -lgen -lnvpair -luutil -lavl -lefi \
- -ladm -lidmap -ltsol -lmd -lumem -lzfs_core
+ -ladm -lidmap -ltsol -lmd -lumem -lzfs_core -lcmdutils
CPPFLAGS += $(INCS) -D_LARGEFILE64_SOURCE=1 -D_REENTRANT
$(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG
diff --git a/usr/src/lib/libzfs/common/libzfs_util.c b/usr/src/lib/libzfs/common/libzfs_util.c
index bcb48094f6..aba044add5 100644
--- a/usr/src/lib/libzfs/common/libzfs_util.c
+++ b/usr/src/lib/libzfs/common/libzfs_util.c
@@ -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
diff --git a/usr/src/lib/libzpool/common/llib-lzpool b/usr/src/lib/libzpool/common/llib-lzpool
index 3636b4e76e..27d01fd54d 100644
--- a/usr/src/lib/libzpool/common/llib-lzpool
+++ b/usr/src/lib/libzpool/common/llib-lzpool
@@ -62,6 +62,7 @@
#include <sys/dsl_userhold.h>
#include <sys/blkptr.h>
#include <sys/abd.h>
+#include <libcmdutils.h>
extern uint64_t metaslab_gang_bang;
extern uint64_t metaslab_df_alloc_threshold;
diff --git a/usr/src/lib/libzpool/common/sys/zfs_context.h b/usr/src/lib/libzpool/common/sys/zfs_context.h
index b858ea719b..6e063b9c17 100644
--- a/usr/src/lib/libzpool/common/sys/zfs_context.h
+++ b/usr/src/lib/libzpool/common/sys/zfs_context.h
@@ -543,7 +543,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/usr/src/lib/libzpool/common/util.c b/usr/src/lib/libzpool/common/util.c
index e929aa5645..363940677c 100644
--- a/usr/src/lib/libzpool/common/util.c
+++ b/usr/src/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, "",