diff options
author | Alexander Motin <mav@FreeBSD.org> | 2018-02-21 21:04:46 +0000 |
---|---|---|
committer | Alexander Motin <mav@FreeBSD.org> | 2018-02-21 21:04:46 +0000 |
commit | 81ef5e369cb2f59309404806160315c1645d0394 (patch) | |
tree | e9a79e11a90d5886dc0c080e403ff4b516122c37 /lib | |
parent | ed2ac05a276d0bac9e07f35d87c8a7095dc69d67 (diff) | |
download | src-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.c | 585 | ||||
-rw-r--r-- | lib/libzpool/common/sys/zfs_context.h | 415 | ||||
-rw-r--r-- | lib/libzpool/common/taskq.c | 342 | ||||
-rw-r--r-- | lib/libzpool/common/util.c | 3 |
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. */ |