* Convert a number to an appropriately human-readable output. */
| 46 | * Convert a number to an appropriately human-readable output. |
| 47 | */ |
| 48 | void |
| 49 | zfs_nicenum_format(uint64_t num, char *buf, size_t buflen, |
| 50 | enum zfs_nicenum_format format) |
| 51 | { |
| 52 | uint64_t n = num; |
| 53 | int index = 0; |
| 54 | const char *u; |
| 55 | const char *units[3][7] = { |
| 56 | [ZFS_NICENUM_1024] = {"", "K", "M", "G", "T", "P", "E"}, |
| 57 | [ZFS_NICENUM_BYTES] = {"B", "K", "M", "G", "T", "P", "E"}, |
| 58 | [ZFS_NICENUM_TIME] = {"ns", "us", "ms", "s", "?", "?", "?"} |
| 59 | }; |
| 60 | |
| 61 | const int units_len[] = {[ZFS_NICENUM_1024] = 6, |
| 62 | [ZFS_NICENUM_BYTES] = 6, |
| 63 | [ZFS_NICENUM_TIME] = 4}; |
| 64 | |
| 65 | const int k_unit[] = { [ZFS_NICENUM_1024] = 1024, |
| 66 | [ZFS_NICENUM_BYTES] = 1024, |
| 67 | [ZFS_NICENUM_TIME] = 1000}; |
| 68 | |
| 69 | double val; |
| 70 | |
| 71 | if (format == ZFS_NICENUM_RAW) { |
| 72 | snprintf(buf, buflen, "%llu", (u_longlong_t)num); |
| 73 | return; |
| 74 | } else if (format == ZFS_NICENUM_RAWTIME && num > 0) { |
| 75 | snprintf(buf, buflen, "%llu", (u_longlong_t)num); |
| 76 | return; |
| 77 | } else if (format == ZFS_NICENUM_RAWTIME && num == 0) { |
| 78 | snprintf(buf, buflen, "%s", "-"); |
| 79 | return; |
| 80 | } |
| 81 | |
| 82 | while (n >= k_unit[format] && index < units_len[format]) { |
| 83 | n /= k_unit[format]; |
| 84 | index++; |
| 85 | } |
| 86 | |
| 87 | u = units[format][index]; |
| 88 | |
| 89 | /* Don't print zero latencies since they're invalid */ |
| 90 | if ((format == ZFS_NICENUM_TIME) && (num == 0)) { |
| 91 | (void) snprintf(buf, buflen, "-"); |
| 92 | } else if ((index == 0) || ((num % |
| 93 | (uint64_t)powl(k_unit[format], index)) == 0)) { |
| 94 | /* |
| 95 | * If this is an even multiple of the base, always display |
| 96 | * without any decimal precision. |
| 97 | */ |
| 98 | (void) snprintf(buf, buflen, "%llu%s", (u_longlong_t)n, u); |
| 99 | |
| 100 | } else { |
| 101 | /* |
| 102 | * We want to choose a precision that reflects the best choice |
| 103 | * for fitting in 5 characters. This can get rather tricky when |
| 104 | * we have numbers that are very close to an order of magnitude. |
| 105 | * For example, when displaying 10239 (which is really 9.999K), |
no test coverage detected