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 /*
223403Sbmc  * 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>
293886Sahl #include <fcntl.h>
30789Sahrens #include <poll.h>
31789Sahrens #include <stdio.h>
32789Sahrens #include <stdlib.h>
333886Sahl #include <string.h>
343886Sahl #include <zlib.h>
35789Sahrens #include <sys/spa.h>
363886Sahl #include <sys/stat.h>
37789Sahrens #include <sys/processor.h>
383886Sahl #include <sys/zfs_context.h>
393886Sahl #include <sys/zmod.h>
402856Snd150628 
41789Sahrens /*
42789Sahrens  * Emulation of kernel services in userland.
43789Sahrens  */
44789Sahrens 
45789Sahrens uint64_t physmem;
46789Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234;
47789Sahrens 
48789Sahrens /*
49789Sahrens  * =========================================================================
50789Sahrens  * threads
51789Sahrens  * =========================================================================
52789Sahrens  */
53789Sahrens /*ARGSUSED*/
54789Sahrens kthread_t *
55789Sahrens zk_thread_create(void (*func)(), void *arg)
56789Sahrens {
57789Sahrens 	thread_t tid;
58789Sahrens 
59789Sahrens 	VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
60789Sahrens 	    &tid) == 0);
61789Sahrens 
62789Sahrens 	return ((void *)(uintptr_t)tid);
63789Sahrens }
64789Sahrens 
65789Sahrens /*
66789Sahrens  * =========================================================================
673403Sbmc  * kstats
683403Sbmc  * =========================================================================
693403Sbmc  */
703403Sbmc /*ARGSUSED*/
713403Sbmc kstat_t *
723403Sbmc kstat_create(char *module, int instance, char *name, char *class,
733403Sbmc     uchar_t type, ulong_t ndata, uchar_t ks_flag)
743403Sbmc {
753403Sbmc 	return (NULL);
763403Sbmc }
773403Sbmc 
783403Sbmc /*ARGSUSED*/
793403Sbmc void
803403Sbmc kstat_install(kstat_t *ksp)
813403Sbmc {}
823403Sbmc 
833403Sbmc /*ARGSUSED*/
843403Sbmc void
853403Sbmc kstat_delete(kstat_t *ksp)
863403Sbmc {}
873403Sbmc 
883403Sbmc /*
893403Sbmc  * =========================================================================
90789Sahrens  * mutexes
91789Sahrens  * =========================================================================
92789Sahrens  */
93789Sahrens void
94789Sahrens zmutex_init(kmutex_t *mp)
95789Sahrens {
96789Sahrens 	mp->m_owner = NULL;
97789Sahrens 	(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
98789Sahrens }
99789Sahrens 
100789Sahrens void
101789Sahrens zmutex_destroy(kmutex_t *mp)
102789Sahrens {
103789Sahrens 	ASSERT(mp->m_owner == NULL);
104789Sahrens 	(void) _mutex_destroy(&(mp)->m_lock);
105789Sahrens 	mp->m_owner = (void *)-1UL;
106789Sahrens }
107789Sahrens 
108789Sahrens void
109789Sahrens mutex_enter(kmutex_t *mp)
110789Sahrens {
111789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
112789Sahrens 	ASSERT(mp->m_owner != curthread);
1132856Snd150628 	VERIFY(mutex_lock(&mp->m_lock) == 0);
114789Sahrens 	ASSERT(mp->m_owner == NULL);
115789Sahrens 	mp->m_owner = curthread;
116789Sahrens }
117789Sahrens 
118789Sahrens int
119789Sahrens mutex_tryenter(kmutex_t *mp)
120789Sahrens {
121789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
122789Sahrens 	if (0 == mutex_trylock(&mp->m_lock)) {
123789Sahrens 		ASSERT(mp->m_owner == NULL);
124789Sahrens 		mp->m_owner = curthread;
125789Sahrens 		return (1);
126789Sahrens 	} else {
127789Sahrens 		return (0);
128789Sahrens 	}
129789Sahrens }
130789Sahrens 
131789Sahrens void
132789Sahrens mutex_exit(kmutex_t *mp)
133789Sahrens {
134789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
135789Sahrens 	mp->m_owner = NULL;
1362856Snd150628 	VERIFY(mutex_unlock(&mp->m_lock) == 0);
137789Sahrens }
138789Sahrens 
139789Sahrens void *
140789Sahrens mutex_owner(kmutex_t *mp)
141789Sahrens {
142789Sahrens 	return (mp->m_owner);
143789Sahrens }
144789Sahrens 
145789Sahrens /*
146789Sahrens  * =========================================================================
147789Sahrens  * rwlocks
148789Sahrens  * =========================================================================
149789Sahrens  */
150789Sahrens /*ARGSUSED*/
151789Sahrens void
152789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
153789Sahrens {
154789Sahrens 	rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
155789Sahrens 	rwlp->rw_owner = NULL;
156789Sahrens }
157789Sahrens 
158789Sahrens void
159789Sahrens rw_destroy(krwlock_t *rwlp)
160789Sahrens {
161789Sahrens 	rwlock_destroy(&rwlp->rw_lock);
162789Sahrens 	rwlp->rw_owner = (void *)-1UL;
163789Sahrens }
164789Sahrens 
165789Sahrens void
166789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw)
167789Sahrens {
168789Sahrens 	ASSERT(!RW_LOCK_HELD(rwlp));
169789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
170789Sahrens 	ASSERT(rwlp->rw_owner != curthread);
171789Sahrens 
172789Sahrens 	if (rw == RW_READER)
173789Sahrens 		(void) rw_rdlock(&rwlp->rw_lock);
174789Sahrens 	else
175789Sahrens 		(void) rw_wrlock(&rwlp->rw_lock);
176789Sahrens 
177789Sahrens 	rwlp->rw_owner = curthread;
178789Sahrens }
179789Sahrens 
180789Sahrens void
181789Sahrens rw_exit(krwlock_t *rwlp)
182789Sahrens {
183789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
184789Sahrens 
185789Sahrens 	rwlp->rw_owner = NULL;
186789Sahrens 	(void) rw_unlock(&rwlp->rw_lock);
187789Sahrens }
188789Sahrens 
189789Sahrens int
190789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw)
191789Sahrens {
192789Sahrens 	int rv;
193789Sahrens 
194789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
195789Sahrens 
196789Sahrens 	if (rw == RW_READER)
197789Sahrens 		rv = rw_tryrdlock(&rwlp->rw_lock);
198789Sahrens 	else
199789Sahrens 		rv = rw_trywrlock(&rwlp->rw_lock);
200789Sahrens 
201789Sahrens 	if (rv == 0) {
202789Sahrens 		rwlp->rw_owner = curthread;
203789Sahrens 		return (1);
204789Sahrens 	}
205789Sahrens 
206789Sahrens 	return (0);
207789Sahrens }
208789Sahrens 
209789Sahrens /*ARGSUSED*/
210789Sahrens int
211789Sahrens rw_tryupgrade(krwlock_t *rwlp)
212789Sahrens {
213789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
214789Sahrens 
215789Sahrens 	return (0);
216789Sahrens }
217789Sahrens 
218789Sahrens /*
219789Sahrens  * =========================================================================
220789Sahrens  * condition variables
221789Sahrens  * =========================================================================
222789Sahrens  */
223789Sahrens /*ARGSUSED*/
224789Sahrens void
225789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg)
226789Sahrens {
2272856Snd150628 	VERIFY(cond_init(cv, type, NULL) == 0);
228789Sahrens }
229789Sahrens 
230789Sahrens void
231789Sahrens cv_destroy(kcondvar_t *cv)
232789Sahrens {
2332856Snd150628 	VERIFY(cond_destroy(cv) == 0);
234789Sahrens }
235789Sahrens 
236789Sahrens void
237789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp)
238789Sahrens {
239789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
240789Sahrens 	mp->m_owner = NULL;
2412856Snd150628 	int ret = cond_wait(cv, &mp->m_lock);
2422856Snd150628 	VERIFY(ret == 0 || ret == EINTR);
243789Sahrens 	mp->m_owner = curthread;
244789Sahrens }
245789Sahrens 
246789Sahrens clock_t
247789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
248789Sahrens {
249789Sahrens 	int error;
250789Sahrens 	timestruc_t ts;
251789Sahrens 	clock_t delta;
252789Sahrens 
253789Sahrens top:
254789Sahrens 	delta = abstime - lbolt;
255789Sahrens 	if (delta <= 0)
256789Sahrens 		return (-1);
257789Sahrens 
258789Sahrens 	ts.tv_sec = delta / hz;
259789Sahrens 	ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
260789Sahrens 
261789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
262789Sahrens 	mp->m_owner = NULL;
263789Sahrens 	error = cond_reltimedwait(cv, &mp->m_lock, &ts);
264789Sahrens 	mp->m_owner = curthread;
265789Sahrens 
266789Sahrens 	if (error == ETIME)
267789Sahrens 		return (-1);
268789Sahrens 
269789Sahrens 	if (error == EINTR)
270789Sahrens 		goto top;
271789Sahrens 
272789Sahrens 	ASSERT(error == 0);
273789Sahrens 
274789Sahrens 	return (1);
275789Sahrens }
276789Sahrens 
277789Sahrens void
278789Sahrens cv_signal(kcondvar_t *cv)
279789Sahrens {
2802856Snd150628 	VERIFY(cond_signal(cv) == 0);
281789Sahrens }
282789Sahrens 
283789Sahrens void
284789Sahrens cv_broadcast(kcondvar_t *cv)
285789Sahrens {
2862856Snd150628 	VERIFY(cond_broadcast(cv) == 0);
287789Sahrens }
288789Sahrens 
289789Sahrens /*
290789Sahrens  * =========================================================================
291789Sahrens  * vnode operations
292789Sahrens  * =========================================================================
293789Sahrens  */
294789Sahrens /*
295789Sahrens  * Note: for the xxxat() versions of these functions, we assume that the
296789Sahrens  * starting vp is always rootdir (which is true for spa_directory.c, the only
297789Sahrens  * ZFS consumer of these interfaces).  We assert this is true, and then emulate
298789Sahrens  * them by adding '/' in front of the path.
299789Sahrens  */
300789Sahrens 
301789Sahrens /*ARGSUSED*/
302789Sahrens int
303789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
304789Sahrens {
305789Sahrens 	int fd;
306789Sahrens 	vnode_t *vp;
307789Sahrens 	int old_umask;
308789Sahrens 	char realpath[MAXPATHLEN];
309789Sahrens 	struct stat64 st;
310789Sahrens 
311789Sahrens 	/*
312789Sahrens 	 * If we're accessing a real disk from userland, we need to use
313789Sahrens 	 * the character interface to avoid caching.  This is particularly
314789Sahrens 	 * important if we're trying to look at a real in-kernel storage
315789Sahrens 	 * pool from userland, e.g. via zdb, because otherwise we won't
316789Sahrens 	 * see the changes occurring under the segmap cache.
317789Sahrens 	 * On the other hand, the stupid character device returns zero
318789Sahrens 	 * for its size.  So -- gag -- we open the block device to get
319789Sahrens 	 * its size, and remember it for subsequent VOP_GETATTR().
320789Sahrens 	 */
321789Sahrens 	if (strncmp(path, "/dev/", 5) == 0) {
322789Sahrens 		char *dsk;
323789Sahrens 		fd = open64(path, O_RDONLY);
324789Sahrens 		if (fd == -1)
325789Sahrens 			return (errno);
326789Sahrens 		if (fstat64(fd, &st) == -1) {
327789Sahrens 			close(fd);
328789Sahrens 			return (errno);
329789Sahrens 		}
330789Sahrens 		close(fd);
331789Sahrens 		(void) sprintf(realpath, "%s", path);
332789Sahrens 		dsk = strstr(path, "/dsk/");
333789Sahrens 		if (dsk != NULL)
334789Sahrens 			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
335789Sahrens 			    dsk + 1);
336789Sahrens 	} else {
337789Sahrens 		(void) sprintf(realpath, "%s", path);
338789Sahrens 		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
339789Sahrens 			return (errno);
340789Sahrens 	}
341789Sahrens 
342789Sahrens 	if (flags & FCREAT)
343789Sahrens 		old_umask = umask(0);
344789Sahrens 
345789Sahrens 	/*
346789Sahrens 	 * The construct 'flags - FREAD' conveniently maps combinations of
347789Sahrens 	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
348789Sahrens 	 */
349789Sahrens 	fd = open64(realpath, flags - FREAD, mode);
350789Sahrens 
351789Sahrens 	if (flags & FCREAT)
352789Sahrens 		(void) umask(old_umask);
353789Sahrens 
354789Sahrens 	if (fd == -1)
355789Sahrens 		return (errno);
356789Sahrens 
357789Sahrens 	if (fstat64(fd, &st) == -1) {
358789Sahrens 		close(fd);
359789Sahrens 		return (errno);
360789Sahrens 	}
361789Sahrens 
362789Sahrens 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
363789Sahrens 
364789Sahrens 	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
365789Sahrens 
366789Sahrens 	vp->v_fd = fd;
367789Sahrens 	vp->v_size = st.st_size;
368789Sahrens 	vp->v_path = spa_strdup(path);
369789Sahrens 
370789Sahrens 	return (0);
371789Sahrens }
372789Sahrens 
373789Sahrens int
374789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
375789Sahrens     int x3, vnode_t *startvp)
376789Sahrens {
377789Sahrens 	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
378789Sahrens 	int ret;
379789Sahrens 
380789Sahrens 	ASSERT(startvp == rootdir);
381789Sahrens 	(void) sprintf(realpath, "/%s", path);
382789Sahrens 
383789Sahrens 	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
384789Sahrens 
385789Sahrens 	umem_free(realpath, strlen(path) + 2);
386789Sahrens 
387789Sahrens 	return (ret);
388789Sahrens }
389789Sahrens 
390789Sahrens /*ARGSUSED*/
391789Sahrens int
392789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
393789Sahrens 	int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
394789Sahrens {
395789Sahrens 	ssize_t iolen, split;
396789Sahrens 
397789Sahrens 	if (uio == UIO_READ) {
398789Sahrens 		iolen = pread64(vp->v_fd, addr, len, offset);
399789Sahrens 	} else {
400789Sahrens 		/*
401789Sahrens 		 * To simulate partial disk writes, we split writes into two
402789Sahrens 		 * system calls so that the process can be killed in between.
403789Sahrens 		 */
404789Sahrens 		split = (len > 0 ? rand() % len : 0);
405789Sahrens 		iolen = pwrite64(vp->v_fd, addr, split, offset);
406789Sahrens 		iolen += pwrite64(vp->v_fd, (char *)addr + split,
407789Sahrens 		    len - split, offset + split);
408789Sahrens 	}
409789Sahrens 
410789Sahrens 	if (iolen == -1)
411789Sahrens 		return (errno);
412789Sahrens 	if (residp)
413789Sahrens 		*residp = len - iolen;
414789Sahrens 	else if (iolen != len)
415789Sahrens 		return (EIO);
416789Sahrens 	return (0);
417789Sahrens }
418789Sahrens 
419789Sahrens void
420789Sahrens vn_close(vnode_t *vp)
421789Sahrens {
422789Sahrens 	close(vp->v_fd);
423789Sahrens 	spa_strfree(vp->v_path);
424789Sahrens 	umem_free(vp, sizeof (vnode_t));
425789Sahrens }
426789Sahrens 
427789Sahrens #ifdef ZFS_DEBUG
428789Sahrens 
429789Sahrens /*
430789Sahrens  * =========================================================================
431789Sahrens  * Figure out which debugging statements to print
432789Sahrens  * =========================================================================
433789Sahrens  */
434789Sahrens 
435789Sahrens static char *dprintf_string;
436789Sahrens static int dprintf_print_all;
437789Sahrens 
438789Sahrens int
439789Sahrens dprintf_find_string(const char *string)
440789Sahrens {
441789Sahrens 	char *tmp_str = dprintf_string;
442789Sahrens 	int len = strlen(string);
443789Sahrens 
444789Sahrens 	/*
445789Sahrens 	 * Find out if this is a string we want to print.
446789Sahrens 	 * String format: file1.c,function_name1,file2.c,file3.c
447789Sahrens 	 */
448789Sahrens 
449789Sahrens 	while (tmp_str != NULL) {
450789Sahrens 		if (strncmp(tmp_str, string, len) == 0 &&
451789Sahrens 		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
452789Sahrens 			return (1);
453789Sahrens 		tmp_str = strchr(tmp_str, ',');
454789Sahrens 		if (tmp_str != NULL)
455789Sahrens 			tmp_str++; /* Get rid of , */
456789Sahrens 	}
457789Sahrens 	return (0);
458789Sahrens }
459789Sahrens 
460789Sahrens void
461789Sahrens dprintf_setup(int *argc, char **argv)
462789Sahrens {
463789Sahrens 	int i, j;
464789Sahrens 
465789Sahrens 	/*
466789Sahrens 	 * Debugging can be specified two ways: by setting the
467789Sahrens 	 * environment variable ZFS_DEBUG, or by including a
468789Sahrens 	 * "debug=..."  argument on the command line.  The command
469789Sahrens 	 * line setting overrides the environment variable.
470789Sahrens 	 */
471789Sahrens 
472789Sahrens 	for (i = 1; i < *argc; i++) {
473789Sahrens 		int len = strlen("debug=");
474789Sahrens 		/* First look for a command line argument */
475789Sahrens 		if (strncmp("debug=", argv[i], len) == 0) {
476789Sahrens 			dprintf_string = argv[i] + len;
477789Sahrens 			/* Remove from args */
478789Sahrens 			for (j = i; j < *argc; j++)
479789Sahrens 				argv[j] = argv[j+1];
480789Sahrens 			argv[j] = NULL;
481789Sahrens 			(*argc)--;
482789Sahrens 		}
483789Sahrens 	}
484789Sahrens 
485789Sahrens 	if (dprintf_string == NULL) {
486789Sahrens 		/* Look for ZFS_DEBUG environment variable */
487789Sahrens 		dprintf_string = getenv("ZFS_DEBUG");
488789Sahrens 	}
489789Sahrens 
490789Sahrens 	/*
491789Sahrens 	 * Are we just turning on all debugging?
492789Sahrens 	 */
493789Sahrens 	if (dprintf_find_string("on"))
494789Sahrens 		dprintf_print_all = 1;
495789Sahrens }
496789Sahrens 
497789Sahrens /*
498789Sahrens  * =========================================================================
499789Sahrens  * debug printfs
500789Sahrens  * =========================================================================
501789Sahrens  */
502789Sahrens void
503789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
504789Sahrens {
505789Sahrens 	const char *newfile;
506789Sahrens 	va_list adx;
507789Sahrens 
508789Sahrens 	/*
509789Sahrens 	 * Get rid of annoying "../common/" prefix to filename.
510789Sahrens 	 */
511789Sahrens 	newfile = strrchr(file, '/');
512789Sahrens 	if (newfile != NULL) {
513789Sahrens 		newfile = newfile + 1; /* Get rid of leading / */
514789Sahrens 	} else {
515789Sahrens 		newfile = file;
516789Sahrens 	}
517789Sahrens 
518789Sahrens 	if (dprintf_print_all ||
519789Sahrens 	    dprintf_find_string(newfile) ||
520789Sahrens 	    dprintf_find_string(func)) {
521789Sahrens 		/* Print out just the function name if requested */
522789Sahrens 		flockfile(stdout);
523789Sahrens 		if (dprintf_find_string("pid"))
524789Sahrens 			(void) printf("%d ", getpid());
525789Sahrens 		if (dprintf_find_string("tid"))
526789Sahrens 			(void) printf("%u ", thr_self());
527789Sahrens 		if (dprintf_find_string("cpu"))
528789Sahrens 			(void) printf("%u ", getcpuid());
529789Sahrens 		if (dprintf_find_string("time"))
530789Sahrens 			(void) printf("%llu ", gethrtime());
531789Sahrens 		if (dprintf_find_string("long"))
532789Sahrens 			(void) printf("%s, line %d: ", newfile, line);
533789Sahrens 		(void) printf("%s: ", func);
534789Sahrens 		va_start(adx, fmt);
535789Sahrens 		(void) vprintf(fmt, adx);
536789Sahrens 		va_end(adx);
537789Sahrens 		funlockfile(stdout);
538789Sahrens 	}
539789Sahrens }
540789Sahrens 
541789Sahrens #endif /* ZFS_DEBUG */
542789Sahrens 
543789Sahrens /*
544789Sahrens  * =========================================================================
545789Sahrens  * cmn_err() and panic()
546789Sahrens  * =========================================================================
547789Sahrens  */
548789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
549789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
550789Sahrens 
551789Sahrens void
552789Sahrens vpanic(const char *fmt, va_list adx)
553789Sahrens {
554789Sahrens 	(void) fprintf(stderr, "error: ");
555789Sahrens 	(void) vfprintf(stderr, fmt, adx);
556789Sahrens 	(void) fprintf(stderr, "\n");
557789Sahrens 
558789Sahrens 	abort();	/* think of it as a "user-level crash dump" */
559789Sahrens }
560789Sahrens 
561789Sahrens void
562789Sahrens panic(const char *fmt, ...)
563789Sahrens {
564789Sahrens 	va_list adx;
565789Sahrens 
566789Sahrens 	va_start(adx, fmt);
567789Sahrens 	vpanic(fmt, adx);
568789Sahrens 	va_end(adx);
569789Sahrens }
570789Sahrens 
5713713Sahrens void
5723713Sahrens vcmn_err(int ce, const char *fmt, va_list adx)
5733713Sahrens {
5743713Sahrens 	if (ce == CE_PANIC)
5753713Sahrens 		vpanic(fmt, adx);
5763713Sahrens 	if (ce != CE_NOTE) {	/* suppress noise in userland stress testing */
5773713Sahrens 		(void) fprintf(stderr, "%s", ce_prefix[ce]);
5783713Sahrens 		(void) vfprintf(stderr, fmt, adx);
5793713Sahrens 		(void) fprintf(stderr, "%s", ce_suffix[ce]);
5803713Sahrens 	}
5813713Sahrens }
5823713Sahrens 
583789Sahrens /*PRINTFLIKE2*/
584789Sahrens void
585789Sahrens cmn_err(int ce, const char *fmt, ...)
586789Sahrens {
587789Sahrens 	va_list adx;
588789Sahrens 
589789Sahrens 	va_start(adx, fmt);
5903713Sahrens 	vcmn_err(ce, fmt, adx);
591789Sahrens 	va_end(adx);
592789Sahrens }
593789Sahrens 
594789Sahrens /*
595789Sahrens  * =========================================================================
5961544Seschrock  * kobj interfaces
5971544Seschrock  * =========================================================================
5981544Seschrock  */
5991544Seschrock struct _buf *
6001544Seschrock kobj_open_file(char *name)
6011544Seschrock {
6021544Seschrock 	struct _buf *file;
6031544Seschrock 	vnode_t *vp;
6041544Seschrock 
6051544Seschrock 	/* set vp as the _fd field of the file */
6061544Seschrock 	if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir) != 0)
6071544Seschrock 		return ((void *)-1UL);
6081544Seschrock 
6091544Seschrock 	file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
6101544Seschrock 	file->_fd = (intptr_t)vp;
6111544Seschrock 	return (file);
6121544Seschrock }
6131544Seschrock 
6141544Seschrock int
6151544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
6161544Seschrock {
6171544Seschrock 	ssize_t resid;
6181544Seschrock 
6191544Seschrock 	vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
6201544Seschrock 	    UIO_SYSSPACE, 0, 0, 0, &resid);
6211544Seschrock 
622*3912Slling 	return (size - resid);
6231544Seschrock }
6241544Seschrock 
6251544Seschrock void
6261544Seschrock kobj_close_file(struct _buf *file)
6271544Seschrock {
6281544Seschrock 	vn_close((vnode_t *)file->_fd);
6291544Seschrock 	umem_free(file, sizeof (struct _buf));
6301544Seschrock }
6311544Seschrock 
6321544Seschrock int
633*3912Slling kobj_get_filesize(struct _buf *file, uint64_t *size)
6341544Seschrock {
6351544Seschrock 	struct stat64 st;
636*3912Slling 	vnode_t *vp = (vnode_t *)file->_fd;
637*3912Slling 
6381544Seschrock 	if (fstat64(vp->v_fd, &st) == -1) {
6391544Seschrock 		vn_close(vp);
6401544Seschrock 		return (errno);
6411544Seschrock 	}
642*3912Slling 	*size = st.st_size;
6431544Seschrock 	return (0);
6441544Seschrock }
6451544Seschrock 
6461544Seschrock /*
6471544Seschrock  * =========================================================================
648789Sahrens  * misc routines
649789Sahrens  * =========================================================================
650789Sahrens  */
651789Sahrens 
652789Sahrens void
653789Sahrens delay(clock_t ticks)
654789Sahrens {
655789Sahrens 	poll(0, 0, ticks * (1000 / hz));
656789Sahrens }
657789Sahrens 
658789Sahrens /*
659789Sahrens  * Find highest one bit set.
660789Sahrens  *	Returns bit number + 1 of highest bit that is set, otherwise returns 0.
661789Sahrens  * High order bit is 31 (or 63 in _LP64 kernel).
662789Sahrens  */
663789Sahrens int
664789Sahrens highbit(ulong_t i)
665789Sahrens {
666789Sahrens 	register int h = 1;
667789Sahrens 
668789Sahrens 	if (i == 0)
669789Sahrens 		return (0);
670789Sahrens #ifdef _LP64
671789Sahrens 	if (i & 0xffffffff00000000ul) {
672789Sahrens 		h += 32; i >>= 32;
673789Sahrens 	}
674789Sahrens #endif
675789Sahrens 	if (i & 0xffff0000) {
676789Sahrens 		h += 16; i >>= 16;
677789Sahrens 	}
678789Sahrens 	if (i & 0xff00) {
679789Sahrens 		h += 8; i >>= 8;
680789Sahrens 	}
681789Sahrens 	if (i & 0xf0) {
682789Sahrens 		h += 4; i >>= 4;
683789Sahrens 	}
684789Sahrens 	if (i & 0xc) {
685789Sahrens 		h += 2; i >>= 2;
686789Sahrens 	}
687789Sahrens 	if (i & 0x2) {
688789Sahrens 		h += 1;
689789Sahrens 	}
690789Sahrens 	return (h);
691789Sahrens }
692789Sahrens 
693789Sahrens static int
694789Sahrens random_get_bytes_common(uint8_t *ptr, size_t len, char *devname)
695789Sahrens {
696789Sahrens 	int fd = open(devname, O_RDONLY);
697789Sahrens 	size_t resid = len;
698789Sahrens 	ssize_t bytes;
699789Sahrens 
700789Sahrens 	ASSERT(fd != -1);
701789Sahrens 
702789Sahrens 	while (resid != 0) {
703789Sahrens 		bytes = read(fd, ptr, resid);
704789Sahrens 		ASSERT(bytes >= 0);
705789Sahrens 		ptr += bytes;
706789Sahrens 		resid -= bytes;
707789Sahrens 	}
708789Sahrens 
709789Sahrens 	close(fd);
710789Sahrens 
711789Sahrens 	return (0);
712789Sahrens }
713789Sahrens 
714789Sahrens int
715789Sahrens random_get_bytes(uint8_t *ptr, size_t len)
716789Sahrens {
717789Sahrens 	return (random_get_bytes_common(ptr, len, "/dev/random"));
718789Sahrens }
719789Sahrens 
720789Sahrens int
721789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len)
722789Sahrens {
723789Sahrens 	return (random_get_bytes_common(ptr, len, "/dev/urandom"));
724789Sahrens }
725789Sahrens 
726789Sahrens /*
727789Sahrens  * =========================================================================
728789Sahrens  * kernel emulation setup & teardown
729789Sahrens  * =========================================================================
730789Sahrens  */
731789Sahrens static int
732789Sahrens umem_out_of_memory(void)
733789Sahrens {
734789Sahrens 	char errmsg[] = "out of memory -- generating core dump\n";
735789Sahrens 
736789Sahrens 	write(fileno(stderr), errmsg, sizeof (errmsg));
737789Sahrens 	abort();
738789Sahrens 	return (0);
739789Sahrens }
740789Sahrens 
741789Sahrens void
742789Sahrens kernel_init(int mode)
743789Sahrens {
744789Sahrens 	umem_nofail_callback(umem_out_of_memory);
745789Sahrens 
746789Sahrens 	physmem = sysconf(_SC_PHYS_PAGES);
747789Sahrens 
748789Sahrens 	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
749789Sahrens 	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
750789Sahrens 
751789Sahrens 	spa_init(mode);
752789Sahrens }
753789Sahrens 
754789Sahrens void
755789Sahrens kernel_fini(void)
756789Sahrens {
757789Sahrens 	spa_fini();
758789Sahrens }
7593886Sahl 
7603886Sahl int
7613886Sahl z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen)
7623886Sahl {
7633886Sahl 	int ret;
7643886Sahl 	uLongf len = *dstlen;
7653886Sahl 
7663886Sahl 	if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK)
7673886Sahl 		*dstlen = (size_t)len;
7683886Sahl 
7693886Sahl 	return (ret);
7703886Sahl }
7713886Sahl 
7723886Sahl int
7733886Sahl z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen,
7743886Sahl     int level)
7753886Sahl {
7763886Sahl 	int ret;
7773886Sahl 	uLongf len = *dstlen;
7783886Sahl 
7793886Sahl 	if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK)
7803886Sahl 		*dstlen = (size_t)len;
7813886Sahl 
7823886Sahl 	return (ret);
7833886Sahl }
784