diff options
Diffstat (limited to 'usr/src/lib')
-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 | 115 | ||||
-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 |
9 files changed, 142 insertions, 75 deletions
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..ca5f15b4cf --- /dev/null +++ b/usr/src/lib/libcmdutils/common/nicenum.c @@ -0,0 +1,115 @@ +/* + * 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 "libcmdutils.h" + +#define INDEX_MAX (7) /* the largest prefix supported */ + +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; + + while (index < INDEX_MAX) { + uint64_t newdiv = divisor * divamt; + + if (newdiv < divamt) + goto overflow; + + 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 365ece14e0..9bab674a6b 100644 --- a/usr/src/lib/libzfs/common/libzfs_util.c +++ b/usr/src/lib/libzfs/common/libzfs_util.c @@ -44,6 +44,7 @@ #include <sys/mnttab.h> #include <sys/mntent.h> #include <sys/types.h> +#include <libcmdutils.h> #include <libzfs.h> #include <libzfs_core.h> @@ -571,42 +572,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 bc43d455e0..301ffc0df8 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, "", |