diff options
author | Jason King <jason.brian.king@gmail.com> | 2017-06-13 04:16:45 -0500 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2017-09-04 20:42:57 -0400 |
commit | 0a0551200ecbcd4f1b17560acaeeb7b6c8b0090e (patch) | |
tree | 4e943314876a263be2f8209de2eea1a87428be80 | |
parent | 30c75cb09b4d5e86a94a25a9a7ab7481510b57b0 (diff) | |
download | illumos-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/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/beadm/beadm.c | 30 | ||||
-rw-r--r-- | usr/src/cmd/du/du.c | 82 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/Makefile | 1 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/df.c | 101 | ||||
-rw-r--r-- | usr/src/cmd/ls/ls.c | 106 | ||||
-rw-r--r-- | usr/src/cmd/stat/fsstat/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/stat/fsstat/fsstat.c | 157 | ||||
-rw-r--r-- | usr/src/cmd/swap/Makefile.com | 2 | ||||
-rw-r--r-- | usr/src/cmd/swap/swap.c | 177 | ||||
-rw-r--r-- | usr/src/cmd/zdb/Makefile.com | 3 | ||||
-rw-r--r-- | usr/src/cmd/zdb/zdb.c | 138 | ||||
-rw-r--r-- | usr/src/cmd/ztest/ztest.c | 21 | ||||
-rw-r--r-- | usr/src/lib/libcmdutils/Makefile.com | 2 | ||||
-rw-r--r-- | usr/src/lib/libcmdutils/common/mapfile-vers | 2 | ||||
-rw-r--r-- | usr/src/lib/libcmdutils/common/nicenum.c | 130 | ||||
-rw-r--r-- | usr/src/lib/libcmdutils/libcmdutils.h | 8 | ||||
-rw-r--r-- | usr/src/lib/libzfs/Makefile.com | 2 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_util.c | 38 | ||||
-rw-r--r-- | usr/src/lib/libzpool/common/llib-lzpool | 1 | ||||
-rw-r--r-- | usr/src/lib/libzpool/common/sys/zfs_context.h | 2 | ||||
-rw-r--r-- | usr/src/lib/libzpool/common/util.c | 47 |
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, "", |