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;
1034831Sgw25295 	mp->initialized = B_TRUE;
104789Sahrens 	(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
105789Sahrens }
106789Sahrens 
107789Sahrens void
108789Sahrens zmutex_destroy(kmutex_t *mp)
109789Sahrens {
1104831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
111789Sahrens 	ASSERT(mp->m_owner == NULL);
112789Sahrens 	(void) _mutex_destroy(&(mp)->m_lock);
113789Sahrens 	mp->m_owner = (void *)-1UL;
1144831Sgw25295 	mp->initialized = B_FALSE;
115789Sahrens }
116789Sahrens 
117789Sahrens void
118789Sahrens mutex_enter(kmutex_t *mp)
119789Sahrens {
1204831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
121789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
122789Sahrens 	ASSERT(mp->m_owner != curthread);
1232856Snd150628 	VERIFY(mutex_lock(&mp->m_lock) == 0);
124789Sahrens 	ASSERT(mp->m_owner == NULL);
125789Sahrens 	mp->m_owner = curthread;
126789Sahrens }
127789Sahrens 
128789Sahrens int
129789Sahrens mutex_tryenter(kmutex_t *mp)
130789Sahrens {
1314831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
132789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
133789Sahrens 	if (0 == mutex_trylock(&mp->m_lock)) {
134789Sahrens 		ASSERT(mp->m_owner == NULL);
135789Sahrens 		mp->m_owner = curthread;
136789Sahrens 		return (1);
137789Sahrens 	} else {
138789Sahrens 		return (0);
139789Sahrens 	}
140789Sahrens }
141789Sahrens 
142789Sahrens void
143789Sahrens mutex_exit(kmutex_t *mp)
144789Sahrens {
1454831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
146789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
147789Sahrens 	mp->m_owner = NULL;
1482856Snd150628 	VERIFY(mutex_unlock(&mp->m_lock) == 0);
149789Sahrens }
150789Sahrens 
151789Sahrens void *
152789Sahrens mutex_owner(kmutex_t *mp)
153789Sahrens {
1544831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
155789Sahrens 	return (mp->m_owner);
156789Sahrens }
157789Sahrens 
158789Sahrens /*
159789Sahrens  * =========================================================================
160789Sahrens  * rwlocks
161789Sahrens  * =========================================================================
162789Sahrens  */
163789Sahrens /*ARGSUSED*/
164789Sahrens void
165789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
166789Sahrens {
167789Sahrens 	rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
168789Sahrens 	rwlp->rw_owner = NULL;
1694831Sgw25295 	rwlp->initialized = B_TRUE;
170789Sahrens }
171789Sahrens 
172789Sahrens void
173789Sahrens rw_destroy(krwlock_t *rwlp)
174789Sahrens {
175789Sahrens 	rwlock_destroy(&rwlp->rw_lock);
176789Sahrens 	rwlp->rw_owner = (void *)-1UL;
1774831Sgw25295 	rwlp->initialized = B_FALSE;
178789Sahrens }
179789Sahrens 
180789Sahrens void
181789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw)
182789Sahrens {
183789Sahrens 	ASSERT(!RW_LOCK_HELD(rwlp));
1844831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
185789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
186789Sahrens 	ASSERT(rwlp->rw_owner != curthread);
187789Sahrens 
188789Sahrens 	if (rw == RW_READER)
189789Sahrens 		(void) rw_rdlock(&rwlp->rw_lock);
190789Sahrens 	else
191789Sahrens 		(void) rw_wrlock(&rwlp->rw_lock);
192789Sahrens 
193789Sahrens 	rwlp->rw_owner = curthread;
194789Sahrens }
195789Sahrens 
196789Sahrens void
197789Sahrens rw_exit(krwlock_t *rwlp)
198789Sahrens {
1994831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
200789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
201789Sahrens 
202789Sahrens 	rwlp->rw_owner = NULL;
203789Sahrens 	(void) rw_unlock(&rwlp->rw_lock);
204789Sahrens }
205789Sahrens 
206789Sahrens int
207789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw)
208789Sahrens {
209789Sahrens 	int rv;
210789Sahrens 
2114831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
212789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
213789Sahrens 
214789Sahrens 	if (rw == RW_READER)
215789Sahrens 		rv = rw_tryrdlock(&rwlp->rw_lock);
216789Sahrens 	else
217789Sahrens 		rv = rw_trywrlock(&rwlp->rw_lock);
218789Sahrens 
219789Sahrens 	if (rv == 0) {
220789Sahrens 		rwlp->rw_owner = curthread;
221789Sahrens 		return (1);
222789Sahrens 	}
223789Sahrens 
224789Sahrens 	return (0);
225789Sahrens }
226789Sahrens 
227789Sahrens /*ARGSUSED*/
228789Sahrens int
229789Sahrens rw_tryupgrade(krwlock_t *rwlp)
230789Sahrens {
2314831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
232789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
233789Sahrens 
234789Sahrens 	return (0);
235789Sahrens }
236789Sahrens 
237789Sahrens /*
238789Sahrens  * =========================================================================
239789Sahrens  * condition variables
240789Sahrens  * =========================================================================
241789Sahrens  */
242789Sahrens /*ARGSUSED*/
243789Sahrens void
244789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg)
245789Sahrens {
2462856Snd150628 	VERIFY(cond_init(cv, type, NULL) == 0);
247789Sahrens }
248789Sahrens 
249789Sahrens void
250789Sahrens cv_destroy(kcondvar_t *cv)
251789Sahrens {
2522856Snd150628 	VERIFY(cond_destroy(cv) == 0);
253789Sahrens }
254789Sahrens 
255789Sahrens void
256789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp)
257789Sahrens {
258789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
259789Sahrens 	mp->m_owner = NULL;
2602856Snd150628 	int ret = cond_wait(cv, &mp->m_lock);
2612856Snd150628 	VERIFY(ret == 0 || ret == EINTR);
262789Sahrens 	mp->m_owner = curthread;
263789Sahrens }
264789Sahrens 
265789Sahrens clock_t
266789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
267789Sahrens {
268789Sahrens 	int error;
269789Sahrens 	timestruc_t ts;
270789Sahrens 	clock_t delta;
271789Sahrens 
272789Sahrens top:
273789Sahrens 	delta = abstime - lbolt;
274789Sahrens 	if (delta <= 0)
275789Sahrens 		return (-1);
276789Sahrens 
277789Sahrens 	ts.tv_sec = delta / hz;
278789Sahrens 	ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
279789Sahrens 
280789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
281789Sahrens 	mp->m_owner = NULL;
282789Sahrens 	error = cond_reltimedwait(cv, &mp->m_lock, &ts);
283789Sahrens 	mp->m_owner = curthread;
284789Sahrens 
285789Sahrens 	if (error == ETIME)
286789Sahrens 		return (-1);
287789Sahrens 
288789Sahrens 	if (error == EINTR)
289789Sahrens 		goto top;
290789Sahrens 
291789Sahrens 	ASSERT(error == 0);
292789Sahrens 
293789Sahrens 	return (1);
294789Sahrens }
295789Sahrens 
296789Sahrens void
297789Sahrens cv_signal(kcondvar_t *cv)
298789Sahrens {
2992856Snd150628 	VERIFY(cond_signal(cv) == 0);
300789Sahrens }
301789Sahrens 
302789Sahrens void
303789Sahrens cv_broadcast(kcondvar_t *cv)
304789Sahrens {
3052856Snd150628 	VERIFY(cond_broadcast(cv) == 0);
306789Sahrens }
307789Sahrens 
308789Sahrens /*
309789Sahrens  * =========================================================================
310789Sahrens  * vnode operations
311789Sahrens  * =========================================================================
312789Sahrens  */
313789Sahrens /*
314789Sahrens  * Note: for the xxxat() versions of these functions, we assume that the
315789Sahrens  * starting vp is always rootdir (which is true for spa_directory.c, the only
316789Sahrens  * ZFS consumer of these interfaces).  We assert this is true, and then emulate
317789Sahrens  * them by adding '/' in front of the path.
318789Sahrens  */
319789Sahrens 
320789Sahrens /*ARGSUSED*/
321789Sahrens int
322789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
323789Sahrens {
324789Sahrens 	int fd;
325789Sahrens 	vnode_t *vp;
326789Sahrens 	int old_umask;
327789Sahrens 	char realpath[MAXPATHLEN];
328789Sahrens 	struct stat64 st;
329789Sahrens 
330789Sahrens 	/*
331789Sahrens 	 * If we're accessing a real disk from userland, we need to use
332789Sahrens 	 * the character interface to avoid caching.  This is particularly
333789Sahrens 	 * important if we're trying to look at a real in-kernel storage
334789Sahrens 	 * pool from userland, e.g. via zdb, because otherwise we won't
335789Sahrens 	 * see the changes occurring under the segmap cache.
336789Sahrens 	 * On the other hand, the stupid character device returns zero
337789Sahrens 	 * for its size.  So -- gag -- we open the block device to get
338789Sahrens 	 * its size, and remember it for subsequent VOP_GETATTR().
339789Sahrens 	 */
340789Sahrens 	if (strncmp(path, "/dev/", 5) == 0) {
341789Sahrens 		char *dsk;
342789Sahrens 		fd = open64(path, O_RDONLY);
343789Sahrens 		if (fd == -1)
344789Sahrens 			return (errno);
345789Sahrens 		if (fstat64(fd, &st) == -1) {
346789Sahrens 			close(fd);
347789Sahrens 			return (errno);
348789Sahrens 		}
349789Sahrens 		close(fd);
350789Sahrens 		(void) sprintf(realpath, "%s", path);
351789Sahrens 		dsk = strstr(path, "/dsk/");
352789Sahrens 		if (dsk != NULL)
353789Sahrens 			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
354789Sahrens 			    dsk + 1);
355789Sahrens 	} else {
356789Sahrens 		(void) sprintf(realpath, "%s", path);
357789Sahrens 		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
358789Sahrens 			return (errno);
359789Sahrens 	}
360789Sahrens 
361789Sahrens 	if (flags & FCREAT)
362789Sahrens 		old_umask = umask(0);
363789Sahrens 
364789Sahrens 	/*
365789Sahrens 	 * The construct 'flags - FREAD' conveniently maps combinations of
366789Sahrens 	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
367789Sahrens 	 */
368789Sahrens 	fd = open64(realpath, flags - FREAD, mode);
369789Sahrens 
370789Sahrens 	if (flags & FCREAT)
371789Sahrens 		(void) umask(old_umask);
372789Sahrens 
373789Sahrens 	if (fd == -1)
374789Sahrens 		return (errno);
375789Sahrens 
376789Sahrens 	if (fstat64(fd, &st) == -1) {
377789Sahrens 		close(fd);
378789Sahrens 		return (errno);
379789Sahrens 	}
380789Sahrens 
381789Sahrens 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
382789Sahrens 
383789Sahrens 	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
384789Sahrens 
385789Sahrens 	vp->v_fd = fd;
386789Sahrens 	vp->v_size = st.st_size;
387789Sahrens 	vp->v_path = spa_strdup(path);
388789Sahrens 
389789Sahrens 	return (0);
390789Sahrens }
391789Sahrens 
3925331Samw /*ARGSUSED*/
393789Sahrens int
394789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
3955331Samw     int x3, vnode_t *startvp, int fd)
396789Sahrens {
397789Sahrens 	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
398789Sahrens 	int ret;
399789Sahrens 
400789Sahrens 	ASSERT(startvp == rootdir);
401789Sahrens 	(void) sprintf(realpath, "/%s", path);
402789Sahrens 
4035331Samw 	/* fd ignored for now, need if want to simulate nbmand support */
404789Sahrens 	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
405789Sahrens 
406789Sahrens 	umem_free(realpath, strlen(path) + 2);
407789Sahrens 
408789Sahrens 	return (ret);
409789Sahrens }
410789Sahrens 
411789Sahrens /*ARGSUSED*/
412789Sahrens int
413789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
414789Sahrens 	int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
415789Sahrens {
416789Sahrens 	ssize_t iolen, split;
417789Sahrens 
418789Sahrens 	if (uio == UIO_READ) {
419789Sahrens 		iolen = pread64(vp->v_fd, addr, len, offset);
420789Sahrens 	} else {
421789Sahrens 		/*
422789Sahrens 		 * To simulate partial disk writes, we split writes into two
423789Sahrens 		 * system calls so that the process can be killed in between.
424789Sahrens 		 */
425789Sahrens 		split = (len > 0 ? rand() % len : 0);
426789Sahrens 		iolen = pwrite64(vp->v_fd, addr, split, offset);
427789Sahrens 		iolen += pwrite64(vp->v_fd, (char *)addr + split,
428789Sahrens 		    len - split, offset + split);
429789Sahrens 	}
430789Sahrens 
431789Sahrens 	if (iolen == -1)
432789Sahrens 		return (errno);
433789Sahrens 	if (residp)
434789Sahrens 		*residp = len - iolen;
435789Sahrens 	else if (iolen != len)
436789Sahrens 		return (EIO);
437789Sahrens 	return (0);
438789Sahrens }
439789Sahrens 
440789Sahrens void
441789Sahrens vn_close(vnode_t *vp)
442789Sahrens {
443789Sahrens 	close(vp->v_fd);
444789Sahrens 	spa_strfree(vp->v_path);
445789Sahrens 	umem_free(vp, sizeof (vnode_t));
446789Sahrens }
447789Sahrens 
448789Sahrens #ifdef ZFS_DEBUG
449789Sahrens 
450789Sahrens /*
451789Sahrens  * =========================================================================
452789Sahrens  * Figure out which debugging statements to print
453789Sahrens  * =========================================================================
454789Sahrens  */
455789Sahrens 
456789Sahrens static char *dprintf_string;
457789Sahrens static int dprintf_print_all;
458789Sahrens 
459789Sahrens int
460789Sahrens dprintf_find_string(const char *string)
461789Sahrens {
462789Sahrens 	char *tmp_str = dprintf_string;
463789Sahrens 	int len = strlen(string);
464789Sahrens 
465789Sahrens 	/*
466789Sahrens 	 * Find out if this is a string we want to print.
467789Sahrens 	 * String format: file1.c,function_name1,file2.c,file3.c
468789Sahrens 	 */
469789Sahrens 
470789Sahrens 	while (tmp_str != NULL) {
471789Sahrens 		if (strncmp(tmp_str, string, len) == 0 &&
472789Sahrens 		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
473789Sahrens 			return (1);
474789Sahrens 		tmp_str = strchr(tmp_str, ',');
475789Sahrens 		if (tmp_str != NULL)
476789Sahrens 			tmp_str++; /* Get rid of , */
477789Sahrens 	}
478789Sahrens 	return (0);
479789Sahrens }
480789Sahrens 
481789Sahrens void
482789Sahrens dprintf_setup(int *argc, char **argv)
483789Sahrens {
484789Sahrens 	int i, j;
485789Sahrens 
486789Sahrens 	/*
487789Sahrens 	 * Debugging can be specified two ways: by setting the
488789Sahrens 	 * environment variable ZFS_DEBUG, or by including a
489789Sahrens 	 * "debug=..."  argument on the command line.  The command
490789Sahrens 	 * line setting overrides the environment variable.
491789Sahrens 	 */
492789Sahrens 
493789Sahrens 	for (i = 1; i < *argc; i++) {
494789Sahrens 		int len = strlen("debug=");
495789Sahrens 		/* First look for a command line argument */
496789Sahrens 		if (strncmp("debug=", argv[i], len) == 0) {
497789Sahrens 			dprintf_string = argv[i] + len;
498789Sahrens 			/* Remove from args */
499789Sahrens 			for (j = i; j < *argc; j++)
500789Sahrens 				argv[j] = argv[j+1];
501789Sahrens 			argv[j] = NULL;
502789Sahrens 			(*argc)--;
503789Sahrens 		}
504789Sahrens 	}
505789Sahrens 
506789Sahrens 	if (dprintf_string == NULL) {
507789Sahrens 		/* Look for ZFS_DEBUG environment variable */
508789Sahrens 		dprintf_string = getenv("ZFS_DEBUG");
509789Sahrens 	}
510789Sahrens 
511789Sahrens 	/*
512789Sahrens 	 * Are we just turning on all debugging?
513789Sahrens 	 */
514789Sahrens 	if (dprintf_find_string("on"))
515789Sahrens 		dprintf_print_all = 1;
516789Sahrens }
517789Sahrens 
518789Sahrens /*
519789Sahrens  * =========================================================================
520789Sahrens  * debug printfs
521789Sahrens  * =========================================================================
522789Sahrens  */
523789Sahrens void
524789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
525789Sahrens {
526789Sahrens 	const char *newfile;
527789Sahrens 	va_list adx;
528789Sahrens 
529789Sahrens 	/*
530789Sahrens 	 * Get rid of annoying "../common/" prefix to filename.
531789Sahrens 	 */
532789Sahrens 	newfile = strrchr(file, '/');
533789Sahrens 	if (newfile != NULL) {
534789Sahrens 		newfile = newfile + 1; /* Get rid of leading / */
535789Sahrens 	} else {
536789Sahrens 		newfile = file;
537789Sahrens 	}
538789Sahrens 
539789Sahrens 	if (dprintf_print_all ||
540789Sahrens 	    dprintf_find_string(newfile) ||
541789Sahrens 	    dprintf_find_string(func)) {
542789Sahrens 		/* Print out just the function name if requested */
543789Sahrens 		flockfile(stdout);
544789Sahrens 		if (dprintf_find_string("pid"))
545789Sahrens 			(void) printf("%d ", getpid());
546789Sahrens 		if (dprintf_find_string("tid"))
547789Sahrens 			(void) printf("%u ", thr_self());
548789Sahrens 		if (dprintf_find_string("cpu"))
549789Sahrens 			(void) printf("%u ", getcpuid());
550789Sahrens 		if (dprintf_find_string("time"))
551789Sahrens 			(void) printf("%llu ", gethrtime());
552789Sahrens 		if (dprintf_find_string("long"))
553789Sahrens 			(void) printf("%s, line %d: ", newfile, line);
554789Sahrens 		(void) printf("%s: ", func);
555789Sahrens 		va_start(adx, fmt);
556789Sahrens 		(void) vprintf(fmt, adx);
557789Sahrens 		va_end(adx);
558789Sahrens 		funlockfile(stdout);
559789Sahrens 	}
560789Sahrens }
561789Sahrens 
562789Sahrens #endif /* ZFS_DEBUG */
563789Sahrens 
564789Sahrens /*
565789Sahrens  * =========================================================================
566789Sahrens  * cmn_err() and panic()
567789Sahrens  * =========================================================================
568789Sahrens  */
569789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
570789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
571789Sahrens 
572789Sahrens void
573789Sahrens vpanic(const char *fmt, va_list adx)
574789Sahrens {
575789Sahrens 	(void) fprintf(stderr, "error: ");
576789Sahrens 	(void) vfprintf(stderr, fmt, adx);
577789Sahrens 	(void) fprintf(stderr, "\n");
578789Sahrens 
579789Sahrens 	abort();	/* think of it as a "user-level crash dump" */
580789Sahrens }
581789Sahrens 
582789Sahrens void
583789Sahrens panic(const char *fmt, ...)
584789Sahrens {
585789Sahrens 	va_list adx;
586789Sahrens 
587789Sahrens 	va_start(adx, fmt);
588789Sahrens 	vpanic(fmt, adx);
589789Sahrens 	va_end(adx);
590789Sahrens }
591789Sahrens 
5923713Sahrens void
5933713Sahrens vcmn_err(int ce, const char *fmt, va_list adx)
5943713Sahrens {
5953713Sahrens 	if (ce == CE_PANIC)
5963713Sahrens 		vpanic(fmt, adx);
5973713Sahrens 	if (ce != CE_NOTE) {	/* suppress noise in userland stress testing */
5983713Sahrens 		(void) fprintf(stderr, "%s", ce_prefix[ce]);
5993713Sahrens 		(void) vfprintf(stderr, fmt, adx);
6003713Sahrens 		(void) fprintf(stderr, "%s", ce_suffix[ce]);
6013713Sahrens 	}
6023713Sahrens }
6033713Sahrens 
604789Sahrens /*PRINTFLIKE2*/
605789Sahrens void
606789Sahrens cmn_err(int ce, const char *fmt, ...)
607789Sahrens {
608789Sahrens 	va_list adx;
609789Sahrens 
610789Sahrens 	va_start(adx, fmt);
6113713Sahrens 	vcmn_err(ce, fmt, adx);
612789Sahrens 	va_end(adx);
613789Sahrens }
614789Sahrens 
615789Sahrens /*
616789Sahrens  * =========================================================================
6171544Seschrock  * kobj interfaces
6181544Seschrock  * =========================================================================
6191544Seschrock  */
6201544Seschrock struct _buf *
6211544Seschrock kobj_open_file(char *name)
6221544Seschrock {
6231544Seschrock 	struct _buf *file;
6241544Seschrock 	vnode_t *vp;
6251544Seschrock 
6261544Seschrock 	/* set vp as the _fd field of the file */
6275331Samw 	if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir,
6285331Samw 	    -1) != 0)
6291544Seschrock 		return ((void *)-1UL);
6301544Seschrock 
6311544Seschrock 	file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
6321544Seschrock 	file->_fd = (intptr_t)vp;
6331544Seschrock 	return (file);
6341544Seschrock }
6351544Seschrock 
6361544Seschrock int
6371544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
6381544Seschrock {
6391544Seschrock 	ssize_t resid;
6401544Seschrock 
6411544Seschrock 	vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
6421544Seschrock 	    UIO_SYSSPACE, 0, 0, 0, &resid);
6431544Seschrock 
6443912Slling 	return (size - resid);
6451544Seschrock }
6461544Seschrock 
6471544Seschrock void
6481544Seschrock kobj_close_file(struct _buf *file)
6491544Seschrock {
6501544Seschrock 	vn_close((vnode_t *)file->_fd);
6511544Seschrock 	umem_free(file, sizeof (struct _buf));
6521544Seschrock }
6531544Seschrock 
6541544Seschrock int
6553912Slling kobj_get_filesize(struct _buf *file, uint64_t *size)
6561544Seschrock {
6571544Seschrock 	struct stat64 st;
6583912Slling 	vnode_t *vp = (vnode_t *)file->_fd;
6593912Slling 
6601544Seschrock 	if (fstat64(vp->v_fd, &st) == -1) {
6611544Seschrock 		vn_close(vp);
6621544Seschrock 		return (errno);
6631544Seschrock 	}
6643912Slling 	*size = st.st_size;
6651544Seschrock 	return (0);
6661544Seschrock }
6671544Seschrock 
6681544Seschrock /*
6691544Seschrock  * =========================================================================
670789Sahrens  * misc routines
671789Sahrens  * =========================================================================
672789Sahrens  */
673789Sahrens 
674789Sahrens void
675789Sahrens delay(clock_t ticks)
676789Sahrens {
677789Sahrens 	poll(0, 0, ticks * (1000 / hz));
678789Sahrens }
679789Sahrens 
680789Sahrens /*
681789Sahrens  * Find highest one bit set.
682789Sahrens  *	Returns bit number + 1 of highest bit that is set, otherwise returns 0.
683789Sahrens  * High order bit is 31 (or 63 in _LP64 kernel).
684789Sahrens  */
685789Sahrens int
686789Sahrens highbit(ulong_t i)
687789Sahrens {
688789Sahrens 	register int h = 1;
689789Sahrens 
690789Sahrens 	if (i == 0)
691789Sahrens 		return (0);
692789Sahrens #ifdef _LP64
693789Sahrens 	if (i & 0xffffffff00000000ul) {
694789Sahrens 		h += 32; i >>= 32;
695789Sahrens 	}
696789Sahrens #endif
697789Sahrens 	if (i & 0xffff0000) {
698789Sahrens 		h += 16; i >>= 16;
699789Sahrens 	}
700789Sahrens 	if (i & 0xff00) {
701789Sahrens 		h += 8; i >>= 8;
702789Sahrens 	}
703789Sahrens 	if (i & 0xf0) {
704789Sahrens 		h += 4; i >>= 4;
705789Sahrens 	}
706789Sahrens 	if (i & 0xc) {
707789Sahrens 		h += 2; i >>= 2;
708789Sahrens 	}
709789Sahrens 	if (i & 0x2) {
710789Sahrens 		h += 1;
711789Sahrens 	}
712789Sahrens 	return (h);
713789Sahrens }
714789Sahrens 
715*5688Sbonwick static int random_fd = -1, urandom_fd = -1;
716*5688Sbonwick 
717789Sahrens static int
718*5688Sbonwick random_get_bytes_common(uint8_t *ptr, size_t len, int fd)
719789Sahrens {
720789Sahrens 	size_t resid = len;
721789Sahrens 	ssize_t bytes;
722789Sahrens 
723789Sahrens 	ASSERT(fd != -1);
724789Sahrens 
725789Sahrens 	while (resid != 0) {
726789Sahrens 		bytes = read(fd, ptr, resid);
727*5688Sbonwick 		ASSERT3S(bytes, >=, 0);
728789Sahrens 		ptr += bytes;
729789Sahrens 		resid -= bytes;
730789Sahrens 	}
731789Sahrens 
732789Sahrens 	return (0);
733789Sahrens }
734789Sahrens 
735789Sahrens int
736789Sahrens random_get_bytes(uint8_t *ptr, size_t len)
737789Sahrens {
738*5688Sbonwick 	return (random_get_bytes_common(ptr, len, random_fd));
739789Sahrens }
740789Sahrens 
741789Sahrens int
742789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len)
743789Sahrens {
744*5688Sbonwick 	return (random_get_bytes_common(ptr, len, urandom_fd));
745789Sahrens }
746789Sahrens 
7473975Sek110237 int
7483975Sek110237 ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result)
7493975Sek110237 {
7503975Sek110237 	char *end;
7513975Sek110237 
7523975Sek110237 	*result = strtoul(hw_serial, &end, base);
7533975Sek110237 	if (*result == 0)
7543975Sek110237 		return (errno);
7553975Sek110237 	return (0);
7563975Sek110237 }
7573975Sek110237 
758789Sahrens /*
759789Sahrens  * =========================================================================
760789Sahrens  * kernel emulation setup & teardown
761789Sahrens  * =========================================================================
762789Sahrens  */
763789Sahrens static int
764789Sahrens umem_out_of_memory(void)
765789Sahrens {
766789Sahrens 	char errmsg[] = "out of memory -- generating core dump\n";
767789Sahrens 
768789Sahrens 	write(fileno(stderr), errmsg, sizeof (errmsg));
769789Sahrens 	abort();
770789Sahrens 	return (0);
771789Sahrens }
772789Sahrens 
773789Sahrens void
774789Sahrens kernel_init(int mode)
775789Sahrens {
776789Sahrens 	umem_nofail_callback(umem_out_of_memory);
777789Sahrens 
778789Sahrens 	physmem = sysconf(_SC_PHYS_PAGES);
779789Sahrens 
780789Sahrens 	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
781789Sahrens 	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
782789Sahrens 
7833975Sek110237 	snprintf(hw_serial, sizeof (hw_serial), "%ld", gethostid());
7843975Sek110237 
785*5688Sbonwick 	VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1);
786*5688Sbonwick 	VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1);
787*5688Sbonwick 
788789Sahrens 	spa_init(mode);
789789Sahrens }
790789Sahrens 
791789Sahrens void
792789Sahrens kernel_fini(void)
793789Sahrens {
794789Sahrens 	spa_fini();
795*5688Sbonwick 
796*5688Sbonwick 	close(random_fd);
797*5688Sbonwick 	close(urandom_fd);
798*5688Sbonwick 
799*5688Sbonwick 	random_fd = -1;
800*5688Sbonwick 	urandom_fd = -1;
801789Sahrens }
8023886Sahl 
8033886Sahl int
8043886Sahl z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen)
8053886Sahl {
8063886Sahl 	int ret;
8073886Sahl 	uLongf len = *dstlen;
8083886Sahl 
8093886Sahl 	if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK)
8103886Sahl 		*dstlen = (size_t)len;
8113886Sahl 
8123886Sahl 	return (ret);
8133886Sahl }
8143886Sahl 
8153886Sahl int
8163886Sahl z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen,
8173886Sahl     int level)
8183886Sahl {
8193886Sahl 	int ret;
8203886Sahl 	uLongf len = *dstlen;
8213886Sahl 
8223886Sahl 	if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK)
8233886Sahl 		*dstlen = (size_t)len;
8243886Sahl 
8253886Sahl 	return (ret);
8263886Sahl }
8274543Smarks 
8285331Samw /*ARGSUSED*/
8295331Samw size_t u8_textprep_str(char *i, size_t *il, char *o, size_t *ol, int nf,
8305331Samw     size_t vers, int *err)
8315331Samw {
8325331Samw 	*err = EINVAL;
8335331Samw 	return ((size_t)-1);
8345331Samw }
8355331Samw 
8364543Smarks uid_t
8374543Smarks crgetuid(cred_t *cr)
8384543Smarks {
8394543Smarks 	return (0);
8404543Smarks }
8414543Smarks 
8424543Smarks gid_t
8434543Smarks crgetgid(cred_t *cr)
8444543Smarks {
8454543Smarks 	return (0);
8464543Smarks }
8474543Smarks 
8484543Smarks int
8494543Smarks crgetngroups(cred_t *cr)
8504543Smarks {
8514543Smarks 	return (0);
8524543Smarks }
8534543Smarks 
8544543Smarks gid_t *
8554543Smarks crgetgroups(cred_t *cr)
8564543Smarks {
8574543Smarks 	return (NULL);
8584543Smarks }
8594543Smarks 
8604543Smarks int
8614543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
8624543Smarks {
8634543Smarks 	return (0);
8644543Smarks }
8654543Smarks 
8664543Smarks int
8674543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
8684543Smarks {
8694543Smarks 	return (0);
8704543Smarks }
8714543Smarks 
8724543Smarks int
8734543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
8744543Smarks {
8754543Smarks 	return (0);
8764543Smarks }
877