1789Sahrens /*
2789Sahrens  * CDDL HEADER START
3789Sahrens  *
4789Sahrens  * The contents of this file are subject to the terms of the
51544Seschrock  * Common Development and Distribution License (the "License").
61544Seschrock  * You may not use this file except in compliance with the License.
7789Sahrens  *
8789Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9789Sahrens  * or http://www.opensolaris.org/os/licensing.
10789Sahrens  * See the License for the specific language governing permissions
11789Sahrens  * and limitations under the License.
12789Sahrens  *
13789Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14789Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15789Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16789Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17789Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18789Sahrens  *
19789Sahrens  * CDDL HEADER END
20789Sahrens  */
21789Sahrens /*
22*3403Sbmc  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23789Sahrens  * Use is subject to license terms.
24789Sahrens  */
25789Sahrens 
26789Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
27789Sahrens 
28789Sahrens #include <assert.h>
29789Sahrens #include <sys/zfs_context.h>
30789Sahrens #include <poll.h>
31789Sahrens #include <string.h>
32789Sahrens #include <stdio.h>
33789Sahrens #include <stdlib.h>
34789Sahrens #include <fcntl.h>
35789Sahrens #include <sys/stat.h>
36789Sahrens #include <sys/spa.h>
37789Sahrens #include <sys/processor.h>
38789Sahrens 
392856Snd150628 
40789Sahrens /*
41789Sahrens  * Emulation of kernel services in userland.
42789Sahrens  */
43789Sahrens 
44789Sahrens uint64_t physmem;
45789Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234;
46789Sahrens 
47789Sahrens /*
48789Sahrens  * =========================================================================
49789Sahrens  * threads
50789Sahrens  * =========================================================================
51789Sahrens  */
52789Sahrens /*ARGSUSED*/
53789Sahrens kthread_t *
54789Sahrens zk_thread_create(void (*func)(), void *arg)
55789Sahrens {
56789Sahrens 	thread_t tid;
57789Sahrens 
58789Sahrens 	VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
59789Sahrens 	    &tid) == 0);
60789Sahrens 
61789Sahrens 	return ((void *)(uintptr_t)tid);
62789Sahrens }
63789Sahrens 
64789Sahrens /*
65789Sahrens  * =========================================================================
66*3403Sbmc  * kstats
67*3403Sbmc  * =========================================================================
68*3403Sbmc  */
69*3403Sbmc /*ARGSUSED*/
70*3403Sbmc kstat_t *
71*3403Sbmc kstat_create(char *module, int instance, char *name, char *class,
72*3403Sbmc     uchar_t type, ulong_t ndata, uchar_t ks_flag)
73*3403Sbmc {
74*3403Sbmc 	return (NULL);
75*3403Sbmc }
76*3403Sbmc 
77*3403Sbmc /*ARGSUSED*/
78*3403Sbmc void
79*3403Sbmc kstat_install(kstat_t *ksp)
80*3403Sbmc {}
81*3403Sbmc 
82*3403Sbmc /*ARGSUSED*/
83*3403Sbmc void
84*3403Sbmc kstat_delete(kstat_t *ksp)
85*3403Sbmc {}
86*3403Sbmc 
87*3403Sbmc /*
88*3403Sbmc  * =========================================================================
89789Sahrens  * mutexes
90789Sahrens  * =========================================================================
91789Sahrens  */
92789Sahrens void
93789Sahrens zmutex_init(kmutex_t *mp)
94789Sahrens {
95789Sahrens 	mp->m_owner = NULL;
96789Sahrens 	(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
97789Sahrens }
98789Sahrens 
99789Sahrens void
100789Sahrens zmutex_destroy(kmutex_t *mp)
101789Sahrens {
102789Sahrens 	ASSERT(mp->m_owner == NULL);
103789Sahrens 	(void) _mutex_destroy(&(mp)->m_lock);
104789Sahrens 	mp->m_owner = (void *)-1UL;
105789Sahrens }
106789Sahrens 
107789Sahrens void
108789Sahrens mutex_enter(kmutex_t *mp)
109789Sahrens {
110789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
111789Sahrens 	ASSERT(mp->m_owner != curthread);
1122856Snd150628 	VERIFY(mutex_lock(&mp->m_lock) == 0);
113789Sahrens 	ASSERT(mp->m_owner == NULL);
114789Sahrens 	mp->m_owner = curthread;
115789Sahrens }
116789Sahrens 
117789Sahrens int
118789Sahrens mutex_tryenter(kmutex_t *mp)
119789Sahrens {
120789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
121789Sahrens 	if (0 == mutex_trylock(&mp->m_lock)) {
122789Sahrens 		ASSERT(mp->m_owner == NULL);
123789Sahrens 		mp->m_owner = curthread;
124789Sahrens 		return (1);
125789Sahrens 	} else {
126789Sahrens 		return (0);
127789Sahrens 	}
128789Sahrens }
129789Sahrens 
130789Sahrens void
131789Sahrens mutex_exit(kmutex_t *mp)
132789Sahrens {
133789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
134789Sahrens 	mp->m_owner = NULL;
1352856Snd150628 	VERIFY(mutex_unlock(&mp->m_lock) == 0);
136789Sahrens }
137789Sahrens 
138789Sahrens void *
139789Sahrens mutex_owner(kmutex_t *mp)
140789Sahrens {
141789Sahrens 	return (mp->m_owner);
142789Sahrens }
143789Sahrens 
144789Sahrens /*
145789Sahrens  * =========================================================================
146789Sahrens  * rwlocks
147789Sahrens  * =========================================================================
148789Sahrens  */
149789Sahrens /*ARGSUSED*/
150789Sahrens void
151789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
152789Sahrens {
153789Sahrens 	rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
154789Sahrens 	rwlp->rw_owner = NULL;
155789Sahrens }
156789Sahrens 
157789Sahrens void
158789Sahrens rw_destroy(krwlock_t *rwlp)
159789Sahrens {
160789Sahrens 	rwlock_destroy(&rwlp->rw_lock);
161789Sahrens 	rwlp->rw_owner = (void *)-1UL;
162789Sahrens }
163789Sahrens 
164789Sahrens void
165789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw)
166789Sahrens {
167789Sahrens 	ASSERT(!RW_LOCK_HELD(rwlp));
168789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
169789Sahrens 	ASSERT(rwlp->rw_owner != curthread);
170789Sahrens 
171789Sahrens 	if (rw == RW_READER)
172789Sahrens 		(void) rw_rdlock(&rwlp->rw_lock);
173789Sahrens 	else
174789Sahrens 		(void) rw_wrlock(&rwlp->rw_lock);
175789Sahrens 
176789Sahrens 	rwlp->rw_owner = curthread;
177789Sahrens }
178789Sahrens 
179789Sahrens void
180789Sahrens rw_exit(krwlock_t *rwlp)
181789Sahrens {
182789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
183789Sahrens 
184789Sahrens 	rwlp->rw_owner = NULL;
185789Sahrens 	(void) rw_unlock(&rwlp->rw_lock);
186789Sahrens }
187789Sahrens 
188789Sahrens int
189789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw)
190789Sahrens {
191789Sahrens 	int rv;
192789Sahrens 
193789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
194789Sahrens 
195789Sahrens 	if (rw == RW_READER)
196789Sahrens 		rv = rw_tryrdlock(&rwlp->rw_lock);
197789Sahrens 	else
198789Sahrens 		rv = rw_trywrlock(&rwlp->rw_lock);
199789Sahrens 
200789Sahrens 	if (rv == 0) {
201789Sahrens 		rwlp->rw_owner = curthread;
202789Sahrens 		return (1);
203789Sahrens 	}
204789Sahrens 
205789Sahrens 	return (0);
206789Sahrens }
207789Sahrens 
208789Sahrens /*ARGSUSED*/
209789Sahrens int
210789Sahrens rw_tryupgrade(krwlock_t *rwlp)
211789Sahrens {
212789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
213789Sahrens 
214789Sahrens 	return (0);
215789Sahrens }
216789Sahrens 
217789Sahrens /*
218789Sahrens  * =========================================================================
219789Sahrens  * condition variables
220789Sahrens  * =========================================================================
221789Sahrens  */
222789Sahrens /*ARGSUSED*/
223789Sahrens void
224789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg)
225789Sahrens {
2262856Snd150628 	VERIFY(cond_init(cv, type, NULL) == 0);
227789Sahrens }
228789Sahrens 
229789Sahrens void
230789Sahrens cv_destroy(kcondvar_t *cv)
231789Sahrens {
2322856Snd150628 	VERIFY(cond_destroy(cv) == 0);
233789Sahrens }
234789Sahrens 
235789Sahrens void
236789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp)
237789Sahrens {
238789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
239789Sahrens 	mp->m_owner = NULL;
2402856Snd150628 	int ret = cond_wait(cv, &mp->m_lock);
2412856Snd150628 	VERIFY(ret == 0 || ret == EINTR);
242789Sahrens 	mp->m_owner = curthread;
243789Sahrens }
244789Sahrens 
245789Sahrens clock_t
246789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
247789Sahrens {
248789Sahrens 	int error;
249789Sahrens 	timestruc_t ts;
250789Sahrens 	clock_t delta;
251789Sahrens 
252789Sahrens top:
253789Sahrens 	delta = abstime - lbolt;
254789Sahrens 	if (delta <= 0)
255789Sahrens 		return (-1);
256789Sahrens 
257789Sahrens 	ts.tv_sec = delta / hz;
258789Sahrens 	ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
259789Sahrens 
260789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
261789Sahrens 	mp->m_owner = NULL;
262789Sahrens 	error = cond_reltimedwait(cv, &mp->m_lock, &ts);
263789Sahrens 	mp->m_owner = curthread;
264789Sahrens 
265789Sahrens 	if (error == ETIME)
266789Sahrens 		return (-1);
267789Sahrens 
268789Sahrens 	if (error == EINTR)
269789Sahrens 		goto top;
270789Sahrens 
271789Sahrens 	ASSERT(error == 0);
272789Sahrens 
273789Sahrens 	return (1);
274789Sahrens }
275789Sahrens 
276789Sahrens void
277789Sahrens cv_signal(kcondvar_t *cv)
278789Sahrens {
2792856Snd150628 	VERIFY(cond_signal(cv) == 0);
280789Sahrens }
281789Sahrens 
282789Sahrens void
283789Sahrens cv_broadcast(kcondvar_t *cv)
284789Sahrens {
2852856Snd150628 	VERIFY(cond_broadcast(cv) == 0);
286789Sahrens }
287789Sahrens 
288789Sahrens /*
289789Sahrens  * =========================================================================
290789Sahrens  * vnode operations
291789Sahrens  * =========================================================================
292789Sahrens  */
293789Sahrens /*
294789Sahrens  * Note: for the xxxat() versions of these functions, we assume that the
295789Sahrens  * starting vp is always rootdir (which is true for spa_directory.c, the only
296789Sahrens  * ZFS consumer of these interfaces).  We assert this is true, and then emulate
297789Sahrens  * them by adding '/' in front of the path.
298789Sahrens  */
299789Sahrens 
300789Sahrens /*ARGSUSED*/
301789Sahrens int
302789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
303789Sahrens {
304789Sahrens 	int fd;
305789Sahrens 	vnode_t *vp;
306789Sahrens 	int old_umask;
307789Sahrens 	char realpath[MAXPATHLEN];
308789Sahrens 	struct stat64 st;
309789Sahrens 
310789Sahrens 	/*
311789Sahrens 	 * If we're accessing a real disk from userland, we need to use
312789Sahrens 	 * the character interface to avoid caching.  This is particularly
313789Sahrens 	 * important if we're trying to look at a real in-kernel storage
314789Sahrens 	 * pool from userland, e.g. via zdb, because otherwise we won't
315789Sahrens 	 * see the changes occurring under the segmap cache.
316789Sahrens 	 * On the other hand, the stupid character device returns zero
317789Sahrens 	 * for its size.  So -- gag -- we open the block device to get
318789Sahrens 	 * its size, and remember it for subsequent VOP_GETATTR().
319789Sahrens 	 */
320789Sahrens 	if (strncmp(path, "/dev/", 5) == 0) {
321789Sahrens 		char *dsk;
322789Sahrens 		fd = open64(path, O_RDONLY);
323789Sahrens 		if (fd == -1)
324789Sahrens 			return (errno);
325789Sahrens 		if (fstat64(fd, &st) == -1) {
326789Sahrens 			close(fd);
327789Sahrens 			return (errno);
328789Sahrens 		}
329789Sahrens 		close(fd);
330789Sahrens 		(void) sprintf(realpath, "%s", path);
331789Sahrens 		dsk = strstr(path, "/dsk/");
332789Sahrens 		if (dsk != NULL)
333789Sahrens 			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
334789Sahrens 			    dsk + 1);
335789Sahrens 	} else {
336789Sahrens 		(void) sprintf(realpath, "%s", path);
337789Sahrens 		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
338789Sahrens 			return (errno);
339789Sahrens 	}
340789Sahrens 
341789Sahrens 	if (flags & FCREAT)
342789Sahrens 		old_umask = umask(0);
343789Sahrens 
344789Sahrens 	/*
345789Sahrens 	 * The construct 'flags - FREAD' conveniently maps combinations of
346789Sahrens 	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
347789Sahrens 	 */
348789Sahrens 	fd = open64(realpath, flags - FREAD, mode);
349789Sahrens 
350789Sahrens 	if (flags & FCREAT)
351789Sahrens 		(void) umask(old_umask);
352789Sahrens 
353789Sahrens 	if (fd == -1)
354789Sahrens 		return (errno);
355789Sahrens 
356789Sahrens 	if (fstat64(fd, &st) == -1) {
357789Sahrens 		close(fd);
358789Sahrens 		return (errno);
359789Sahrens 	}
360789Sahrens 
361789Sahrens 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
362789Sahrens 
363789Sahrens 	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
364789Sahrens 
365789Sahrens 	vp->v_fd = fd;
366789Sahrens 	vp->v_size = st.st_size;
367789Sahrens 	vp->v_path = spa_strdup(path);
368789Sahrens 
369789Sahrens 	return (0);
370789Sahrens }
371789Sahrens 
372789Sahrens int
373789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
374789Sahrens     int x3, vnode_t *startvp)
375789Sahrens {
376789Sahrens 	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
377789Sahrens 	int ret;
378789Sahrens 
379789Sahrens 	ASSERT(startvp == rootdir);
380789Sahrens 	(void) sprintf(realpath, "/%s", path);
381789Sahrens 
382789Sahrens 	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
383789Sahrens 
384789Sahrens 	umem_free(realpath, strlen(path) + 2);
385789Sahrens 
386789Sahrens 	return (ret);
387789Sahrens }
388789Sahrens 
389789Sahrens /*ARGSUSED*/
390789Sahrens int
391789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
392789Sahrens 	int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
393789Sahrens {
394789Sahrens 	ssize_t iolen, split;
395789Sahrens 
396789Sahrens 	if (uio == UIO_READ) {
397789Sahrens 		iolen = pread64(vp->v_fd, addr, len, offset);
398789Sahrens 	} else {
399789Sahrens 		/*
400789Sahrens 		 * To simulate partial disk writes, we split writes into two
401789Sahrens 		 * system calls so that the process can be killed in between.
402789Sahrens 		 */
403789Sahrens 		split = (len > 0 ? rand() % len : 0);
404789Sahrens 		iolen = pwrite64(vp->v_fd, addr, split, offset);
405789Sahrens 		iolen += pwrite64(vp->v_fd, (char *)addr + split,
406789Sahrens 		    len - split, offset + split);
407789Sahrens 	}
408789Sahrens 
409789Sahrens 	if (iolen == -1)
410789Sahrens 		return (errno);
411789Sahrens 	if (residp)
412789Sahrens 		*residp = len - iolen;
413789Sahrens 	else if (iolen != len)
414789Sahrens 		return (EIO);
415789Sahrens 	return (0);
416789Sahrens }
417789Sahrens 
418789Sahrens void
419789Sahrens vn_close(vnode_t *vp)
420789Sahrens {
421789Sahrens 	close(vp->v_fd);
422789Sahrens 	spa_strfree(vp->v_path);
423789Sahrens 	umem_free(vp, sizeof (vnode_t));
424789Sahrens }
425789Sahrens 
426789Sahrens #ifdef ZFS_DEBUG
427789Sahrens 
428789Sahrens /*
429789Sahrens  * =========================================================================
430789Sahrens  * Figure out which debugging statements to print
431789Sahrens  * =========================================================================
432789Sahrens  */
433789Sahrens 
434789Sahrens static char *dprintf_string;
435789Sahrens static int dprintf_print_all;
436789Sahrens 
437789Sahrens int
438789Sahrens dprintf_find_string(const char *string)
439789Sahrens {
440789Sahrens 	char *tmp_str = dprintf_string;
441789Sahrens 	int len = strlen(string);
442789Sahrens 
443789Sahrens 	/*
444789Sahrens 	 * Find out if this is a string we want to print.
445789Sahrens 	 * String format: file1.c,function_name1,file2.c,file3.c
446789Sahrens 	 */
447789Sahrens 
448789Sahrens 	while (tmp_str != NULL) {
449789Sahrens 		if (strncmp(tmp_str, string, len) == 0 &&
450789Sahrens 		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
451789Sahrens 			return (1);
452789Sahrens 		tmp_str = strchr(tmp_str, ',');
453789Sahrens 		if (tmp_str != NULL)
454789Sahrens 			tmp_str++; /* Get rid of , */
455789Sahrens 	}
456789Sahrens 	return (0);
457789Sahrens }
458789Sahrens 
459789Sahrens void
460789Sahrens dprintf_setup(int *argc, char **argv)
461789Sahrens {
462789Sahrens 	int i, j;
463789Sahrens 
464789Sahrens 	/*
465789Sahrens 	 * Debugging can be specified two ways: by setting the
466789Sahrens 	 * environment variable ZFS_DEBUG, or by including a
467789Sahrens 	 * "debug=..."  argument on the command line.  The command
468789Sahrens 	 * line setting overrides the environment variable.
469789Sahrens 	 */
470789Sahrens 
471789Sahrens 	for (i = 1; i < *argc; i++) {
472789Sahrens 		int len = strlen("debug=");
473789Sahrens 		/* First look for a command line argument */
474789Sahrens 		if (strncmp("debug=", argv[i], len) == 0) {
475789Sahrens 			dprintf_string = argv[i] + len;
476789Sahrens 			/* Remove from args */
477789Sahrens 			for (j = i; j < *argc; j++)
478789Sahrens 				argv[j] = argv[j+1];
479789Sahrens 			argv[j] = NULL;
480789Sahrens 			(*argc)--;
481789Sahrens 		}
482789Sahrens 	}
483789Sahrens 
484789Sahrens 	if (dprintf_string == NULL) {
485789Sahrens 		/* Look for ZFS_DEBUG environment variable */
486789Sahrens 		dprintf_string = getenv("ZFS_DEBUG");
487789Sahrens 	}
488789Sahrens 
489789Sahrens 	/*
490789Sahrens 	 * Are we just turning on all debugging?
491789Sahrens 	 */
492789Sahrens 	if (dprintf_find_string("on"))
493789Sahrens 		dprintf_print_all = 1;
494789Sahrens }
495789Sahrens 
496789Sahrens /*
497789Sahrens  * =========================================================================
498789Sahrens  * debug printfs
499789Sahrens  * =========================================================================
500789Sahrens  */
501789Sahrens void
502789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
503789Sahrens {
504789Sahrens 	const char *newfile;
505789Sahrens 	va_list adx;
506789Sahrens 
507789Sahrens 	/*
508789Sahrens 	 * Get rid of annoying "../common/" prefix to filename.
509789Sahrens 	 */
510789Sahrens 	newfile = strrchr(file, '/');
511789Sahrens 	if (newfile != NULL) {
512789Sahrens 		newfile = newfile + 1; /* Get rid of leading / */
513789Sahrens 	} else {
514789Sahrens 		newfile = file;
515789Sahrens 	}
516789Sahrens 
517789Sahrens 	if (dprintf_print_all ||
518789Sahrens 	    dprintf_find_string(newfile) ||
519789Sahrens 	    dprintf_find_string(func)) {
520789Sahrens 		/* Print out just the function name if requested */
521789Sahrens 		flockfile(stdout);
522789Sahrens 		if (dprintf_find_string("pid"))
523789Sahrens 			(void) printf("%d ", getpid());
524789Sahrens 		if (dprintf_find_string("tid"))
525789Sahrens 			(void) printf("%u ", thr_self());
526789Sahrens 		if (dprintf_find_string("cpu"))
527789Sahrens 			(void) printf("%u ", getcpuid());
528789Sahrens 		if (dprintf_find_string("time"))
529789Sahrens 			(void) printf("%llu ", gethrtime());
530789Sahrens 		if (dprintf_find_string("long"))
531789Sahrens 			(void) printf("%s, line %d: ", newfile, line);
532789Sahrens 		(void) printf("%s: ", func);
533789Sahrens 		va_start(adx, fmt);
534789Sahrens 		(void) vprintf(fmt, adx);
535789Sahrens 		va_end(adx);
536789Sahrens 		funlockfile(stdout);
537789Sahrens 	}
538789Sahrens }
539789Sahrens 
540789Sahrens #endif /* ZFS_DEBUG */
541789Sahrens 
542789Sahrens /*
543789Sahrens  * =========================================================================
544789Sahrens  * cmn_err() and panic()
545789Sahrens  * =========================================================================
546789Sahrens  */
547789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
548789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
549789Sahrens 
550789Sahrens void
551789Sahrens vpanic(const char *fmt, va_list adx)
552789Sahrens {
553789Sahrens 	(void) fprintf(stderr, "error: ");
554789Sahrens 	(void) vfprintf(stderr, fmt, adx);
555789Sahrens 	(void) fprintf(stderr, "\n");
556789Sahrens 
557789Sahrens 	abort();	/* think of it as a "user-level crash dump" */
558789Sahrens }
559789Sahrens 
560789Sahrens void
561789Sahrens panic(const char *fmt, ...)
562789Sahrens {
563789Sahrens 	va_list adx;
564789Sahrens 
565789Sahrens 	va_start(adx, fmt);
566789Sahrens 	vpanic(fmt, adx);
567789Sahrens 	va_end(adx);
568789Sahrens }
569789Sahrens 
570789Sahrens /*PRINTFLIKE2*/
571789Sahrens void
572789Sahrens cmn_err(int ce, const char *fmt, ...)
573789Sahrens {
574789Sahrens 	va_list adx;
575789Sahrens 
576789Sahrens 	va_start(adx, fmt);
577789Sahrens 	if (ce == CE_PANIC)
578789Sahrens 		vpanic(fmt, adx);
579789Sahrens 	if (ce != CE_NOTE) {	/* suppress noise in userland stress testing */
580789Sahrens 		(void) fprintf(stderr, "%s", ce_prefix[ce]);
581789Sahrens 		(void) vfprintf(stderr, fmt, adx);
582789Sahrens 		(void) fprintf(stderr, "%s", ce_suffix[ce]);
583789Sahrens 	}
584789Sahrens 	va_end(adx);
585789Sahrens }
586789Sahrens 
587789Sahrens /*
588789Sahrens  * =========================================================================
5891544Seschrock  * kobj interfaces
5901544Seschrock  * =========================================================================
5911544Seschrock  */
5921544Seschrock struct _buf *
5931544Seschrock kobj_open_file(char *name)
5941544Seschrock {
5951544Seschrock 	struct _buf *file;
5961544Seschrock 	vnode_t *vp;
5971544Seschrock 
5981544Seschrock 	/* set vp as the _fd field of the file */
5991544Seschrock 	if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir) != 0)
6001544Seschrock 		return ((void *)-1UL);
6011544Seschrock 
6021544Seschrock 	file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
6031544Seschrock 	file->_fd = (intptr_t)vp;
6041544Seschrock 	return (file);
6051544Seschrock }
6061544Seschrock 
6071544Seschrock int
6081544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
6091544Seschrock {
6101544Seschrock 	ssize_t resid;
6111544Seschrock 
6121544Seschrock 	vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
6131544Seschrock 	    UIO_SYSSPACE, 0, 0, 0, &resid);
6141544Seschrock 
6151544Seschrock 	return (0);
6161544Seschrock }
6171544Seschrock 
6181544Seschrock void
6191544Seschrock kobj_close_file(struct _buf *file)
6201544Seschrock {
6211544Seschrock 	vn_close((vnode_t *)file->_fd);
6221544Seschrock 	umem_free(file, sizeof (struct _buf));
6231544Seschrock }
6241544Seschrock 
6251544Seschrock int
6261544Seschrock kobj_fstat(intptr_t fd, struct bootstat *bst)
6271544Seschrock {
6281544Seschrock 	struct stat64 st;
6291544Seschrock 	vnode_t *vp = (vnode_t *)fd;
6301544Seschrock 	if (fstat64(vp->v_fd, &st) == -1) {
6311544Seschrock 		vn_close(vp);
6321544Seschrock 		return (errno);
6331544Seschrock 	}
6341544Seschrock 	bst->st_size = (uint64_t)st.st_size;
6351544Seschrock 	return (0);
6361544Seschrock }
6371544Seschrock 
6381544Seschrock /*
6391544Seschrock  * =========================================================================
640789Sahrens  * misc routines
641789Sahrens  * =========================================================================
642789Sahrens  */
643789Sahrens 
644789Sahrens void
645789Sahrens delay(clock_t ticks)
646789Sahrens {
647789Sahrens 	poll(0, 0, ticks * (1000 / hz));
648789Sahrens }
649789Sahrens 
650789Sahrens /*
651789Sahrens  * Find highest one bit set.
652789Sahrens  *	Returns bit number + 1 of highest bit that is set, otherwise returns 0.
653789Sahrens  * High order bit is 31 (or 63 in _LP64 kernel).
654789Sahrens  */
655789Sahrens int
656789Sahrens highbit(ulong_t i)
657789Sahrens {
658789Sahrens 	register int h = 1;
659789Sahrens 
660789Sahrens 	if (i == 0)
661789Sahrens 		return (0);
662789Sahrens #ifdef _LP64
663789Sahrens 	if (i & 0xffffffff00000000ul) {
664789Sahrens 		h += 32; i >>= 32;
665789Sahrens 	}
666789Sahrens #endif
667789Sahrens 	if (i & 0xffff0000) {
668789Sahrens 		h += 16; i >>= 16;
669789Sahrens 	}
670789Sahrens 	if (i & 0xff00) {
671789Sahrens 		h += 8; i >>= 8;
672789Sahrens 	}
673789Sahrens 	if (i & 0xf0) {
674789Sahrens 		h += 4; i >>= 4;
675789Sahrens 	}
676789Sahrens 	if (i & 0xc) {
677789Sahrens 		h += 2; i >>= 2;
678789Sahrens 	}
679789Sahrens 	if (i & 0x2) {
680789Sahrens 		h += 1;
681789Sahrens 	}
682789Sahrens 	return (h);
683789Sahrens }
684789Sahrens 
685789Sahrens static int
686789Sahrens random_get_bytes_common(uint8_t *ptr, size_t len, char *devname)
687789Sahrens {
688789Sahrens 	int fd = open(devname, O_RDONLY);
689789Sahrens 	size_t resid = len;
690789Sahrens 	ssize_t bytes;
691789Sahrens 
692789Sahrens 	ASSERT(fd != -1);
693789Sahrens 
694789Sahrens 	while (resid != 0) {
695789Sahrens 		bytes = read(fd, ptr, resid);
696789Sahrens 		ASSERT(bytes >= 0);
697789Sahrens 		ptr += bytes;
698789Sahrens 		resid -= bytes;
699789Sahrens 	}
700789Sahrens 
701789Sahrens 	close(fd);
702789Sahrens 
703789Sahrens 	return (0);
704789Sahrens }
705789Sahrens 
706789Sahrens int
707789Sahrens random_get_bytes(uint8_t *ptr, size_t len)
708789Sahrens {
709789Sahrens 	return (random_get_bytes_common(ptr, len, "/dev/random"));
710789Sahrens }
711789Sahrens 
712789Sahrens int
713789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len)
714789Sahrens {
715789Sahrens 	return (random_get_bytes_common(ptr, len, "/dev/urandom"));
716789Sahrens }
717789Sahrens 
718789Sahrens /*
719789Sahrens  * =========================================================================
720789Sahrens  * kernel emulation setup & teardown
721789Sahrens  * =========================================================================
722789Sahrens  */
723789Sahrens static int
724789Sahrens umem_out_of_memory(void)
725789Sahrens {
726789Sahrens 	char errmsg[] = "out of memory -- generating core dump\n";
727789Sahrens 
728789Sahrens 	write(fileno(stderr), errmsg, sizeof (errmsg));
729789Sahrens 	abort();
730789Sahrens 	return (0);
731789Sahrens }
732789Sahrens 
733789Sahrens void
734789Sahrens kernel_init(int mode)
735789Sahrens {
736789Sahrens 	umem_nofail_callback(umem_out_of_memory);
737789Sahrens 
738789Sahrens 	physmem = sysconf(_SC_PHYS_PAGES);
739789Sahrens 
740789Sahrens 	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
741789Sahrens 	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
742789Sahrens 
743789Sahrens 	spa_init(mode);
744789Sahrens }
745789Sahrens 
746789Sahrens void
747789Sahrens kernel_fini(void)
748789Sahrens {
749789Sahrens 	spa_fini();
750789Sahrens }
751