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 /*
228662SJordan.Vaughan@Sun.com  * Copyright 2009 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>
398662SJordan.Vaughan@Sun.com #include <sys/systeminfo.h>
402856Snd150628 
41789Sahrens /*
42789Sahrens  * Emulation of kernel services in userland.
43789Sahrens  */
44789Sahrens 
45789Sahrens uint64_t physmem;
46789Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234;
478662SJordan.Vaughan@Sun.com char hw_serial[HW_HOSTID_LEN];
483975Sek110237 
493975Sek110237 struct utsname utsname = {
503975Sek110237 	"userland", "libzpool", "1", "1", "na"
513975Sek110237 };
52789Sahrens 
53789Sahrens /*
54789Sahrens  * =========================================================================
55789Sahrens  * threads
56789Sahrens  * =========================================================================
57789Sahrens  */
58789Sahrens /*ARGSUSED*/
59789Sahrens kthread_t *
60789Sahrens zk_thread_create(void (*func)(), void *arg)
61789Sahrens {
62789Sahrens 	thread_t tid;
63789Sahrens 
64789Sahrens 	VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
65789Sahrens 	    &tid) == 0);
66789Sahrens 
67789Sahrens 	return ((void *)(uintptr_t)tid);
68789Sahrens }
69789Sahrens 
70789Sahrens /*
71789Sahrens  * =========================================================================
723403Sbmc  * kstats
733403Sbmc  * =========================================================================
743403Sbmc  */
753403Sbmc /*ARGSUSED*/
763403Sbmc kstat_t *
773403Sbmc kstat_create(char *module, int instance, char *name, char *class,
783403Sbmc     uchar_t type, ulong_t ndata, uchar_t ks_flag)
793403Sbmc {
803403Sbmc 	return (NULL);
813403Sbmc }
823403Sbmc 
833403Sbmc /*ARGSUSED*/
843403Sbmc void
853403Sbmc kstat_install(kstat_t *ksp)
863403Sbmc {}
873403Sbmc 
883403Sbmc /*ARGSUSED*/
893403Sbmc void
903403Sbmc kstat_delete(kstat_t *ksp)
913403Sbmc {}
923403Sbmc 
933403Sbmc /*
943403Sbmc  * =========================================================================
95789Sahrens  * mutexes
96789Sahrens  * =========================================================================
97789Sahrens  */
98789Sahrens void
99789Sahrens zmutex_init(kmutex_t *mp)
100789Sahrens {
101789Sahrens 	mp->m_owner = NULL;
1024831Sgw25295 	mp->initialized = B_TRUE;
103789Sahrens 	(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
104789Sahrens }
105789Sahrens 
106789Sahrens void
107789Sahrens zmutex_destroy(kmutex_t *mp)
108789Sahrens {
1094831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
110789Sahrens 	ASSERT(mp->m_owner == NULL);
111789Sahrens 	(void) _mutex_destroy(&(mp)->m_lock);
112789Sahrens 	mp->m_owner = (void *)-1UL;
1134831Sgw25295 	mp->initialized = B_FALSE;
114789Sahrens }
115789Sahrens 
116789Sahrens void
117789Sahrens mutex_enter(kmutex_t *mp)
118789Sahrens {
1194831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
120789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
121789Sahrens 	ASSERT(mp->m_owner != curthread);
1222856Snd150628 	VERIFY(mutex_lock(&mp->m_lock) == 0);
123789Sahrens 	ASSERT(mp->m_owner == NULL);
124789Sahrens 	mp->m_owner = curthread;
125789Sahrens }
126789Sahrens 
127789Sahrens int
128789Sahrens mutex_tryenter(kmutex_t *mp)
129789Sahrens {
1304831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
131789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
132789Sahrens 	if (0 == mutex_trylock(&mp->m_lock)) {
133789Sahrens 		ASSERT(mp->m_owner == NULL);
134789Sahrens 		mp->m_owner = curthread;
135789Sahrens 		return (1);
136789Sahrens 	} else {
137789Sahrens 		return (0);
138789Sahrens 	}
139789Sahrens }
140789Sahrens 
141789Sahrens void
142789Sahrens mutex_exit(kmutex_t *mp)
143789Sahrens {
1444831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
145789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
146789Sahrens 	mp->m_owner = NULL;
1472856Snd150628 	VERIFY(mutex_unlock(&mp->m_lock) == 0);
148789Sahrens }
149789Sahrens 
150789Sahrens void *
151789Sahrens mutex_owner(kmutex_t *mp)
152789Sahrens {
1534831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
154789Sahrens 	return (mp->m_owner);
155789Sahrens }
156789Sahrens 
157789Sahrens /*
158789Sahrens  * =========================================================================
159789Sahrens  * rwlocks
160789Sahrens  * =========================================================================
161789Sahrens  */
162789Sahrens /*ARGSUSED*/
163789Sahrens void
164789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
165789Sahrens {
166789Sahrens 	rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
167789Sahrens 	rwlp->rw_owner = NULL;
1684831Sgw25295 	rwlp->initialized = B_TRUE;
169789Sahrens }
170789Sahrens 
171789Sahrens void
172789Sahrens rw_destroy(krwlock_t *rwlp)
173789Sahrens {
174789Sahrens 	rwlock_destroy(&rwlp->rw_lock);
175789Sahrens 	rwlp->rw_owner = (void *)-1UL;
1764831Sgw25295 	rwlp->initialized = B_FALSE;
177789Sahrens }
178789Sahrens 
179789Sahrens void
180789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw)
181789Sahrens {
182789Sahrens 	ASSERT(!RW_LOCK_HELD(rwlp));
1834831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
184789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
185789Sahrens 	ASSERT(rwlp->rw_owner != curthread);
186789Sahrens 
187789Sahrens 	if (rw == RW_READER)
1886689Smaybee 		VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
189789Sahrens 	else
1906689Smaybee 		VERIFY(rw_wrlock(&rwlp->rw_lock) == 0);
191789Sahrens 
192789Sahrens 	rwlp->rw_owner = curthread;
193789Sahrens }
194789Sahrens 
195789Sahrens void
196789Sahrens rw_exit(krwlock_t *rwlp)
197789Sahrens {
1984831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
199789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
200789Sahrens 
201789Sahrens 	rwlp->rw_owner = NULL;
2026689Smaybee 	VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
203789Sahrens }
204789Sahrens 
205789Sahrens int
206789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw)
207789Sahrens {
208789Sahrens 	int rv;
209789Sahrens 
2104831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
211789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
212789Sahrens 
213789Sahrens 	if (rw == RW_READER)
214789Sahrens 		rv = rw_tryrdlock(&rwlp->rw_lock);
215789Sahrens 	else
216789Sahrens 		rv = rw_trywrlock(&rwlp->rw_lock);
217789Sahrens 
218789Sahrens 	if (rv == 0) {
219789Sahrens 		rwlp->rw_owner = curthread;
220789Sahrens 		return (1);
221789Sahrens 	}
222789Sahrens 
223789Sahrens 	return (0);
224789Sahrens }
225789Sahrens 
226789Sahrens /*ARGSUSED*/
227789Sahrens int
228789Sahrens rw_tryupgrade(krwlock_t *rwlp)
229789Sahrens {
2304831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
231789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
232789Sahrens 
233789Sahrens 	return (0);
234789Sahrens }
235789Sahrens 
236789Sahrens /*
237789Sahrens  * =========================================================================
238789Sahrens  * condition variables
239789Sahrens  * =========================================================================
240789Sahrens  */
241789Sahrens /*ARGSUSED*/
242789Sahrens void
243789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg)
244789Sahrens {
2452856Snd150628 	VERIFY(cond_init(cv, type, NULL) == 0);
246789Sahrens }
247789Sahrens 
248789Sahrens void
249789Sahrens cv_destroy(kcondvar_t *cv)
250789Sahrens {
2512856Snd150628 	VERIFY(cond_destroy(cv) == 0);
252789Sahrens }
253789Sahrens 
254789Sahrens void
255789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp)
256789Sahrens {
257789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
258789Sahrens 	mp->m_owner = NULL;
2592856Snd150628 	int ret = cond_wait(cv, &mp->m_lock);
2602856Snd150628 	VERIFY(ret == 0 || ret == EINTR);
261789Sahrens 	mp->m_owner = curthread;
262789Sahrens }
263789Sahrens 
264789Sahrens clock_t
265789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
266789Sahrens {
267789Sahrens 	int error;
268789Sahrens 	timestruc_t ts;
269789Sahrens 	clock_t delta;
270789Sahrens 
271789Sahrens top:
272789Sahrens 	delta = abstime - lbolt;
273789Sahrens 	if (delta <= 0)
274789Sahrens 		return (-1);
275789Sahrens 
276789Sahrens 	ts.tv_sec = delta / hz;
277789Sahrens 	ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
278789Sahrens 
279789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
280789Sahrens 	mp->m_owner = NULL;
281789Sahrens 	error = cond_reltimedwait(cv, &mp->m_lock, &ts);
282789Sahrens 	mp->m_owner = curthread;
283789Sahrens 
284789Sahrens 	if (error == ETIME)
285789Sahrens 		return (-1);
286789Sahrens 
287789Sahrens 	if (error == EINTR)
288789Sahrens 		goto top;
289789Sahrens 
290789Sahrens 	ASSERT(error == 0);
291789Sahrens 
292789Sahrens 	return (1);
293789Sahrens }
294789Sahrens 
295789Sahrens void
296789Sahrens cv_signal(kcondvar_t *cv)
297789Sahrens {
2982856Snd150628 	VERIFY(cond_signal(cv) == 0);
299789Sahrens }
300789Sahrens 
301789Sahrens void
302789Sahrens cv_broadcast(kcondvar_t *cv)
303789Sahrens {
3042856Snd150628 	VERIFY(cond_broadcast(cv) == 0);
305789Sahrens }
306789Sahrens 
307789Sahrens /*
308789Sahrens  * =========================================================================
309789Sahrens  * vnode operations
310789Sahrens  * =========================================================================
311789Sahrens  */
312789Sahrens /*
313789Sahrens  * Note: for the xxxat() versions of these functions, we assume that the
314789Sahrens  * starting vp is always rootdir (which is true for spa_directory.c, the only
315789Sahrens  * ZFS consumer of these interfaces).  We assert this is true, and then emulate
316789Sahrens  * them by adding '/' in front of the path.
317789Sahrens  */
318789Sahrens 
319789Sahrens /*ARGSUSED*/
320789Sahrens int
321789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
322789Sahrens {
323789Sahrens 	int fd;
324789Sahrens 	vnode_t *vp;
325789Sahrens 	int old_umask;
326789Sahrens 	char realpath[MAXPATHLEN];
327789Sahrens 	struct stat64 st;
328789Sahrens 
329789Sahrens 	/*
330789Sahrens 	 * If we're accessing a real disk from userland, we need to use
331789Sahrens 	 * the character interface to avoid caching.  This is particularly
332789Sahrens 	 * important if we're trying to look at a real in-kernel storage
333789Sahrens 	 * pool from userland, e.g. via zdb, because otherwise we won't
334789Sahrens 	 * see the changes occurring under the segmap cache.
335789Sahrens 	 * On the other hand, the stupid character device returns zero
336789Sahrens 	 * for its size.  So -- gag -- we open the block device to get
337789Sahrens 	 * its size, and remember it for subsequent VOP_GETATTR().
338789Sahrens 	 */
339789Sahrens 	if (strncmp(path, "/dev/", 5) == 0) {
340789Sahrens 		char *dsk;
341789Sahrens 		fd = open64(path, O_RDONLY);
342789Sahrens 		if (fd == -1)
343789Sahrens 			return (errno);
344789Sahrens 		if (fstat64(fd, &st) == -1) {
345789Sahrens 			close(fd);
346789Sahrens 			return (errno);
347789Sahrens 		}
348789Sahrens 		close(fd);
349789Sahrens 		(void) sprintf(realpath, "%s", path);
350789Sahrens 		dsk = strstr(path, "/dsk/");
351789Sahrens 		if (dsk != NULL)
352789Sahrens 			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
353789Sahrens 			    dsk + 1);
354789Sahrens 	} else {
355789Sahrens 		(void) sprintf(realpath, "%s", path);
356789Sahrens 		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
357789Sahrens 			return (errno);
358789Sahrens 	}
359789Sahrens 
360789Sahrens 	if (flags & FCREAT)
361789Sahrens 		old_umask = umask(0);
362789Sahrens 
363789Sahrens 	/*
364789Sahrens 	 * The construct 'flags - FREAD' conveniently maps combinations of
365789Sahrens 	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
366789Sahrens 	 */
367789Sahrens 	fd = open64(realpath, flags - FREAD, mode);
368789Sahrens 
369789Sahrens 	if (flags & FCREAT)
370789Sahrens 		(void) umask(old_umask);
371789Sahrens 
372789Sahrens 	if (fd == -1)
373789Sahrens 		return (errno);
374789Sahrens 
375789Sahrens 	if (fstat64(fd, &st) == -1) {
376789Sahrens 		close(fd);
377789Sahrens 		return (errno);
378789Sahrens 	}
379789Sahrens 
380789Sahrens 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
381789Sahrens 
382789Sahrens 	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
383789Sahrens 
384789Sahrens 	vp->v_fd = fd;
385789Sahrens 	vp->v_size = st.st_size;
386789Sahrens 	vp->v_path = spa_strdup(path);
387789Sahrens 
388789Sahrens 	return (0);
389789Sahrens }
390789Sahrens 
3915331Samw /*ARGSUSED*/
392789Sahrens int
393789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
3945331Samw     int x3, vnode_t *startvp, int fd)
395789Sahrens {
396789Sahrens 	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
397789Sahrens 	int ret;
398789Sahrens 
399789Sahrens 	ASSERT(startvp == rootdir);
400789Sahrens 	(void) sprintf(realpath, "/%s", path);
401789Sahrens 
4025331Samw 	/* fd ignored for now, need if want to simulate nbmand support */
403789Sahrens 	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
404789Sahrens 
405789Sahrens 	umem_free(realpath, strlen(path) + 2);
406789Sahrens 
407789Sahrens 	return (ret);
408789Sahrens }
409789Sahrens 
410789Sahrens /*ARGSUSED*/
411789Sahrens int
412789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
413789Sahrens 	int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
414789Sahrens {
415789Sahrens 	ssize_t iolen, split;
416789Sahrens 
417789Sahrens 	if (uio == UIO_READ) {
418789Sahrens 		iolen = pread64(vp->v_fd, addr, len, offset);
419789Sahrens 	} else {
420789Sahrens 		/*
421789Sahrens 		 * To simulate partial disk writes, we split writes into two
422789Sahrens 		 * system calls so that the process can be killed in between.
423789Sahrens 		 */
424789Sahrens 		split = (len > 0 ? rand() % len : 0);
425789Sahrens 		iolen = pwrite64(vp->v_fd, addr, split, offset);
426789Sahrens 		iolen += pwrite64(vp->v_fd, (char *)addr + split,
427789Sahrens 		    len - split, offset + split);
428789Sahrens 	}
429789Sahrens 
430789Sahrens 	if (iolen == -1)
431789Sahrens 		return (errno);
432789Sahrens 	if (residp)
433789Sahrens 		*residp = len - iolen;
434789Sahrens 	else if (iolen != len)
435789Sahrens 		return (EIO);
436789Sahrens 	return (0);
437789Sahrens }
438789Sahrens 
439789Sahrens void
440789Sahrens vn_close(vnode_t *vp)
441789Sahrens {
442789Sahrens 	close(vp->v_fd);
443789Sahrens 	spa_strfree(vp->v_path);
444789Sahrens 	umem_free(vp, sizeof (vnode_t));
445789Sahrens }
446789Sahrens 
447*10850SGeorge.Wilson@Sun.COM /*
448*10850SGeorge.Wilson@Sun.COM  * At a minimum we need to update the size since vdev_reopen()
449*10850SGeorge.Wilson@Sun.COM  * will no longer call vn_openat().
450*10850SGeorge.Wilson@Sun.COM  */
451*10850SGeorge.Wilson@Sun.COM int
452*10850SGeorge.Wilson@Sun.COM fop_getattr(vnode_t *vp, vattr_t *vap)
453*10850SGeorge.Wilson@Sun.COM {
454*10850SGeorge.Wilson@Sun.COM 	struct stat64 st;
455*10850SGeorge.Wilson@Sun.COM 
456*10850SGeorge.Wilson@Sun.COM 	if (fstat64(vp->v_fd, &st) == -1) {
457*10850SGeorge.Wilson@Sun.COM 		close(vp->v_fd);
458*10850SGeorge.Wilson@Sun.COM 		return (errno);
459*10850SGeorge.Wilson@Sun.COM 	}
460*10850SGeorge.Wilson@Sun.COM 
461*10850SGeorge.Wilson@Sun.COM 	vap->va_size = st.st_size;
462*10850SGeorge.Wilson@Sun.COM 	return (0);
463*10850SGeorge.Wilson@Sun.COM }
464*10850SGeorge.Wilson@Sun.COM 
465789Sahrens #ifdef ZFS_DEBUG
466789Sahrens 
467789Sahrens /*
468789Sahrens  * =========================================================================
469789Sahrens  * Figure out which debugging statements to print
470789Sahrens  * =========================================================================
471789Sahrens  */
472789Sahrens 
473789Sahrens static char *dprintf_string;
474789Sahrens static int dprintf_print_all;
475789Sahrens 
476789Sahrens int
477789Sahrens dprintf_find_string(const char *string)
478789Sahrens {
479789Sahrens 	char *tmp_str = dprintf_string;
480789Sahrens 	int len = strlen(string);
481789Sahrens 
482789Sahrens 	/*
483789Sahrens 	 * Find out if this is a string we want to print.
484789Sahrens 	 * String format: file1.c,function_name1,file2.c,file3.c
485789Sahrens 	 */
486789Sahrens 
487789Sahrens 	while (tmp_str != NULL) {
488789Sahrens 		if (strncmp(tmp_str, string, len) == 0 &&
489789Sahrens 		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
490789Sahrens 			return (1);
491789Sahrens 		tmp_str = strchr(tmp_str, ',');
492789Sahrens 		if (tmp_str != NULL)
493789Sahrens 			tmp_str++; /* Get rid of , */
494789Sahrens 	}
495789Sahrens 	return (0);
496789Sahrens }
497789Sahrens 
498789Sahrens void
499789Sahrens dprintf_setup(int *argc, char **argv)
500789Sahrens {
501789Sahrens 	int i, j;
502789Sahrens 
503789Sahrens 	/*
504789Sahrens 	 * Debugging can be specified two ways: by setting the
505789Sahrens 	 * environment variable ZFS_DEBUG, or by including a
506789Sahrens 	 * "debug=..."  argument on the command line.  The command
507789Sahrens 	 * line setting overrides the environment variable.
508789Sahrens 	 */
509789Sahrens 
510789Sahrens 	for (i = 1; i < *argc; i++) {
511789Sahrens 		int len = strlen("debug=");
512789Sahrens 		/* First look for a command line argument */
513789Sahrens 		if (strncmp("debug=", argv[i], len) == 0) {
514789Sahrens 			dprintf_string = argv[i] + len;
515789Sahrens 			/* Remove from args */
516789Sahrens 			for (j = i; j < *argc; j++)
517789Sahrens 				argv[j] = argv[j+1];
518789Sahrens 			argv[j] = NULL;
519789Sahrens 			(*argc)--;
520789Sahrens 		}
521789Sahrens 	}
522789Sahrens 
523789Sahrens 	if (dprintf_string == NULL) {
524789Sahrens 		/* Look for ZFS_DEBUG environment variable */
525789Sahrens 		dprintf_string = getenv("ZFS_DEBUG");
526789Sahrens 	}
527789Sahrens 
528789Sahrens 	/*
529789Sahrens 	 * Are we just turning on all debugging?
530789Sahrens 	 */
531789Sahrens 	if (dprintf_find_string("on"))
532789Sahrens 		dprintf_print_all = 1;
533789Sahrens }
534789Sahrens 
535789Sahrens /*
536789Sahrens  * =========================================================================
537789Sahrens  * debug printfs
538789Sahrens  * =========================================================================
539789Sahrens  */
540789Sahrens void
541789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
542789Sahrens {
543789Sahrens 	const char *newfile;
544789Sahrens 	va_list adx;
545789Sahrens 
546789Sahrens 	/*
547789Sahrens 	 * Get rid of annoying "../common/" prefix to filename.
548789Sahrens 	 */
549789Sahrens 	newfile = strrchr(file, '/');
550789Sahrens 	if (newfile != NULL) {
551789Sahrens 		newfile = newfile + 1; /* Get rid of leading / */
552789Sahrens 	} else {
553789Sahrens 		newfile = file;
554789Sahrens 	}
555789Sahrens 
556789Sahrens 	if (dprintf_print_all ||
557789Sahrens 	    dprintf_find_string(newfile) ||
558789Sahrens 	    dprintf_find_string(func)) {
559789Sahrens 		/* Print out just the function name if requested */
560789Sahrens 		flockfile(stdout);
561789Sahrens 		if (dprintf_find_string("pid"))
562789Sahrens 			(void) printf("%d ", getpid());
563789Sahrens 		if (dprintf_find_string("tid"))
564789Sahrens 			(void) printf("%u ", thr_self());
565789Sahrens 		if (dprintf_find_string("cpu"))
566789Sahrens 			(void) printf("%u ", getcpuid());
567789Sahrens 		if (dprintf_find_string("time"))
568789Sahrens 			(void) printf("%llu ", gethrtime());
569789Sahrens 		if (dprintf_find_string("long"))
570789Sahrens 			(void) printf("%s, line %d: ", newfile, line);
571789Sahrens 		(void) printf("%s: ", func);
572789Sahrens 		va_start(adx, fmt);
573789Sahrens 		(void) vprintf(fmt, adx);
574789Sahrens 		va_end(adx);
575789Sahrens 		funlockfile(stdout);
576789Sahrens 	}
577789Sahrens }
578789Sahrens 
579789Sahrens #endif /* ZFS_DEBUG */
580789Sahrens 
581789Sahrens /*
582789Sahrens  * =========================================================================
583789Sahrens  * cmn_err() and panic()
584789Sahrens  * =========================================================================
585789Sahrens  */
586789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
587789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
588789Sahrens 
589789Sahrens void
590789Sahrens vpanic(const char *fmt, va_list adx)
591789Sahrens {
592789Sahrens 	(void) fprintf(stderr, "error: ");
593789Sahrens 	(void) vfprintf(stderr, fmt, adx);
594789Sahrens 	(void) fprintf(stderr, "\n");
595789Sahrens 
596789Sahrens 	abort();	/* think of it as a "user-level crash dump" */
597789Sahrens }
598789Sahrens 
599789Sahrens void
600789Sahrens panic(const char *fmt, ...)
601789Sahrens {
602789Sahrens 	va_list adx;
603789Sahrens 
604789Sahrens 	va_start(adx, fmt);
605789Sahrens 	vpanic(fmt, adx);
606789Sahrens 	va_end(adx);
607789Sahrens }
608789Sahrens 
6093713Sahrens void
6103713Sahrens vcmn_err(int ce, const char *fmt, va_list adx)
6113713Sahrens {
6123713Sahrens 	if (ce == CE_PANIC)
6133713Sahrens 		vpanic(fmt, adx);
6143713Sahrens 	if (ce != CE_NOTE) {	/* suppress noise in userland stress testing */
6153713Sahrens 		(void) fprintf(stderr, "%s", ce_prefix[ce]);
6163713Sahrens 		(void) vfprintf(stderr, fmt, adx);
6173713Sahrens 		(void) fprintf(stderr, "%s", ce_suffix[ce]);
6183713Sahrens 	}
6193713Sahrens }
6203713Sahrens 
621789Sahrens /*PRINTFLIKE2*/
622789Sahrens void
623789Sahrens cmn_err(int ce, const char *fmt, ...)
624789Sahrens {
625789Sahrens 	va_list adx;
626789Sahrens 
627789Sahrens 	va_start(adx, fmt);
6283713Sahrens 	vcmn_err(ce, fmt, adx);
629789Sahrens 	va_end(adx);
630789Sahrens }
631789Sahrens 
632789Sahrens /*
633789Sahrens  * =========================================================================
6341544Seschrock  * kobj interfaces
6351544Seschrock  * =========================================================================
6361544Seschrock  */
6371544Seschrock struct _buf *
6381544Seschrock kobj_open_file(char *name)
6391544Seschrock {
6401544Seschrock 	struct _buf *file;
6411544Seschrock 	vnode_t *vp;
6421544Seschrock 
6431544Seschrock 	/* set vp as the _fd field of the file */
6445331Samw 	if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir,
6455331Samw 	    -1) != 0)
6461544Seschrock 		return ((void *)-1UL);
6471544Seschrock 
6481544Seschrock 	file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
6491544Seschrock 	file->_fd = (intptr_t)vp;
6501544Seschrock 	return (file);
6511544Seschrock }
6521544Seschrock 
6531544Seschrock int
6541544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
6551544Seschrock {
6561544Seschrock 	ssize_t resid;
6571544Seschrock 
6581544Seschrock 	vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
6591544Seschrock 	    UIO_SYSSPACE, 0, 0, 0, &resid);
6601544Seschrock 
6613912Slling 	return (size - resid);
6621544Seschrock }
6631544Seschrock 
6641544Seschrock void
6651544Seschrock kobj_close_file(struct _buf *file)
6661544Seschrock {
6671544Seschrock 	vn_close((vnode_t *)file->_fd);
6681544Seschrock 	umem_free(file, sizeof (struct _buf));
6691544Seschrock }
6701544Seschrock 
6711544Seschrock int
6723912Slling kobj_get_filesize(struct _buf *file, uint64_t *size)
6731544Seschrock {
6741544Seschrock 	struct stat64 st;
6753912Slling 	vnode_t *vp = (vnode_t *)file->_fd;
6763912Slling 
6771544Seschrock 	if (fstat64(vp->v_fd, &st) == -1) {
6781544Seschrock 		vn_close(vp);
6791544Seschrock 		return (errno);
6801544Seschrock 	}
6813912Slling 	*size = st.st_size;
6821544Seschrock 	return (0);
6831544Seschrock }
6841544Seschrock 
6851544Seschrock /*
6861544Seschrock  * =========================================================================
687789Sahrens  * misc routines
688789Sahrens  * =========================================================================
689789Sahrens  */
690789Sahrens 
691789Sahrens void
692789Sahrens delay(clock_t ticks)
693789Sahrens {
694789Sahrens 	poll(0, 0, ticks * (1000 / hz));
695789Sahrens }
696789Sahrens 
697789Sahrens /*
698789Sahrens  * Find highest one bit set.
699789Sahrens  *	Returns bit number + 1 of highest bit that is set, otherwise returns 0.
700789Sahrens  * High order bit is 31 (or 63 in _LP64 kernel).
701789Sahrens  */
702789Sahrens int
703789Sahrens highbit(ulong_t i)
704789Sahrens {
705789Sahrens 	register int h = 1;
706789Sahrens 
707789Sahrens 	if (i == 0)
708789Sahrens 		return (0);
709789Sahrens #ifdef _LP64
710789Sahrens 	if (i & 0xffffffff00000000ul) {
711789Sahrens 		h += 32; i >>= 32;
712789Sahrens 	}
713789Sahrens #endif
714789Sahrens 	if (i & 0xffff0000) {
715789Sahrens 		h += 16; i >>= 16;
716789Sahrens 	}
717789Sahrens 	if (i & 0xff00) {
718789Sahrens 		h += 8; i >>= 8;
719789Sahrens 	}
720789Sahrens 	if (i & 0xf0) {
721789Sahrens 		h += 4; i >>= 4;
722789Sahrens 	}
723789Sahrens 	if (i & 0xc) {
724789Sahrens 		h += 2; i >>= 2;
725789Sahrens 	}
726789Sahrens 	if (i & 0x2) {
727789Sahrens 		h += 1;
728789Sahrens 	}
729789Sahrens 	return (h);
730789Sahrens }
731789Sahrens 
7325688Sbonwick static int random_fd = -1, urandom_fd = -1;
7335688Sbonwick 
734789Sahrens static int
7355688Sbonwick random_get_bytes_common(uint8_t *ptr, size_t len, int fd)
736789Sahrens {
737789Sahrens 	size_t resid = len;
738789Sahrens 	ssize_t bytes;
739789Sahrens 
740789Sahrens 	ASSERT(fd != -1);
741789Sahrens 
742789Sahrens 	while (resid != 0) {
743789Sahrens 		bytes = read(fd, ptr, resid);
7445688Sbonwick 		ASSERT3S(bytes, >=, 0);
745789Sahrens 		ptr += bytes;
746789Sahrens 		resid -= bytes;
747789Sahrens 	}
748789Sahrens 
749789Sahrens 	return (0);
750789Sahrens }
751789Sahrens 
752789Sahrens int
753789Sahrens random_get_bytes(uint8_t *ptr, size_t len)
754789Sahrens {
7555688Sbonwick 	return (random_get_bytes_common(ptr, len, random_fd));
756789Sahrens }
757789Sahrens 
758789Sahrens int
759789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len)
760789Sahrens {
7615688Sbonwick 	return (random_get_bytes_common(ptr, len, urandom_fd));
762789Sahrens }
763789Sahrens 
7643975Sek110237 int
7653975Sek110237 ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result)
7663975Sek110237 {
7673975Sek110237 	char *end;
7683975Sek110237 
7693975Sek110237 	*result = strtoul(hw_serial, &end, base);
7703975Sek110237 	if (*result == 0)
7713975Sek110237 		return (errno);
7723975Sek110237 	return (0);
7733975Sek110237 }
7743975Sek110237 
775789Sahrens /*
776789Sahrens  * =========================================================================
777789Sahrens  * kernel emulation setup & teardown
778789Sahrens  * =========================================================================
779789Sahrens  */
780789Sahrens static int
781789Sahrens umem_out_of_memory(void)
782789Sahrens {
783789Sahrens 	char errmsg[] = "out of memory -- generating core dump\n";
784789Sahrens 
785789Sahrens 	write(fileno(stderr), errmsg, sizeof (errmsg));
786789Sahrens 	abort();
787789Sahrens 	return (0);
788789Sahrens }
789789Sahrens 
790789Sahrens void
791789Sahrens kernel_init(int mode)
792789Sahrens {
793789Sahrens 	umem_nofail_callback(umem_out_of_memory);
794789Sahrens 
795789Sahrens 	physmem = sysconf(_SC_PHYS_PAGES);
796789Sahrens 
797789Sahrens 	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
798789Sahrens 	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
799789Sahrens 
8008662SJordan.Vaughan@Sun.com 	(void) snprintf(hw_serial, sizeof (hw_serial), "%ld", gethostid());
8013975Sek110237 
8025688Sbonwick 	VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1);
8035688Sbonwick 	VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1);
8045688Sbonwick 
8057837SMatthew.Ahrens@Sun.COM 	system_taskq_init();
8067837SMatthew.Ahrens@Sun.COM 
807789Sahrens 	spa_init(mode);
808789Sahrens }
809789Sahrens 
810789Sahrens void
811789Sahrens kernel_fini(void)
812789Sahrens {
813789Sahrens 	spa_fini();
8145688Sbonwick 
81510612SRicardo.M.Correia@Sun.COM 	system_taskq_fini();
81610612SRicardo.M.Correia@Sun.COM 
8175688Sbonwick 	close(random_fd);
8185688Sbonwick 	close(urandom_fd);
8195688Sbonwick 
8205688Sbonwick 	random_fd = -1;
8215688Sbonwick 	urandom_fd = -1;
822789Sahrens }
8233886Sahl 
8243886Sahl int
8253886Sahl z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen)
8263886Sahl {
8273886Sahl 	int ret;
8283886Sahl 	uLongf len = *dstlen;
8293886Sahl 
8303886Sahl 	if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK)
8313886Sahl 		*dstlen = (size_t)len;
8323886Sahl 
8333886Sahl 	return (ret);
8343886Sahl }
8353886Sahl 
8363886Sahl int
8373886Sahl z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen,
8383886Sahl     int level)
8393886Sahl {
8403886Sahl 	int ret;
8413886Sahl 	uLongf len = *dstlen;
8423886Sahl 
8433886Sahl 	if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK)
8443886Sahl 		*dstlen = (size_t)len;
8453886Sahl 
8463886Sahl 	return (ret);
8473886Sahl }
8484543Smarks 
8494543Smarks uid_t
8504543Smarks crgetuid(cred_t *cr)
8514543Smarks {
8524543Smarks 	return (0);
8534543Smarks }
8544543Smarks 
8554543Smarks gid_t
8564543Smarks crgetgid(cred_t *cr)
8574543Smarks {
8584543Smarks 	return (0);
8594543Smarks }
8604543Smarks 
8614543Smarks int
8624543Smarks crgetngroups(cred_t *cr)
8634543Smarks {
8644543Smarks 	return (0);
8654543Smarks }
8664543Smarks 
8674543Smarks gid_t *
8684543Smarks crgetgroups(cred_t *cr)
8694543Smarks {
8704543Smarks 	return (NULL);
8714543Smarks }
8724543Smarks 
8734543Smarks int
8744543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
8754543Smarks {
8764543Smarks 	return (0);
8774543Smarks }
8784543Smarks 
8794543Smarks int
8804543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
8814543Smarks {
8824543Smarks 	return (0);
8834543Smarks }
8844543Smarks 
8854543Smarks int
8864543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
8874543Smarks {
8884543Smarks 	return (0);
8894543Smarks }
8905959Smarks 
8915959Smarks ksiddomain_t *
8925959Smarks ksid_lookupdomain(const char *dom)
8935959Smarks {
8945959Smarks 	ksiddomain_t *kd;
8955959Smarks 
8965959Smarks 	kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL);
8975959Smarks 	kd->kd_name = spa_strdup(dom);
8985959Smarks 	return (kd);
8995959Smarks }
9005959Smarks 
9015959Smarks void
9025959Smarks ksiddomain_rele(ksiddomain_t *ksid)
9035959Smarks {
9045959Smarks 	spa_strfree(ksid->kd_name);
9055959Smarks 	umem_free(ksid, sizeof (ksiddomain_t));
9065959Smarks }
90710272SMatthew.Ahrens@Sun.COM 
90810272SMatthew.Ahrens@Sun.COM /*
90910272SMatthew.Ahrens@Sun.COM  * Do not change the length of the returned string; it must be freed
91010272SMatthew.Ahrens@Sun.COM  * with strfree().
91110272SMatthew.Ahrens@Sun.COM  */
91210272SMatthew.Ahrens@Sun.COM char *
91310272SMatthew.Ahrens@Sun.COM kmem_asprintf(const char *fmt, ...)
91410272SMatthew.Ahrens@Sun.COM {
91510272SMatthew.Ahrens@Sun.COM 	int size;
91610272SMatthew.Ahrens@Sun.COM 	va_list adx;
91710272SMatthew.Ahrens@Sun.COM 	char *buf;
91810272SMatthew.Ahrens@Sun.COM 
91910272SMatthew.Ahrens@Sun.COM 	va_start(adx, fmt);
92010272SMatthew.Ahrens@Sun.COM 	size = vsnprintf(NULL, 0, fmt, adx) + 1;
92110272SMatthew.Ahrens@Sun.COM 	va_end(adx);
92210272SMatthew.Ahrens@Sun.COM 
92310272SMatthew.Ahrens@Sun.COM 	buf = kmem_alloc(size, KM_SLEEP);
92410272SMatthew.Ahrens@Sun.COM 
92510272SMatthew.Ahrens@Sun.COM 	va_start(adx, fmt);
92610272SMatthew.Ahrens@Sun.COM 	size = vsnprintf(buf, size, fmt, adx);
92710272SMatthew.Ahrens@Sun.COM 	va_end(adx);
92810272SMatthew.Ahrens@Sun.COM 
92910272SMatthew.Ahrens@Sun.COM 	return (buf);
93010272SMatthew.Ahrens@Sun.COM }
931