aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/libspl/include/sys/sysmacros.h3
-rw-r--r--lib/libzfs/libzfs_pool.c2
-rw-r--r--lib/libzfs/libzfs_util.c94
-rw-r--r--lib/libzpool/kernel.c44
-rw-r--r--lib/libzpool/util.c7
5 files changed, 134 insertions, 16 deletions
diff --git a/lib/libspl/include/sys/sysmacros.h b/lib/libspl/include/sys/sysmacros.h
index 5d10657be..c2525dd2a 100644
--- a/lib/libspl/include/sys/sysmacros.h
+++ b/lib/libspl/include/sys/sysmacros.h
@@ -39,6 +39,9 @@
#ifndef ABS
#define ABS(a) ((a) < 0 ? -(a) : (a))
#endif
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof (a[0]))
+#endif
#define makedevice(maj, min) makedev(maj, min)
#define _sysconf(a) sysconf(a)
diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c
index 8cacc01dd..789df407c 100644
--- a/lib/libzfs/libzfs_pool.c
+++ b/lib/libzfs/libzfs_pool.c
@@ -3538,7 +3538,6 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
* If it's a raidz device, we need to stick in the parity level.
*/
if (strcmp(path, VDEV_TYPE_RAIDZ) == 0) {
-
verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NPARITY,
&value) == 0);
(void) snprintf(buf, sizeof (buf), "%s%llu", path,
@@ -3552,7 +3551,6 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
*/
if (name_flags & VDEV_NAME_TYPE_ID) {
uint64_t id;
-
verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID,
&id) == 0);
(void) snprintf(tmpbuf, sizeof (tmpbuf), "%s-%llu",
diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c
index 57c2ac853..926ed4ed8 100644
--- a/lib/libzfs/libzfs_util.c
+++ b/lib/libzfs/libzfs_util.c
@@ -596,27 +596,49 @@ zfs_strdup(libzfs_handle_t *hdl, const char *str)
* Convert a number to an appropriately human-readable output.
*/
void
-zfs_nicenum(uint64_t num, char *buf, size_t buflen)
+zfs_nicenum_format(uint64_t num, char *buf, size_t buflen,
+ enum zfs_nicenum_format format)
{
uint64_t n = num;
int index = 0;
- char u;
+ const char *u;
+ const char *units[3][7] = {
+ [ZFS_NICENUM_1024] = {"", "K", "M", "G", "T", "P", "E"},
+ [ZFS_NICENUM_TIME] = {"ns", "us", "ms", "s", "?", "?", "?"}
+ };
+
+ const int units_len[] = {[ZFS_NICENUM_1024] = 6,
+ [ZFS_NICENUM_TIME] = 4};
+
+ const int k_unit[] = { [ZFS_NICENUM_1024] = 1024,
+ [ZFS_NICENUM_TIME] = 1000};
- while (n >= 1024 && index < 6) {
- n /= 1024;
+ double val;
+
+ if (format == ZFS_NICENUM_RAW) {
+ snprintf(buf, buflen, "%llu", (u_longlong_t) num);
+ return;
+ }
+
+
+ while (n >= k_unit[format] && index < units_len[format]) {
+ n /= k_unit[format];
index++;
}
- u = " KMGTPE"[index];
+ u = units[format][index];
- if (index == 0) {
- (void) snprintf(buf, buflen, "%llu", (u_longlong_t) n);
- } else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
+ /* Don't print 0ns times */
+ if ((format == ZFS_NICENUM_TIME) && (num == 0)) {
+ (void) snprintf(buf, buflen, "-");
+ } else if ((index == 0) || ((num %
+ (uint64_t) powl(k_unit[format], index)) == 0)) {
/*
* If this is an even multiple of the base, always display
* without any decimal precision.
*/
- (void) snprintf(buf, buflen, "%llu%c", (u_longlong_t) n, u);
+ (void) snprintf(buf, buflen, "%llu%s", (u_longlong_t) n, u);
+
} else {
/*
* We want to choose a precision that reflects the best choice
@@ -629,13 +651,61 @@ zfs_nicenum(uint64_t num, char *buf, size_t buflen)
*/
int i;
for (i = 2; i >= 0; i--) {
- if (snprintf(buf, buflen, "%.*f%c", i,
- (double)num / (1ULL << 10 * index), u) <= 5)
- break;
+ val = (double) num /
+ (uint64_t) powl(k_unit[format], index);
+
+ /*
+ * Don't print floating point values for time. Note,
+ * we use floor() instead of round() here, since
+ * round can result in undesirable results. For
+ * example, if "num" is in the range of
+ * 999500-999999, it will print out "1000us". This
+ * doesn't happen if we use floor().
+ */
+ if (format == ZFS_NICENUM_TIME) {
+ if (snprintf(buf, buflen, "%d%s",
+ (unsigned int) floor(val), u) <= 5)
+ break;
+
+ } else {
+ if (snprintf(buf, buflen, "%.*f%s", i,
+ val, u) <= 5)
+ break;
+ }
}
}
}
+/*
+ * Convert a number to an appropriately human-readable output.
+ */
+void
+zfs_nicenum(uint64_t num, char *buf, size_t buflen)
+{
+ zfs_nicenum_format(num, buf, buflen, ZFS_NICENUM_1024);
+}
+
+/*
+ * Convert a time to an appropriately human-readable output.
+ * @num: Time in nanoseconds
+ */
+void
+zfs_nicetime(uint64_t num, char *buf, size_t buflen)
+{
+ zfs_nicenum_format(num, buf, buflen, ZFS_NICENUM_TIME);
+}
+
+/*
+ * Print out a raw number with correct column spacing
+ */
+void
+zfs_niceraw(uint64_t num, char *buf, size_t buflen)
+{
+ zfs_nicenum_format(num, buf, buflen, ZFS_NICENUM_RAW);
+}
+
+
+
void
libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
{
diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c
index 49d17ece3..3d85093e2 100644
--- a/lib/libzpool/kernel.c
+++ b/lib/libzpool/kernel.c
@@ -1071,6 +1071,50 @@ highbit64(uint64_t i)
return (h);
}
+/*
+ * Find lowest one bit set.
+ * Returns bit number + 1 of lowest bit that is set, otherwise returns 0.
+ * This is basically a reimplementation of ffsll(), which is GNU specific.
+ */
+int
+lowbit64(uint64_t i)
+{
+ register int h = 64;
+ if (i == 0)
+ return (0);
+
+ if (i & 0x00000000ffffffffULL)
+ h -= 32;
+ else
+ i >>= 32;
+
+ if (i & 0x0000ffff)
+ h -= 16;
+ else
+ i >>= 16;
+
+ if (i & 0x00ff)
+ h -= 8;
+ else
+ i >>= 8;
+
+ if (i & 0x0f)
+ h -= 4;
+ else
+ i >>= 4;
+
+ if (i & 0x3)
+ h -= 2;
+ else
+ i >>= 2;
+
+ if (i & 0x1)
+ h -= 1;
+
+ return (h);
+}
+
+
static int random_fd = -1, urandom_fd = -1;
static int
diff --git a/lib/libzpool/util.c b/lib/libzpool/util.c
index 231043d75..7a0748c03 100644
--- a/lib/libzpool/util.c
+++ b/lib/libzpool/util.c
@@ -67,7 +67,7 @@ static void
show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
{
vdev_stat_t *vs;
- vdev_stat_t v0 = { 0 };
+ vdev_stat_t *v0 = { 0 };
uint64_t sec;
uint64_t is_log = 0;
nvlist_t **child;
@@ -76,6 +76,8 @@ show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
char rops[6], wops[6], rbytes[6], wbytes[6], rerr[6], werr[6], cerr[6];
char *prefix = "";
+ v0 = umem_zalloc(sizeof (*v0), UMEM_NOFAIL);
+
if (indent == 0 && desc != NULL) {
(void) printf(" "
" capacity operations bandwidth ---- errors ----\n");
@@ -91,7 +93,7 @@ show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
if (nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
(uint64_t **)&vs, &c) != 0)
- vs = &v0;
+ vs = v0;
sec = MAX(1, vs->vs_timestamp / NANOSEC);
@@ -114,6 +116,7 @@ show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
vs->vs_space ? 6 : 0, vs->vs_space ? avail : "",
rops, wops, rbytes, wbytes, rerr, werr, cerr);
}
+ free(v0);
if (nvlist_lookup_nvlist_array(nv, ctype, &child, &children) != 0)
return;