diff options
author | Don Brady <[email protected]> | 2018-11-05 12:22:33 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2018-11-05 11:22:33 -0800 |
commit | e89f1295d4faa88bb05a62c8dd5f781657db5955 (patch) | |
tree | 8e39dfe33c6849e00813e54ec95c09a24448a43a /lib/libzpool/util.c | |
parent | 6644e5bb6e1a6c25c5006c819abf93c7bb662e80 (diff) |
Add libzutil for libzfs or libzpool consumers
Adds a libzutil for utility functions that are common to libzfs and
libzpool consumers (most of what was in libzfs_import.c). This
removes the need for utilities to link against both libzpool and
libzfs.
Reviewed-by: Matthew Ahrens <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Don Brady <[email protected]>
Closes #8050
Diffstat (limited to 'lib/libzpool/util.c')
-rw-r--r-- | lib/libzpool/util.c | 155 |
1 files changed, 55 insertions, 100 deletions
diff --git a/lib/libzpool/util.c b/lib/libzpool/util.c index 8a6f4c325..87772bcb7 100644 --- a/lib/libzpool/util.c +++ b/lib/libzpool/util.c @@ -34,112 +34,14 @@ #include <sys/spa.h> #include <sys/fs/zfs.h> #include <sys/refcount.h> +#include <sys/zfs_ioctl.h> #include <dlfcn.h> +#include <libzutil.h> /* * Routines needed by more than one client of libzpool. */ -/* The largest suffix that can fit, aka an exabyte (2^60 / 10^18) */ -#define INDEX_MAX (6) - -/* Verify INDEX_MAX fits */ -CTASSERT_GLOBAL(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", (u_longlong_t)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", - (u_longlong_t)(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); -} - static void show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent) { @@ -300,3 +202,56 @@ set_global_var(char *arg) return (0); } + +static nvlist_t * +refresh_config(void *unused, nvlist_t *tryconfig) +{ + return (spa_tryimport(tryconfig)); +} + +static int +pool_active(void *unused, const char *name, uint64_t guid, + boolean_t *isactive) +{ + zfs_cmd_t *zcp; + nvlist_t *innvl; + char *packed = NULL; + size_t size = 0; + int fd, ret; + + /* + * Use ZFS_IOC_POOL_SYNC to confirm if a pool is active + */ + + fd = open("/dev/zfs", O_RDWR); + if (fd < 0) + return (-1); + + zcp = umem_zalloc(sizeof (zfs_cmd_t), UMEM_NOFAIL); + + innvl = fnvlist_alloc(); + fnvlist_add_boolean_value(innvl, "force", B_FALSE); + + (void) strlcpy(zcp->zc_name, name, sizeof (zcp->zc_name)); + packed = fnvlist_pack(innvl, &size); + zcp->zc_nvlist_src = (uint64_t)(uintptr_t)packed; + zcp->zc_nvlist_src_size = size; + + ret = ioctl(fd, ZFS_IOC_POOL_SYNC, zcp); + + fnvlist_pack_free(packed, size); + free((void *)(uintptr_t)zcp->zc_nvlist_dst); + nvlist_free(innvl); + umem_free(zcp, sizeof (zfs_cmd_t)); + + (void) close(fd); + + *isactive = (ret == 0); + + return (0); +} + +const pool_config_ops_t libzpool_config_ops = { + .pco_refresh_config = refresh_config, + .pco_pool_active = pool_active, +}; |