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 /*
225959Smarks  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23789Sahrens  * Use is subject to license terms.
24789Sahrens  */
25789Sahrens 
26789Sahrens #include <assert.h>
273886Sahl #include <fcntl.h>
28789Sahrens #include <poll.h>
29789Sahrens #include <stdio.h>
30789Sahrens #include <stdlib.h>
313886Sahl #include <string.h>
323886Sahl #include <zlib.h>
33789Sahrens #include <sys/spa.h>
343886Sahl #include <sys/stat.h>
35789Sahrens #include <sys/processor.h>
363886Sahl #include <sys/zfs_context.h>
373886Sahl #include <sys/zmod.h>
383975Sek110237 #include <sys/utsname.h>
392856Snd150628 
40789Sahrens /*
41789Sahrens  * Emulation of kernel services in userland.
42789Sahrens  */
43789Sahrens 
44789Sahrens uint64_t physmem;
45789Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234;
463975Sek110237 char hw_serial[11];
473975Sek110237 
483975Sek110237 struct utsname utsname = {
493975Sek110237 	"userland", "libzpool", "1", "1", "na"
503975Sek110237 };
51789Sahrens 
52789Sahrens /*
53789Sahrens  * =========================================================================
54789Sahrens  * threads
55789Sahrens  * =========================================================================
56789Sahrens  */
57789Sahrens /*ARGSUSED*/
58789Sahrens kthread_t *
59789Sahrens zk_thread_create(void (*func)(), void *arg)
60789Sahrens {
61789Sahrens 	thread_t tid;
62789Sahrens 
63789Sahrens 	VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
64789Sahrens 	    &tid) == 0);
65789Sahrens 
66789Sahrens 	return ((void *)(uintptr_t)tid);
67789Sahrens }
68789Sahrens 
69789Sahrens /*
70789Sahrens  * =========================================================================
713403Sbmc  * kstats
723403Sbmc  * =========================================================================
733403Sbmc  */
743403Sbmc /*ARGSUSED*/
753403Sbmc kstat_t *
763403Sbmc kstat_create(char *module, int instance, char *name, char *class,
773403Sbmc     uchar_t type, ulong_t ndata, uchar_t ks_flag)
783403Sbmc {
793403Sbmc 	return (NULL);
803403Sbmc }
813403Sbmc 
823403Sbmc /*ARGSUSED*/
833403Sbmc void
843403Sbmc kstat_install(kstat_t *ksp)
853403Sbmc {}
863403Sbmc 
873403Sbmc /*ARGSUSED*/
883403Sbmc void
893403Sbmc kstat_delete(kstat_t *ksp)
903403Sbmc {}
913403Sbmc 
923403Sbmc /*
933403Sbmc  * =========================================================================
94789Sahrens  * mutexes
95789Sahrens  * =========================================================================
96789Sahrens  */
97789Sahrens void
98789Sahrens zmutex_init(kmutex_t *mp)
99789Sahrens {
100789Sahrens 	mp->m_owner = NULL;
1014831Sgw25295 	mp->initialized = B_TRUE;
102789Sahrens 	(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
103789Sahrens }
104789Sahrens 
105789Sahrens void
106789Sahrens zmutex_destroy(kmutex_t *mp)
107789Sahrens {
1084831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
109789Sahrens 	ASSERT(mp->m_owner == NULL);
110789Sahrens 	(void) _mutex_destroy(&(mp)->m_lock);
111789Sahrens 	mp->m_owner = (void *)-1UL;
1124831Sgw25295 	mp->initialized = B_FALSE;
113789Sahrens }
114789Sahrens 
115789Sahrens void
116789Sahrens mutex_enter(kmutex_t *mp)
117789Sahrens {
1184831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
119789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
120789Sahrens 	ASSERT(mp->m_owner != curthread);
1212856Snd150628 	VERIFY(mutex_lock(&mp->m_lock) == 0);
122789Sahrens 	ASSERT(mp->m_owner == NULL);
123789Sahrens 	mp->m_owner = curthread;
124789Sahrens }
125789Sahrens 
126789Sahrens int
127789Sahrens mutex_tryenter(kmutex_t *mp)
128789Sahrens {
1294831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
130789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
131789Sahrens 	if (0 == mutex_trylock(&mp->m_lock)) {
132789Sahrens 		ASSERT(mp->m_owner == NULL);
133789Sahrens 		mp->m_owner = curthread;
134789Sahrens 		return (1);
135789Sahrens 	} else {
136789Sahrens 		return (0);
137789Sahrens 	}
138789Sahrens }
139789Sahrens 
140789Sahrens void
141789Sahrens mutex_exit(kmutex_t *mp)
142789Sahrens {
1434831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
144789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
145789Sahrens 	mp->m_owner = NULL;
1462856Snd150628 	VERIFY(mutex_unlock(&mp->m_lock) == 0);
147789Sahrens }
148789Sahrens 
149789Sahrens void *
150789Sahrens mutex_owner(kmutex_t *mp)
151789Sahrens {
1524831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
153789Sahrens 	return (mp->m_owner);
154789Sahrens }
155789Sahrens 
156789Sahrens /*
157789Sahrens  * =========================================================================
158789Sahrens  * rwlocks
159789Sahrens  * =========================================================================
160789Sahrens  */
161789Sahrens /*ARGSUSED*/
162789Sahrens void
163789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
164789Sahrens {
165789Sahrens 	rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
166789Sahrens 	rwlp->rw_owner = NULL;
1674831Sgw25295 	rwlp->initialized = B_TRUE;
168789Sahrens }
169789Sahrens 
170789Sahrens void
171789Sahrens rw_destroy(krwlock_t *rwlp)
172789Sahrens {
173789Sahrens 	rwlock_destroy(&rwlp->rw_lock);
174789Sahrens 	rwlp->rw_owner = (void *)-1UL;
1754831Sgw25295 	rwlp->initialized = B_FALSE;
176789Sahrens }
177789Sahrens 
178789Sahrens void
179789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw)
180789Sahrens {
181789Sahrens 	ASSERT(!RW_LOCK_HELD(rwlp));
1824831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
183789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
184789Sahrens 	ASSERT(rwlp->rw_owner != curthread);
185789Sahrens 
186789Sahrens 	if (rw == RW_READER)
1876689Smaybee 		VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
188789Sahrens 	else
1896689Smaybee 		VERIFY(rw_wrlock(&rwlp->rw_lock) == 0);
190789Sahrens 
191789Sahrens 	rwlp->rw_owner = curthread;
192789Sahrens }
193789Sahrens 
194789Sahrens void
195789Sahrens rw_exit(krwlock_t *rwlp)
196789Sahrens {
1974831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
198789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
199789Sahrens 
200789Sahrens 	rwlp->rw_owner = NULL;
2016689Smaybee 	VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
202789Sahrens }
203789Sahrens 
204789Sahrens int
205789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw)
206789Sahrens {
207789Sahrens 	int rv;
208789Sahrens 
2094831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
210789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
211789Sahrens 
212789Sahrens 	if (rw == RW_READER)
213789Sahrens 		rv = rw_tryrdlock(&rwlp->rw_lock);
214789Sahrens 	else
215789Sahrens 		rv = rw_trywrlock(&rwlp->rw_lock);
216789Sahrens 
217789Sahrens 	if (rv == 0) {
218789Sahrens 		rwlp->rw_owner = curthread;
219789Sahrens 		return (1);
220789Sahrens 	}
221789Sahrens 
222789Sahrens 	return (0);
223789Sahrens }
224789Sahrens 
225789Sahrens /*ARGSUSED*/
226789Sahrens int
227789Sahrens rw_tryupgrade(krwlock_t *rwlp)
228789Sahrens {
2294831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
230789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
231789Sahrens 
232789Sahrens 	return (0);
233789Sahrens }
234789Sahrens 
235789Sahrens /*
236789Sahrens  * =========================================================================
237789Sahrens  * condition variables
238789Sahrens  * =========================================================================
239789Sahrens  */
240789Sahrens /*ARGSUSED*/
241789Sahrens void
242789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg)
243789Sahrens {
2442856Snd150628 	VERIFY(cond_init(cv, type, NULL) == 0);
245789Sahrens }
246789Sahrens 
247789Sahrens void
248789Sahrens cv_destroy(kcondvar_t *cv)
249789Sahrens {
2502856Snd150628 	VERIFY(cond_destroy(cv) == 0);
251789Sahrens }
252789Sahrens 
253789Sahrens void
254789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp)
255789Sahrens {
256789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
257789Sahrens 	mp->m_owner = NULL;
2582856Snd150628 	int ret = cond_wait(cv, &mp->m_lock);
2592856Snd150628 	VERIFY(ret == 0 || ret == EINTR);
260789Sahrens 	mp->m_owner = curthread;
261789Sahrens }
262789Sahrens 
263789Sahrens clock_t
264789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
265789Sahrens {
266789Sahrens 	int error;
267789Sahrens 	timestruc_t ts;
268789Sahrens 	clock_t delta;
269789Sahrens 
270789Sahrens top:
271789Sahrens 	delta = abstime - lbolt;
272789Sahrens 	if (delta <= 0)
273789Sahrens 		return (-1);
274789Sahrens 
275789Sahrens 	ts.tv_sec = delta / hz;
276789Sahrens 	ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
277789Sahrens 
278789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
279789Sahrens 	mp->m_owner = NULL;
280789Sahrens 	error = cond_reltimedwait(cv, &mp->m_lock, &ts);
281789Sahrens 	mp->m_owner = curthread;
282789Sahrens 
283789Sahrens 	if (error == ETIME)
284789Sahrens 		return (-1);
285789Sahrens 
286789Sahrens 	if (error == EINTR)
287789Sahrens 		goto top;
288789Sahrens 
289789Sahrens 	ASSERT(error == 0);
290789Sahrens 
291789Sahrens 	return (1);
292789Sahrens }
293789Sahrens 
294789Sahrens void
295789Sahrens cv_signal(kcondvar_t *cv)
296789Sahrens {
2972856Snd150628 	VERIFY(cond_signal(cv) == 0);
298789Sahrens }
299789Sahrens 
300789Sahrens void
301789Sahrens cv_broadcast(kcondvar_t *cv)
302789Sahrens {
3032856Snd150628 	VERIFY(cond_broadcast(cv) == 0);
304789Sahrens }
305789Sahrens 
306789Sahrens /*
307789Sahrens  * =========================================================================
308789Sahrens  * vnode operations
309789Sahrens  * =========================================================================
310789Sahrens  */
311789Sahrens /*
312789Sahrens  * Note: for the xxxat() versions of these functions, we assume that the
313789Sahrens  * starting vp is always rootdir (which is true for spa_directory.c, the only
314789Sahrens  * ZFS consumer of these interfaces).  We assert this is true, and then emulate
315789Sahrens  * them by adding '/' in front of the path.
316789Sahrens  */
317789Sahrens 
318789Sahrens /*ARGSUSED*/
319789Sahrens int
320789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
321789Sahrens {
322789Sahrens 	int fd;
323789Sahrens 	vnode_t *vp;
324789Sahrens 	int old_umask;
325789Sahrens 	char realpath[MAXPATHLEN];
326789Sahrens 	struct stat64 st;
327789Sahrens 
328789Sahrens 	/*
329789Sahrens 	 * If we're accessing a real disk from userland, we need to use
330789Sahrens 	 * the character interface to avoid caching.  This is particularly
331789Sahrens 	 * important if we're trying to look at a real in-kernel storage
332789Sahrens 	 * pool from userland, e.g. via zdb, because otherwise we won't
333789Sahrens 	 * see the changes occurring under the segmap cache.
334789Sahrens 	 * On the other hand, the stupid character device returns zero
335789Sahrens 	 * for its size.  So -- gag -- we open the block device to get
336789Sahrens 	 * its size, and remember it for subsequent VOP_GETATTR().
337789Sahrens 	 */
338789Sahrens 	if (strncmp(path, "/dev/", 5) == 0) {
339789Sahrens 		char *dsk;
340789Sahrens 		fd = open64(path, O_RDONLY);
341789Sahrens 		if (fd == -1)
342789Sahrens 			return (errno);
343789Sahrens 		if (fstat64(fd, &st) == -1) {
344789Sahrens 			close(fd);
345789Sahrens 			return (errno);
346789Sahrens 		}
347789Sahrens 		close(fd);
348789Sahrens 		(void) sprintf(realpath, "%s", path);
349789Sahrens 		dsk = strstr(path, "/dsk/");
350789Sahrens 		if (dsk != NULL)
351789Sahrens 			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
352789Sahrens 			    dsk + 1);
353789Sahrens 	} else {
354789Sahrens 		(void) sprintf(realpath, "%s", path);
355789Sahrens 		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
356789Sahrens 			return (errno);
357789Sahrens 	}
358789Sahrens 
359789Sahrens 	if (flags & FCREAT)
360789Sahrens 		old_umask = umask(0);
361789Sahrens 
362789Sahrens 	/*
363789Sahrens 	 * The construct 'flags - FREAD' conveniently maps combinations of
364789Sahrens 	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
365789Sahrens 	 */
366789Sahrens 	fd = open64(realpath, flags - FREAD, mode);
367789Sahrens 
368789Sahrens 	if (flags & FCREAT)
369789Sahrens 		(void) umask(old_umask);
370789Sahrens 
371789Sahrens 	if (fd == -1)
372789Sahrens 		return (errno);
373789Sahrens 
374789Sahrens 	if (fstat64(fd, &st) == -1) {
375789Sahrens 		close(fd);
376789Sahrens 		return (errno);
377789Sahrens 	}
378789Sahrens 
379789Sahrens 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
380789Sahrens 
381789Sahrens 	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
382789Sahrens 
383789Sahrens 	vp->v_fd = fd;
384789Sahrens 	vp->v_size = st.st_size;
385789Sahrens 	vp->v_path = spa_strdup(path);
386789Sahrens 
387789Sahrens 	return (0);
388789Sahrens }
389789Sahrens 
3905331Samw /*ARGSUSED*/
391789Sahrens int
392789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
3935331Samw     int x3, vnode_t *startvp, int fd)
394789Sahrens {
395789Sahrens 	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
396789Sahrens 	int ret;
397789Sahrens 
398789Sahrens 	ASSERT(startvp == rootdir);
399789Sahrens 	(void) sprintf(realpath, "/%s", path);
400789Sahrens 
4015331Samw 	/* fd ignored for now, need if want to simulate nbmand support */
402789Sahrens 	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
403789Sahrens 
404789Sahrens 	umem_free(realpath, strlen(path) + 2);
405789Sahrens 
406789Sahrens 	return (ret);
407789Sahrens }
408789Sahrens 
409789Sahrens /*ARGSUSED*/
410789Sahrens int
411789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
412789Sahrens 	int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
413789Sahrens {
414789Sahrens 	ssize_t iolen, split;
415789Sahrens 
416789Sahrens 	if (uio == UIO_READ) {
417789Sahrens 		iolen = pread64(vp->v_fd, addr, len, offset);
418789Sahrens 	} else {
419789Sahrens 		/*
420789Sahrens 		 * To simulate partial disk writes, we split writes into two
421789Sahrens 		 * system calls so that the process can be killed in between.
422789Sahrens 		 */
423789Sahrens 		split = (len > 0 ? rand() % len : 0);
424789Sahrens 		iolen = pwrite64(vp->v_fd, addr, split, offset);
425789Sahrens 		iolen += pwrite64(vp->v_fd, (char *)addr + split,
426789Sahrens 		    len - split, offset + split);
427789Sahrens 	}
428789Sahrens 
429789Sahrens 	if (iolen == -1)
430789Sahrens 		return (errno);
431789Sahrens 	if (residp)
432789Sahrens 		*residp = len - iolen;
433789Sahrens 	else if (iolen != len)
434789Sahrens 		return (EIO);
435789Sahrens 	return (0);
436789Sahrens }
437789Sahrens 
438789Sahrens void
439789Sahrens vn_close(vnode_t *vp)
440789Sahrens {
441789Sahrens 	close(vp->v_fd);
442789Sahrens 	spa_strfree(vp->v_path);
443789Sahrens 	umem_free(vp, sizeof (vnode_t));
444789Sahrens }
445789Sahrens 
446789Sahrens #ifdef ZFS_DEBUG
447789Sahrens 
448789Sahrens /*
449789Sahrens  * =========================================================================
450789Sahrens  * Figure out which debugging statements to print
451789Sahrens  * =========================================================================
452789Sahrens  */
453789Sahrens 
454789Sahrens static char *dprintf_string;
455789Sahrens static int dprintf_print_all;
456789Sahrens 
457789Sahrens int
458789Sahrens dprintf_find_string(const char *string)
459789Sahrens {
460789Sahrens 	char *tmp_str = dprintf_string;
461789Sahrens 	int len = strlen(string);
462789Sahrens 
463789Sahrens 	/*
464789Sahrens 	 * Find out if this is a string we want to print.
465789Sahrens 	 * String format: file1.c,function_name1,file2.c,file3.c
466789Sahrens 	 */
467789Sahrens 
468789Sahrens 	while (tmp_str != NULL) {
469789Sahrens 		if (strncmp(tmp_str, string, len) == 0 &&
470789Sahrens 		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
471789Sahrens 			return (1);
472789Sahrens 		tmp_str = strchr(tmp_str, ',');
473789Sahrens 		if (tmp_str != NULL)
474789Sahrens 			tmp_str++; /* Get rid of , */
475789Sahrens 	}
476789Sahrens 	return (0);
477789Sahrens }
478789Sahrens 
479789Sahrens void
480789Sahrens dprintf_setup(int *argc, char **argv)
481789Sahrens {
482789Sahrens 	int i, j;
483789Sahrens 
484789Sahrens 	/*
485789Sahrens 	 * Debugging can be specified two ways: by setting the
486789Sahrens 	 * environment variable ZFS_DEBUG, or by including a
487789Sahrens 	 * "debug=..."  argument on the command line.  The command
488789Sahrens 	 * line setting overrides the environment variable.
489789Sahrens 	 */
490789Sahrens 
491789Sahrens 	for (i = 1; i < *argc; i++) {
492789Sahrens 		int len = strlen("debug=");
493789Sahrens 		/* First look for a command line argument */
494789Sahrens 		if (strncmp("debug=", argv[i], len) == 0) {
495789Sahrens 			dprintf_string = argv[i] + len;
496789Sahrens 			/* Remove from args */
497789Sahrens 			for (j = i; j < *argc; j++)
498789Sahrens 				argv[j] = argv[j+1];
499789Sahrens 			argv[j] = NULL;
500789Sahrens 			(*argc)--;
501789Sahrens 		}
502789Sahrens 	}
503789Sahrens 
504789Sahrens 	if (dprintf_string == NULL) {
505789Sahrens 		/* Look for ZFS_DEBUG environment variable */
506789Sahrens 		dprintf_string = getenv("ZFS_DEBUG");
507789Sahrens 	}
508789Sahrens 
509789Sahrens 	/*
510789Sahrens 	 * Are we just turning on all debugging?
511789Sahrens 	 */
512789Sahrens 	if (dprintf_find_string("on"))
513789Sahrens 		dprintf_print_all = 1;
514789Sahrens }
515789Sahrens 
516789Sahrens /*
517789Sahrens  * =========================================================================
518789Sahrens  * debug printfs
519789Sahrens  * =========================================================================
520789Sahrens  */
521789Sahrens void
522789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
523789Sahrens {
524789Sahrens 	const char *newfile;
525789Sahrens 	va_list adx;
526789Sahrens 
527789Sahrens 	/*
528789Sahrens 	 * Get rid of annoying "../common/" prefix to filename.
529789Sahrens 	 */
530789Sahrens 	newfile = strrchr(file, '/');
531789Sahrens 	if (newfile != NULL) {
532789Sahrens 		newfile = newfile + 1; /* Get rid of leading / */
533789Sahrens 	} else {
534789Sahrens 		newfile = file;
535789Sahrens 	}
536789Sahrens 
537789Sahrens 	if (dprintf_print_all ||
538789Sahrens 	    dprintf_find_string(newfile) ||
539789Sahrens 	    dprintf_find_string(func)) {
540789Sahrens 		/* Print out just the function name if requested */
541789Sahrens 		flockfile(stdout);
542789Sahrens 		if (dprintf_find_string("pid"))
543789Sahrens 			(void) printf("%d ", getpid());
544789Sahrens 		if (dprintf_find_string("tid"))
545789Sahrens 			(void) printf("%u ", thr_self());
546789Sahrens 		if (dprintf_find_string("cpu"))
547789Sahrens 			(void) printf("%u ", getcpuid());
548789Sahrens 		if (dprintf_find_string("time"))
549789Sahrens 			(void) printf("%llu ", gethrtime());
550789Sahrens 		if (dprintf_find_string("long"))
551789Sahrens 			(void) printf("%s, line %d: ", newfile, line);
552789Sahrens 		(void) printf("%s: ", func);
553789Sahrens 		va_start(adx, fmt);
554789Sahrens 		(void) vprintf(fmt, adx);
555789Sahrens 		va_end(adx);
556789Sahrens 		funlockfile(stdout);
557789Sahrens 	}
558789Sahrens }
559789Sahrens 
560789Sahrens #endif /* ZFS_DEBUG */
561789Sahrens 
562789Sahrens /*
563789Sahrens  * =========================================================================
564789Sahrens  * cmn_err() and panic()
565789Sahrens  * =========================================================================
566789Sahrens  */
567789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
568789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
569789Sahrens 
570789Sahrens void
571789Sahrens vpanic(const char *fmt, va_list adx)
572789Sahrens {
573789Sahrens 	(void) fprintf(stderr, "error: ");
574789Sahrens 	(void) vfprintf(stderr, fmt, adx);
575789Sahrens 	(void) fprintf(stderr, "\n");
576789Sahrens 
577789Sahrens 	abort();	/* think of it as a "user-level crash dump" */
578789Sahrens }
579789Sahrens 
580789Sahrens void
581789Sahrens panic(const char *fmt, ...)
582789Sahrens {
583789Sahrens 	va_list adx;
584789Sahrens 
585789Sahrens 	va_start(adx, fmt);
586789Sahrens 	vpanic(fmt, adx);
587789Sahrens 	va_end(adx);
588789Sahrens }
589789Sahrens 
5903713Sahrens void
5913713Sahrens vcmn_err(int ce, const char *fmt, va_list adx)
5923713Sahrens {
5933713Sahrens 	if (ce == CE_PANIC)
5943713Sahrens 		vpanic(fmt, adx);
5953713Sahrens 	if (ce != CE_NOTE) {	/* suppress noise in userland stress testing */
5963713Sahrens 		(void) fprintf(stderr, "%s", ce_prefix[ce]);
5973713Sahrens 		(void) vfprintf(stderr, fmt, adx);
5983713Sahrens 		(void) fprintf(stderr, "%s", ce_suffix[ce]);
5993713Sahrens 	}
6003713Sahrens }
6013713Sahrens 
602789Sahrens /*PRINTFLIKE2*/
603789Sahrens void
604789Sahrens cmn_err(int ce, const char *fmt, ...)
605789Sahrens {
606789Sahrens 	va_list adx;
607789Sahrens 
608789Sahrens 	va_start(adx, fmt);
6093713Sahrens 	vcmn_err(ce, fmt, adx);
610789Sahrens 	va_end(adx);
611789Sahrens }
612789Sahrens 
613789Sahrens /*
614789Sahrens  * =========================================================================
6151544Seschrock  * kobj interfaces
6161544Seschrock  * =========================================================================
6171544Seschrock  */
6181544Seschrock struct _buf *
6191544Seschrock kobj_open_file(char *name)
6201544Seschrock {
6211544Seschrock 	struct _buf *file;
6221544Seschrock 	vnode_t *vp;
6231544Seschrock 
6241544Seschrock 	/* set vp as the _fd field of the file */
6255331Samw 	if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir,
6265331Samw 	    -1) != 0)
6271544Seschrock 		return ((void *)-1UL);
6281544Seschrock 
6291544Seschrock 	file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
6301544Seschrock 	file->_fd = (intptr_t)vp;
6311544Seschrock 	return (file);
6321544Seschrock }
6331544Seschrock 
6341544Seschrock int
6351544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
6361544Seschrock {
6371544Seschrock 	ssize_t resid;
6381544Seschrock 
6391544Seschrock 	vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
6401544Seschrock 	    UIO_SYSSPACE, 0, 0, 0, &resid);
6411544Seschrock 
6423912Slling 	return (size - resid);
6431544Seschrock }
6441544Seschrock 
6451544Seschrock void
6461544Seschrock kobj_close_file(struct _buf *file)
6471544Seschrock {
6481544Seschrock 	vn_close((vnode_t *)file->_fd);
6491544Seschrock 	umem_free(file, sizeof (struct _buf));
6501544Seschrock }
6511544Seschrock 
6521544Seschrock int
6533912Slling kobj_get_filesize(struct _buf *file, uint64_t *size)
6541544Seschrock {
6551544Seschrock 	struct stat64 st;
6563912Slling 	vnode_t *vp = (vnode_t *)file->_fd;
6573912Slling 
6581544Seschrock 	if (fstat64(vp->v_fd, &st) == -1) {
6591544Seschrock 		vn_close(vp);
6601544Seschrock 		return (errno);
6611544Seschrock 	}
6623912Slling 	*size = st.st_size;
6631544Seschrock 	return (0);
6641544Seschrock }
6651544Seschrock 
6661544Seschrock /*
6671544Seschrock  * =========================================================================
668789Sahrens  * misc routines
669789Sahrens  * =========================================================================
670789Sahrens  */
671789Sahrens 
672789Sahrens void
673789Sahrens delay(clock_t ticks)
674789Sahrens {
675789Sahrens 	poll(0, 0, ticks * (1000 / hz));
676789Sahrens }
677789Sahrens 
678789Sahrens /*
679789Sahrens  * Find highest one bit set.
680789Sahrens  *	Returns bit number + 1 of highest bit that is set, otherwise returns 0.
681789Sahrens  * High order bit is 31 (or 63 in _LP64 kernel).
682789Sahrens  */
683789Sahrens int
684789Sahrens highbit(ulong_t i)
685789Sahrens {
686789Sahrens 	register int h = 1;
687789Sahrens 
688789Sahrens 	if (i == 0)
689789Sahrens 		return (0);
690789Sahrens #ifdef _LP64
691789Sahrens 	if (i & 0xffffffff00000000ul) {
692789Sahrens 		h += 32; i >>= 32;
693789Sahrens 	}
694789Sahrens #endif
695789Sahrens 	if (i & 0xffff0000) {
696789Sahrens 		h += 16; i >>= 16;
697789Sahrens 	}
698789Sahrens 	if (i & 0xff00) {
699789Sahrens 		h += 8; i >>= 8;
700789Sahrens 	}
701789Sahrens 	if (i & 0xf0) {
702789Sahrens 		h += 4; i >>= 4;
703789Sahrens 	}
704789Sahrens 	if (i & 0xc) {
705789Sahrens 		h += 2; i >>= 2;
706789Sahrens 	}
707789Sahrens 	if (i & 0x2) {
708789Sahrens 		h += 1;
709789Sahrens 	}
710789Sahrens 	return (h);
711789Sahrens }
712789Sahrens 
7135688Sbonwick static int random_fd = -1, urandom_fd = -1;
7145688Sbonwick 
715789Sahrens static int
7165688Sbonwick random_get_bytes_common(uint8_t *ptr, size_t len, int fd)
717789Sahrens {
718789Sahrens 	size_t resid = len;
719789Sahrens 	ssize_t bytes;
720789Sahrens 
721789Sahrens 	ASSERT(fd != -1);
722789Sahrens 
723789Sahrens 	while (resid != 0) {
724789Sahrens 		bytes = read(fd, ptr, resid);
7255688Sbonwick 		ASSERT3S(bytes, >=, 0);
726789Sahrens 		ptr += bytes;
727789Sahrens 		resid -= bytes;
728789Sahrens 	}
729789Sahrens 
730789Sahrens 	return (0);
731789Sahrens }
732789Sahrens 
733789Sahrens int
734789Sahrens random_get_bytes(uint8_t *ptr, size_t len)
735789Sahrens {
7365688Sbonwick 	return (random_get_bytes_common(ptr, len, random_fd));
737789Sahrens }
738789Sahrens 
739789Sahrens int
740789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len)
741789Sahrens {
7425688Sbonwick 	return (random_get_bytes_common(ptr, len, urandom_fd));
743789Sahrens }
744789Sahrens 
7453975Sek110237 int
7463975Sek110237 ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result)
7473975Sek110237 {
7483975Sek110237 	char *end;
7493975Sek110237 
7503975Sek110237 	*result = strtoul(hw_serial, &end, base);
7513975Sek110237 	if (*result == 0)
7523975Sek110237 		return (errno);
7533975Sek110237 	return (0);
7543975Sek110237 }
7553975Sek110237 
756789Sahrens /*
757789Sahrens  * =========================================================================
758789Sahrens  * kernel emulation setup & teardown
759789Sahrens  * =========================================================================
760789Sahrens  */
761789Sahrens static int
762789Sahrens umem_out_of_memory(void)
763789Sahrens {
764789Sahrens 	char errmsg[] = "out of memory -- generating core dump\n";
765789Sahrens 
766789Sahrens 	write(fileno(stderr), errmsg, sizeof (errmsg));
767789Sahrens 	abort();
768789Sahrens 	return (0);
769789Sahrens }
770789Sahrens 
771789Sahrens void
772789Sahrens kernel_init(int mode)
773789Sahrens {
774789Sahrens 	umem_nofail_callback(umem_out_of_memory);
775789Sahrens 
776789Sahrens 	physmem = sysconf(_SC_PHYS_PAGES);
777789Sahrens 
778789Sahrens 	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
779789Sahrens 	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
780789Sahrens 
7813975Sek110237 	snprintf(hw_serial, sizeof (hw_serial), "%ld", gethostid());
7823975Sek110237 
7835688Sbonwick 	VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1);
7845688Sbonwick 	VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1);
7855688Sbonwick 
786*7837SMatthew.Ahrens@Sun.COM 	system_taskq_init();
787*7837SMatthew.Ahrens@Sun.COM 
788789Sahrens 	spa_init(mode);
789789Sahrens }
790789Sahrens 
791789Sahrens void
792789Sahrens kernel_fini(void)
793789Sahrens {
794789Sahrens 	spa_fini();
7955688Sbonwick 
7965688Sbonwick 	close(random_fd);
7975688Sbonwick 	close(urandom_fd);
7985688Sbonwick 
7995688Sbonwick 	random_fd = -1;
8005688Sbonwick 	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 
8284543Smarks uid_t
8294543Smarks crgetuid(cred_t *cr)
8304543Smarks {
8314543Smarks 	return (0);
8324543Smarks }
8334543Smarks 
8344543Smarks gid_t
8354543Smarks crgetgid(cred_t *cr)
8364543Smarks {
8374543Smarks 	return (0);
8384543Smarks }
8394543Smarks 
8404543Smarks int
8414543Smarks crgetngroups(cred_t *cr)
8424543Smarks {
8434543Smarks 	return (0);
8444543Smarks }
8454543Smarks 
8464543Smarks gid_t *
8474543Smarks crgetgroups(cred_t *cr)
8484543Smarks {
8494543Smarks 	return (NULL);
8504543Smarks }
8514543Smarks 
8524543Smarks int
8534543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
8544543Smarks {
8554543Smarks 	return (0);
8564543Smarks }
8574543Smarks 
8584543Smarks int
8594543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
8604543Smarks {
8614543Smarks 	return (0);
8624543Smarks }
8634543Smarks 
8644543Smarks int
8654543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
8664543Smarks {
8674543Smarks 	return (0);
8684543Smarks }
8695959Smarks 
8705959Smarks ksiddomain_t *
8715959Smarks ksid_lookupdomain(const char *dom)
8725959Smarks {
8735959Smarks 	ksiddomain_t *kd;
8745959Smarks 
8755959Smarks 	kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL);
8765959Smarks 	kd->kd_name = spa_strdup(dom);
8775959Smarks 	return (kd);
8785959Smarks }
8795959Smarks 
8805959Smarks void
8815959Smarks ksiddomain_rele(ksiddomain_t *ksid)
8825959Smarks {
8835959Smarks 	spa_strfree(ksid->kd_name);
8845959Smarks 	umem_free(ksid, sizeof (ksiddomain_t));
8855959Smarks }
886