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>
403975Sek110237 #include <sys/utsname.h>
412856Snd150628 
42789Sahrens /*
43789Sahrens  * Emulation of kernel services in userland.
44789Sahrens  */
45789Sahrens 
46789Sahrens uint64_t physmem;
47789Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234;
483975Sek110237 char hw_serial[11];
493975Sek110237 
503975Sek110237 struct utsname utsname = {
513975Sek110237 	"userland", "libzpool", "1", "1", "na"
523975Sek110237 };
53789Sahrens 
54789Sahrens /*
55789Sahrens  * =========================================================================
56789Sahrens  * threads
57789Sahrens  * =========================================================================
58789Sahrens  */
59789Sahrens /*ARGSUSED*/
60789Sahrens kthread_t *
61789Sahrens zk_thread_create(void (*func)(), void *arg)
62789Sahrens {
63789Sahrens 	thread_t tid;
64789Sahrens 
65789Sahrens 	VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
66789Sahrens 	    &tid) == 0);
67789Sahrens 
68789Sahrens 	return ((void *)(uintptr_t)tid);
69789Sahrens }
70789Sahrens 
71789Sahrens /*
72789Sahrens  * =========================================================================
733403Sbmc  * kstats
743403Sbmc  * =========================================================================
753403Sbmc  */
763403Sbmc /*ARGSUSED*/
773403Sbmc kstat_t *
783403Sbmc kstat_create(char *module, int instance, char *name, char *class,
793403Sbmc     uchar_t type, ulong_t ndata, uchar_t ks_flag)
803403Sbmc {
813403Sbmc 	return (NULL);
823403Sbmc }
833403Sbmc 
843403Sbmc /*ARGSUSED*/
853403Sbmc void
863403Sbmc kstat_install(kstat_t *ksp)
873403Sbmc {}
883403Sbmc 
893403Sbmc /*ARGSUSED*/
903403Sbmc void
913403Sbmc kstat_delete(kstat_t *ksp)
923403Sbmc {}
933403Sbmc 
943403Sbmc /*
953403Sbmc  * =========================================================================
96789Sahrens  * mutexes
97789Sahrens  * =========================================================================
98789Sahrens  */
99789Sahrens void
100789Sahrens zmutex_init(kmutex_t *mp)
101789Sahrens {
102789Sahrens 	mp->m_owner = NULL;
103789Sahrens 	(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
104789Sahrens }
105789Sahrens 
106789Sahrens void
107789Sahrens zmutex_destroy(kmutex_t *mp)
108789Sahrens {
109789Sahrens 	ASSERT(mp->m_owner == NULL);
110789Sahrens 	(void) _mutex_destroy(&(mp)->m_lock);
111789Sahrens 	mp->m_owner = (void *)-1UL;
112789Sahrens }
113789Sahrens 
114789Sahrens void
115789Sahrens mutex_enter(kmutex_t *mp)
116789Sahrens {
117789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
118789Sahrens 	ASSERT(mp->m_owner != curthread);
1192856Snd150628 	VERIFY(mutex_lock(&mp->m_lock) == 0);
120789Sahrens 	ASSERT(mp->m_owner == NULL);
121789Sahrens 	mp->m_owner = curthread;
122789Sahrens }
123789Sahrens 
124789Sahrens int
125789Sahrens mutex_tryenter(kmutex_t *mp)
126789Sahrens {
127789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
128789Sahrens 	if (0 == mutex_trylock(&mp->m_lock)) {
129789Sahrens 		ASSERT(mp->m_owner == NULL);
130789Sahrens 		mp->m_owner = curthread;
131789Sahrens 		return (1);
132789Sahrens 	} else {
133789Sahrens 		return (0);
134789Sahrens 	}
135789Sahrens }
136789Sahrens 
137789Sahrens void
138789Sahrens mutex_exit(kmutex_t *mp)
139789Sahrens {
140789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
141789Sahrens 	mp->m_owner = NULL;
1422856Snd150628 	VERIFY(mutex_unlock(&mp->m_lock) == 0);
143789Sahrens }
144789Sahrens 
145789Sahrens void *
146789Sahrens mutex_owner(kmutex_t *mp)
147789Sahrens {
148789Sahrens 	return (mp->m_owner);
149789Sahrens }
150789Sahrens 
151789Sahrens /*
152789Sahrens  * =========================================================================
153789Sahrens  * rwlocks
154789Sahrens  * =========================================================================
155789Sahrens  */
156789Sahrens /*ARGSUSED*/
157789Sahrens void
158789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
159789Sahrens {
160789Sahrens 	rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
161789Sahrens 	rwlp->rw_owner = NULL;
162789Sahrens }
163789Sahrens 
164789Sahrens void
165789Sahrens rw_destroy(krwlock_t *rwlp)
166789Sahrens {
167789Sahrens 	rwlock_destroy(&rwlp->rw_lock);
168789Sahrens 	rwlp->rw_owner = (void *)-1UL;
169789Sahrens }
170789Sahrens 
171789Sahrens void
172789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw)
173789Sahrens {
174789Sahrens 	ASSERT(!RW_LOCK_HELD(rwlp));
175789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
176789Sahrens 	ASSERT(rwlp->rw_owner != curthread);
177789Sahrens 
178789Sahrens 	if (rw == RW_READER)
179789Sahrens 		(void) rw_rdlock(&rwlp->rw_lock);
180789Sahrens 	else
181789Sahrens 		(void) rw_wrlock(&rwlp->rw_lock);
182789Sahrens 
183789Sahrens 	rwlp->rw_owner = curthread;
184789Sahrens }
185789Sahrens 
186789Sahrens void
187789Sahrens rw_exit(krwlock_t *rwlp)
188789Sahrens {
189789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
190789Sahrens 
191789Sahrens 	rwlp->rw_owner = NULL;
192789Sahrens 	(void) rw_unlock(&rwlp->rw_lock);
193789Sahrens }
194789Sahrens 
195789Sahrens int
196789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw)
197789Sahrens {
198789Sahrens 	int rv;
199789Sahrens 
200789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
201789Sahrens 
202789Sahrens 	if (rw == RW_READER)
203789Sahrens 		rv = rw_tryrdlock(&rwlp->rw_lock);
204789Sahrens 	else
205789Sahrens 		rv = rw_trywrlock(&rwlp->rw_lock);
206789Sahrens 
207789Sahrens 	if (rv == 0) {
208789Sahrens 		rwlp->rw_owner = curthread;
209789Sahrens 		return (1);
210789Sahrens 	}
211789Sahrens 
212789Sahrens 	return (0);
213789Sahrens }
214789Sahrens 
215789Sahrens /*ARGSUSED*/
216789Sahrens int
217789Sahrens rw_tryupgrade(krwlock_t *rwlp)
218789Sahrens {
219789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
220789Sahrens 
221789Sahrens 	return (0);
222789Sahrens }
223789Sahrens 
224789Sahrens /*
225789Sahrens  * =========================================================================
226789Sahrens  * condition variables
227789Sahrens  * =========================================================================
228789Sahrens  */
229789Sahrens /*ARGSUSED*/
230789Sahrens void
231789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg)
232789Sahrens {
2332856Snd150628 	VERIFY(cond_init(cv, type, NULL) == 0);
234789Sahrens }
235789Sahrens 
236789Sahrens void
237789Sahrens cv_destroy(kcondvar_t *cv)
238789Sahrens {
2392856Snd150628 	VERIFY(cond_destroy(cv) == 0);
240789Sahrens }
241789Sahrens 
242789Sahrens void
243789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp)
244789Sahrens {
245789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
246789Sahrens 	mp->m_owner = NULL;
2472856Snd150628 	int ret = cond_wait(cv, &mp->m_lock);
2482856Snd150628 	VERIFY(ret == 0 || ret == EINTR);
249789Sahrens 	mp->m_owner = curthread;
250789Sahrens }
251789Sahrens 
252789Sahrens clock_t
253789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
254789Sahrens {
255789Sahrens 	int error;
256789Sahrens 	timestruc_t ts;
257789Sahrens 	clock_t delta;
258789Sahrens 
259789Sahrens top:
260789Sahrens 	delta = abstime - lbolt;
261789Sahrens 	if (delta <= 0)
262789Sahrens 		return (-1);
263789Sahrens 
264789Sahrens 	ts.tv_sec = delta / hz;
265789Sahrens 	ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
266789Sahrens 
267789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
268789Sahrens 	mp->m_owner = NULL;
269789Sahrens 	error = cond_reltimedwait(cv, &mp->m_lock, &ts);
270789Sahrens 	mp->m_owner = curthread;
271789Sahrens 
272789Sahrens 	if (error == ETIME)
273789Sahrens 		return (-1);
274789Sahrens 
275789Sahrens 	if (error == EINTR)
276789Sahrens 		goto top;
277789Sahrens 
278789Sahrens 	ASSERT(error == 0);
279789Sahrens 
280789Sahrens 	return (1);
281789Sahrens }
282789Sahrens 
283789Sahrens void
284789Sahrens cv_signal(kcondvar_t *cv)
285789Sahrens {
2862856Snd150628 	VERIFY(cond_signal(cv) == 0);
287789Sahrens }
288789Sahrens 
289789Sahrens void
290789Sahrens cv_broadcast(kcondvar_t *cv)
291789Sahrens {
2922856Snd150628 	VERIFY(cond_broadcast(cv) == 0);
293789Sahrens }
294789Sahrens 
295789Sahrens /*
296789Sahrens  * =========================================================================
297789Sahrens  * vnode operations
298789Sahrens  * =========================================================================
299789Sahrens  */
300789Sahrens /*
301789Sahrens  * Note: for the xxxat() versions of these functions, we assume that the
302789Sahrens  * starting vp is always rootdir (which is true for spa_directory.c, the only
303789Sahrens  * ZFS consumer of these interfaces).  We assert this is true, and then emulate
304789Sahrens  * them by adding '/' in front of the path.
305789Sahrens  */
306789Sahrens 
307789Sahrens /*ARGSUSED*/
308789Sahrens int
309789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
310789Sahrens {
311789Sahrens 	int fd;
312789Sahrens 	vnode_t *vp;
313789Sahrens 	int old_umask;
314789Sahrens 	char realpath[MAXPATHLEN];
315789Sahrens 	struct stat64 st;
316789Sahrens 
317789Sahrens 	/*
318789Sahrens 	 * If we're accessing a real disk from userland, we need to use
319789Sahrens 	 * the character interface to avoid caching.  This is particularly
320789Sahrens 	 * important if we're trying to look at a real in-kernel storage
321789Sahrens 	 * pool from userland, e.g. via zdb, because otherwise we won't
322789Sahrens 	 * see the changes occurring under the segmap cache.
323789Sahrens 	 * On the other hand, the stupid character device returns zero
324789Sahrens 	 * for its size.  So -- gag -- we open the block device to get
325789Sahrens 	 * its size, and remember it for subsequent VOP_GETATTR().
326789Sahrens 	 */
327789Sahrens 	if (strncmp(path, "/dev/", 5) == 0) {
328789Sahrens 		char *dsk;
329789Sahrens 		fd = open64(path, O_RDONLY);
330789Sahrens 		if (fd == -1)
331789Sahrens 			return (errno);
332789Sahrens 		if (fstat64(fd, &st) == -1) {
333789Sahrens 			close(fd);
334789Sahrens 			return (errno);
335789Sahrens 		}
336789Sahrens 		close(fd);
337789Sahrens 		(void) sprintf(realpath, "%s", path);
338789Sahrens 		dsk = strstr(path, "/dsk/");
339789Sahrens 		if (dsk != NULL)
340789Sahrens 			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
341789Sahrens 			    dsk + 1);
342789Sahrens 	} else {
343789Sahrens 		(void) sprintf(realpath, "%s", path);
344789Sahrens 		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
345789Sahrens 			return (errno);
346789Sahrens 	}
347789Sahrens 
348789Sahrens 	if (flags & FCREAT)
349789Sahrens 		old_umask = umask(0);
350789Sahrens 
351789Sahrens 	/*
352789Sahrens 	 * The construct 'flags - FREAD' conveniently maps combinations of
353789Sahrens 	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
354789Sahrens 	 */
355789Sahrens 	fd = open64(realpath, flags - FREAD, mode);
356789Sahrens 
357789Sahrens 	if (flags & FCREAT)
358789Sahrens 		(void) umask(old_umask);
359789Sahrens 
360789Sahrens 	if (fd == -1)
361789Sahrens 		return (errno);
362789Sahrens 
363789Sahrens 	if (fstat64(fd, &st) == -1) {
364789Sahrens 		close(fd);
365789Sahrens 		return (errno);
366789Sahrens 	}
367789Sahrens 
368789Sahrens 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
369789Sahrens 
370789Sahrens 	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
371789Sahrens 
372789Sahrens 	vp->v_fd = fd;
373789Sahrens 	vp->v_size = st.st_size;
374789Sahrens 	vp->v_path = spa_strdup(path);
375789Sahrens 
376789Sahrens 	return (0);
377789Sahrens }
378789Sahrens 
379789Sahrens int
380789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
381789Sahrens     int x3, vnode_t *startvp)
382789Sahrens {
383789Sahrens 	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
384789Sahrens 	int ret;
385789Sahrens 
386789Sahrens 	ASSERT(startvp == rootdir);
387789Sahrens 	(void) sprintf(realpath, "/%s", path);
388789Sahrens 
389789Sahrens 	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
390789Sahrens 
391789Sahrens 	umem_free(realpath, strlen(path) + 2);
392789Sahrens 
393789Sahrens 	return (ret);
394789Sahrens }
395789Sahrens 
396789Sahrens /*ARGSUSED*/
397789Sahrens int
398789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
399789Sahrens 	int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
400789Sahrens {
401789Sahrens 	ssize_t iolen, split;
402789Sahrens 
403789Sahrens 	if (uio == UIO_READ) {
404789Sahrens 		iolen = pread64(vp->v_fd, addr, len, offset);
405789Sahrens 	} else {
406789Sahrens 		/*
407789Sahrens 		 * To simulate partial disk writes, we split writes into two
408789Sahrens 		 * system calls so that the process can be killed in between.
409789Sahrens 		 */
410789Sahrens 		split = (len > 0 ? rand() % len : 0);
411789Sahrens 		iolen = pwrite64(vp->v_fd, addr, split, offset);
412789Sahrens 		iolen += pwrite64(vp->v_fd, (char *)addr + split,
413789Sahrens 		    len - split, offset + split);
414789Sahrens 	}
415789Sahrens 
416789Sahrens 	if (iolen == -1)
417789Sahrens 		return (errno);
418789Sahrens 	if (residp)
419789Sahrens 		*residp = len - iolen;
420789Sahrens 	else if (iolen != len)
421789Sahrens 		return (EIO);
422789Sahrens 	return (0);
423789Sahrens }
424789Sahrens 
425789Sahrens void
426789Sahrens vn_close(vnode_t *vp)
427789Sahrens {
428789Sahrens 	close(vp->v_fd);
429789Sahrens 	spa_strfree(vp->v_path);
430789Sahrens 	umem_free(vp, sizeof (vnode_t));
431789Sahrens }
432789Sahrens 
433789Sahrens #ifdef ZFS_DEBUG
434789Sahrens 
435789Sahrens /*
436789Sahrens  * =========================================================================
437789Sahrens  * Figure out which debugging statements to print
438789Sahrens  * =========================================================================
439789Sahrens  */
440789Sahrens 
441789Sahrens static char *dprintf_string;
442789Sahrens static int dprintf_print_all;
443789Sahrens 
444789Sahrens int
445789Sahrens dprintf_find_string(const char *string)
446789Sahrens {
447789Sahrens 	char *tmp_str = dprintf_string;
448789Sahrens 	int len = strlen(string);
449789Sahrens 
450789Sahrens 	/*
451789Sahrens 	 * Find out if this is a string we want to print.
452789Sahrens 	 * String format: file1.c,function_name1,file2.c,file3.c
453789Sahrens 	 */
454789Sahrens 
455789Sahrens 	while (tmp_str != NULL) {
456789Sahrens 		if (strncmp(tmp_str, string, len) == 0 &&
457789Sahrens 		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
458789Sahrens 			return (1);
459789Sahrens 		tmp_str = strchr(tmp_str, ',');
460789Sahrens 		if (tmp_str != NULL)
461789Sahrens 			tmp_str++; /* Get rid of , */
462789Sahrens 	}
463789Sahrens 	return (0);
464789Sahrens }
465789Sahrens 
466789Sahrens void
467789Sahrens dprintf_setup(int *argc, char **argv)
468789Sahrens {
469789Sahrens 	int i, j;
470789Sahrens 
471789Sahrens 	/*
472789Sahrens 	 * Debugging can be specified two ways: by setting the
473789Sahrens 	 * environment variable ZFS_DEBUG, or by including a
474789Sahrens 	 * "debug=..."  argument on the command line.  The command
475789Sahrens 	 * line setting overrides the environment variable.
476789Sahrens 	 */
477789Sahrens 
478789Sahrens 	for (i = 1; i < *argc; i++) {
479789Sahrens 		int len = strlen("debug=");
480789Sahrens 		/* First look for a command line argument */
481789Sahrens 		if (strncmp("debug=", argv[i], len) == 0) {
482789Sahrens 			dprintf_string = argv[i] + len;
483789Sahrens 			/* Remove from args */
484789Sahrens 			for (j = i; j < *argc; j++)
485789Sahrens 				argv[j] = argv[j+1];
486789Sahrens 			argv[j] = NULL;
487789Sahrens 			(*argc)--;
488789Sahrens 		}
489789Sahrens 	}
490789Sahrens 
491789Sahrens 	if (dprintf_string == NULL) {
492789Sahrens 		/* Look for ZFS_DEBUG environment variable */
493789Sahrens 		dprintf_string = getenv("ZFS_DEBUG");
494789Sahrens 	}
495789Sahrens 
496789Sahrens 	/*
497789Sahrens 	 * Are we just turning on all debugging?
498789Sahrens 	 */
499789Sahrens 	if (dprintf_find_string("on"))
500789Sahrens 		dprintf_print_all = 1;
501789Sahrens }
502789Sahrens 
503789Sahrens /*
504789Sahrens  * =========================================================================
505789Sahrens  * debug printfs
506789Sahrens  * =========================================================================
507789Sahrens  */
508789Sahrens void
509789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
510789Sahrens {
511789Sahrens 	const char *newfile;
512789Sahrens 	va_list adx;
513789Sahrens 
514789Sahrens 	/*
515789Sahrens 	 * Get rid of annoying "../common/" prefix to filename.
516789Sahrens 	 */
517789Sahrens 	newfile = strrchr(file, '/');
518789Sahrens 	if (newfile != NULL) {
519789Sahrens 		newfile = newfile + 1; /* Get rid of leading / */
520789Sahrens 	} else {
521789Sahrens 		newfile = file;
522789Sahrens 	}
523789Sahrens 
524789Sahrens 	if (dprintf_print_all ||
525789Sahrens 	    dprintf_find_string(newfile) ||
526789Sahrens 	    dprintf_find_string(func)) {
527789Sahrens 		/* Print out just the function name if requested */
528789Sahrens 		flockfile(stdout);
529789Sahrens 		if (dprintf_find_string("pid"))
530789Sahrens 			(void) printf("%d ", getpid());
531789Sahrens 		if (dprintf_find_string("tid"))
532789Sahrens 			(void) printf("%u ", thr_self());
533789Sahrens 		if (dprintf_find_string("cpu"))
534789Sahrens 			(void) printf("%u ", getcpuid());
535789Sahrens 		if (dprintf_find_string("time"))
536789Sahrens 			(void) printf("%llu ", gethrtime());
537789Sahrens 		if (dprintf_find_string("long"))
538789Sahrens 			(void) printf("%s, line %d: ", newfile, line);
539789Sahrens 		(void) printf("%s: ", func);
540789Sahrens 		va_start(adx, fmt);
541789Sahrens 		(void) vprintf(fmt, adx);
542789Sahrens 		va_end(adx);
543789Sahrens 		funlockfile(stdout);
544789Sahrens 	}
545789Sahrens }
546789Sahrens 
547789Sahrens #endif /* ZFS_DEBUG */
548789Sahrens 
549789Sahrens /*
550789Sahrens  * =========================================================================
551789Sahrens  * cmn_err() and panic()
552789Sahrens  * =========================================================================
553789Sahrens  */
554789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
555789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
556789Sahrens 
557789Sahrens void
558789Sahrens vpanic(const char *fmt, va_list adx)
559789Sahrens {
560789Sahrens 	(void) fprintf(stderr, "error: ");
561789Sahrens 	(void) vfprintf(stderr, fmt, adx);
562789Sahrens 	(void) fprintf(stderr, "\n");
563789Sahrens 
564789Sahrens 	abort();	/* think of it as a "user-level crash dump" */
565789Sahrens }
566789Sahrens 
567789Sahrens void
568789Sahrens panic(const char *fmt, ...)
569789Sahrens {
570789Sahrens 	va_list adx;
571789Sahrens 
572789Sahrens 	va_start(adx, fmt);
573789Sahrens 	vpanic(fmt, adx);
574789Sahrens 	va_end(adx);
575789Sahrens }
576789Sahrens 
5773713Sahrens void
5783713Sahrens vcmn_err(int ce, const char *fmt, va_list adx)
5793713Sahrens {
5803713Sahrens 	if (ce == CE_PANIC)
5813713Sahrens 		vpanic(fmt, adx);
5823713Sahrens 	if (ce != CE_NOTE) {	/* suppress noise in userland stress testing */
5833713Sahrens 		(void) fprintf(stderr, "%s", ce_prefix[ce]);
5843713Sahrens 		(void) vfprintf(stderr, fmt, adx);
5853713Sahrens 		(void) fprintf(stderr, "%s", ce_suffix[ce]);
5863713Sahrens 	}
5873713Sahrens }
5883713Sahrens 
589789Sahrens /*PRINTFLIKE2*/
590789Sahrens void
591789Sahrens cmn_err(int ce, const char *fmt, ...)
592789Sahrens {
593789Sahrens 	va_list adx;
594789Sahrens 
595789Sahrens 	va_start(adx, fmt);
5963713Sahrens 	vcmn_err(ce, fmt, adx);
597789Sahrens 	va_end(adx);
598789Sahrens }
599789Sahrens 
600789Sahrens /*
601789Sahrens  * =========================================================================
6021544Seschrock  * kobj interfaces
6031544Seschrock  * =========================================================================
6041544Seschrock  */
6051544Seschrock struct _buf *
6061544Seschrock kobj_open_file(char *name)
6071544Seschrock {
6081544Seschrock 	struct _buf *file;
6091544Seschrock 	vnode_t *vp;
6101544Seschrock 
6111544Seschrock 	/* set vp as the _fd field of the file */
6121544Seschrock 	if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir) != 0)
6131544Seschrock 		return ((void *)-1UL);
6141544Seschrock 
6151544Seschrock 	file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
6161544Seschrock 	file->_fd = (intptr_t)vp;
6171544Seschrock 	return (file);
6181544Seschrock }
6191544Seschrock 
6201544Seschrock int
6211544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
6221544Seschrock {
6231544Seschrock 	ssize_t resid;
6241544Seschrock 
6251544Seschrock 	vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
6261544Seschrock 	    UIO_SYSSPACE, 0, 0, 0, &resid);
6271544Seschrock 
6283912Slling 	return (size - resid);
6291544Seschrock }
6301544Seschrock 
6311544Seschrock void
6321544Seschrock kobj_close_file(struct _buf *file)
6331544Seschrock {
6341544Seschrock 	vn_close((vnode_t *)file->_fd);
6351544Seschrock 	umem_free(file, sizeof (struct _buf));
6361544Seschrock }
6371544Seschrock 
6381544Seschrock int
6393912Slling kobj_get_filesize(struct _buf *file, uint64_t *size)
6401544Seschrock {
6411544Seschrock 	struct stat64 st;
6423912Slling 	vnode_t *vp = (vnode_t *)file->_fd;
6433912Slling 
6441544Seschrock 	if (fstat64(vp->v_fd, &st) == -1) {
6451544Seschrock 		vn_close(vp);
6461544Seschrock 		return (errno);
6471544Seschrock 	}
6483912Slling 	*size = st.st_size;
6491544Seschrock 	return (0);
6501544Seschrock }
6511544Seschrock 
6521544Seschrock /*
6531544Seschrock  * =========================================================================
654789Sahrens  * misc routines
655789Sahrens  * =========================================================================
656789Sahrens  */
657789Sahrens 
658789Sahrens void
659789Sahrens delay(clock_t ticks)
660789Sahrens {
661789Sahrens 	poll(0, 0, ticks * (1000 / hz));
662789Sahrens }
663789Sahrens 
664789Sahrens /*
665789Sahrens  * Find highest one bit set.
666789Sahrens  *	Returns bit number + 1 of highest bit that is set, otherwise returns 0.
667789Sahrens  * High order bit is 31 (or 63 in _LP64 kernel).
668789Sahrens  */
669789Sahrens int
670789Sahrens highbit(ulong_t i)
671789Sahrens {
672789Sahrens 	register int h = 1;
673789Sahrens 
674789Sahrens 	if (i == 0)
675789Sahrens 		return (0);
676789Sahrens #ifdef _LP64
677789Sahrens 	if (i & 0xffffffff00000000ul) {
678789Sahrens 		h += 32; i >>= 32;
679789Sahrens 	}
680789Sahrens #endif
681789Sahrens 	if (i & 0xffff0000) {
682789Sahrens 		h += 16; i >>= 16;
683789Sahrens 	}
684789Sahrens 	if (i & 0xff00) {
685789Sahrens 		h += 8; i >>= 8;
686789Sahrens 	}
687789Sahrens 	if (i & 0xf0) {
688789Sahrens 		h += 4; i >>= 4;
689789Sahrens 	}
690789Sahrens 	if (i & 0xc) {
691789Sahrens 		h += 2; i >>= 2;
692789Sahrens 	}
693789Sahrens 	if (i & 0x2) {
694789Sahrens 		h += 1;
695789Sahrens 	}
696789Sahrens 	return (h);
697789Sahrens }
698789Sahrens 
699789Sahrens static int
700789Sahrens random_get_bytes_common(uint8_t *ptr, size_t len, char *devname)
701789Sahrens {
702789Sahrens 	int fd = open(devname, O_RDONLY);
703789Sahrens 	size_t resid = len;
704789Sahrens 	ssize_t bytes;
705789Sahrens 
706789Sahrens 	ASSERT(fd != -1);
707789Sahrens 
708789Sahrens 	while (resid != 0) {
709789Sahrens 		bytes = read(fd, ptr, resid);
710789Sahrens 		ASSERT(bytes >= 0);
711789Sahrens 		ptr += bytes;
712789Sahrens 		resid -= bytes;
713789Sahrens 	}
714789Sahrens 
715789Sahrens 	close(fd);
716789Sahrens 
717789Sahrens 	return (0);
718789Sahrens }
719789Sahrens 
720789Sahrens int
721789Sahrens random_get_bytes(uint8_t *ptr, size_t len)
722789Sahrens {
723789Sahrens 	return (random_get_bytes_common(ptr, len, "/dev/random"));
724789Sahrens }
725789Sahrens 
726789Sahrens int
727789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len)
728789Sahrens {
729789Sahrens 	return (random_get_bytes_common(ptr, len, "/dev/urandom"));
730789Sahrens }
731789Sahrens 
7323975Sek110237 int
7333975Sek110237 ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result)
7343975Sek110237 {
7353975Sek110237 	char *end;
7363975Sek110237 
7373975Sek110237 	*result = strtoul(hw_serial, &end, base);
7383975Sek110237 	if (*result == 0)
7393975Sek110237 		return (errno);
7403975Sek110237 	return (0);
7413975Sek110237 }
7423975Sek110237 
743789Sahrens /*
744789Sahrens  * =========================================================================
745789Sahrens  * kernel emulation setup & teardown
746789Sahrens  * =========================================================================
747789Sahrens  */
748789Sahrens static int
749789Sahrens umem_out_of_memory(void)
750789Sahrens {
751789Sahrens 	char errmsg[] = "out of memory -- generating core dump\n";
752789Sahrens 
753789Sahrens 	write(fileno(stderr), errmsg, sizeof (errmsg));
754789Sahrens 	abort();
755789Sahrens 	return (0);
756789Sahrens }
757789Sahrens 
758789Sahrens void
759789Sahrens kernel_init(int mode)
760789Sahrens {
761789Sahrens 	umem_nofail_callback(umem_out_of_memory);
762789Sahrens 
763789Sahrens 	physmem = sysconf(_SC_PHYS_PAGES);
764789Sahrens 
765789Sahrens 	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
766789Sahrens 	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
767789Sahrens 
7683975Sek110237 	snprintf(hw_serial, sizeof (hw_serial), "%ld", gethostid());
7693975Sek110237 
770789Sahrens 	spa_init(mode);
771789Sahrens }
772789Sahrens 
773789Sahrens void
774789Sahrens kernel_fini(void)
775789Sahrens {
776789Sahrens 	spa_fini();
777789Sahrens }
7783886Sahl 
7793886Sahl int
7803886Sahl z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen)
7813886Sahl {
7823886Sahl 	int ret;
7833886Sahl 	uLongf len = *dstlen;
7843886Sahl 
7853886Sahl 	if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK)
7863886Sahl 		*dstlen = (size_t)len;
7873886Sahl 
7883886Sahl 	return (ret);
7893886Sahl }
7903886Sahl 
7913886Sahl int
7923886Sahl z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen,
7933886Sahl     int level)
7943886Sahl {
7953886Sahl 	int ret;
7963886Sahl 	uLongf len = *dstlen;
7973886Sahl 
7983886Sahl 	if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK)
7993886Sahl 		*dstlen = (size_t)len;
8003886Sahl 
8013886Sahl 	return (ret);
8023886Sahl }
803*4543Smarks 
804*4543Smarks uid_t
805*4543Smarks crgetuid(cred_t *cr)
806*4543Smarks {
807*4543Smarks 	return (0);
808*4543Smarks }
809*4543Smarks 
810*4543Smarks gid_t
811*4543Smarks crgetgid(cred_t *cr)
812*4543Smarks {
813*4543Smarks 	return (0);
814*4543Smarks }
815*4543Smarks 
816*4543Smarks int
817*4543Smarks crgetngroups(cred_t *cr)
818*4543Smarks {
819*4543Smarks 	return (0);
820*4543Smarks }
821*4543Smarks 
822*4543Smarks gid_t *
823*4543Smarks crgetgroups(cred_t *cr)
824*4543Smarks {
825*4543Smarks 	return (NULL);
826*4543Smarks }
827*4543Smarks 
828*4543Smarks int
829*4543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
830*4543Smarks {
831*4543Smarks 	return (0);
832*4543Smarks }
833*4543Smarks 
834*4543Smarks int
835*4543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
836*4543Smarks {
837*4543Smarks 	return (0);
838*4543Smarks }
839*4543Smarks 
840*4543Smarks int
841*4543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
842*4543Smarks {
843*4543Smarks 	return (0);
844*4543Smarks }
845