aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2018-02-21 21:04:46 +0000
committerAlexander Motin <mav@FreeBSD.org>2018-02-21 21:04:46 +0000
commit81ef5e369cb2f59309404806160315c1645d0394 (patch)
treee9a79e11a90d5886dc0c080e403ff4b516122c37 /lib
parented2ac05a276d0bac9e07f35d87c8a7095dc69d67 (diff)
downloadsrc-81ef5e369cb2f59309404806160315c1645d0394.tar.gz
src-81ef5e369cb2f59309404806160315c1645d0394.zip
8809 libzpool should leverage work done in libfakekernel
illumos/illumos-gate@f06dce2c1f0f3af78581e7574f65bfba843ddb6e Reviewed by: Sebastien Roy <sebastien.roy@delphix.com> Reviewed by: Prakash Surya <prakash.surya@delphix.com> Reviewed by: Gordon Ross <gordon.w.ross@gmail.com> Approved by: Richard Lowe <richlowe@richlowe.net> Author: Andrew Stormont <astormont@racktopsystems.com>
Notes
Notes: svn path=/vendor-sys/illumos/dist/; revision=329753
Diffstat (limited to 'lib')
-rw-r--r--lib/libzpool/common/kernel.c585
-rw-r--r--lib/libzpool/common/sys/zfs_context.h415
-rw-r--r--lib/libzpool/common/taskq.c342
-rw-r--r--lib/libzpool/common/util.c3
4 files changed, 33 insertions, 1312 deletions
diff --git a/lib/libzpool/common/kernel.c b/lib/libzpool/common/kernel.c
index d646df7efa9c..1d94907b1abc 100644
--- a/lib/libzpool/common/kernel.c
+++ b/lib/libzpool/common/kernel.c
@@ -22,6 +22,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2017 RackTop Systems.
*/
#include <assert.h>
@@ -41,12 +42,14 @@
#include <sys/utsname.h>
#include <sys/systeminfo.h>
+extern void system_taskq_init(void);
+extern void system_taskq_fini(void);
+
/*
* Emulation of kernel services in userland.
*/
-int aok;
-uint64_t physmem;
+pgcnt_t physmem;
vnode_t *rootdir = (vnode_t *)0xabcd1234;
char hw_serial[HW_HOSTID_LEN];
kmutex_t cpu_lock;
@@ -59,336 +62,6 @@ struct utsname utsname = {
"userland", "libzpool", "1", "1", "na"
};
-/* this only exists to have its address taken */
-struct proc p0;
-
-/*
- * =========================================================================
- * threads
- * =========================================================================
- */
-/*ARGSUSED*/
-kthread_t *
-zk_thread_create(void (*func)(), void *arg)
-{
- thread_t tid;
-
- VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
- &tid) == 0);
-
- return ((void *)(uintptr_t)tid);
-}
-
-/*
- * =========================================================================
- * kstats
- * =========================================================================
- */
-/*ARGSUSED*/
-kstat_t *
-kstat_create(const char *module, int instance, const char *name,
- const char *class, uchar_t type, ulong_t ndata, uchar_t ks_flag)
-{
- return (NULL);
-}
-
-/*ARGSUSED*/
-void
-kstat_named_init(kstat_named_t *knp, const char *name, uchar_t type)
-{}
-
-/*ARGSUSED*/
-void
-kstat_install(kstat_t *ksp)
-{}
-
-/*ARGSUSED*/
-void
-kstat_delete(kstat_t *ksp)
-{}
-
-/*ARGSUSED*/
-void
-kstat_waitq_enter(kstat_io_t *kiop)
-{}
-
-/*ARGSUSED*/
-void
-kstat_waitq_exit(kstat_io_t *kiop)
-{}
-
-/*ARGSUSED*/
-void
-kstat_runq_enter(kstat_io_t *kiop)
-{}
-
-/*ARGSUSED*/
-void
-kstat_runq_exit(kstat_io_t *kiop)
-{}
-
-/*ARGSUSED*/
-void
-kstat_waitq_to_runq(kstat_io_t *kiop)
-{}
-
-/*ARGSUSED*/
-void
-kstat_runq_back_to_waitq(kstat_io_t *kiop)
-{}
-
-/*
- * =========================================================================
- * mutexes
- * =========================================================================
- */
-void
-zmutex_init(kmutex_t *mp)
-{
- mp->m_owner = NULL;
- mp->initialized = B_TRUE;
- (void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
-}
-
-void
-zmutex_destroy(kmutex_t *mp)
-{
- ASSERT(mp->initialized == B_TRUE);
- ASSERT(mp->m_owner == NULL);
- (void) _mutex_destroy(&(mp)->m_lock);
- mp->m_owner = (void *)-1UL;
- mp->initialized = B_FALSE;
-}
-
-void
-mutex_enter(kmutex_t *mp)
-{
- ASSERT(mp->initialized == B_TRUE);
- ASSERT(mp->m_owner != (void *)-1UL);
- ASSERT(mp->m_owner != curthread);
- VERIFY(mutex_lock(&mp->m_lock) == 0);
- ASSERT(mp->m_owner == NULL);
- mp->m_owner = curthread;
-}
-
-int
-mutex_tryenter(kmutex_t *mp)
-{
- ASSERT(mp->initialized == B_TRUE);
- ASSERT(mp->m_owner != (void *)-1UL);
- if (0 == mutex_trylock(&mp->m_lock)) {
- ASSERT(mp->m_owner == NULL);
- mp->m_owner = curthread;
- return (1);
- } else {
- return (0);
- }
-}
-
-void
-mutex_exit(kmutex_t *mp)
-{
- ASSERT(mp->initialized == B_TRUE);
- ASSERT(mutex_owner(mp) == curthread);
- mp->m_owner = NULL;
- VERIFY(mutex_unlock(&mp->m_lock) == 0);
-}
-
-void *
-mutex_owner(kmutex_t *mp)
-{
- ASSERT(mp->initialized == B_TRUE);
- return (mp->m_owner);
-}
-
-/*
- * =========================================================================
- * rwlocks
- * =========================================================================
- */
-/*ARGSUSED*/
-void
-rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
-{
- rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
- rwlp->rw_owner = NULL;
- rwlp->initialized = B_TRUE;
-}
-
-void
-rw_destroy(krwlock_t *rwlp)
-{
- rwlock_destroy(&rwlp->rw_lock);
- rwlp->rw_owner = (void *)-1UL;
- rwlp->initialized = B_FALSE;
-}
-
-void
-rw_enter(krwlock_t *rwlp, krw_t rw)
-{
- ASSERT(!RW_LOCK_HELD(rwlp));
- ASSERT(rwlp->initialized == B_TRUE);
- ASSERT(rwlp->rw_owner != (void *)-1UL);
- ASSERT(rwlp->rw_owner != curthread);
-
- if (rw == RW_WRITER)
- VERIFY(rw_wrlock(&rwlp->rw_lock) == 0);
- else
- VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
-
- rwlp->rw_owner = curthread;
-}
-
-void
-rw_exit(krwlock_t *rwlp)
-{
- ASSERT(rwlp->initialized == B_TRUE);
- ASSERT(rwlp->rw_owner != (void *)-1UL);
-
- rwlp->rw_owner = NULL;
- VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
-}
-
-int
-rw_tryenter(krwlock_t *rwlp, krw_t rw)
-{
- int rv;
-
- ASSERT(rwlp->initialized == B_TRUE);
- ASSERT(rwlp->rw_owner != (void *)-1UL);
-
- if (rw == RW_WRITER)
- rv = rw_trywrlock(&rwlp->rw_lock);
- else
- rv = rw_tryrdlock(&rwlp->rw_lock);
-
- if (rv == 0) {
- rwlp->rw_owner = curthread;
- return (1);
- }
-
- return (0);
-}
-
-/*ARGSUSED*/
-int
-rw_tryupgrade(krwlock_t *rwlp)
-{
- ASSERT(rwlp->initialized == B_TRUE);
- ASSERT(rwlp->rw_owner != (void *)-1UL);
-
- return (0);
-}
-
-/*
- * =========================================================================
- * condition variables
- * =========================================================================
- */
-/*ARGSUSED*/
-void
-cv_init(kcondvar_t *cv, char *name, int type, void *arg)
-{
- VERIFY(cond_init(cv, type, NULL) == 0);
-}
-
-void
-cv_destroy(kcondvar_t *cv)
-{
- VERIFY(cond_destroy(cv) == 0);
-}
-
-void
-cv_wait(kcondvar_t *cv, kmutex_t *mp)
-{
- ASSERT(mutex_owner(mp) == curthread);
- mp->m_owner = NULL;
- int ret = cond_wait(cv, &mp->m_lock);
- VERIFY(ret == 0 || ret == EINTR);
- mp->m_owner = curthread;
-}
-
-clock_t
-cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
-{
- int error;
- timestruc_t ts;
- clock_t delta;
-
-top:
- delta = abstime - ddi_get_lbolt();
- if (delta <= 0)
- return (-1);
-
- ts.tv_sec = delta / hz;
- ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
-
- ASSERT(mutex_owner(mp) == curthread);
- mp->m_owner = NULL;
- error = cond_reltimedwait(cv, &mp->m_lock, &ts);
- mp->m_owner = curthread;
-
- if (error == ETIME)
- return (-1);
-
- if (error == EINTR)
- goto top;
-
- ASSERT(error == 0);
-
- return (1);
-}
-
-/*ARGSUSED*/
-clock_t
-cv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res,
- int flag)
-{
- int error;
- timestruc_t ts;
- hrtime_t delta;
-
- ASSERT(flag == 0 || flag == CALLOUT_FLAG_ABSOLUTE);
-
-top:
- delta = tim;
- if (flag & CALLOUT_FLAG_ABSOLUTE)
- delta -= gethrtime();
-
- if (delta <= 0)
- return (-1);
-
- ts.tv_sec = delta / NANOSEC;
- ts.tv_nsec = delta % NANOSEC;
-
- ASSERT(mutex_owner(mp) == curthread);
- mp->m_owner = NULL;
- error = cond_reltimedwait(cv, &mp->m_lock, &ts);
- mp->m_owner = curthread;
-
- if (error == ETIME)
- return (-1);
-
- if (error == EINTR)
- goto top;
-
- ASSERT(error == 0);
-
- return (1);
-}
-
-void
-cv_signal(kcondvar_t *cv)
-{
- VERIFY(cond_signal(cv) == 0);
-}
-
-void
-cv_broadcast(kcondvar_t *cv)
-{
- VERIFY(cond_broadcast(cv) == 0);
-}
-
/*
* =========================================================================
* vnode operations
@@ -690,56 +363,6 @@ __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
/*
* =========================================================================
- * cmn_err() and panic()
- * =========================================================================
- */
-static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
-static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
-
-void
-vpanic(const char *fmt, va_list adx)
-{
- char buf[512];
- (void) vsnprintf(buf, 512, fmt, adx);
- assfail(buf, NULL, 0);
- abort(); /* necessary to make vpanic meet noreturn requirements */
-}
-
-void
-panic(const char *fmt, ...)
-{
- va_list adx;
-
- va_start(adx, fmt);
- vpanic(fmt, adx);
- va_end(adx);
-}
-
-void
-vcmn_err(int ce, const char *fmt, va_list adx)
-{
- if (ce == CE_PANIC)
- vpanic(fmt, adx);
- if (ce != CE_NOTE) { /* suppress noise in userland stress testing */
- (void) fprintf(stderr, "%s", ce_prefix[ce]);
- (void) vfprintf(stderr, fmt, adx);
- (void) fprintf(stderr, "%s", ce_suffix[ce]);
- }
-}
-
-/*PRINTFLIKE2*/
-void
-cmn_err(int ce, const char *fmt, ...)
-{
- va_list adx;
-
- va_start(adx, fmt);
- vcmn_err(ce, fmt, adx);
- va_end(adx);
-}
-
-/*
- * =========================================================================
* kobj interfaces
* =========================================================================
*/
@@ -793,124 +416,6 @@ kobj_get_filesize(struct _buf *file, uint64_t *size)
/*
* =========================================================================
- * misc routines
- * =========================================================================
- */
-
-void
-delay(clock_t ticks)
-{
- poll(0, 0, ticks * (1000 / hz));
-}
-
-/*
- * Find highest one bit set.
- * Returns bit number + 1 of highest bit that is set, otherwise returns 0.
- */
-int
-highbit64(uint64_t i)
-{
- int h = 1;
-
- if (i == 0)
- return (0);
- if (i & 0xffffffff00000000ULL) {
- h += 32; i >>= 32;
- }
- if (i & 0xffff0000) {
- h += 16; i >>= 16;
- }
- if (i & 0xff00) {
- h += 8; i >>= 8;
- }
- if (i & 0xf0) {
- h += 4; i >>= 4;
- }
- if (i & 0xc) {
- h += 2; i >>= 2;
- }
- if (i & 0x2) {
- h += 1;
- }
- return (h);
-}
-
-static int random_fd = -1, urandom_fd = -1;
-
-static int
-random_get_bytes_common(uint8_t *ptr, size_t len, int fd)
-{
- size_t resid = len;
- ssize_t bytes;
-
- ASSERT(fd != -1);
-
- while (resid != 0) {
- bytes = read(fd, ptr, resid);
- ASSERT3S(bytes, >=, 0);
- ptr += bytes;
- resid -= bytes;
- }
-
- return (0);
-}
-
-int
-random_get_bytes(uint8_t *ptr, size_t len)
-{
- return (random_get_bytes_common(ptr, len, random_fd));
-}
-
-int
-random_get_pseudo_bytes(uint8_t *ptr, size_t len)
-{
- return (random_get_bytes_common(ptr, len, urandom_fd));
-}
-
-int
-ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result)
-{
- char *end;
-
- *result = strtoul(hw_serial, &end, base);
- if (*result == 0)
- return (errno);
- return (0);
-}
-
-int
-ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result)
-{
- char *end;
-
- *result = strtoull(str, &end, base);
- if (*result == 0)
- return (errno);
- return (0);
-}
-
-/* ARGSUSED */
-cyclic_id_t
-cyclic_add(cyc_handler_t *hdlr, cyc_time_t *when)
-{
- return (1);
-}
-
-/* ARGSUSED */
-void
-cyclic_remove(cyclic_id_t id)
-{
-}
-
-/* ARGSUSED */
-int
-cyclic_reprogram(cyclic_id_t id, hrtime_t expiration)
-{
- return (1);
-}
-
-/*
- * =========================================================================
* kernel emulation setup & teardown
* =========================================================================
*/
@@ -939,9 +444,6 @@ kernel_init(int mode)
(void) snprintf(hw_serial, sizeof (hw_serial), "%ld",
(mode & FWRITE) ? gethostid() : 0);
- VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1);
- VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1);
-
system_taskq_init();
mutex_init(&cpu_lock, NULL, MUTEX_DEFAULT, NULL);
@@ -957,12 +459,6 @@ kernel_fini(void)
spa_fini();
system_taskq_fini();
-
- close(random_fd);
- close(urandom_fd);
-
- random_fd = -1;
- urandom_fd = -1;
}
int
@@ -990,36 +486,6 @@ z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen,
return (ret);
}
-uid_t
-crgetuid(cred_t *cr)
-{
- return (0);
-}
-
-uid_t
-crgetruid(cred_t *cr)
-{
- return (0);
-}
-
-gid_t
-crgetgid(cred_t *cr)
-{
- return (0);
-}
-
-int
-crgetngroups(cred_t *cr)
-{
- return (0);
-}
-
-gid_t *
-crgetgroups(cred_t *cr)
-{
- return (NULL);
-}
-
int
zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
{
@@ -1038,47 +504,6 @@ zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
return (0);
}
-ksiddomain_t *
-ksid_lookupdomain(const char *dom)
-{
- ksiddomain_t *kd;
-
- kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL);
- kd->kd_name = spa_strdup(dom);
- return (kd);
-}
-
-void
-ksiddomain_rele(ksiddomain_t *ksid)
-{
- spa_strfree(ksid->kd_name);
- umem_free(ksid, sizeof (ksiddomain_t));
-}
-
-/*
- * Do not change the length of the returned string; it must be freed
- * with strfree().
- */
-char *
-kmem_asprintf(const char *fmt, ...)
-{
- int size;
- va_list adx;
- char *buf;
-
- va_start(adx, fmt);
- size = vsnprintf(NULL, 0, fmt, adx) + 1;
- va_end(adx);
-
- buf = kmem_alloc(size, KM_SLEEP);
-
- va_start(adx, fmt);
- size = vsnprintf(buf, size, fmt, adx);
- va_end(adx);
-
- return (buf);
-}
-
/* ARGSUSED */
int
zfs_onexit_fd_hold(int fd, minor_t *minorp)
diff --git a/lib/libzpool/common/sys/zfs_context.h b/lib/libzpool/common/sys/zfs_context.h
index d8d1f8e9191f..d7aa62cdbda9 100644
--- a/lib/libzpool/common/sys/zfs_context.h
+++ b/lib/libzpool/common/sys/zfs_context.h
@@ -23,6 +23,7 @@
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright 2017 RackTop Systems.
*/
#ifndef _SYS_ZFS_CONTEXT_H
@@ -32,14 +33,10 @@
extern "C" {
#endif
-#define _SYS_MUTEX_H
-#define _SYS_RWLOCK_H
-#define _SYS_CONDVAR_H
-#define _SYS_SYSTM_H
-#define _SYS_T_LOCK_H
+#define _SYNCH_H
+
#define _SYS_VNODE_H
#define _SYS_VFS_H
-#define _SYS_SUNDDI_H
#define _SYS_CALLB_H
#include <stdio.h>
@@ -51,7 +48,6 @@ extern "C" {
#include <errno.h>
#include <string.h>
#include <strings.h>
-#include <synch.h>
#include <thread.h>
#include <assert.h>
#include <alloca.h>
@@ -80,25 +76,28 @@ extern "C" {
#include <sys/u8_textprep.h>
#include <sys/sysevent/eventdefs.h>
#include <sys/sysevent/dev.h>
-#include <sys/sunddi.h>
#include <sys/debug.h>
+#include <sys/taskq.h>
+#include <sys/taskq_impl.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/condvar.h>
+#include <sys/cmn_err.h>
+#include <sys/kmem.h>
+#include <sys/systm.h>
+#include <sys/random.h>
+#include <sys/buf.h>
+#include <sys/sid.h>
+#include <sys/acl.h>
+#include <sys/bitmap.h>
+#include <sys/systeminfo.h>
+#include <sys/cpuvar.h>
+#include <sys/pset.h>
+#include <sys/kobj.h>
+#include <sys/fm/util.h>
#include "zfs.h"
/*
- * Debugging
- */
-
-/*
- * Note that we are not using the debugging levels.
- */
-
-#define CE_CONT 0 /* continuation */
-#define CE_NOTE 1 /* notice */
-#define CE_WARN 2 /* warning */
-#define CE_PANIC 3 /* panic */
-#define CE_IGNORE 4 /* print nothing */
-
-/*
* ZFS debugging
*/
@@ -106,15 +105,6 @@ extern "C" {
extern void dprintf_setup(int *argc, char **argv);
#endif /* ZFS_DEBUG */
-extern void cmn_err(int, const char *, ...);
-extern void vcmn_err(int, const char *, __va_list);
-extern void panic(const char *, ...) __NORETURN;
-extern void vpanic(const char *, __va_list) __NORETURN;
-
-#define fm_panic panic
-
-extern int aok;
-
/*
* DTrace SDT probes have different signatures in userland than they do in
* the kernel. If they're being used in kernel code, re-define them out of
@@ -174,232 +164,15 @@ extern int aok;
/*
* Threads
*/
-#define curthread ((void *)(uintptr_t)thr_self())
-
#define kpreempt(x) yield()
-
-typedef struct kthread kthread_t;
-
-#define thread_create(stk, stksize, func, arg, len, pp, state, pri) \
- zk_thread_create(func, arg)
-#define thread_exit() thr_exit(NULL)
-#define thread_join(t) panic("libzpool cannot join threads")
-
#define newproc(f, a, cid, pri, ctp, pid) (ENOSYS)
-/* in libzpool, p0 exists only to have its address taken */
-struct proc {
- uintptr_t this_is_never_used_dont_dereference_it;
-};
-
-extern struct proc p0;
-#define curproc (&p0)
-
-#define PS_NONE -1
-
-extern kthread_t *zk_thread_create(void (*func)(void*), void *arg,
- uint64_t len);
-
-#define issig(why) (FALSE)
-#define ISSIG(thr, why) (FALSE)
-
-/*
- * Mutexes
- */
-typedef struct kmutex {
- void *m_owner;
- boolean_t initialized;
- mutex_t m_lock;
-} kmutex_t;
-
-#define MUTEX_DEFAULT USYNC_THREAD
-#undef MUTEX_HELD
-#undef MUTEX_NOT_HELD
-#define MUTEX_HELD(m) _mutex_held(&(m)->m_lock)
-#define MUTEX_NOT_HELD(m) (!MUTEX_HELD(m))
-
-/*
- * Argh -- we have to get cheesy here because the kernel and userland
- * have different signatures for the same routine.
- */
-extern int _mutex_init(mutex_t *mp, int type, void *arg);
-extern int _mutex_destroy(mutex_t *mp);
-
-#define mutex_init(mp, b, c, d) zmutex_init((kmutex_t *)(mp))
-#define mutex_destroy(mp) zmutex_destroy((kmutex_t *)(mp))
-
-extern void zmutex_init(kmutex_t *mp);
-extern void zmutex_destroy(kmutex_t *mp);
-extern void mutex_enter(kmutex_t *mp);
-extern void mutex_exit(kmutex_t *mp);
-extern int mutex_tryenter(kmutex_t *mp);
-extern void *mutex_owner(kmutex_t *mp);
-
-/*
- * RW locks
- */
-typedef struct krwlock {
- void *rw_owner;
- boolean_t initialized;
- rwlock_t rw_lock;
-} krwlock_t;
-
-typedef int krw_t;
-
-#define RW_READER 0
-#define RW_WRITER 1
-#define RW_DEFAULT USYNC_THREAD
-
-#undef RW_READ_HELD
-#define RW_READ_HELD(x) _rw_read_held(&(x)->rw_lock)
-
-#undef RW_WRITE_HELD
-#define RW_WRITE_HELD(x) _rw_write_held(&(x)->rw_lock)
-
-#undef RW_LOCK_HELD
-#define RW_LOCK_HELD(x) (RW_READ_HELD(x) || RW_WRITE_HELD(x))
-
-extern void rw_init(krwlock_t *rwlp, char *name, int type, void *arg);
-extern void rw_destroy(krwlock_t *rwlp);
-extern void rw_enter(krwlock_t *rwlp, krw_t rw);
-extern int rw_tryenter(krwlock_t *rwlp, krw_t rw);
-extern int rw_tryupgrade(krwlock_t *rwlp);
-extern void rw_exit(krwlock_t *rwlp);
-#define rw_downgrade(rwlp) do { } while (0)
-
-extern uid_t crgetuid(cred_t *cr);
-extern uid_t crgetruid(cred_t *cr);
-extern gid_t crgetgid(cred_t *cr);
-extern int crgetngroups(cred_t *cr);
-extern gid_t *crgetgroups(cred_t *cr);
-
-/*
- * Condition variables
- */
-typedef cond_t kcondvar_t;
-
-#define CV_DEFAULT USYNC_THREAD
-#define CALLOUT_FLAG_ABSOLUTE 0x2
-
-extern void cv_init(kcondvar_t *cv, char *name, int type, void *arg);
-extern void cv_destroy(kcondvar_t *cv);
-extern void cv_wait(kcondvar_t *cv, kmutex_t *mp);
-extern clock_t cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime);
-extern clock_t cv_timedwait_hires(kcondvar_t *cvp, kmutex_t *mp, hrtime_t tim,
- hrtime_t res, int flag);
-extern void cv_signal(kcondvar_t *cv);
-extern void cv_broadcast(kcondvar_t *cv);
-
-/*
- * Thread-specific data
- */
-#define tsd_get(k) pthread_getspecific(k)
-#define tsd_set(k, v) pthread_setspecific(k, v)
-#define tsd_create(kp, d) pthread_key_create(kp, d)
-#define tsd_destroy(kp) /* nothing */
-
/*
- * kstat creation, installation and deletion
- */
-extern kstat_t *kstat_create(const char *, int,
- const char *, const char *, uchar_t, ulong_t, uchar_t);
-extern void kstat_named_init(kstat_named_t *, const char *, uchar_t);
-extern void kstat_install(kstat_t *);
-extern void kstat_delete(kstat_t *);
-extern void kstat_waitq_enter(kstat_io_t *);
-extern void kstat_waitq_exit(kstat_io_t *);
-extern void kstat_runq_enter(kstat_io_t *);
-extern void kstat_runq_exit(kstat_io_t *);
-extern void kstat_waitq_to_runq(kstat_io_t *);
-extern void kstat_runq_back_to_waitq(kstat_io_t *);
-
-/*
- * Kernel memory
- */
-#define KM_SLEEP UMEM_NOFAIL
-#define KM_PUSHPAGE KM_SLEEP
-#define KM_NOSLEEP UMEM_DEFAULT
-#define KM_NORMALPRI 0 /* not needed with UMEM_DEFAULT */
-#define KMC_NODEBUG UMC_NODEBUG
-#define KMC_NOTOUCH 0 /* not needed for userland caches */
-#define kmem_alloc(_s, _f) umem_alloc(_s, _f)
-#define kmem_zalloc(_s, _f) umem_zalloc(_s, _f)
-#define kmem_free(_b, _s) umem_free(_b, _s)
-#define kmem_cache_create(_a, _b, _c, _d, _e, _f, _g, _h, _i) \
- umem_cache_create(_a, _b, _c, _d, _e, _f, _g, _h, _i)
-#define kmem_cache_destroy(_c) umem_cache_destroy(_c)
-#define kmem_cache_alloc(_c, _f) umem_cache_alloc(_c, _f)
-#define kmem_cache_free(_c, _b) umem_cache_free(_c, _b)
-#define kmem_debugging() 0
-#define kmem_cache_reap_now(_c) /* nothing */
-#define kmem_cache_set_move(_c, _cb) /* nothing */
-#define vmem_qcache_reap(_v) /* nothing */
-#define POINTER_INVALIDATE(_pp) /* nothing */
-#define POINTER_IS_VALID(_p) 0
-
-extern vmem_t *zio_arena;
-
-typedef umem_cache_t kmem_cache_t;
-
-typedef enum kmem_cbrc {
- KMEM_CBRC_YES,
- KMEM_CBRC_NO,
- KMEM_CBRC_LATER,
- KMEM_CBRC_DONT_NEED,
- KMEM_CBRC_DONT_KNOW
-} kmem_cbrc_t;
-
-/*
- * Task queues
+ * vnodes
*/
-typedef struct taskq taskq_t;
-typedef uintptr_t taskqid_t;
-typedef void (task_func_t)(void *);
-
-typedef struct taskq_ent {
- struct taskq_ent *tqent_next;
- struct taskq_ent *tqent_prev;
- task_func_t *tqent_func;
- void *tqent_arg;
- uintptr_t tqent_flags;
-} taskq_ent_t;
-
-#define TQENT_FLAG_PREALLOC 0x1 /* taskq_dispatch_ent used */
-
-#define TASKQ_PREPOPULATE 0x0001
-#define TASKQ_CPR_SAFE 0x0002 /* Use CPR safe protocol */
-#define TASKQ_DYNAMIC 0x0004 /* Use dynamic thread scheduling */
-#define TASKQ_THREADS_CPU_PCT 0x0008 /* Scale # threads by # cpus */
-#define TASKQ_DC_BATCH 0x0010 /* Mark threads as batch */
-
-#define TQ_SLEEP KM_SLEEP /* Can block for memory */
-#define TQ_NOSLEEP KM_NOSLEEP /* cannot block for memory; may fail */
-#define TQ_NOQUEUE 0x02 /* Do not enqueue if can't dispatch */
-#define TQ_FRONT 0x08 /* Queue in front */
-
-
-extern taskq_t *system_taskq;
-
-extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
-#define taskq_create_proc(a, b, c, d, e, p, f) \
- (taskq_create(a, b, c, d, e, f))
-#define taskq_create_sysdc(a, b, d, e, p, dc, f) \
- (taskq_create(a, b, maxclsyspri, d, e, f))
-extern taskqid_t taskq_dispatch(taskq_t *, task_func_t, void *, uint_t);
-extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
- taskq_ent_t *);
-extern void taskq_destroy(taskq_t *);
-extern void taskq_wait(taskq_t *);
-extern int taskq_member(taskq_t *, void *);
-extern void system_taskq_init(void);
-extern void system_taskq_fini(void);
-
#define XVA_MAPSIZE 3
#define XVA_MAGIC 0x78766174
-/*
- * vnodes
- */
typedef struct vnode {
uint64_t v_size;
int v_fd;
@@ -499,26 +272,13 @@ extern void vn_close(vnode_t *vp);
extern vnode_t *rootdir;
#include <sys/file.h> /* for FREAD, FWRITE, etc */
+#include <sys/sunddi.h> /* for ddi_strtoul, ddi_strtoull, etc */
+#include <sys/cyclic.h> /* for cyclic_add, cyclic remove, etc */
+#include <vm/seg_kmem.h> /* for zio_arena */
/*
* Random stuff
*/
-#define ddi_get_lbolt() (gethrtime() >> 23)
-#define ddi_get_lbolt64() (gethrtime() >> 23)
-#define hz 119 /* frequency when using gethrtime() >> 23 for lbolt */
-
-extern void delay(clock_t ticks);
-
-#define SEC_TO_TICK(sec) ((sec) * hz)
-#define NSEC_TO_TICK(usec) ((usec) / (NANOSEC / hz))
-
-#define gethrestime_sec() time(NULL)
-#define gethrestime(t) \
- do {\
- (t)->tv_sec = gethrestime_sec();\
- (t)->tv_nsec = 0;\
- } while (0);
-
#define max_ncpus 64
#define boot_ncpus (sysconf(_SC_NPROCESSORS_ONLN))
@@ -527,22 +287,10 @@ extern void delay(clock_t ticks);
#define CPU_SEQID (thr_self() & (max_ncpus - 1))
-#define kcred NULL
-#define CRED() NULL
-
-#define ptob(x) ((x) * PAGESIZE)
-
-extern uint64_t physmem;
-
-extern int highbit64(uint64_t i);
-extern int random_get_bytes(uint8_t *ptr, size_t len);
-extern int random_get_pseudo_bytes(uint8_t *ptr, size_t len);
-
extern void kernel_init(int);
extern void kernel_fini(void);
struct spa;
-extern void nicenum(uint64_t num, char *buf, size_t);
extern void show_pool_stats(struct spa *);
extern int set_global_var(char *arg);
@@ -570,127 +318,14 @@ typedef struct callb_cpr {
#define zone_dataset_visible(x, y) (1)
#define INGLOBALZONE(z) (1)
-extern char *kmem_asprintf(const char *fmt, ...);
-#define strfree(str) kmem_free((str), strlen(str) + 1)
-
-/*
- * Hostname information
- */
-extern char hw_serial[]; /* for userland-emulated hostid access */
-extern int ddi_strtoul(const char *str, char **nptr, int base,
- unsigned long *result);
-
-extern int ddi_strtoull(const char *str, char **nptr, int base,
- u_longlong_t *result);
-
-/* ZFS Boot Related stuff. */
-
-struct _buf {
- intptr_t _fd;
-};
-
-struct bootstat {
- uint64_t st_size;
-};
-
-typedef struct ace_object {
- uid_t a_who;
- uint32_t a_access_mask;
- uint16_t a_flags;
- uint16_t a_type;
- uint8_t a_obj_type[16];
- uint8_t a_inherit_obj_type[16];
-} ace_object_t;
-
-
-#define ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05
-#define ACE_ACCESS_DENIED_OBJECT_ACE_TYPE 0x06
-#define ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07
-#define ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08
-
-extern struct _buf *kobj_open_file(char *name);
-extern int kobj_read_file(struct _buf *file, char *buf, unsigned size,
- unsigned off);
-extern void kobj_close_file(struct _buf *file);
-extern int kobj_get_filesize(struct _buf *file, uint64_t *size);
extern int zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr);
extern int zfs_secpolicy_rename_perms(const char *from, const char *to,
cred_t *cr);
extern int zfs_secpolicy_destroy_perms(const char *name, cred_t *cr);
-extern zoneid_t getzoneid(void);
-
-/* SID stuff */
-typedef struct ksiddomain {
- uint_t kd_ref;
- uint_t kd_len;
- char *kd_name;
-} ksiddomain_t;
-ksiddomain_t *ksid_lookupdomain(const char *);
-void ksiddomain_rele(ksiddomain_t *);
-
-#define DDI_SLEEP KM_SLEEP
#define ddi_log_sysevent(_a, _b, _c, _d, _e, _f, _g) \
sysevent_post_event(_c, _d, _b, "libzpool", _e, _f)
-/*
- * Cyclic information
- */
-extern kmutex_t cpu_lock;
-
-typedef uintptr_t cyclic_id_t;
-typedef uint16_t cyc_level_t;
-typedef void (*cyc_func_t)(void *);
-
-#define CY_LOW_LEVEL 0
-#define CY_INFINITY INT64_MAX
-#define CYCLIC_NONE ((cyclic_id_t)0)
-
-typedef struct cyc_time {
- hrtime_t cyt_when;
- hrtime_t cyt_interval;
-} cyc_time_t;
-
-typedef struct cyc_handler {
- cyc_func_t cyh_func;
- void *cyh_arg;
- cyc_level_t cyh_level;
-} cyc_handler_t;
-
-extern cyclic_id_t cyclic_add(cyc_handler_t *, cyc_time_t *);
-extern void cyclic_remove(cyclic_id_t);
-extern int cyclic_reprogram(cyclic_id_t, hrtime_t);
-
-/*
- * Buf structure
- */
-#define B_BUSY 0x0001
-#define B_DONE 0x0002
-#define B_ERROR 0x0004
-#define B_READ 0x0040 /* read when I/O occurs */
-#define B_WRITE 0x0100 /* non-read pseudo-flag */
-
-typedef struct buf {
- int b_flags;
- size_t b_bcount;
- union {
- caddr_t b_addr;
- } b_un;
-
- lldaddr_t _b_blkno;
-#define b_lblkno _b_blkno._f
- size_t b_resid;
- size_t b_bufsize;
- int (*b_iodone)(struct buf *);
- int b_error;
- void *b_private;
-} buf_t;
-
-extern void bioinit(buf_t *);
-extern void biodone(buf_t *);
-extern void bioerror(buf_t *, int);
-extern int geterror(buf_t *);
-
#ifdef __cplusplus
}
#endif
diff --git a/lib/libzpool/common/taskq.c b/lib/libzpool/common/taskq.c
index a4ab58963d75..e69de29bb2d1 100644
--- a/lib/libzpool/common/taskq.c
+++ b/lib/libzpool/common/taskq.c
@@ -1,342 +0,0 @@
-/*
- * 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 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
- * Copyright (c) 2014 by Delphix. All rights reserved.
- */
-
-#include <sys/zfs_context.h>
-
-int taskq_now;
-taskq_t *system_taskq;
-
-#define TASKQ_ACTIVE 0x00010000
-#define TASKQ_NAMELEN 31
-
-struct taskq {
- char tq_name[TASKQ_NAMELEN + 1];
- kmutex_t tq_lock;
- krwlock_t tq_threadlock;
- kcondvar_t tq_dispatch_cv;
- kcondvar_t tq_wait_cv;
- thread_t *tq_threadlist;
- int tq_flags;
- int tq_active;
- int tq_nthreads;
- int tq_nalloc;
- int tq_minalloc;
- int tq_maxalloc;
- kcondvar_t tq_maxalloc_cv;
- int tq_maxalloc_wait;
- taskq_ent_t *tq_freelist;
- taskq_ent_t tq_task;
-};
-
-static taskq_ent_t *
-task_alloc(taskq_t *tq, int tqflags)
-{
- taskq_ent_t *t;
- int rv;
-
-again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) {
- tq->tq_freelist = t->tqent_next;
- } else {
- if (tq->tq_nalloc >= tq->tq_maxalloc) {
- if (!(tqflags & KM_SLEEP))
- return (NULL);
-
- /*
- * We don't want to exceed tq_maxalloc, but we can't
- * wait for other tasks to complete (and thus free up
- * task structures) without risking deadlock with
- * the caller. So, we just delay for one second
- * to throttle the allocation rate. If we have tasks
- * complete before one second timeout expires then
- * taskq_ent_free will signal us and we will
- * immediately retry the allocation.
- */
- tq->tq_maxalloc_wait++;
- rv = cv_timedwait(&tq->tq_maxalloc_cv,
- &tq->tq_lock, ddi_get_lbolt() + hz);
- tq->tq_maxalloc_wait--;
- if (rv > 0)
- goto again; /* signaled */
- }
- mutex_exit(&tq->tq_lock);
-
- t = kmem_alloc(sizeof (taskq_ent_t), tqflags);
-
- mutex_enter(&tq->tq_lock);
- if (t != NULL)
- tq->tq_nalloc++;
- }
- return (t);
-}
-
-static void
-task_free(taskq_t *tq, taskq_ent_t *t)
-{
- if (tq->tq_nalloc <= tq->tq_minalloc) {
- t->tqent_next = tq->tq_freelist;
- tq->tq_freelist = t;
- } else {
- tq->tq_nalloc--;
- mutex_exit(&tq->tq_lock);
- kmem_free(t, sizeof (taskq_ent_t));
- mutex_enter(&tq->tq_lock);
- }
-
- if (tq->tq_maxalloc_wait)
- cv_signal(&tq->tq_maxalloc_cv);
-}
-
-taskqid_t
-taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t tqflags)
-{
- taskq_ent_t *t;
-
- if (taskq_now) {
- func(arg);
- return (1);
- }
-
- mutex_enter(&tq->tq_lock);
- ASSERT(tq->tq_flags & TASKQ_ACTIVE);
- if ((t = task_alloc(tq, tqflags)) == NULL) {
- mutex_exit(&tq->tq_lock);
- return (0);
- }
- if (tqflags & TQ_FRONT) {
- t->tqent_next = tq->tq_task.tqent_next;
- t->tqent_prev = &tq->tq_task;
- } else {
- t->tqent_next = &tq->tq_task;
- t->tqent_prev = tq->tq_task.tqent_prev;
- }
- t->tqent_next->tqent_prev = t;
- t->tqent_prev->tqent_next = t;
- t->tqent_func = func;
- t->tqent_arg = arg;
- t->tqent_flags = 0;
- cv_signal(&tq->tq_dispatch_cv);
- mutex_exit(&tq->tq_lock);
- return (1);
-}
-
-void
-taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
- taskq_ent_t *t)
-{
- ASSERT(func != NULL);
- ASSERT(!(tq->tq_flags & TASKQ_DYNAMIC));
-
- /*
- * Mark it as a prealloc'd task. This is important
- * to ensure that we don't free it later.
- */
- t->tqent_flags |= TQENT_FLAG_PREALLOC;
- /*
- * Enqueue the task to the underlying queue.
- */
- mutex_enter(&tq->tq_lock);
-
- if (flags & TQ_FRONT) {
- t->tqent_next = tq->tq_task.tqent_next;
- t->tqent_prev = &tq->tq_task;
- } else {
- t->tqent_next = &tq->tq_task;
- t->tqent_prev = tq->tq_task.tqent_prev;
- }
- t->tqent_next->tqent_prev = t;
- t->tqent_prev->tqent_next = t;
- t->tqent_func = func;
- t->tqent_arg = arg;
- cv_signal(&tq->tq_dispatch_cv);
- mutex_exit(&tq->tq_lock);
-}
-
-void
-taskq_wait(taskq_t *tq)
-{
- mutex_enter(&tq->tq_lock);
- while (tq->tq_task.tqent_next != &tq->tq_task || tq->tq_active != 0)
- cv_wait(&tq->tq_wait_cv, &tq->tq_lock);
- mutex_exit(&tq->tq_lock);
-}
-
-static void *
-taskq_thread(void *arg)
-{
- taskq_t *tq = arg;
- taskq_ent_t *t;
- boolean_t prealloc;
-
- mutex_enter(&tq->tq_lock);
- while (tq->tq_flags & TASKQ_ACTIVE) {
- if ((t = tq->tq_task.tqent_next) == &tq->tq_task) {
- if (--tq->tq_active == 0)
- cv_broadcast(&tq->tq_wait_cv);
- cv_wait(&tq->tq_dispatch_cv, &tq->tq_lock);
- tq->tq_active++;
- continue;
- }
- t->tqent_prev->tqent_next = t->tqent_next;
- t->tqent_next->tqent_prev = t->tqent_prev;
- t->tqent_next = NULL;
- t->tqent_prev = NULL;
- prealloc = t->tqent_flags & TQENT_FLAG_PREALLOC;
- mutex_exit(&tq->tq_lock);
-
- rw_enter(&tq->tq_threadlock, RW_READER);
- t->tqent_func(t->tqent_arg);
- rw_exit(&tq->tq_threadlock);
-
- mutex_enter(&tq->tq_lock);
- if (!prealloc)
- task_free(tq, t);
- }
- tq->tq_nthreads--;
- cv_broadcast(&tq->tq_wait_cv);
- mutex_exit(&tq->tq_lock);
- return (NULL);
-}
-
-/*ARGSUSED*/
-taskq_t *
-taskq_create(const char *name, int nthreads, pri_t pri,
- int minalloc, int maxalloc, uint_t flags)
-{
- taskq_t *tq = kmem_zalloc(sizeof (taskq_t), KM_SLEEP);
- int t;
-
- if (flags & TASKQ_THREADS_CPU_PCT) {
- int pct;
- ASSERT3S(nthreads, >=, 0);
- ASSERT3S(nthreads, <=, 100);
- pct = MIN(nthreads, 100);
- pct = MAX(pct, 0);
-
- nthreads = (sysconf(_SC_NPROCESSORS_ONLN) * pct) / 100;
- nthreads = MAX(nthreads, 1); /* need at least 1 thread */
- } else {
- ASSERT3S(nthreads, >=, 1);
- }
-
- rw_init(&tq->tq_threadlock, NULL, RW_DEFAULT, NULL);
- mutex_init(&tq->tq_lock, NULL, MUTEX_DEFAULT, NULL);
- cv_init(&tq->tq_dispatch_cv, NULL, CV_DEFAULT, NULL);
- cv_init(&tq->tq_wait_cv, NULL, CV_DEFAULT, NULL);
- cv_init(&tq->tq_maxalloc_cv, NULL, CV_DEFAULT, NULL);
- (void) strncpy(tq->tq_name, name, TASKQ_NAMELEN + 1);
- tq->tq_flags = flags | TASKQ_ACTIVE;
- tq->tq_active = nthreads;
- tq->tq_nthreads = nthreads;
- tq->tq_minalloc = minalloc;
- tq->tq_maxalloc = maxalloc;
- tq->tq_task.tqent_next = &tq->tq_task;
- tq->tq_task.tqent_prev = &tq->tq_task;
- tq->tq_threadlist = kmem_alloc(nthreads * sizeof (thread_t), KM_SLEEP);
-
- if (flags & TASKQ_PREPOPULATE) {
- mutex_enter(&tq->tq_lock);
- while (minalloc-- > 0)
- task_free(tq, task_alloc(tq, KM_SLEEP));
- mutex_exit(&tq->tq_lock);
- }
-
- for (t = 0; t < nthreads; t++)
- (void) thr_create(0, 0, taskq_thread,
- tq, THR_BOUND, &tq->tq_threadlist[t]);
-
- return (tq);
-}
-
-void
-taskq_destroy(taskq_t *tq)
-{
- int t;
- int nthreads = tq->tq_nthreads;
-
- taskq_wait(tq);
-
- mutex_enter(&tq->tq_lock);
-
- tq->tq_flags &= ~TASKQ_ACTIVE;
- cv_broadcast(&tq->tq_dispatch_cv);
-
- while (tq->tq_nthreads != 0)
- cv_wait(&tq->tq_wait_cv, &tq->tq_lock);
-
- tq->tq_minalloc = 0;
- while (tq->tq_nalloc != 0) {
- ASSERT(tq->tq_freelist != NULL);
- task_free(tq, task_alloc(tq, KM_SLEEP));
- }
-
- mutex_exit(&tq->tq_lock);
-
- for (t = 0; t < nthreads; t++)
- (void) thr_join(tq->tq_threadlist[t], NULL, NULL);
-
- kmem_free(tq->tq_threadlist, nthreads * sizeof (thread_t));
-
- rw_destroy(&tq->tq_threadlock);
- mutex_destroy(&tq->tq_lock);
- cv_destroy(&tq->tq_dispatch_cv);
- cv_destroy(&tq->tq_wait_cv);
- cv_destroy(&tq->tq_maxalloc_cv);
-
- kmem_free(tq, sizeof (taskq_t));
-}
-
-int
-taskq_member(taskq_t *tq, void *t)
-{
- int i;
-
- if (taskq_now)
- return (1);
-
- for (i = 0; i < tq->tq_nthreads; i++)
- if (tq->tq_threadlist[i] == (thread_t)(uintptr_t)t)
- return (1);
-
- return (0);
-}
-
-void
-system_taskq_init(void)
-{
- system_taskq = taskq_create("system_taskq", 64, minclsyspri, 4, 512,
- TASKQ_DYNAMIC | TASKQ_PREPOPULATE);
-}
-
-void
-system_taskq_fini(void)
-{
- taskq_destroy(system_taskq);
- system_taskq = NULL; /* defensive */
-}
diff --git a/lib/libzpool/common/util.c b/lib/libzpool/common/util.c
index 363940677c19..c9da9adca788 100644
--- a/lib/libzpool/common/util.c
+++ b/lib/libzpool/common/util.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 by Delphix. All rights reserved.
+ * Copyright 2017 RackTop Systems.
*/
#include <assert.h>
@@ -34,6 +35,8 @@
#include <sys/refcount.h>
#include <dlfcn.h>
+extern void nicenum(uint64_t num, char *buf, size_t);
+
/*
* Routines needed by more than one client of libzpool.
*/