mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 02:44:41 +03:00
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 <mahrens@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Don Brady <don.brady@delphix.com> Closes #8050
This commit is contained in:
committed by
Brian Behlendorf
parent
6644e5bb6e
commit
e89f1295d4
@@ -188,11 +188,10 @@ nodist_libzpool_la_SOURCES = \
|
||||
$(LUA_C)
|
||||
|
||||
libzpool_la_LIBADD = \
|
||||
$(top_builddir)/lib/libavl/libavl.la \
|
||||
$(top_builddir)/lib/libicp/libicp.la \
|
||||
$(top_builddir)/lib/libnvpair/libnvpair.la \
|
||||
$(top_builddir)/lib/libspl/libspl.la \
|
||||
$(top_builddir)/lib/libunicode/libunicode.la
|
||||
$(top_builddir)/lib/libunicode/libunicode.la \
|
||||
$(top_builddir)/lib/libzutil/libzutil.la
|
||||
|
||||
libzpool_la_LIBADD += $(ZLIB) -ldl
|
||||
libzpool_la_LDFLAGS = -pthread -version-info 2:0:0
|
||||
|
||||
+55
-100
@@ -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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user