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 /*
221544Seschrock  * Copyright 2006 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 
39*2856Snd150628 
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  * =========================================================================
66789Sahrens  * mutexes
67789Sahrens  * =========================================================================
68789Sahrens  */
69789Sahrens void
70789Sahrens zmutex_init(kmutex_t *mp)
71789Sahrens {
72789Sahrens 	mp->m_owner = NULL;
73789Sahrens 	(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
74789Sahrens }
75789Sahrens 
76789Sahrens void
77789Sahrens zmutex_destroy(kmutex_t *mp)
78789Sahrens {
79789Sahrens 	ASSERT(mp->m_owner == NULL);
80789Sahrens 	(void) _mutex_destroy(&(mp)->m_lock);
81789Sahrens 	mp->m_owner = (void *)-1UL;
82789Sahrens }
83789Sahrens 
84789Sahrens void
85789Sahrens mutex_enter(kmutex_t *mp)
86789Sahrens {
87789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
88789Sahrens 	ASSERT(mp->m_owner != curthread);
89*2856Snd150628 	VERIFY(mutex_lock(&mp->m_lock) == 0);
90789Sahrens 	ASSERT(mp->m_owner == NULL);
91789Sahrens 	mp->m_owner = curthread;
92789Sahrens }
93789Sahrens 
94789Sahrens int
95789Sahrens mutex_tryenter(kmutex_t *mp)
96789Sahrens {
97789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
98789Sahrens 	if (0 == mutex_trylock(&mp->m_lock)) {
99789Sahrens 		ASSERT(mp->m_owner == NULL);
100789Sahrens 		mp->m_owner = curthread;
101789Sahrens 		return (1);
102789Sahrens 	} else {
103789Sahrens 		return (0);
104789Sahrens 	}
105789Sahrens }
106789Sahrens 
107789Sahrens void
108789Sahrens mutex_exit(kmutex_t *mp)
109789Sahrens {
110789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
111789Sahrens 	mp->m_owner = NULL;
112*2856Snd150628 	VERIFY(mutex_unlock(&mp->m_lock) == 0);
113789Sahrens }
114789Sahrens 
115789Sahrens void *
116789Sahrens mutex_owner(kmutex_t *mp)
117789Sahrens {
118789Sahrens 	return (mp->m_owner);
119789Sahrens }
120789Sahrens 
121789Sahrens /*
122789Sahrens  * =========================================================================
123789Sahrens  * rwlocks
124789Sahrens  * =========================================================================
125789Sahrens  */
126789Sahrens /*ARGSUSED*/
127789Sahrens void
128789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
129789Sahrens {
130789Sahrens 	rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
131789Sahrens 	rwlp->rw_owner = NULL;
132789Sahrens }
133789Sahrens 
134789Sahrens void
135789Sahrens rw_destroy(krwlock_t *rwlp)
136789Sahrens {
137789Sahrens 	rwlock_destroy(&rwlp->rw_lock);
138789Sahrens 	rwlp->rw_owner = (void *)-1UL;
139789Sahrens }
140789Sahrens 
141789Sahrens void
142789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw)
143789Sahrens {
144789Sahrens 	ASSERT(!RW_LOCK_HELD(rwlp));
145789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
146789Sahrens 	ASSERT(rwlp->rw_owner != curthread);
147789Sahrens 
148789Sahrens 	if (rw == RW_READER)
149789Sahrens 		(void) rw_rdlock(&rwlp->rw_lock);
150789Sahrens 	else
151789Sahrens 		(void) rw_wrlock(&rwlp->rw_lock);
152789Sahrens 
153789Sahrens 	rwlp->rw_owner = curthread;
154789Sahrens }
155789Sahrens 
156789Sahrens void
157789Sahrens rw_exit(krwlock_t *rwlp)
158789Sahrens {
159789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
160789Sahrens 
161789Sahrens 	rwlp->rw_owner = NULL;
162789Sahrens 	(void) rw_unlock(&rwlp->rw_lock);
163789Sahrens }
164789Sahrens 
165789Sahrens int
166789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw)
167789Sahrens {
168789Sahrens 	int rv;
169789Sahrens 
170789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
171789Sahrens 
172789Sahrens 	if (rw == RW_READER)
173789Sahrens 		rv = rw_tryrdlock(&rwlp->rw_lock);
174789Sahrens 	else
175789Sahrens 		rv = rw_trywrlock(&rwlp->rw_lock);
176789Sahrens 
177789Sahrens 	if (rv == 0) {
178789Sahrens 		rwlp->rw_owner = curthread;
179789Sahrens 		return (1);
180789Sahrens 	}
181789Sahrens 
182789Sahrens 	return (0);
183789Sahrens }
184789Sahrens 
185789Sahrens /*ARGSUSED*/
186789Sahrens int
187789Sahrens rw_tryupgrade(krwlock_t *rwlp)
188789Sahrens {
189789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
190789Sahrens 
191789Sahrens 	return (0);
192789Sahrens }
193789Sahrens 
194789Sahrens /*
195789Sahrens  * =========================================================================
196789Sahrens  * condition variables
197789Sahrens  * =========================================================================
198789Sahrens  */
199789Sahrens /*ARGSUSED*/
200789Sahrens void
201789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg)
202789Sahrens {
203*2856Snd150628 	VERIFY(cond_init(cv, type, NULL) == 0);
204789Sahrens }
205789Sahrens 
206789Sahrens void
207789Sahrens cv_destroy(kcondvar_t *cv)
208789Sahrens {
209*2856Snd150628 	VERIFY(cond_destroy(cv) == 0);
210789Sahrens }
211789Sahrens 
212789Sahrens void
213789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp)
214789Sahrens {
215789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
216789Sahrens 	mp->m_owner = NULL;
217*2856Snd150628 	int ret = cond_wait(cv, &mp->m_lock);
218*2856Snd150628 	VERIFY(ret == 0 || ret == EINTR);
219789Sahrens 	mp->m_owner = curthread;
220789Sahrens }
221789Sahrens 
222789Sahrens clock_t
223789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
224789Sahrens {
225789Sahrens 	int error;
226789Sahrens 	timestruc_t ts;
227789Sahrens 	clock_t delta;
228789Sahrens 
229789Sahrens top:
230789Sahrens 	delta = abstime - lbolt;
231789Sahrens 	if (delta <= 0)
232789Sahrens 		return (-1);
233789Sahrens 
234789Sahrens 	ts.tv_sec = delta / hz;
235789Sahrens 	ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
236789Sahrens 
237789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
238789Sahrens 	mp->m_owner = NULL;
239789Sahrens 	error = cond_reltimedwait(cv, &mp->m_lock, &ts);
240789Sahrens 	mp->m_owner = curthread;
241789Sahrens 
242789Sahrens 	if (error == ETIME)
243789Sahrens 		return (-1);
244789Sahrens 
245789Sahrens 	if (error == EINTR)
246789Sahrens 		goto top;
247789Sahrens 
248789Sahrens 	ASSERT(error == 0);
249789Sahrens 
250789Sahrens 	return (1);
251789Sahrens }
252789Sahrens 
253789Sahrens void
254789Sahrens cv_signal(kcondvar_t *cv)
255789Sahrens {
256*2856Snd150628 	VERIFY(cond_signal(cv) == 0);
257789Sahrens }
258789Sahrens 
259789Sahrens void
260789Sahrens cv_broadcast(kcondvar_t *cv)
261789Sahrens {
262*2856Snd150628 	VERIFY(cond_broadcast(cv) == 0);
263789Sahrens }
264789Sahrens 
265789Sahrens /*
266789Sahrens  * =========================================================================
267789Sahrens  * vnode operations
268789Sahrens  * =========================================================================
269789Sahrens  */
270789Sahrens /*
271789Sahrens  * Note: for the xxxat() versions of these functions, we assume that the
272789Sahrens  * starting vp is always rootdir (which is true for spa_directory.c, the only
273789Sahrens  * ZFS consumer of these interfaces).  We assert this is true, and then emulate
274789Sahrens  * them by adding '/' in front of the path.
275789Sahrens  */
276789Sahrens 
277789Sahrens /*ARGSUSED*/
278789Sahrens int
279789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
280789Sahrens {
281789Sahrens 	int fd;
282789Sahrens 	vnode_t *vp;
283789Sahrens 	int old_umask;
284789Sahrens 	char realpath[MAXPATHLEN];
285789Sahrens 	struct stat64 st;
286789Sahrens 
287789Sahrens 	/*
288789Sahrens 	 * If we're accessing a real disk from userland, we need to use
289789Sahrens 	 * the character interface to avoid caching.  This is particularly
290789Sahrens 	 * important if we're trying to look at a real in-kernel storage
291789Sahrens 	 * pool from userland, e.g. via zdb, because otherwise we won't
292789Sahrens 	 * see the changes occurring under the segmap cache.
293789Sahrens 	 * On the other hand, the stupid character device returns zero
294789Sahrens 	 * for its size.  So -- gag -- we open the block device to get
295789Sahrens 	 * its size, and remember it for subsequent VOP_GETATTR().
296789Sahrens 	 */
297789Sahrens 	if (strncmp(path, "/dev/", 5) == 0) {
298789Sahrens 		char *dsk;
299789Sahrens 		fd = open64(path, O_RDONLY);
300789Sahrens 		if (fd == -1)
301789Sahrens 			return (errno);
302789Sahrens 		if (fstat64(fd, &st) == -1) {
303789Sahrens 			close(fd);
304789Sahrens 			return (errno);
305789Sahrens 		}
306789Sahrens 		close(fd);
307789Sahrens 		(void) sprintf(realpath, "%s", path);
308789Sahrens 		dsk = strstr(path, "/dsk/");
309789Sahrens 		if (dsk != NULL)
310789Sahrens 			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
311789Sahrens 			    dsk + 1);
312789Sahrens 	} else {
313789Sahrens 		(void) sprintf(realpath, "%s", path);
314789Sahrens 		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
315789Sahrens 			return (errno);
316789Sahrens 	}
317789Sahrens 
318789Sahrens 	if (flags & FCREAT)
319789Sahrens 		old_umask = umask(0);
320789Sahrens 
321789Sahrens 	/*
322789Sahrens 	 * The construct 'flags - FREAD' conveniently maps combinations of
323789Sahrens 	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
324789Sahrens 	 */
325789Sahrens 	fd = open64(realpath, flags - FREAD, mode);
326789Sahrens 
327789Sahrens 	if (flags & FCREAT)
328789Sahrens 		(void) umask(old_umask);
329789Sahrens 
330789Sahrens 	if (fd == -1)
331789Sahrens 		return (errno);
332789Sahrens 
333789Sahrens 	if (fstat64(fd, &st) == -1) {
334789Sahrens 		close(fd);
335789Sahrens 		return (errno);
336789Sahrens 	}
337789Sahrens 
338789Sahrens 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
339789Sahrens 
340789Sahrens 	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
341789Sahrens 
342789Sahrens 	vp->v_fd = fd;
343789Sahrens 	vp->v_size = st.st_size;
344789Sahrens 	vp->v_path = spa_strdup(path);
345789Sahrens 
346789Sahrens 	return (0);
347789Sahrens }
348789Sahrens 
349789Sahrens int
350789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
351789Sahrens     int x3, vnode_t *startvp)
352789Sahrens {
353789Sahrens 	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
354789Sahrens 	int ret;
355789Sahrens 
356789Sahrens 	ASSERT(startvp == rootdir);
357789Sahrens 	(void) sprintf(realpath, "/%s", path);
358789Sahrens 
359789Sahrens 	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
360789Sahrens 
361789Sahrens 	umem_free(realpath, strlen(path) + 2);
362789Sahrens 
363789Sahrens 	return (ret);
364789Sahrens }
365789Sahrens 
366789Sahrens /*ARGSUSED*/
367789Sahrens int
368789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
369789Sahrens 	int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
370789Sahrens {
371789Sahrens 	ssize_t iolen, split;
372789Sahrens 
373789Sahrens 	if (uio == UIO_READ) {
374789Sahrens 		iolen = pread64(vp->v_fd, addr, len, offset);
375789Sahrens 	} else {
376789Sahrens 		/*
377789Sahrens 		 * To simulate partial disk writes, we split writes into two
378789Sahrens 		 * system calls so that the process can be killed in between.
379789Sahrens 		 */
380789Sahrens 		split = (len > 0 ? rand() % len : 0);
381789Sahrens 		iolen = pwrite64(vp->v_fd, addr, split, offset);
382789Sahrens 		iolen += pwrite64(vp->v_fd, (char *)addr + split,
383789Sahrens 		    len - split, offset + split);
384789Sahrens 	}
385789Sahrens 
386789Sahrens 	if (iolen == -1)
387789Sahrens 		return (errno);
388789Sahrens 	if (residp)
389789Sahrens 		*residp = len - iolen;
390789Sahrens 	else if (iolen != len)
391789Sahrens 		return (EIO);
392789Sahrens 	return (0);
393789Sahrens }
394789Sahrens 
395789Sahrens void
396789Sahrens vn_close(vnode_t *vp)
397789Sahrens {
398789Sahrens 	close(vp->v_fd);
399789Sahrens 	spa_strfree(vp->v_path);
400789Sahrens 	umem_free(vp, sizeof (vnode_t));
401789Sahrens }
402789Sahrens 
403789Sahrens #ifdef ZFS_DEBUG
404789Sahrens 
405789Sahrens /*
406789Sahrens  * =========================================================================
407789Sahrens  * Figure out which debugging statements to print
408789Sahrens  * =========================================================================
409789Sahrens  */
410789Sahrens 
411789Sahrens static char *dprintf_string;
412789Sahrens static int dprintf_print_all;
413789Sahrens 
414789Sahrens int
415789Sahrens dprintf_find_string(const char *string)
416789Sahrens {
417789Sahrens 	char *tmp_str = dprintf_string;
418789Sahrens 	int len = strlen(string);
419789Sahrens 
420789Sahrens 	/*
421789Sahrens 	 * Find out if this is a string we want to print.
422789Sahrens 	 * String format: file1.c,function_name1,file2.c,file3.c
423789Sahrens 	 */
424789Sahrens 
425789Sahrens 	while (tmp_str != NULL) {
426789Sahrens 		if (strncmp(tmp_str, string, len) == 0 &&
427789Sahrens 		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
428789Sahrens 			return (1);
429789Sahrens 		tmp_str = strchr(tmp_str, ',');
430789Sahrens 		if (tmp_str != NULL)
431789Sahrens 			tmp_str++; /* Get rid of , */
432789Sahrens 	}
433789Sahrens 	return (0);
434789Sahrens }
435789Sahrens 
436789Sahrens void
437789Sahrens dprintf_setup(int *argc, char **argv)
438789Sahrens {
439789Sahrens 	int i, j;
440789Sahrens 
441789Sahrens 	/*
442789Sahrens 	 * Debugging can be specified two ways: by setting the
443789Sahrens 	 * environment variable ZFS_DEBUG, or by including a
444789Sahrens 	 * "debug=..."  argument on the command line.  The command
445789Sahrens 	 * line setting overrides the environment variable.
446789Sahrens 	 */
447789Sahrens 
448789Sahrens 	for (i = 1; i < *argc; i++) {
449789Sahrens 		int len = strlen("debug=");
450789Sahrens 		/* First look for a command line argument */
451789Sahrens 		if (strncmp("debug=", argv[i], len) == 0) {
452789Sahrens 			dprintf_string = argv[i] + len;
453789Sahrens 			/* Remove from args */
454789Sahrens 			for (j = i; j < *argc; j++)
455789Sahrens 				argv[j] = argv[j+1];
456789Sahrens 			argv[j] = NULL;
457789Sahrens 			(*argc)--;
458789Sahrens 		}
459789Sahrens 	}
460789Sahrens 
461789Sahrens 	if (dprintf_string == NULL) {
462789Sahrens 		/* Look for ZFS_DEBUG environment variable */
463789Sahrens 		dprintf_string = getenv("ZFS_DEBUG");
464789Sahrens 	}
465789Sahrens 
466789Sahrens 	/*
467789Sahrens 	 * Are we just turning on all debugging?
468789Sahrens 	 */
469789Sahrens 	if (dprintf_find_string("on"))
470789Sahrens 		dprintf_print_all = 1;
471789Sahrens }
472789Sahrens 
473789Sahrens /*
474789Sahrens  * =========================================================================
475789Sahrens  * debug printfs
476789Sahrens  * =========================================================================
477789Sahrens  */
478789Sahrens void
479789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
480789Sahrens {
481789Sahrens 	const char *newfile;
482789Sahrens 	va_list adx;
483789Sahrens 
484789Sahrens 	/*
485789Sahrens 	 * Get rid of annoying "../common/" prefix to filename.
486789Sahrens 	 */
487789Sahrens 	newfile = strrchr(file, '/');
488789Sahrens 	if (newfile != NULL) {
489789Sahrens 		newfile = newfile + 1; /* Get rid of leading / */
490789Sahrens 	} else {
491789Sahrens 		newfile = file;
492789Sahrens 	}
493789Sahrens 
494789Sahrens 	if (dprintf_print_all ||
495789Sahrens 	    dprintf_find_string(newfile) ||
496789Sahrens 	    dprintf_find_string(func)) {
497789Sahrens 		/* Print out just the function name if requested */
498789Sahrens 		flockfile(stdout);
499789Sahrens 		if (dprintf_find_string("pid"))
500789Sahrens 			(void) printf("%d ", getpid());
501789Sahrens 		if (dprintf_find_string("tid"))
502789Sahrens 			(void) printf("%u ", thr_self());
503789Sahrens 		if (dprintf_find_string("cpu"))
504789Sahrens 			(void) printf("%u ", getcpuid());
505789Sahrens 		if (dprintf_find_string("time"))
506789Sahrens 			(void) printf("%llu ", gethrtime());
507789Sahrens 		if (dprintf_find_string("long"))
508789Sahrens 			(void) printf("%s, line %d: ", newfile, line);
509789Sahrens 		(void) printf("%s: ", func);
510789Sahrens 		va_start(adx, fmt);
511789Sahrens 		(void) vprintf(fmt, adx);
512789Sahrens 		va_end(adx);
513789Sahrens 		funlockfile(stdout);
514789Sahrens 	}
515789Sahrens }
516789Sahrens 
517789Sahrens #endif /* ZFS_DEBUG */
518789Sahrens 
519789Sahrens /*
520789Sahrens  * =========================================================================
521789Sahrens  * cmn_err() and panic()
522789Sahrens  * =========================================================================
523789Sahrens  */
524789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
525789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
526789Sahrens 
527789Sahrens void
528789Sahrens vpanic(const char *fmt, va_list adx)
529789Sahrens {
530789Sahrens 	(void) fprintf(stderr, "error: ");
531789Sahrens 	(void) vfprintf(stderr, fmt, adx);
532789Sahrens 	(void) fprintf(stderr, "\n");
533789Sahrens 
534789Sahrens 	abort();	/* think of it as a "user-level crash dump" */
535789Sahrens }
536789Sahrens 
537789Sahrens void
538789Sahrens panic(const char *fmt, ...)
539789Sahrens {
540789Sahrens 	va_list adx;
541789Sahrens 
542789Sahrens 	va_start(adx, fmt);
543789Sahrens 	vpanic(fmt, adx);
544789Sahrens 	va_end(adx);
545789Sahrens }
546789Sahrens 
547789Sahrens /*PRINTFLIKE2*/
548789Sahrens void
549789Sahrens cmn_err(int ce, const char *fmt, ...)
550789Sahrens {
551789Sahrens 	va_list adx;
552789Sahrens 
553789Sahrens 	va_start(adx, fmt);
554789Sahrens 	if (ce == CE_PANIC)
555789Sahrens 		vpanic(fmt, adx);
556789Sahrens 	if (ce != CE_NOTE) {	/* suppress noise in userland stress testing */
557789Sahrens 		(void) fprintf(stderr, "%s", ce_prefix[ce]);
558789Sahrens 		(void) vfprintf(stderr, fmt, adx);
559789Sahrens 		(void) fprintf(stderr, "%s", ce_suffix[ce]);
560789Sahrens 	}
561789Sahrens 	va_end(adx);
562789Sahrens }
563789Sahrens 
564789Sahrens /*
565789Sahrens  * =========================================================================
5661544Seschrock  * kobj interfaces
5671544Seschrock  * =========================================================================
5681544Seschrock  */
5691544Seschrock struct _buf *
5701544Seschrock kobj_open_file(char *name)
5711544Seschrock {
5721544Seschrock 	struct _buf *file;
5731544Seschrock 	vnode_t *vp;
5741544Seschrock 
5751544Seschrock 	/* set vp as the _fd field of the file */
5761544Seschrock 	if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir) != 0)
5771544Seschrock 		return ((void *)-1UL);
5781544Seschrock 
5791544Seschrock 	file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
5801544Seschrock 	file->_fd = (intptr_t)vp;
5811544Seschrock 	return (file);
5821544Seschrock }
5831544Seschrock 
5841544Seschrock int
5851544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
5861544Seschrock {
5871544Seschrock 	ssize_t resid;
5881544Seschrock 
5891544Seschrock 	vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
5901544Seschrock 	    UIO_SYSSPACE, 0, 0, 0, &resid);
5911544Seschrock 
5921544Seschrock 	return (0);
5931544Seschrock }
5941544Seschrock 
5951544Seschrock void
5961544Seschrock kobj_close_file(struct _buf *file)
5971544Seschrock {
5981544Seschrock 	vn_close((vnode_t *)file->_fd);
5991544Seschrock 	umem_free(file, sizeof (struct _buf));
6001544Seschrock }
6011544Seschrock 
6021544Seschrock int
6031544Seschrock kobj_fstat(intptr_t fd, struct bootstat *bst)
6041544Seschrock {
6051544Seschrock 	struct stat64 st;
6061544Seschrock 	vnode_t *vp = (vnode_t *)fd;
6071544Seschrock 	if (fstat64(vp->v_fd, &st) == -1) {
6081544Seschrock 		vn_close(vp);
6091544Seschrock 		return (errno);
6101544Seschrock 	}
6111544Seschrock 	bst->st_size = (uint64_t)st.st_size;
6121544Seschrock 	return (0);
6131544Seschrock }
6141544Seschrock 
6151544Seschrock /*
6161544Seschrock  * =========================================================================
617789Sahrens  * misc routines
618789Sahrens  * =========================================================================
619789Sahrens  */
620789Sahrens 
621789Sahrens void
622789Sahrens delay(clock_t ticks)
623789Sahrens {
624789Sahrens 	poll(0, 0, ticks * (1000 / hz));
625789Sahrens }
626789Sahrens 
627789Sahrens /*
628789Sahrens  * Find highest one bit set.
629789Sahrens  *	Returns bit number + 1 of highest bit that is set, otherwise returns 0.
630789Sahrens  * High order bit is 31 (or 63 in _LP64 kernel).
631789Sahrens  */
632789Sahrens int
633789Sahrens highbit(ulong_t i)
634789Sahrens {
635789Sahrens 	register int h = 1;
636789Sahrens 
637789Sahrens 	if (i == 0)
638789Sahrens 		return (0);
639789Sahrens #ifdef _LP64
640789Sahrens 	if (i & 0xffffffff00000000ul) {
641789Sahrens 		h += 32; i >>= 32;
642789Sahrens 	}
643789Sahrens #endif
644789Sahrens 	if (i & 0xffff0000) {
645789Sahrens 		h += 16; i >>= 16;
646789Sahrens 	}
647789Sahrens 	if (i & 0xff00) {
648789Sahrens 		h += 8; i >>= 8;
649789Sahrens 	}
650789Sahrens 	if (i & 0xf0) {
651789Sahrens 		h += 4; i >>= 4;
652789Sahrens 	}
653789Sahrens 	if (i & 0xc) {
654789Sahrens 		h += 2; i >>= 2;
655789Sahrens 	}
656789Sahrens 	if (i & 0x2) {
657789Sahrens 		h += 1;
658789Sahrens 	}
659789Sahrens 	return (h);
660789Sahrens }
661789Sahrens 
662789Sahrens static int
663789Sahrens random_get_bytes_common(uint8_t *ptr, size_t len, char *devname)
664789Sahrens {
665789Sahrens 	int fd = open(devname, O_RDONLY);
666789Sahrens 	size_t resid = len;
667789Sahrens 	ssize_t bytes;
668789Sahrens 
669789Sahrens 	ASSERT(fd != -1);
670789Sahrens 
671789Sahrens 	while (resid != 0) {
672789Sahrens 		bytes = read(fd, ptr, resid);
673789Sahrens 		ASSERT(bytes >= 0);
674789Sahrens 		ptr += bytes;
675789Sahrens 		resid -= bytes;
676789Sahrens 	}
677789Sahrens 
678789Sahrens 	close(fd);
679789Sahrens 
680789Sahrens 	return (0);
681789Sahrens }
682789Sahrens 
683789Sahrens int
684789Sahrens random_get_bytes(uint8_t *ptr, size_t len)
685789Sahrens {
686789Sahrens 	return (random_get_bytes_common(ptr, len, "/dev/random"));
687789Sahrens }
688789Sahrens 
689789Sahrens int
690789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len)
691789Sahrens {
692789Sahrens 	return (random_get_bytes_common(ptr, len, "/dev/urandom"));
693789Sahrens }
694789Sahrens 
695789Sahrens /*
696789Sahrens  * =========================================================================
697789Sahrens  * kernel emulation setup & teardown
698789Sahrens  * =========================================================================
699789Sahrens  */
700789Sahrens static int
701789Sahrens umem_out_of_memory(void)
702789Sahrens {
703789Sahrens 	char errmsg[] = "out of memory -- generating core dump\n";
704789Sahrens 
705789Sahrens 	write(fileno(stderr), errmsg, sizeof (errmsg));
706789Sahrens 	abort();
707789Sahrens 	return (0);
708789Sahrens }
709789Sahrens 
710789Sahrens void
711789Sahrens kernel_init(int mode)
712789Sahrens {
713789Sahrens 	umem_nofail_callback(umem_out_of_memory);
714789Sahrens 
715789Sahrens 	physmem = sysconf(_SC_PHYS_PAGES);
716789Sahrens 
717789Sahrens 	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
718789Sahrens 	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
719789Sahrens 
720789Sahrens 	spa_init(mode);
721789Sahrens }
722789Sahrens 
723789Sahrens void
724789Sahrens kernel_fini(void)
725789Sahrens {
726789Sahrens 	spa_fini();
727789Sahrens }
728