193f3d2b8Schs /*
293f3d2b8Schs  * CDDL HEADER START
393f3d2b8Schs  *
493f3d2b8Schs  * The contents of this file are subject to the terms of the
593f3d2b8Schs  * Common Development and Distribution License (the "License").
693f3d2b8Schs  * You may not use this file except in compliance with the License.
793f3d2b8Schs  *
893f3d2b8Schs  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
993f3d2b8Schs  * or http://www.opensolaris.org/os/licensing.
1093f3d2b8Schs  * See the License for the specific language governing permissions
1193f3d2b8Schs  * and limitations under the License.
1293f3d2b8Schs  *
1393f3d2b8Schs  * When distributing Covered Code, include this CDDL HEADER in each
1493f3d2b8Schs  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1593f3d2b8Schs  * If applicable, add the following below this CDDL HEADER, with the
1693f3d2b8Schs  * fields enclosed by brackets "[]" replaced with your own identifying
1793f3d2b8Schs  * information: Portions Copyright [yyyy] [name of copyright owner]
1893f3d2b8Schs  *
1993f3d2b8Schs  * CDDL HEADER END
2093f3d2b8Schs  */
2193f3d2b8Schs /*
2293f3d2b8Schs  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
2393f3d2b8Schs  * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
2493f3d2b8Schs  * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
2593f3d2b8Schs  */
2693f3d2b8Schs 
2793f3d2b8Schs #include <assert.h>
2893f3d2b8Schs #include <fcntl.h>
2993f3d2b8Schs #include <poll.h>
3093f3d2b8Schs #include <stdio.h>
3193f3d2b8Schs #include <stdlib.h>
3293f3d2b8Schs #include <string.h>
3393f3d2b8Schs #include <zlib.h>
3493f3d2b8Schs #include <libgen.h>
3593f3d2b8Schs #include <sys/spa.h>
3693f3d2b8Schs #include <sys/stat.h>
3793f3d2b8Schs #include <sys/processor.h>
3893f3d2b8Schs #include <sys/zfs_context.h>
3993f3d2b8Schs #include <sys/rrwlock.h>
4093f3d2b8Schs #include <sys/zmod.h>
4193f3d2b8Schs #include <sys/utsname.h>
4293f3d2b8Schs #include <sys/systeminfo.h>
4393f3d2b8Schs 
44*48290834Ssimonb #ifdef __NetBSD__
45*48290834Ssimonb #include <sys/dkio.h>
46*48290834Ssimonb #include <sys/ioctl.h>
47*48290834Ssimonb #endif
48*48290834Ssimonb 
4993f3d2b8Schs /*
5093f3d2b8Schs  * Emulation of kernel services in userland.
5193f3d2b8Schs  */
5293f3d2b8Schs 
5393f3d2b8Schs #ifndef __FreeBSD__
5493f3d2b8Schs int aok;
5593f3d2b8Schs #endif
5693f3d2b8Schs uint64_t physmem;
5793f3d2b8Schs vnode_t *rootdir = (vnode_t *)0xabcd1234;
5893f3d2b8Schs char hw_serial[HW_HOSTID_LEN];
5993f3d2b8Schs #ifdef illumos
6093f3d2b8Schs kmutex_t cpu_lock;
6193f3d2b8Schs #endif
6293f3d2b8Schs 
6393f3d2b8Schs /* If set, all blocks read will be copied to the specified directory. */
6493f3d2b8Schs char *vn_dumpdir = NULL;
6593f3d2b8Schs 
6693f3d2b8Schs struct utsname utsname = {
6793f3d2b8Schs 	"userland", "libzpool", "1", "1", "na"
6893f3d2b8Schs };
6993f3d2b8Schs 
7093f3d2b8Schs /* this only exists to have its address taken */
7193f3d2b8Schs struct proc p0;
7293f3d2b8Schs 
7393f3d2b8Schs /*
7493f3d2b8Schs  * =========================================================================
7593f3d2b8Schs  * threads
7693f3d2b8Schs  * =========================================================================
7793f3d2b8Schs  */
7893f3d2b8Schs /*ARGSUSED*/
7993f3d2b8Schs kthread_t *
zk_thread_create(void (* func)(),void * arg)8093f3d2b8Schs zk_thread_create(void (*func)(), void *arg)
8193f3d2b8Schs {
8293f3d2b8Schs 	thread_t tid;
8393f3d2b8Schs 
8493f3d2b8Schs 	VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
8593f3d2b8Schs 	    &tid) == 0);
8693f3d2b8Schs 
8793f3d2b8Schs 	return ((void *)(uintptr_t)tid);
8893f3d2b8Schs }
8993f3d2b8Schs 
9093f3d2b8Schs /*
9193f3d2b8Schs  * =========================================================================
9293f3d2b8Schs  * kstats
9393f3d2b8Schs  * =========================================================================
9493f3d2b8Schs  */
9593f3d2b8Schs /*ARGSUSED*/
9693f3d2b8Schs kstat_t *
kstat_create(char * module,int instance,char * name,char * class,uchar_t type,ulong_t ndata,uchar_t ks_flag)9793f3d2b8Schs kstat_create(char *module, int instance, char *name, char *class,
9893f3d2b8Schs     uchar_t type, ulong_t ndata, uchar_t ks_flag)
9993f3d2b8Schs {
10093f3d2b8Schs 	return (NULL);
10193f3d2b8Schs }
10293f3d2b8Schs 
10393f3d2b8Schs /*ARGSUSED*/
10493f3d2b8Schs void
kstat_named_init(kstat_named_t * knp,const char * name,uchar_t type)10593f3d2b8Schs kstat_named_init(kstat_named_t *knp, const char *name, uchar_t type)
10693f3d2b8Schs {}
10793f3d2b8Schs 
10893f3d2b8Schs /*ARGSUSED*/
10993f3d2b8Schs void
kstat_install(kstat_t * ksp)11093f3d2b8Schs kstat_install(kstat_t *ksp)
11193f3d2b8Schs {}
11293f3d2b8Schs 
11393f3d2b8Schs /*ARGSUSED*/
11493f3d2b8Schs void
kstat_delete(kstat_t * ksp)11593f3d2b8Schs kstat_delete(kstat_t *ksp)
11693f3d2b8Schs {}
11793f3d2b8Schs 
11893f3d2b8Schs /*
11993f3d2b8Schs  * =========================================================================
12093f3d2b8Schs  * mutexes
12193f3d2b8Schs  * =========================================================================
12293f3d2b8Schs  */
12393f3d2b8Schs void
zmutex_init(kmutex_t * mp)12493f3d2b8Schs zmutex_init(kmutex_t *mp)
12593f3d2b8Schs {
12693f3d2b8Schs 	mp->m_owner = NULL;
12793f3d2b8Schs 	mp->initialized = B_TRUE;
12893f3d2b8Schs 	(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
12993f3d2b8Schs }
13093f3d2b8Schs 
13193f3d2b8Schs void
zmutex_destroy(kmutex_t * mp)13293f3d2b8Schs zmutex_destroy(kmutex_t *mp)
13393f3d2b8Schs {
13493f3d2b8Schs 	ASSERT(mp->initialized == B_TRUE);
13593f3d2b8Schs 	ASSERT(mp->m_owner == NULL);
13693f3d2b8Schs 	(void) _mutex_destroy(&(mp)->m_lock);
13793f3d2b8Schs 	mp->m_owner = (void *)-1UL;
13893f3d2b8Schs 	mp->initialized = B_FALSE;
13993f3d2b8Schs }
14093f3d2b8Schs 
14193f3d2b8Schs int
zmutex_owned(kmutex_t * mp)14293f3d2b8Schs zmutex_owned(kmutex_t *mp)
14393f3d2b8Schs {
14493f3d2b8Schs 	ASSERT(mp->initialized == B_TRUE);
14593f3d2b8Schs 
14693f3d2b8Schs 	return (mp->m_owner == curthread);
14793f3d2b8Schs }
14893f3d2b8Schs 
14993f3d2b8Schs void
mutex_enter(kmutex_t * mp)15093f3d2b8Schs mutex_enter(kmutex_t *mp)
15193f3d2b8Schs {
15293f3d2b8Schs 	ASSERT(mp->initialized == B_TRUE);
15393f3d2b8Schs 	ASSERT(mp->m_owner != (void *)-1UL);
15493f3d2b8Schs 	ASSERT(mp->m_owner != curthread);
15593f3d2b8Schs 	VERIFY(mutex_lock(&mp->m_lock) == 0);
15693f3d2b8Schs 	ASSERT(mp->m_owner == NULL);
15793f3d2b8Schs 	mp->m_owner = curthread;
15893f3d2b8Schs }
15993f3d2b8Schs 
16093f3d2b8Schs int
mutex_tryenter(kmutex_t * mp)16193f3d2b8Schs mutex_tryenter(kmutex_t *mp)
16293f3d2b8Schs {
16393f3d2b8Schs 	ASSERT(mp->initialized == B_TRUE);
16493f3d2b8Schs 	ASSERT(mp->m_owner != (void *)-1UL);
16593f3d2b8Schs 	if (0 == mutex_trylock(&mp->m_lock)) {
16693f3d2b8Schs 		ASSERT(mp->m_owner == NULL);
16793f3d2b8Schs 		mp->m_owner = curthread;
16893f3d2b8Schs 		return (1);
16993f3d2b8Schs 	} else {
17093f3d2b8Schs 		return (0);
17193f3d2b8Schs 	}
17293f3d2b8Schs }
17393f3d2b8Schs 
17493f3d2b8Schs void
mutex_exit(kmutex_t * mp)17593f3d2b8Schs mutex_exit(kmutex_t *mp)
17693f3d2b8Schs {
17793f3d2b8Schs 	ASSERT(mp->initialized == B_TRUE);
17893f3d2b8Schs 	ASSERT(mutex_owner(mp) == curthread);
17993f3d2b8Schs 	mp->m_owner = NULL;
18093f3d2b8Schs 	VERIFY(mutex_unlock(&mp->m_lock) == 0);
18193f3d2b8Schs }
18293f3d2b8Schs 
18393f3d2b8Schs void *
mutex_owner(kmutex_t * mp)18493f3d2b8Schs mutex_owner(kmutex_t *mp)
18593f3d2b8Schs {
18693f3d2b8Schs 	ASSERT(mp->initialized == B_TRUE);
18793f3d2b8Schs 	return (mp->m_owner);
18893f3d2b8Schs }
18993f3d2b8Schs 
19093f3d2b8Schs /*
19193f3d2b8Schs  * =========================================================================
19293f3d2b8Schs  * rwlocks
19393f3d2b8Schs  * =========================================================================
19493f3d2b8Schs  */
19593f3d2b8Schs /*ARGSUSED*/
19693f3d2b8Schs void
rw_init(krwlock_t * rwlp,char * name,int type,void * arg)19793f3d2b8Schs rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
19893f3d2b8Schs {
19993f3d2b8Schs 	rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
20093f3d2b8Schs 	rwlp->rw_owner = NULL;
20193f3d2b8Schs 	rwlp->initialized = B_TRUE;
20293f3d2b8Schs 	rwlp->rw_count = 0;
20393f3d2b8Schs }
20493f3d2b8Schs 
20593f3d2b8Schs void
rw_destroy(krwlock_t * rwlp)20693f3d2b8Schs rw_destroy(krwlock_t *rwlp)
20793f3d2b8Schs {
20893f3d2b8Schs 	ASSERT(rwlp->rw_count == 0);
20993f3d2b8Schs 	rwlock_destroy(&rwlp->rw_lock);
21093f3d2b8Schs 	rwlp->rw_owner = (void *)-1UL;
21193f3d2b8Schs 	rwlp->initialized = B_FALSE;
21293f3d2b8Schs }
21393f3d2b8Schs 
21493f3d2b8Schs void
rw_enter(krwlock_t * rwlp,krw_t rw)21593f3d2b8Schs rw_enter(krwlock_t *rwlp, krw_t rw)
21693f3d2b8Schs {
21793f3d2b8Schs 	//ASSERT(!RW_LOCK_HELD(rwlp));
21893f3d2b8Schs 	ASSERT(rwlp->initialized == B_TRUE);
21993f3d2b8Schs 	ASSERT(rwlp->rw_owner != (void *)-1UL);
22093f3d2b8Schs 	ASSERT(rwlp->rw_owner != curthread);
22193f3d2b8Schs 
22293f3d2b8Schs 	if (rw == RW_READER) {
22393f3d2b8Schs 		VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
22493f3d2b8Schs 		ASSERT(rwlp->rw_count >= 0);
22593f3d2b8Schs 		atomic_add_int(&rwlp->rw_count, 1);
22693f3d2b8Schs 	} else {
22793f3d2b8Schs 		VERIFY(rw_wrlock(&rwlp->rw_lock) == 0);
22893f3d2b8Schs 		ASSERT(rwlp->rw_count == 0);
22993f3d2b8Schs 		rwlp->rw_count = -1;
23093f3d2b8Schs 		rwlp->rw_owner = curthread;
23193f3d2b8Schs 	}
23293f3d2b8Schs }
23393f3d2b8Schs 
23493f3d2b8Schs void
rw_exit(krwlock_t * rwlp)23593f3d2b8Schs rw_exit(krwlock_t *rwlp)
23693f3d2b8Schs {
23793f3d2b8Schs 	ASSERT(rwlp->initialized == B_TRUE);
23893f3d2b8Schs 	ASSERT(rwlp->rw_owner != (void *)-1UL);
23993f3d2b8Schs 
24093f3d2b8Schs 	if (rwlp->rw_owner == curthread) {
24193f3d2b8Schs 		/* Write locked. */
24293f3d2b8Schs 		ASSERT(rwlp->rw_count == -1);
24393f3d2b8Schs 		rwlp->rw_count = 0;
24493f3d2b8Schs 		rwlp->rw_owner = NULL;
24593f3d2b8Schs 	} else {
24693f3d2b8Schs 		/* Read locked. */
24793f3d2b8Schs 		ASSERT(rwlp->rw_count > 0);
24893f3d2b8Schs 		atomic_add_int(&rwlp->rw_count, -1);
24993f3d2b8Schs 	}
25093f3d2b8Schs 	VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
25193f3d2b8Schs }
25293f3d2b8Schs 
25393f3d2b8Schs int
rw_tryenter(krwlock_t * rwlp,krw_t rw)25493f3d2b8Schs rw_tryenter(krwlock_t *rwlp, krw_t rw)
25593f3d2b8Schs {
25693f3d2b8Schs 	int rv;
25793f3d2b8Schs 
25893f3d2b8Schs 	ASSERT(rwlp->initialized == B_TRUE);
25993f3d2b8Schs 	ASSERT(rwlp->rw_owner != (void *)-1UL);
26093f3d2b8Schs 	ASSERT(rwlp->rw_owner != curthread);
26193f3d2b8Schs 
26293f3d2b8Schs 	if (rw == RW_READER)
26393f3d2b8Schs 		rv = rw_tryrdlock(&rwlp->rw_lock);
26493f3d2b8Schs 	else
26593f3d2b8Schs 		rv = rw_trywrlock(&rwlp->rw_lock);
26693f3d2b8Schs 
26793f3d2b8Schs 	if (rv == 0) {
26893f3d2b8Schs 		ASSERT(rwlp->rw_owner == NULL);
26993f3d2b8Schs 		if (rw == RW_READER) {
27093f3d2b8Schs 			ASSERT(rwlp->rw_count >= 0);
27193f3d2b8Schs 			atomic_add_int(&rwlp->rw_count, 1);
27293f3d2b8Schs 		} else {
27393f3d2b8Schs 			ASSERT(rwlp->rw_count == 0);
27493f3d2b8Schs 			rwlp->rw_count = -1;
27593f3d2b8Schs 			rwlp->rw_owner = curthread;
27693f3d2b8Schs 		}
27793f3d2b8Schs 		return (1);
27893f3d2b8Schs 	}
27993f3d2b8Schs 
28093f3d2b8Schs 	return (0);
28193f3d2b8Schs }
28293f3d2b8Schs 
28393f3d2b8Schs /*ARGSUSED*/
28493f3d2b8Schs int
rw_tryupgrade(krwlock_t * rwlp)28593f3d2b8Schs rw_tryupgrade(krwlock_t *rwlp)
28693f3d2b8Schs {
28793f3d2b8Schs 	ASSERT(rwlp->initialized == B_TRUE);
28893f3d2b8Schs 	ASSERT(rwlp->rw_owner != (void *)-1UL);
28993f3d2b8Schs 
29093f3d2b8Schs 	return (0);
29193f3d2b8Schs }
29293f3d2b8Schs 
29393f3d2b8Schs int
rw_lock_held(krwlock_t * rwlp)29493f3d2b8Schs rw_lock_held(krwlock_t *rwlp)
29593f3d2b8Schs {
29693f3d2b8Schs 
29793f3d2b8Schs 	return (rwlp->rw_count != 0);
29893f3d2b8Schs }
29993f3d2b8Schs 
30093f3d2b8Schs /*
30193f3d2b8Schs  * =========================================================================
30293f3d2b8Schs  * condition variables
30393f3d2b8Schs  * =========================================================================
30493f3d2b8Schs  */
30593f3d2b8Schs /*ARGSUSED*/
30693f3d2b8Schs void
cv_init(kcondvar_t * cv,char * name,int type,void * arg)30793f3d2b8Schs cv_init(kcondvar_t *cv, char *name, int type, void *arg)
30893f3d2b8Schs {
30993f3d2b8Schs 	VERIFY(cond_init(cv, name, NULL) == 0);
31093f3d2b8Schs }
31193f3d2b8Schs 
31293f3d2b8Schs void
cv_destroy(kcondvar_t * cv)31393f3d2b8Schs cv_destroy(kcondvar_t *cv)
31493f3d2b8Schs {
31593f3d2b8Schs 	VERIFY(cond_destroy(cv) == 0);
31693f3d2b8Schs }
31793f3d2b8Schs 
31893f3d2b8Schs void
cv_wait(kcondvar_t * cv,kmutex_t * mp)31993f3d2b8Schs cv_wait(kcondvar_t *cv, kmutex_t *mp)
32093f3d2b8Schs {
32193f3d2b8Schs 	ASSERT(mutex_owner(mp) == curthread);
32293f3d2b8Schs 	mp->m_owner = NULL;
32393f3d2b8Schs 	int ret = cond_wait(cv, &mp->m_lock);
32493f3d2b8Schs 	VERIFY(ret == 0 || ret == EINTR);
32593f3d2b8Schs 	mp->m_owner = curthread;
32693f3d2b8Schs }
32793f3d2b8Schs 
32893f3d2b8Schs clock_t
cv_timedwait(kcondvar_t * cv,kmutex_t * mp,clock_t abstime)32993f3d2b8Schs cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
33093f3d2b8Schs {
33193f3d2b8Schs 	int error;
33293f3d2b8Schs 	struct timespec ts;
33393f3d2b8Schs 	struct timeval tv;
33493f3d2b8Schs 	clock_t delta;
33593f3d2b8Schs 
33693f3d2b8Schs 	abstime += ddi_get_lbolt();
33793f3d2b8Schs top:
33893f3d2b8Schs 	delta = abstime - ddi_get_lbolt();
33993f3d2b8Schs 	if (delta <= 0)
34093f3d2b8Schs 		return (-1);
34193f3d2b8Schs 
34293f3d2b8Schs 	if (gettimeofday(&tv, NULL) != 0)
34393f3d2b8Schs 		assert(!"gettimeofday() failed");
34493f3d2b8Schs 
34593f3d2b8Schs 	ts.tv_sec = tv.tv_sec + delta / hz;
34693f3d2b8Schs 	ts.tv_nsec = tv.tv_usec * 1000 + (delta % hz) * (NANOSEC / hz);
34793f3d2b8Schs 	ASSERT(ts.tv_nsec >= 0);
34893f3d2b8Schs 
34993f3d2b8Schs 	if (ts.tv_nsec >= NANOSEC) {
35093f3d2b8Schs 		ts.tv_sec++;
35193f3d2b8Schs 		ts.tv_nsec -= NANOSEC;
35293f3d2b8Schs 	}
35393f3d2b8Schs 
35493f3d2b8Schs 	ASSERT(mutex_owner(mp) == curthread);
35593f3d2b8Schs 	mp->m_owner = NULL;
35693f3d2b8Schs 	error = pthread_cond_timedwait(cv, &mp->m_lock, &ts);
35793f3d2b8Schs 	mp->m_owner = curthread;
35893f3d2b8Schs 
35993f3d2b8Schs 	if (error == EINTR)
36093f3d2b8Schs 		goto top;
36193f3d2b8Schs 
36293f3d2b8Schs 	if (error == ETIMEDOUT)
36393f3d2b8Schs 		return (-1);
36493f3d2b8Schs 
36593f3d2b8Schs 	ASSERT(error == 0);
36693f3d2b8Schs 
36793f3d2b8Schs 	return (1);
36893f3d2b8Schs }
36993f3d2b8Schs 
37093f3d2b8Schs /*ARGSUSED*/
37193f3d2b8Schs clock_t
cv_timedwait_hires(kcondvar_t * cv,kmutex_t * mp,hrtime_t tim,hrtime_t res,int flag)37293f3d2b8Schs cv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res,
37393f3d2b8Schs     int flag)
37493f3d2b8Schs {
37593f3d2b8Schs 	int error;
37693f3d2b8Schs 	timestruc_t ts;
37793f3d2b8Schs 	hrtime_t delta;
37893f3d2b8Schs 
37993f3d2b8Schs 	ASSERT(flag == 0 || flag == CALLOUT_FLAG_ABSOLUTE);
38093f3d2b8Schs 
38193f3d2b8Schs top:
38293f3d2b8Schs 	delta = tim;
38393f3d2b8Schs 	if (flag & CALLOUT_FLAG_ABSOLUTE)
38493f3d2b8Schs 		delta -= gethrtime();
38593f3d2b8Schs 
38693f3d2b8Schs 	if (delta <= 0)
38793f3d2b8Schs 		return (-1);
38893f3d2b8Schs 
38993f3d2b8Schs 	ts.tv_sec = delta / NANOSEC;
39093f3d2b8Schs 	ts.tv_nsec = delta % NANOSEC;
39193f3d2b8Schs 
39293f3d2b8Schs 	ASSERT(mutex_owner(mp) == curthread);
39393f3d2b8Schs 	mp->m_owner = NULL;
39493f3d2b8Schs 	error = pthread_cond_timedwait(cv, &mp->m_lock, &ts);
39593f3d2b8Schs 	mp->m_owner = curthread;
39693f3d2b8Schs 
39793f3d2b8Schs 	if (error == ETIMEDOUT)
39893f3d2b8Schs 		return (-1);
39993f3d2b8Schs 
40093f3d2b8Schs 	if (error == EINTR)
40193f3d2b8Schs 		goto top;
40293f3d2b8Schs 
40393f3d2b8Schs 	ASSERT(error == 0);
40493f3d2b8Schs 
40593f3d2b8Schs 	return (1);
40693f3d2b8Schs }
40793f3d2b8Schs 
40893f3d2b8Schs void
cv_signal(kcondvar_t * cv)40993f3d2b8Schs cv_signal(kcondvar_t *cv)
41093f3d2b8Schs {
41193f3d2b8Schs 	VERIFY(cond_signal(cv) == 0);
41293f3d2b8Schs }
41393f3d2b8Schs 
41493f3d2b8Schs void
cv_broadcast(kcondvar_t * cv)41593f3d2b8Schs cv_broadcast(kcondvar_t *cv)
41693f3d2b8Schs {
41793f3d2b8Schs 	VERIFY(cond_broadcast(cv) == 0);
41893f3d2b8Schs }
41993f3d2b8Schs 
42093f3d2b8Schs /*
42193f3d2b8Schs  * =========================================================================
42293f3d2b8Schs  * vnode operations
42393f3d2b8Schs  * =========================================================================
42493f3d2b8Schs  */
42593f3d2b8Schs /*
42693f3d2b8Schs  * Note: for the xxxat() versions of these functions, we assume that the
42793f3d2b8Schs  * starting vp is always rootdir (which is true for spa_directory.c, the only
42893f3d2b8Schs  * ZFS consumer of these interfaces).  We assert this is true, and then emulate
42993f3d2b8Schs  * them by adding '/' in front of the path.
43093f3d2b8Schs  */
43193f3d2b8Schs 
43293f3d2b8Schs /*ARGSUSED*/
43393f3d2b8Schs int
vn_open(char * path,int x1,int flags,int mode,vnode_t ** vpp,int x2,int x3)43493f3d2b8Schs vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
43593f3d2b8Schs {
43693f3d2b8Schs 	int fd;
43793f3d2b8Schs 	int dump_fd;
43893f3d2b8Schs 	vnode_t *vp;
43993f3d2b8Schs 	int old_umask;
44093f3d2b8Schs 	char realpath[MAXPATHLEN];
44193f3d2b8Schs 	struct stat64 st;
44293f3d2b8Schs 
44393f3d2b8Schs 	/*
44493f3d2b8Schs 	 * If we're accessing a real disk from userland, we need to use
44593f3d2b8Schs 	 * the character interface to avoid caching.  This is particularly
44693f3d2b8Schs 	 * important if we're trying to look at a real in-kernel storage
44793f3d2b8Schs 	 * pool from userland, e.g. via zdb, because otherwise we won't
44893f3d2b8Schs 	 * see the changes occurring under the segmap cache.
44993f3d2b8Schs 	 * On the other hand, the stupid character device returns zero
45093f3d2b8Schs 	 * for its size.  So -- gag -- we open the block device to get
45193f3d2b8Schs 	 * its size, and remember it for subsequent VOP_GETATTR().
45293f3d2b8Schs 	 */
45393f3d2b8Schs 	if (strncmp(path, "/dev/", 5) == 0) {
45493f3d2b8Schs 		char *dsk;
455*48290834Ssimonb #ifdef __NetBSD__
456*48290834Ssimonb 		/*
457*48290834Ssimonb 		 * For NetBSD, we've been passed in a block device name
458*48290834Ssimonb 		 * but need to convert to the character device name.
459*48290834Ssimonb 		 * XXX a bit ugly...
460*48290834Ssimonb 		 */
461*48290834Ssimonb 		char rawpath[MAXPATHLEN];
462*48290834Ssimonb 
463*48290834Ssimonb 		snprintf(rawpath, sizeof(rawpath), "/dev/r%s", path + 5);
464*48290834Ssimonb 		path = rawpath;	/* gets strdup()'d below */
465*48290834Ssimonb #endif	/* __NetBSD__ */
46693f3d2b8Schs 		fd = open64(path, O_RDONLY);
46793f3d2b8Schs 		if (fd == -1)
46893f3d2b8Schs 			return (errno);
46993f3d2b8Schs 		if (fstat64(fd, &st) == -1) {
47093f3d2b8Schs 			close(fd);
47193f3d2b8Schs 			return (errno);
47293f3d2b8Schs 		}
473*48290834Ssimonb #ifdef __NetBSD__
474*48290834Ssimonb 		if (st.st_size == 0) {
475*48290834Ssimonb 			off_t dsize;
476*48290834Ssimonb 
477*48290834Ssimonb 			if (ioctl(fd, DIOCGMEDIASIZE, &dsize) == 0)
478*48290834Ssimonb 				st.st_size = dsize;
479*48290834Ssimonb 		}
480*48290834Ssimonb #endif	/* __NetBSD__ */
48193f3d2b8Schs 		close(fd);
48293f3d2b8Schs 		(void) sprintf(realpath, "%s", path);
48393f3d2b8Schs 		dsk = strstr(path, "/dsk/");
48493f3d2b8Schs 		if (dsk != NULL)
48593f3d2b8Schs 			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
48693f3d2b8Schs 			    dsk + 1);
48793f3d2b8Schs 	} else {
48893f3d2b8Schs 		(void) sprintf(realpath, "%s", path);
48993f3d2b8Schs 		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
49093f3d2b8Schs 			return (errno);
49193f3d2b8Schs 	}
49293f3d2b8Schs 
49393f3d2b8Schs 	if (flags & FCREAT)
49493f3d2b8Schs 		old_umask = umask(0);
49593f3d2b8Schs 
49693f3d2b8Schs 	/*
49793f3d2b8Schs 	 * The construct 'flags - FREAD' conveniently maps combinations of
49893f3d2b8Schs 	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
49993f3d2b8Schs 	 */
50093f3d2b8Schs 	fd = open64(realpath, flags - FREAD, mode);
50193f3d2b8Schs 
50293f3d2b8Schs 	if (flags & FCREAT)
50393f3d2b8Schs 		(void) umask(old_umask);
50493f3d2b8Schs 
50593f3d2b8Schs 	if (vn_dumpdir != NULL) {
50693f3d2b8Schs 		char dumppath[MAXPATHLEN];
50793f3d2b8Schs 		(void) snprintf(dumppath, sizeof (dumppath),
50893f3d2b8Schs 		    "%s/%s", vn_dumpdir, basename(realpath));
50993f3d2b8Schs 		dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666);
51093f3d2b8Schs 		if (dump_fd == -1)
51193f3d2b8Schs 			return (errno);
51293f3d2b8Schs 	} else {
51393f3d2b8Schs 		dump_fd = -1;
51493f3d2b8Schs 	}
51593f3d2b8Schs 
51693f3d2b8Schs 	if (fd == -1)
51793f3d2b8Schs 		return (errno);
51893f3d2b8Schs 
51993f3d2b8Schs 	if (fstat64(fd, &st) == -1) {
52093f3d2b8Schs 		close(fd);
52193f3d2b8Schs 		return (errno);
52293f3d2b8Schs 	}
52393f3d2b8Schs 
52493f3d2b8Schs 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
52593f3d2b8Schs 
52693f3d2b8Schs 	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
52793f3d2b8Schs 
52893f3d2b8Schs 	vp->v_fd = fd;
52993f3d2b8Schs 	vp->v_size = st.st_size;
53093f3d2b8Schs 	vp->v_path = spa_strdup(path);
53193f3d2b8Schs 	vp->v_dump_fd = dump_fd;
53293f3d2b8Schs 
53393f3d2b8Schs 	return (0);
53493f3d2b8Schs }
53593f3d2b8Schs 
53693f3d2b8Schs /*ARGSUSED*/
53793f3d2b8Schs int
vn_openat(char * path,int x1,int flags,int mode,vnode_t ** vpp,int x2,int x3,vnode_t * startvp,int fd)53893f3d2b8Schs vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
53993f3d2b8Schs     int x3, vnode_t *startvp, int fd)
54093f3d2b8Schs {
54193f3d2b8Schs 	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
54293f3d2b8Schs 	int ret;
54393f3d2b8Schs 
54493f3d2b8Schs 	ASSERT(startvp == rootdir);
54593f3d2b8Schs 	(void) sprintf(realpath, "/%s", path);
54693f3d2b8Schs 
54793f3d2b8Schs 	/* fd ignored for now, need if want to simulate nbmand support */
54893f3d2b8Schs 	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
54993f3d2b8Schs 
55093f3d2b8Schs 	umem_free(realpath, strlen(path) + 2);
55193f3d2b8Schs 
55293f3d2b8Schs 	return (ret);
55393f3d2b8Schs }
55493f3d2b8Schs 
55593f3d2b8Schs /*ARGSUSED*/
55693f3d2b8Schs int
vn_rdwr(int uio,vnode_t * vp,void * addr,ssize_t len,offset_t offset,int x1,int x2,rlim64_t x3,void * x4,ssize_t * residp)55793f3d2b8Schs vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
55893f3d2b8Schs     int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
55993f3d2b8Schs {
56093f3d2b8Schs 	ssize_t iolen, split;
56193f3d2b8Schs 
56293f3d2b8Schs 	if (uio == UIO_READ) {
56393f3d2b8Schs 		iolen = pread64(vp->v_fd, addr, len, offset);
56493f3d2b8Schs 		if (vp->v_dump_fd != -1) {
56593f3d2b8Schs 			int status =
56693f3d2b8Schs 			    pwrite64(vp->v_dump_fd, addr, iolen, offset);
56793f3d2b8Schs 			ASSERT(status != -1);
56893f3d2b8Schs 		}
56993f3d2b8Schs 	} else {
57093f3d2b8Schs 		/*
57193f3d2b8Schs 		 * To simulate partial disk writes, we split writes into two
57293f3d2b8Schs 		 * system calls so that the process can be killed in between.
57393f3d2b8Schs 		 */
57493f3d2b8Schs 		int sectors = len >> SPA_MINBLOCKSHIFT;
57593f3d2b8Schs 		split = (sectors > 0 ? rand() % sectors : 0) <<
57693f3d2b8Schs 		    SPA_MINBLOCKSHIFT;
57793f3d2b8Schs 		iolen = pwrite64(vp->v_fd, addr, split, offset);
57893f3d2b8Schs 		iolen += pwrite64(vp->v_fd, (char *)addr + split,
57993f3d2b8Schs 		    len - split, offset + split);
58093f3d2b8Schs 	}
58193f3d2b8Schs 
58293f3d2b8Schs 	if (iolen == -1)
58393f3d2b8Schs 		return (errno);
58493f3d2b8Schs 	if (residp)
58593f3d2b8Schs 		*residp = len - iolen;
58693f3d2b8Schs 	else if (iolen != len)
58793f3d2b8Schs 		return (EIO);
58893f3d2b8Schs 	return (0);
58993f3d2b8Schs }
59093f3d2b8Schs 
59193f3d2b8Schs void
vn_close(vnode_t * vp,int openflag,cred_t * cr,kthread_t * td)59293f3d2b8Schs vn_close(vnode_t *vp, int openflag, cred_t *cr, kthread_t *td)
59393f3d2b8Schs {
59493f3d2b8Schs 	close(vp->v_fd);
59593f3d2b8Schs 	if (vp->v_dump_fd != -1)
59693f3d2b8Schs 		close(vp->v_dump_fd);
59793f3d2b8Schs 	spa_strfree(vp->v_path);
59893f3d2b8Schs 	umem_free(vp, sizeof (vnode_t));
59993f3d2b8Schs }
60093f3d2b8Schs 
60193f3d2b8Schs /*
60293f3d2b8Schs  * At a minimum we need to update the size since vdev_reopen()
60393f3d2b8Schs  * will no longer call vn_openat().
60493f3d2b8Schs  */
60593f3d2b8Schs int
fop_getattr(vnode_t * vp,vattr_t * vap)60693f3d2b8Schs fop_getattr(vnode_t *vp, vattr_t *vap)
60793f3d2b8Schs {
60893f3d2b8Schs 	struct stat64 st;
60993f3d2b8Schs 
61093f3d2b8Schs 	if (fstat64(vp->v_fd, &st) == -1) {
61193f3d2b8Schs 		close(vp->v_fd);
61293f3d2b8Schs 		return (errno);
61393f3d2b8Schs 	}
614*48290834Ssimonb #ifdef __NetBSD__
615*48290834Ssimonb 	if (st.st_size == 0) {
616*48290834Ssimonb 		off_t dsize;
617*48290834Ssimonb 
618*48290834Ssimonb 		if (ioctl(vp->v_fd, DIOCGMEDIASIZE, &dsize) == 0)
619*48290834Ssimonb 			st.st_size = dsize;
620*48290834Ssimonb 	}
621*48290834Ssimonb #endif	/* __NetBSD__ */
62293f3d2b8Schs 
62393f3d2b8Schs 	vap->va_size = st.st_size;
62493f3d2b8Schs 	return (0);
62593f3d2b8Schs }
62693f3d2b8Schs 
62793f3d2b8Schs #ifdef ZFS_DEBUG
62893f3d2b8Schs 
62993f3d2b8Schs /*
63093f3d2b8Schs  * =========================================================================
63193f3d2b8Schs  * Figure out which debugging statements to print
63293f3d2b8Schs  * =========================================================================
63393f3d2b8Schs  */
63493f3d2b8Schs 
63593f3d2b8Schs static char *dprintf_string;
63693f3d2b8Schs static int dprintf_print_all;
63793f3d2b8Schs 
63893f3d2b8Schs int
dprintf_find_string(const char * string)63993f3d2b8Schs dprintf_find_string(const char *string)
64093f3d2b8Schs {
64193f3d2b8Schs 	char *tmp_str = dprintf_string;
64293f3d2b8Schs 	int len = strlen(string);
64393f3d2b8Schs 
64493f3d2b8Schs 	/*
64593f3d2b8Schs 	 * Find out if this is a string we want to print.
64693f3d2b8Schs 	 * String format: file1.c,function_name1,file2.c,file3.c
64793f3d2b8Schs 	 */
64893f3d2b8Schs 
64993f3d2b8Schs 	while (tmp_str != NULL) {
65093f3d2b8Schs 		if (strncmp(tmp_str, string, len) == 0 &&
65193f3d2b8Schs 		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
65293f3d2b8Schs 			return (1);
65393f3d2b8Schs 		tmp_str = strchr(tmp_str, ',');
65493f3d2b8Schs 		if (tmp_str != NULL)
65593f3d2b8Schs 			tmp_str++; /* Get rid of , */
65693f3d2b8Schs 	}
65793f3d2b8Schs 	return (0);
65893f3d2b8Schs }
65993f3d2b8Schs 
66093f3d2b8Schs void
dprintf_setup(int * argc,char ** argv)66193f3d2b8Schs dprintf_setup(int *argc, char **argv)
66293f3d2b8Schs {
66393f3d2b8Schs 	int i, j;
66493f3d2b8Schs 
66593f3d2b8Schs 	/*
66693f3d2b8Schs 	 * Debugging can be specified two ways: by setting the
66793f3d2b8Schs 	 * environment variable ZFS_DEBUG, or by including a
66893f3d2b8Schs 	 * "debug=..."  argument on the command line.  The command
66993f3d2b8Schs 	 * line setting overrides the environment variable.
67093f3d2b8Schs 	 */
67193f3d2b8Schs 
67293f3d2b8Schs 	for (i = 1; i < *argc; i++) {
67393f3d2b8Schs 		int len = strlen("debug=");
67493f3d2b8Schs 		/* First look for a command line argument */
67593f3d2b8Schs 		if (strncmp("debug=", argv[i], len) == 0) {
67693f3d2b8Schs 			dprintf_string = argv[i] + len;
67793f3d2b8Schs 			/* Remove from args */
67893f3d2b8Schs 			for (j = i; j < *argc; j++)
67993f3d2b8Schs 				argv[j] = argv[j+1];
68093f3d2b8Schs 			argv[j] = NULL;
68193f3d2b8Schs 			(*argc)--;
68293f3d2b8Schs 		}
68393f3d2b8Schs 	}
68493f3d2b8Schs 
68593f3d2b8Schs 	if (dprintf_string == NULL) {
68693f3d2b8Schs 		/* Look for ZFS_DEBUG environment variable */
68793f3d2b8Schs 		dprintf_string = getenv("ZFS_DEBUG");
68893f3d2b8Schs 	}
68993f3d2b8Schs 
69093f3d2b8Schs 	/*
69193f3d2b8Schs 	 * Are we just turning on all debugging?
69293f3d2b8Schs 	 */
69393f3d2b8Schs 	if (dprintf_find_string("on"))
69493f3d2b8Schs 		dprintf_print_all = 1;
69593f3d2b8Schs 
69693f3d2b8Schs 	if (dprintf_string != NULL)
69793f3d2b8Schs 		zfs_flags |= ZFS_DEBUG_DPRINTF;
69893f3d2b8Schs }
69993f3d2b8Schs 
70093f3d2b8Schs int
sysctl_handle_64(SYSCTL_HANDLER_ARGS)70193f3d2b8Schs sysctl_handle_64(SYSCTL_HANDLER_ARGS)
70293f3d2b8Schs {
70393f3d2b8Schs 	return (0);
70493f3d2b8Schs }
70593f3d2b8Schs 
70693f3d2b8Schs /*
70793f3d2b8Schs  * =========================================================================
70893f3d2b8Schs  * debug printfs
70993f3d2b8Schs  * =========================================================================
71093f3d2b8Schs  */
71193f3d2b8Schs void
__dprintf(const char * file,const char * func,int line,const char * fmt,...)71293f3d2b8Schs __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
71393f3d2b8Schs {
71493f3d2b8Schs 	const char *newfile;
71593f3d2b8Schs 	va_list adx;
71693f3d2b8Schs 
71793f3d2b8Schs 	/*
71893f3d2b8Schs 	 * Get rid of annoying "../common/" prefix to filename.
71993f3d2b8Schs 	 */
72093f3d2b8Schs 	newfile = strrchr(file, '/');
72193f3d2b8Schs 	if (newfile != NULL) {
72293f3d2b8Schs 		newfile = newfile + 1; /* Get rid of leading / */
72393f3d2b8Schs 	} else {
72493f3d2b8Schs 		newfile = file;
72593f3d2b8Schs 	}
72693f3d2b8Schs 
72793f3d2b8Schs 	if (dprintf_print_all ||
72893f3d2b8Schs 	    dprintf_find_string(newfile) ||
72993f3d2b8Schs 	    dprintf_find_string(func)) {
73093f3d2b8Schs 		/* Print out just the function name if requested */
73193f3d2b8Schs 		flockfile(stdout);
73293f3d2b8Schs 		if (dprintf_find_string("pid"))
73393f3d2b8Schs 			(void) printf("%d ", getpid());
73493f3d2b8Schs 		if (dprintf_find_string("tid"))
73593f3d2b8Schs 			(void) printf("%lu ", thr_self());
73693f3d2b8Schs #if 0
73793f3d2b8Schs 		if (dprintf_find_string("cpu"))
73893f3d2b8Schs 			(void) printf("%u ", getcpuid());
73993f3d2b8Schs #endif
74093f3d2b8Schs 		if (dprintf_find_string("time"))
74193f3d2b8Schs 			(void) printf("%llu ", gethrtime());
74293f3d2b8Schs 		if (dprintf_find_string("long"))
74393f3d2b8Schs 			(void) printf("%s, line %d: ", newfile, line);
74493f3d2b8Schs 		(void) printf("%s: ", func);
74593f3d2b8Schs 		va_start(adx, fmt);
74693f3d2b8Schs 		(void) vprintf(fmt, adx);
74793f3d2b8Schs 		va_end(adx);
74893f3d2b8Schs 		funlockfile(stdout);
74993f3d2b8Schs 	}
75093f3d2b8Schs }
75193f3d2b8Schs 
75293f3d2b8Schs #endif /* ZFS_DEBUG */
75393f3d2b8Schs 
75493f3d2b8Schs /*
75593f3d2b8Schs  * =========================================================================
75693f3d2b8Schs  * cmn_err() and panic()
75793f3d2b8Schs  * =========================================================================
75893f3d2b8Schs  */
75993f3d2b8Schs static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
76093f3d2b8Schs static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
76193f3d2b8Schs 
76293f3d2b8Schs void
vpanic(const char * fmt,va_list adx)76393f3d2b8Schs vpanic(const char *fmt, va_list adx)
76493f3d2b8Schs {
76593f3d2b8Schs 	(void) fprintf(stderr, "error: ");
76693f3d2b8Schs 	(void) vfprintf(stderr, fmt, adx);
76793f3d2b8Schs 	(void) fprintf(stderr, "\n");
76893f3d2b8Schs 
76993f3d2b8Schs 	abort();	/* think of it as a "user-level crash dump" */
77093f3d2b8Schs }
77193f3d2b8Schs 
77293f3d2b8Schs void
panic(const char * fmt,...)77393f3d2b8Schs panic(const char *fmt, ...)
77493f3d2b8Schs {
77593f3d2b8Schs 	va_list adx;
77693f3d2b8Schs 
77793f3d2b8Schs 	va_start(adx, fmt);
77893f3d2b8Schs 	vpanic(fmt, adx);
77993f3d2b8Schs 	va_end(adx);
78093f3d2b8Schs }
78193f3d2b8Schs 
78293f3d2b8Schs void
vcmn_err(int ce,const char * fmt,va_list adx)78393f3d2b8Schs vcmn_err(int ce, const char *fmt, va_list adx)
78493f3d2b8Schs {
78593f3d2b8Schs 	if (ce == CE_PANIC)
78693f3d2b8Schs 		vpanic(fmt, adx);
78793f3d2b8Schs 	if (ce != CE_NOTE) {	/* suppress noise in userland stress testing */
78893f3d2b8Schs 		(void) fprintf(stderr, "%s", ce_prefix[ce]);
78993f3d2b8Schs 		(void) vfprintf(stderr, fmt, adx);
79093f3d2b8Schs 		(void) fprintf(stderr, "%s", ce_suffix[ce]);
79193f3d2b8Schs 	}
79293f3d2b8Schs }
79393f3d2b8Schs 
79493f3d2b8Schs /*PRINTFLIKE2*/
79593f3d2b8Schs void
cmn_err(int ce,const char * fmt,...)79693f3d2b8Schs cmn_err(int ce, const char *fmt, ...)
79793f3d2b8Schs {
79893f3d2b8Schs 	va_list adx;
79993f3d2b8Schs 
80093f3d2b8Schs 	va_start(adx, fmt);
80193f3d2b8Schs 	vcmn_err(ce, fmt, adx);
80293f3d2b8Schs 	va_end(adx);
80393f3d2b8Schs }
80493f3d2b8Schs 
80593f3d2b8Schs /*
80693f3d2b8Schs  * =========================================================================
80793f3d2b8Schs  * kobj interfaces
80893f3d2b8Schs  * =========================================================================
80993f3d2b8Schs  */
81093f3d2b8Schs struct _buf *
kobj_open_file(char * name)81193f3d2b8Schs kobj_open_file(char *name)
81293f3d2b8Schs {
81393f3d2b8Schs 	struct _buf *file;
81493f3d2b8Schs 	vnode_t *vp;
81593f3d2b8Schs 
81693f3d2b8Schs 	/* set vp as the _fd field of the file */
81793f3d2b8Schs 	if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir,
81893f3d2b8Schs 	    -1) != 0)
81993f3d2b8Schs 		return ((void *)-1UL);
82093f3d2b8Schs 
82193f3d2b8Schs 	file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
82293f3d2b8Schs 	file->_fd = (intptr_t)vp;
82393f3d2b8Schs 	return (file);
82493f3d2b8Schs }
82593f3d2b8Schs 
82693f3d2b8Schs int
kobj_read_file(struct _buf * file,char * buf,unsigned size,unsigned off)82793f3d2b8Schs kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
82893f3d2b8Schs {
82993f3d2b8Schs 	ssize_t resid;
83093f3d2b8Schs 
83193f3d2b8Schs 	vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
83293f3d2b8Schs 	    UIO_SYSSPACE, 0, 0, 0, &resid);
83393f3d2b8Schs 
83493f3d2b8Schs 	return (size - resid);
83593f3d2b8Schs }
83693f3d2b8Schs 
83793f3d2b8Schs void
kobj_close_file(struct _buf * file)83893f3d2b8Schs kobj_close_file(struct _buf *file)
83993f3d2b8Schs {
84093f3d2b8Schs 	vn_close((vnode_t *)file->_fd, 0, NULL, NULL);
84193f3d2b8Schs 	umem_free(file, sizeof (struct _buf));
84293f3d2b8Schs }
84393f3d2b8Schs 
84493f3d2b8Schs int
kobj_get_filesize(struct _buf * file,uint64_t * size)84593f3d2b8Schs kobj_get_filesize(struct _buf *file, uint64_t *size)
84693f3d2b8Schs {
84793f3d2b8Schs 	struct stat64 st;
84893f3d2b8Schs 	vnode_t *vp = (vnode_t *)file->_fd;
84993f3d2b8Schs 
85093f3d2b8Schs 	if (fstat64(vp->v_fd, &st) == -1) {
85193f3d2b8Schs 		vn_close(vp, 0, NULL, NULL);
85293f3d2b8Schs 		return (errno);
85393f3d2b8Schs 	}
85493f3d2b8Schs 	*size = st.st_size;
85593f3d2b8Schs 	return (0);
85693f3d2b8Schs }
85793f3d2b8Schs 
85893f3d2b8Schs /*
85993f3d2b8Schs  * =========================================================================
86093f3d2b8Schs  * misc routines
86193f3d2b8Schs  * =========================================================================
86293f3d2b8Schs  */
86393f3d2b8Schs 
86493f3d2b8Schs void
delay(clock_t ticks)86593f3d2b8Schs delay(clock_t ticks)
86693f3d2b8Schs {
86793f3d2b8Schs 	poll(0, 0, ticks * (1000 / hz));
86893f3d2b8Schs }
86993f3d2b8Schs 
87093f3d2b8Schs #if 0
87193f3d2b8Schs /*
87293f3d2b8Schs  * Find highest one bit set.
87393f3d2b8Schs  *	Returns bit number + 1 of highest bit that is set, otherwise returns 0.
87493f3d2b8Schs  */
87593f3d2b8Schs int
87693f3d2b8Schs highbit64(uint64_t i)
87793f3d2b8Schs {
87893f3d2b8Schs 	int h = 1;
87993f3d2b8Schs 
88093f3d2b8Schs 	if (i == 0)
88193f3d2b8Schs 		return (0);
88293f3d2b8Schs 	if (i & 0xffffffff00000000ULL) {
88393f3d2b8Schs 		h += 32; i >>= 32;
88493f3d2b8Schs 	}
88593f3d2b8Schs 	if (i & 0xffff0000) {
88693f3d2b8Schs 		h += 16; i >>= 16;
88793f3d2b8Schs 	}
88893f3d2b8Schs 	if (i & 0xff00) {
88993f3d2b8Schs 		h += 8; i >>= 8;
89093f3d2b8Schs 	}
89193f3d2b8Schs 	if (i & 0xf0) {
89293f3d2b8Schs 		h += 4; i >>= 4;
89393f3d2b8Schs 	}
89493f3d2b8Schs 	if (i & 0xc) {
89593f3d2b8Schs 		h += 2; i >>= 2;
89693f3d2b8Schs 	}
89793f3d2b8Schs 	if (i & 0x2) {
89893f3d2b8Schs 		h += 1;
89993f3d2b8Schs 	}
90093f3d2b8Schs 	return (h);
90193f3d2b8Schs }
90293f3d2b8Schs #endif
90393f3d2b8Schs 
90493f3d2b8Schs static int random_fd = -1, urandom_fd = -1;
90593f3d2b8Schs 
90693f3d2b8Schs static int
random_get_bytes_common(uint8_t * ptr,size_t len,int fd)90793f3d2b8Schs random_get_bytes_common(uint8_t *ptr, size_t len, int fd)
90893f3d2b8Schs {
90993f3d2b8Schs 	size_t resid = len;
91093f3d2b8Schs 	ssize_t bytes;
91193f3d2b8Schs 
91293f3d2b8Schs 	ASSERT(fd != -1);
91393f3d2b8Schs 
91493f3d2b8Schs 	while (resid != 0) {
91593f3d2b8Schs 		bytes = read(fd, ptr, resid);
91693f3d2b8Schs 		ASSERT3S(bytes, >=, 0);
91793f3d2b8Schs 		ptr += bytes;
91893f3d2b8Schs 		resid -= bytes;
91993f3d2b8Schs 	}
92093f3d2b8Schs 
92193f3d2b8Schs 	return (0);
92293f3d2b8Schs }
92393f3d2b8Schs 
92493f3d2b8Schs int
random_get_bytes(uint8_t * ptr,size_t len)92593f3d2b8Schs random_get_bytes(uint8_t *ptr, size_t len)
92693f3d2b8Schs {
92793f3d2b8Schs 	return (random_get_bytes_common(ptr, len, random_fd));
92893f3d2b8Schs }
92993f3d2b8Schs 
93093f3d2b8Schs int
random_get_pseudo_bytes(uint8_t * ptr,size_t len)93193f3d2b8Schs random_get_pseudo_bytes(uint8_t *ptr, size_t len)
93293f3d2b8Schs {
93393f3d2b8Schs 	return (random_get_bytes_common(ptr, len, urandom_fd));
93493f3d2b8Schs }
93593f3d2b8Schs 
93693f3d2b8Schs int
ddi_strtoul(const char * hw_serial,char ** nptr,int base,unsigned long * result)93793f3d2b8Schs ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result)
93893f3d2b8Schs {
93993f3d2b8Schs 	char *end;
94093f3d2b8Schs 
94193f3d2b8Schs 	*result = strtoul(hw_serial, &end, base);
94293f3d2b8Schs 	if (*result == 0)
94393f3d2b8Schs 		return (errno);
94493f3d2b8Schs 	return (0);
94593f3d2b8Schs }
94693f3d2b8Schs 
94793f3d2b8Schs int
ddi_strtoull(const char * str,char ** nptr,int base,u_longlong_t * result)94893f3d2b8Schs ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result)
94993f3d2b8Schs {
95093f3d2b8Schs 	char *end;
95193f3d2b8Schs 
95293f3d2b8Schs 	*result = strtoull(str, &end, base);
95393f3d2b8Schs 	if (*result == 0)
95493f3d2b8Schs 		return (errno);
95593f3d2b8Schs 	return (0);
95693f3d2b8Schs }
95793f3d2b8Schs 
958eada09acSchs #ifndef __FreeBSD__
95993f3d2b8Schs /* ARGSUSED */
96093f3d2b8Schs cyclic_id_t
cyclic_add(cyc_handler_t * hdlr,cyc_time_t * when)96193f3d2b8Schs cyclic_add(cyc_handler_t *hdlr, cyc_time_t *when)
96293f3d2b8Schs {
96393f3d2b8Schs 	return (1);
96493f3d2b8Schs }
96593f3d2b8Schs 
96693f3d2b8Schs /* ARGSUSED */
96793f3d2b8Schs void
cyclic_remove(cyclic_id_t id)96893f3d2b8Schs cyclic_remove(cyclic_id_t id)
96993f3d2b8Schs {
97093f3d2b8Schs }
97193f3d2b8Schs 
97293f3d2b8Schs /* ARGSUSED */
97393f3d2b8Schs int
cyclic_reprogram(cyclic_id_t id,hrtime_t expiration)97493f3d2b8Schs cyclic_reprogram(cyclic_id_t id, hrtime_t expiration)
97593f3d2b8Schs {
97693f3d2b8Schs 	return (1);
97793f3d2b8Schs }
97893f3d2b8Schs #endif
97993f3d2b8Schs 
98093f3d2b8Schs /*
98193f3d2b8Schs  * =========================================================================
98293f3d2b8Schs  * kernel emulation setup & teardown
98393f3d2b8Schs  * =========================================================================
98493f3d2b8Schs  */
98593f3d2b8Schs static int
umem_out_of_memory(void)98693f3d2b8Schs umem_out_of_memory(void)
98793f3d2b8Schs {
98893f3d2b8Schs 	char errmsg[] = "out of memory -- generating core dump\n";
98993f3d2b8Schs 
99093f3d2b8Schs 	write(fileno(stderr), errmsg, sizeof (errmsg));
99193f3d2b8Schs 	abort();
99293f3d2b8Schs 	return (0);
99393f3d2b8Schs }
99493f3d2b8Schs 
99593f3d2b8Schs void
kernel_init(int mode)99693f3d2b8Schs kernel_init(int mode)
99793f3d2b8Schs {
99893f3d2b8Schs 	extern uint_t rrw_tsd_key;
99993f3d2b8Schs 
100093f3d2b8Schs 	umem_nofail_callback(umem_out_of_memory);
100193f3d2b8Schs 
100293f3d2b8Schs 	physmem = sysconf(_SC_PHYS_PAGES);
100393f3d2b8Schs 
100493f3d2b8Schs 	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
100593f3d2b8Schs 	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
100693f3d2b8Schs 
100793f3d2b8Schs 	(void) snprintf(hw_serial, sizeof (hw_serial), "%lu",
100893f3d2b8Schs 	    (mode & FWRITE) ? (unsigned long)gethostid() : 0);
100993f3d2b8Schs 
101093f3d2b8Schs 	VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1);
101193f3d2b8Schs 	VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1);
101293f3d2b8Schs 
101393f3d2b8Schs 	system_taskq_init();
101493f3d2b8Schs 
101593f3d2b8Schs #ifdef illumos
101693f3d2b8Schs 	mutex_init(&cpu_lock, NULL, MUTEX_DEFAULT, NULL);
101793f3d2b8Schs #endif
101893f3d2b8Schs 
101993f3d2b8Schs 	spa_init(mode);
102093f3d2b8Schs 
102193f3d2b8Schs 	tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
102293f3d2b8Schs }
102393f3d2b8Schs 
102493f3d2b8Schs void
kernel_fini(void)102593f3d2b8Schs kernel_fini(void)
102693f3d2b8Schs {
102793f3d2b8Schs 	spa_fini();
102893f3d2b8Schs 
102993f3d2b8Schs 	system_taskq_fini();
103093f3d2b8Schs 
103193f3d2b8Schs 	close(random_fd);
103293f3d2b8Schs 	close(urandom_fd);
103393f3d2b8Schs 
103493f3d2b8Schs 	random_fd = -1;
103593f3d2b8Schs 	urandom_fd = -1;
103693f3d2b8Schs }
103793f3d2b8Schs 
103893f3d2b8Schs int
z_uncompress(void * dst,size_t * dstlen,const void * src,size_t srclen)103993f3d2b8Schs z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen)
104093f3d2b8Schs {
104193f3d2b8Schs 	int ret;
104293f3d2b8Schs 	uLongf len = *dstlen;
104393f3d2b8Schs 
104493f3d2b8Schs 	if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK)
104593f3d2b8Schs 		*dstlen = (size_t)len;
104693f3d2b8Schs 
104793f3d2b8Schs 	return (ret);
104893f3d2b8Schs }
104993f3d2b8Schs 
105093f3d2b8Schs int
z_compress_level(void * dst,size_t * dstlen,const void * src,size_t srclen,int level)105193f3d2b8Schs z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen,
105293f3d2b8Schs     int level)
105393f3d2b8Schs {
105493f3d2b8Schs 	int ret;
105593f3d2b8Schs 	uLongf len = *dstlen;
105693f3d2b8Schs 
105793f3d2b8Schs 	if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK)
105893f3d2b8Schs 		*dstlen = (size_t)len;
105993f3d2b8Schs 
106093f3d2b8Schs 	return (ret);
106193f3d2b8Schs }
106293f3d2b8Schs 
106393f3d2b8Schs uid_t
crgetuid(cred_t * cr)106493f3d2b8Schs crgetuid(cred_t *cr)
106593f3d2b8Schs {
106693f3d2b8Schs 	return (0);
106793f3d2b8Schs }
106893f3d2b8Schs 
106993f3d2b8Schs uid_t
crgetruid(cred_t * cr)107093f3d2b8Schs crgetruid(cred_t *cr)
107193f3d2b8Schs {
107293f3d2b8Schs 	return (0);
107393f3d2b8Schs }
107493f3d2b8Schs 
107593f3d2b8Schs gid_t
crgetgid(cred_t * cr)107693f3d2b8Schs crgetgid(cred_t *cr)
107793f3d2b8Schs {
107893f3d2b8Schs 	return (0);
107993f3d2b8Schs }
108093f3d2b8Schs 
108193f3d2b8Schs int
crgetngroups(cred_t * cr)108293f3d2b8Schs crgetngroups(cred_t *cr)
108393f3d2b8Schs {
108493f3d2b8Schs 	return (0);
108593f3d2b8Schs }
108693f3d2b8Schs 
108793f3d2b8Schs gid_t *
crgetgroups(cred_t * cr)108893f3d2b8Schs crgetgroups(cred_t *cr)
108993f3d2b8Schs {
109093f3d2b8Schs 	return (NULL);
109193f3d2b8Schs }
109293f3d2b8Schs 
109393f3d2b8Schs int
zfs_secpolicy_snapshot_perms(const char * name,cred_t * cr)109493f3d2b8Schs zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
109593f3d2b8Schs {
109693f3d2b8Schs 	return (0);
109793f3d2b8Schs }
109893f3d2b8Schs 
109993f3d2b8Schs int
zfs_secpolicy_rename_perms(const char * from,const char * to,cred_t * cr)110093f3d2b8Schs zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
110193f3d2b8Schs {
110293f3d2b8Schs 	return (0);
110393f3d2b8Schs }
110493f3d2b8Schs 
110593f3d2b8Schs int
zfs_secpolicy_destroy_perms(const char * name,cred_t * cr)110693f3d2b8Schs zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
110793f3d2b8Schs {
110893f3d2b8Schs 	return (0);
110993f3d2b8Schs }
111093f3d2b8Schs 
111193f3d2b8Schs ksiddomain_t *
ksid_lookupdomain(const char * dom)111293f3d2b8Schs ksid_lookupdomain(const char *dom)
111393f3d2b8Schs {
111493f3d2b8Schs 	ksiddomain_t *kd;
111593f3d2b8Schs 
111693f3d2b8Schs 	kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL);
111793f3d2b8Schs 	kd->kd_name = spa_strdup(dom);
111893f3d2b8Schs 	return (kd);
111993f3d2b8Schs }
112093f3d2b8Schs 
112193f3d2b8Schs void
ksiddomain_rele(ksiddomain_t * ksid)112293f3d2b8Schs ksiddomain_rele(ksiddomain_t *ksid)
112393f3d2b8Schs {
112493f3d2b8Schs 	spa_strfree(ksid->kd_name);
112593f3d2b8Schs 	umem_free(ksid, sizeof (ksiddomain_t));
112693f3d2b8Schs }
112793f3d2b8Schs 
112893f3d2b8Schs /*
112993f3d2b8Schs  * Do not change the length of the returned string; it must be freed
113093f3d2b8Schs  * with strfree().
113193f3d2b8Schs  */
113293f3d2b8Schs char *
kmem_asprintf(const char * fmt,...)113393f3d2b8Schs kmem_asprintf(const char *fmt, ...)
113493f3d2b8Schs {
113593f3d2b8Schs 	int size;
113693f3d2b8Schs 	va_list adx;
113793f3d2b8Schs 	char *buf;
113893f3d2b8Schs 
113993f3d2b8Schs 	va_start(adx, fmt);
114093f3d2b8Schs 	size = vsnprintf(NULL, 0, fmt, adx) + 1;
114193f3d2b8Schs 	va_end(adx);
114293f3d2b8Schs 
114393f3d2b8Schs 	buf = kmem_alloc(size, KM_SLEEP);
114493f3d2b8Schs 
114593f3d2b8Schs 	va_start(adx, fmt);
114693f3d2b8Schs 	size = vsnprintf(buf, size, fmt, adx);
114793f3d2b8Schs 	va_end(adx);
114893f3d2b8Schs 
114993f3d2b8Schs 	return (buf);
115093f3d2b8Schs }
115193f3d2b8Schs 
115293f3d2b8Schs /* ARGSUSED */
115393f3d2b8Schs int
zfs_onexit_fd_hold(int fd,minor_t * minorp)115493f3d2b8Schs zfs_onexit_fd_hold(int fd, minor_t *minorp)
115593f3d2b8Schs {
115693f3d2b8Schs 	*minorp = 0;
115793f3d2b8Schs 	return (0);
115893f3d2b8Schs }
115993f3d2b8Schs 
116093f3d2b8Schs /* ARGSUSED */
116193f3d2b8Schs void
zfs_onexit_fd_rele(int fd)116293f3d2b8Schs zfs_onexit_fd_rele(int fd)
116393f3d2b8Schs {
116493f3d2b8Schs }
116593f3d2b8Schs 
116693f3d2b8Schs /* ARGSUSED */
116793f3d2b8Schs int
zfs_onexit_add_cb(minor_t minor,void (* func)(void *),void * data,uint64_t * action_handle)116893f3d2b8Schs zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
116993f3d2b8Schs     uint64_t *action_handle)
117093f3d2b8Schs {
117193f3d2b8Schs 	return (0);
117293f3d2b8Schs }
117393f3d2b8Schs 
117493f3d2b8Schs /* ARGSUSED */
117593f3d2b8Schs int
zfs_onexit_del_cb(minor_t minor,uint64_t action_handle,boolean_t fire)117693f3d2b8Schs zfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire)
117793f3d2b8Schs {
117893f3d2b8Schs 	return (0);
117993f3d2b8Schs }
118093f3d2b8Schs 
118193f3d2b8Schs /* ARGSUSED */
118293f3d2b8Schs int
zfs_onexit_cb_data(minor_t minor,uint64_t action_handle,void ** data)118393f3d2b8Schs zfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data)
118493f3d2b8Schs {
118593f3d2b8Schs 	return (0);
118693f3d2b8Schs }
118793f3d2b8Schs 
118893f3d2b8Schs #ifdef __FreeBSD__
118993f3d2b8Schs /* ARGSUSED */
119093f3d2b8Schs int
zvol_create_minors(const char * name)119193f3d2b8Schs zvol_create_minors(const char *name)
119293f3d2b8Schs {
119393f3d2b8Schs 	return (0);
119493f3d2b8Schs }
119593f3d2b8Schs #endif
119693f3d2b8Schs 
119793f3d2b8Schs #ifdef illumos
119893f3d2b8Schs void
bioinit(buf_t * bp)119993f3d2b8Schs bioinit(buf_t *bp)
120093f3d2b8Schs {
120193f3d2b8Schs 	bzero(bp, sizeof (buf_t));
120293f3d2b8Schs }
120393f3d2b8Schs 
120493f3d2b8Schs void
biodone(buf_t * bp)120593f3d2b8Schs biodone(buf_t *bp)
120693f3d2b8Schs {
120793f3d2b8Schs 	if (bp->b_iodone != NULL) {
120893f3d2b8Schs 		(*(bp->b_iodone))(bp);
120993f3d2b8Schs 		return;
121093f3d2b8Schs 	}
121193f3d2b8Schs 	ASSERT((bp->b_flags & B_DONE) == 0);
121293f3d2b8Schs 	bp->b_flags |= B_DONE;
121393f3d2b8Schs }
121493f3d2b8Schs 
121593f3d2b8Schs void
bioerror(buf_t * bp,int error)121693f3d2b8Schs bioerror(buf_t *bp, int error)
121793f3d2b8Schs {
121893f3d2b8Schs 	ASSERT(bp != NULL);
121993f3d2b8Schs 	ASSERT(error >= 0);
122093f3d2b8Schs 
122193f3d2b8Schs 	if (error != 0) {
122293f3d2b8Schs 		bp->b_flags |= B_ERROR;
122393f3d2b8Schs 	} else {
122493f3d2b8Schs 		bp->b_flags &= ~B_ERROR;
122593f3d2b8Schs 	}
122693f3d2b8Schs 	bp->b_error = error;
122793f3d2b8Schs }
122893f3d2b8Schs 
122993f3d2b8Schs 
123093f3d2b8Schs int
geterror(struct buf * bp)123193f3d2b8Schs geterror(struct buf *bp)
123293f3d2b8Schs {
123393f3d2b8Schs 	int error = 0;
123493f3d2b8Schs 
123593f3d2b8Schs 	if (bp->b_flags & B_ERROR) {
123693f3d2b8Schs 		error = bp->b_error;
123793f3d2b8Schs 		if (!error)
123893f3d2b8Schs 			error = EIO;
123993f3d2b8Schs 	}
124093f3d2b8Schs 	return (error);
124193f3d2b8Schs }
124293f3d2b8Schs #endif
1243