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 /*
2212527SChris.Kirby@oracle.com  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23789Sahrens  */
24789Sahrens 
25789Sahrens #include <assert.h>
263886Sahl #include <fcntl.h>
27789Sahrens #include <poll.h>
28789Sahrens #include <stdio.h>
29789Sahrens #include <stdlib.h>
303886Sahl #include <string.h>
313886Sahl #include <zlib.h>
32789Sahrens #include <sys/spa.h>
333886Sahl #include <sys/stat.h>
34789Sahrens #include <sys/processor.h>
353886Sahl #include <sys/zfs_context.h>
363886Sahl #include <sys/zmod.h>
373975Sek110237 #include <sys/utsname.h>
388662SJordan.Vaughan@Sun.com #include <sys/systeminfo.h>
392856Snd150628 
40789Sahrens /*
41789Sahrens  * Emulation of kernel services in userland.
42789Sahrens  */
43789Sahrens 
4411726SVictor.Latushkin@Sun.COM int aok;
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 
5311173SJonathan.Adams@Sun.COM /* this only exists to have its address taken */
5411173SJonathan.Adams@Sun.COM struct proc p0;
5511173SJonathan.Adams@Sun.COM 
56789Sahrens /*
57789Sahrens  * =========================================================================
58789Sahrens  * threads
59789Sahrens  * =========================================================================
60789Sahrens  */
61789Sahrens /*ARGSUSED*/
62789Sahrens kthread_t *
63789Sahrens zk_thread_create(void (*func)(), void *arg)
64789Sahrens {
65789Sahrens 	thread_t tid;
66789Sahrens 
67789Sahrens 	VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
68789Sahrens 	    &tid) == 0);
69789Sahrens 
70789Sahrens 	return ((void *)(uintptr_t)tid);
71789Sahrens }
72789Sahrens 
73789Sahrens /*
74789Sahrens  * =========================================================================
753403Sbmc  * kstats
763403Sbmc  * =========================================================================
773403Sbmc  */
783403Sbmc /*ARGSUSED*/
793403Sbmc kstat_t *
803403Sbmc kstat_create(char *module, int instance, char *name, char *class,
813403Sbmc     uchar_t type, ulong_t ndata, uchar_t ks_flag)
823403Sbmc {
833403Sbmc 	return (NULL);
843403Sbmc }
853403Sbmc 
863403Sbmc /*ARGSUSED*/
873403Sbmc void
883403Sbmc kstat_install(kstat_t *ksp)
893403Sbmc {}
903403Sbmc 
913403Sbmc /*ARGSUSED*/
923403Sbmc void
933403Sbmc kstat_delete(kstat_t *ksp)
943403Sbmc {}
953403Sbmc 
963403Sbmc /*
973403Sbmc  * =========================================================================
98789Sahrens  * mutexes
99789Sahrens  * =========================================================================
100789Sahrens  */
101789Sahrens void
102789Sahrens zmutex_init(kmutex_t *mp)
103789Sahrens {
104789Sahrens 	mp->m_owner = NULL;
1054831Sgw25295 	mp->initialized = B_TRUE;
106789Sahrens 	(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
107789Sahrens }
108789Sahrens 
109789Sahrens void
110789Sahrens zmutex_destroy(kmutex_t *mp)
111789Sahrens {
1124831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
113789Sahrens 	ASSERT(mp->m_owner == NULL);
114789Sahrens 	(void) _mutex_destroy(&(mp)->m_lock);
115789Sahrens 	mp->m_owner = (void *)-1UL;
1164831Sgw25295 	mp->initialized = B_FALSE;
117789Sahrens }
118789Sahrens 
119789Sahrens void
120789Sahrens mutex_enter(kmutex_t *mp)
121789Sahrens {
1224831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
123789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
124789Sahrens 	ASSERT(mp->m_owner != curthread);
1252856Snd150628 	VERIFY(mutex_lock(&mp->m_lock) == 0);
126789Sahrens 	ASSERT(mp->m_owner == NULL);
127789Sahrens 	mp->m_owner = curthread;
128789Sahrens }
129789Sahrens 
130789Sahrens int
131789Sahrens mutex_tryenter(kmutex_t *mp)
132789Sahrens {
1334831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
134789Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
135789Sahrens 	if (0 == mutex_trylock(&mp->m_lock)) {
136789Sahrens 		ASSERT(mp->m_owner == NULL);
137789Sahrens 		mp->m_owner = curthread;
138789Sahrens 		return (1);
139789Sahrens 	} else {
140789Sahrens 		return (0);
141789Sahrens 	}
142789Sahrens }
143789Sahrens 
144789Sahrens void
145789Sahrens mutex_exit(kmutex_t *mp)
146789Sahrens {
1474831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
148789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
149789Sahrens 	mp->m_owner = NULL;
1502856Snd150628 	VERIFY(mutex_unlock(&mp->m_lock) == 0);
151789Sahrens }
152789Sahrens 
153789Sahrens void *
154789Sahrens mutex_owner(kmutex_t *mp)
155789Sahrens {
1564831Sgw25295 	ASSERT(mp->initialized == B_TRUE);
157789Sahrens 	return (mp->m_owner);
158789Sahrens }
159789Sahrens 
160789Sahrens /*
161789Sahrens  * =========================================================================
162789Sahrens  * rwlocks
163789Sahrens  * =========================================================================
164789Sahrens  */
165789Sahrens /*ARGSUSED*/
166789Sahrens void
167789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
168789Sahrens {
169789Sahrens 	rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
170789Sahrens 	rwlp->rw_owner = NULL;
1714831Sgw25295 	rwlp->initialized = B_TRUE;
172789Sahrens }
173789Sahrens 
174789Sahrens void
175789Sahrens rw_destroy(krwlock_t *rwlp)
176789Sahrens {
177789Sahrens 	rwlock_destroy(&rwlp->rw_lock);
178789Sahrens 	rwlp->rw_owner = (void *)-1UL;
1794831Sgw25295 	rwlp->initialized = B_FALSE;
180789Sahrens }
181789Sahrens 
182789Sahrens void
183789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw)
184789Sahrens {
185789Sahrens 	ASSERT(!RW_LOCK_HELD(rwlp));
1864831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
187789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
188789Sahrens 	ASSERT(rwlp->rw_owner != curthread);
189789Sahrens 
190789Sahrens 	if (rw == RW_READER)
1916689Smaybee 		VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
192789Sahrens 	else
1936689Smaybee 		VERIFY(rw_wrlock(&rwlp->rw_lock) == 0);
194789Sahrens 
195789Sahrens 	rwlp->rw_owner = curthread;
196789Sahrens }
197789Sahrens 
198789Sahrens void
199789Sahrens rw_exit(krwlock_t *rwlp)
200789Sahrens {
2014831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
202789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
203789Sahrens 
204789Sahrens 	rwlp->rw_owner = NULL;
2056689Smaybee 	VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
206789Sahrens }
207789Sahrens 
208789Sahrens int
209789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw)
210789Sahrens {
211789Sahrens 	int rv;
212789Sahrens 
2134831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
214789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
215789Sahrens 
216789Sahrens 	if (rw == RW_READER)
217789Sahrens 		rv = rw_tryrdlock(&rwlp->rw_lock);
218789Sahrens 	else
219789Sahrens 		rv = rw_trywrlock(&rwlp->rw_lock);
220789Sahrens 
221789Sahrens 	if (rv == 0) {
222789Sahrens 		rwlp->rw_owner = curthread;
223789Sahrens 		return (1);
224789Sahrens 	}
225789Sahrens 
226789Sahrens 	return (0);
227789Sahrens }
228789Sahrens 
229789Sahrens /*ARGSUSED*/
230789Sahrens int
231789Sahrens rw_tryupgrade(krwlock_t *rwlp)
232789Sahrens {
2334831Sgw25295 	ASSERT(rwlp->initialized == B_TRUE);
234789Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
235789Sahrens 
236789Sahrens 	return (0);
237789Sahrens }
238789Sahrens 
239789Sahrens /*
240789Sahrens  * =========================================================================
241789Sahrens  * condition variables
242789Sahrens  * =========================================================================
243789Sahrens  */
244789Sahrens /*ARGSUSED*/
245789Sahrens void
246789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg)
247789Sahrens {
2482856Snd150628 	VERIFY(cond_init(cv, type, NULL) == 0);
249789Sahrens }
250789Sahrens 
251789Sahrens void
252789Sahrens cv_destroy(kcondvar_t *cv)
253789Sahrens {
2542856Snd150628 	VERIFY(cond_destroy(cv) == 0);
255789Sahrens }
256789Sahrens 
257789Sahrens void
258789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp)
259789Sahrens {
260789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
261789Sahrens 	mp->m_owner = NULL;
2622856Snd150628 	int ret = cond_wait(cv, &mp->m_lock);
2632856Snd150628 	VERIFY(ret == 0 || ret == EINTR);
264789Sahrens 	mp->m_owner = curthread;
265789Sahrens }
266789Sahrens 
267789Sahrens clock_t
268789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
269789Sahrens {
270789Sahrens 	int error;
271789Sahrens 	timestruc_t ts;
272789Sahrens 	clock_t delta;
273789Sahrens 
274789Sahrens top:
27511066Srafael.vanoni@sun.com 	delta = abstime - ddi_get_lbolt();
276789Sahrens 	if (delta <= 0)
277789Sahrens 		return (-1);
278789Sahrens 
279789Sahrens 	ts.tv_sec = delta / hz;
280789Sahrens 	ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
281789Sahrens 
282789Sahrens 	ASSERT(mutex_owner(mp) == curthread);
283789Sahrens 	mp->m_owner = NULL;
284789Sahrens 	error = cond_reltimedwait(cv, &mp->m_lock, &ts);
285789Sahrens 	mp->m_owner = curthread;
286789Sahrens 
287789Sahrens 	if (error == ETIME)
288789Sahrens 		return (-1);
289789Sahrens 
290789Sahrens 	if (error == EINTR)
291789Sahrens 		goto top;
292789Sahrens 
293789Sahrens 	ASSERT(error == 0);
294789Sahrens 
295789Sahrens 	return (1);
296789Sahrens }
297789Sahrens 
298789Sahrens void
299789Sahrens cv_signal(kcondvar_t *cv)
300789Sahrens {
3012856Snd150628 	VERIFY(cond_signal(cv) == 0);
302789Sahrens }
303789Sahrens 
304789Sahrens void
305789Sahrens cv_broadcast(kcondvar_t *cv)
306789Sahrens {
3072856Snd150628 	VERIFY(cond_broadcast(cv) == 0);
308789Sahrens }
309789Sahrens 
310789Sahrens /*
311789Sahrens  * =========================================================================
312789Sahrens  * vnode operations
313789Sahrens  * =========================================================================
314789Sahrens  */
315789Sahrens /*
316789Sahrens  * Note: for the xxxat() versions of these functions, we assume that the
317789Sahrens  * starting vp is always rootdir (which is true for spa_directory.c, the only
318789Sahrens  * ZFS consumer of these interfaces).  We assert this is true, and then emulate
319789Sahrens  * them by adding '/' in front of the path.
320789Sahrens  */
321789Sahrens 
322789Sahrens /*ARGSUSED*/
323789Sahrens int
324789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
325789Sahrens {
326789Sahrens 	int fd;
327789Sahrens 	vnode_t *vp;
328789Sahrens 	int old_umask;
329789Sahrens 	char realpath[MAXPATHLEN];
330789Sahrens 	struct stat64 st;
331789Sahrens 
332789Sahrens 	/*
333789Sahrens 	 * If we're accessing a real disk from userland, we need to use
334789Sahrens 	 * the character interface to avoid caching.  This is particularly
335789Sahrens 	 * important if we're trying to look at a real in-kernel storage
336789Sahrens 	 * pool from userland, e.g. via zdb, because otherwise we won't
337789Sahrens 	 * see the changes occurring under the segmap cache.
338789Sahrens 	 * On the other hand, the stupid character device returns zero
339789Sahrens 	 * for its size.  So -- gag -- we open the block device to get
340789Sahrens 	 * its size, and remember it for subsequent VOP_GETATTR().
341789Sahrens 	 */
342789Sahrens 	if (strncmp(path, "/dev/", 5) == 0) {
343789Sahrens 		char *dsk;
344789Sahrens 		fd = open64(path, O_RDONLY);
345789Sahrens 		if (fd == -1)
346789Sahrens 			return (errno);
347789Sahrens 		if (fstat64(fd, &st) == -1) {
348789Sahrens 			close(fd);
349789Sahrens 			return (errno);
350789Sahrens 		}
351789Sahrens 		close(fd);
352789Sahrens 		(void) sprintf(realpath, "%s", path);
353789Sahrens 		dsk = strstr(path, "/dsk/");
354789Sahrens 		if (dsk != NULL)
355789Sahrens 			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
356789Sahrens 			    dsk + 1);
357789Sahrens 	} else {
358789Sahrens 		(void) sprintf(realpath, "%s", path);
359789Sahrens 		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
360789Sahrens 			return (errno);
361789Sahrens 	}
362789Sahrens 
363789Sahrens 	if (flags & FCREAT)
364789Sahrens 		old_umask = umask(0);
365789Sahrens 
366789Sahrens 	/*
367789Sahrens 	 * The construct 'flags - FREAD' conveniently maps combinations of
368789Sahrens 	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
369789Sahrens 	 */
370789Sahrens 	fd = open64(realpath, flags - FREAD, mode);
371789Sahrens 
372789Sahrens 	if (flags & FCREAT)
373789Sahrens 		(void) umask(old_umask);
374789Sahrens 
375789Sahrens 	if (fd == -1)
376789Sahrens 		return (errno);
377789Sahrens 
378789Sahrens 	if (fstat64(fd, &st) == -1) {
379789Sahrens 		close(fd);
380789Sahrens 		return (errno);
381789Sahrens 	}
382789Sahrens 
383789Sahrens 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
384789Sahrens 
385789Sahrens 	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
386789Sahrens 
387789Sahrens 	vp->v_fd = fd;
388789Sahrens 	vp->v_size = st.st_size;
389789Sahrens 	vp->v_path = spa_strdup(path);
390789Sahrens 
391789Sahrens 	return (0);
392789Sahrens }
393789Sahrens 
3945331Samw /*ARGSUSED*/
395789Sahrens int
396789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
3975331Samw     int x3, vnode_t *startvp, int fd)
398789Sahrens {
399789Sahrens 	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
400789Sahrens 	int ret;
401789Sahrens 
402789Sahrens 	ASSERT(startvp == rootdir);
403789Sahrens 	(void) sprintf(realpath, "/%s", path);
404789Sahrens 
4055331Samw 	/* fd ignored for now, need if want to simulate nbmand support */
406789Sahrens 	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
407789Sahrens 
408789Sahrens 	umem_free(realpath, strlen(path) + 2);
409789Sahrens 
410789Sahrens 	return (ret);
411789Sahrens }
412789Sahrens 
413789Sahrens /*ARGSUSED*/
414789Sahrens int
415789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
416789Sahrens 	int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
417789Sahrens {
418789Sahrens 	ssize_t iolen, split;
419789Sahrens 
420789Sahrens 	if (uio == UIO_READ) {
421789Sahrens 		iolen = pread64(vp->v_fd, addr, len, offset);
422789Sahrens 	} else {
423789Sahrens 		/*
424789Sahrens 		 * To simulate partial disk writes, we split writes into two
425789Sahrens 		 * system calls so that the process can be killed in between.
426789Sahrens 		 */
427789Sahrens 		split = (len > 0 ? rand() % len : 0);
428789Sahrens 		iolen = pwrite64(vp->v_fd, addr, split, offset);
429789Sahrens 		iolen += pwrite64(vp->v_fd, (char *)addr + split,
430789Sahrens 		    len - split, offset + split);
431789Sahrens 	}
432789Sahrens 
433789Sahrens 	if (iolen == -1)
434789Sahrens 		return (errno);
435789Sahrens 	if (residp)
436789Sahrens 		*residp = len - iolen;
437789Sahrens 	else if (iolen != len)
438789Sahrens 		return (EIO);
439789Sahrens 	return (0);
440789Sahrens }
441789Sahrens 
442789Sahrens void
443789Sahrens vn_close(vnode_t *vp)
444789Sahrens {
445789Sahrens 	close(vp->v_fd);
446789Sahrens 	spa_strfree(vp->v_path);
447789Sahrens 	umem_free(vp, sizeof (vnode_t));
448789Sahrens }
449789Sahrens 
45010850SGeorge.Wilson@Sun.COM /*
45110850SGeorge.Wilson@Sun.COM  * At a minimum we need to update the size since vdev_reopen()
45210850SGeorge.Wilson@Sun.COM  * will no longer call vn_openat().
45310850SGeorge.Wilson@Sun.COM  */
45410850SGeorge.Wilson@Sun.COM int
45510850SGeorge.Wilson@Sun.COM fop_getattr(vnode_t *vp, vattr_t *vap)
45610850SGeorge.Wilson@Sun.COM {
45710850SGeorge.Wilson@Sun.COM 	struct stat64 st;
45810850SGeorge.Wilson@Sun.COM 
45910850SGeorge.Wilson@Sun.COM 	if (fstat64(vp->v_fd, &st) == -1) {
46010850SGeorge.Wilson@Sun.COM 		close(vp->v_fd);
46110850SGeorge.Wilson@Sun.COM 		return (errno);
46210850SGeorge.Wilson@Sun.COM 	}
46310850SGeorge.Wilson@Sun.COM 
46410850SGeorge.Wilson@Sun.COM 	vap->va_size = st.st_size;
46510850SGeorge.Wilson@Sun.COM 	return (0);
46610850SGeorge.Wilson@Sun.COM }
46710850SGeorge.Wilson@Sun.COM 
468789Sahrens #ifdef ZFS_DEBUG
469789Sahrens 
470789Sahrens /*
471789Sahrens  * =========================================================================
472789Sahrens  * Figure out which debugging statements to print
473789Sahrens  * =========================================================================
474789Sahrens  */
475789Sahrens 
476789Sahrens static char *dprintf_string;
477789Sahrens static int dprintf_print_all;
478789Sahrens 
479789Sahrens int
480789Sahrens dprintf_find_string(const char *string)
481789Sahrens {
482789Sahrens 	char *tmp_str = dprintf_string;
483789Sahrens 	int len = strlen(string);
484789Sahrens 
485789Sahrens 	/*
486789Sahrens 	 * Find out if this is a string we want to print.
487789Sahrens 	 * String format: file1.c,function_name1,file2.c,file3.c
488789Sahrens 	 */
489789Sahrens 
490789Sahrens 	while (tmp_str != NULL) {
491789Sahrens 		if (strncmp(tmp_str, string, len) == 0 &&
492789Sahrens 		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
493789Sahrens 			return (1);
494789Sahrens 		tmp_str = strchr(tmp_str, ',');
495789Sahrens 		if (tmp_str != NULL)
496789Sahrens 			tmp_str++; /* Get rid of , */
497789Sahrens 	}
498789Sahrens 	return (0);
499789Sahrens }
500789Sahrens 
501789Sahrens void
502789Sahrens dprintf_setup(int *argc, char **argv)
503789Sahrens {
504789Sahrens 	int i, j;
505789Sahrens 
506789Sahrens 	/*
507789Sahrens 	 * Debugging can be specified two ways: by setting the
508789Sahrens 	 * environment variable ZFS_DEBUG, or by including a
509789Sahrens 	 * "debug=..."  argument on the command line.  The command
510789Sahrens 	 * line setting overrides the environment variable.
511789Sahrens 	 */
512789Sahrens 
513789Sahrens 	for (i = 1; i < *argc; i++) {
514789Sahrens 		int len = strlen("debug=");
515789Sahrens 		/* First look for a command line argument */
516789Sahrens 		if (strncmp("debug=", argv[i], len) == 0) {
517789Sahrens 			dprintf_string = argv[i] + len;
518789Sahrens 			/* Remove from args */
519789Sahrens 			for (j = i; j < *argc; j++)
520789Sahrens 				argv[j] = argv[j+1];
521789Sahrens 			argv[j] = NULL;
522789Sahrens 			(*argc)--;
523789Sahrens 		}
524789Sahrens 	}
525789Sahrens 
526789Sahrens 	if (dprintf_string == NULL) {
527789Sahrens 		/* Look for ZFS_DEBUG environment variable */
528789Sahrens 		dprintf_string = getenv("ZFS_DEBUG");
529789Sahrens 	}
530789Sahrens 
531789Sahrens 	/*
532789Sahrens 	 * Are we just turning on all debugging?
533789Sahrens 	 */
534789Sahrens 	if (dprintf_find_string("on"))
535789Sahrens 		dprintf_print_all = 1;
536789Sahrens }
537789Sahrens 
538789Sahrens /*
539789Sahrens  * =========================================================================
540789Sahrens  * debug printfs
541789Sahrens  * =========================================================================
542789Sahrens  */
543789Sahrens void
544789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
545789Sahrens {
546789Sahrens 	const char *newfile;
547789Sahrens 	va_list adx;
548789Sahrens 
549789Sahrens 	/*
550789Sahrens 	 * Get rid of annoying "../common/" prefix to filename.
551789Sahrens 	 */
552789Sahrens 	newfile = strrchr(file, '/');
553789Sahrens 	if (newfile != NULL) {
554789Sahrens 		newfile = newfile + 1; /* Get rid of leading / */
555789Sahrens 	} else {
556789Sahrens 		newfile = file;
557789Sahrens 	}
558789Sahrens 
559789Sahrens 	if (dprintf_print_all ||
560789Sahrens 	    dprintf_find_string(newfile) ||
561789Sahrens 	    dprintf_find_string(func)) {
562789Sahrens 		/* Print out just the function name if requested */
563789Sahrens 		flockfile(stdout);
564789Sahrens 		if (dprintf_find_string("pid"))
565789Sahrens 			(void) printf("%d ", getpid());
566789Sahrens 		if (dprintf_find_string("tid"))
567789Sahrens 			(void) printf("%u ", thr_self());
568789Sahrens 		if (dprintf_find_string("cpu"))
569789Sahrens 			(void) printf("%u ", getcpuid());
570789Sahrens 		if (dprintf_find_string("time"))
571789Sahrens 			(void) printf("%llu ", gethrtime());
572789Sahrens 		if (dprintf_find_string("long"))
573789Sahrens 			(void) printf("%s, line %d: ", newfile, line);
574789Sahrens 		(void) printf("%s: ", func);
575789Sahrens 		va_start(adx, fmt);
576789Sahrens 		(void) vprintf(fmt, adx);
577789Sahrens 		va_end(adx);
578789Sahrens 		funlockfile(stdout);
579789Sahrens 	}
580789Sahrens }
581789Sahrens 
582789Sahrens #endif /* ZFS_DEBUG */
583789Sahrens 
584789Sahrens /*
585789Sahrens  * =========================================================================
586789Sahrens  * cmn_err() and panic()
587789Sahrens  * =========================================================================
588789Sahrens  */
589789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
590789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
591789Sahrens 
592789Sahrens void
593789Sahrens vpanic(const char *fmt, va_list adx)
594789Sahrens {
595789Sahrens 	(void) fprintf(stderr, "error: ");
596789Sahrens 	(void) vfprintf(stderr, fmt, adx);
597789Sahrens 	(void) fprintf(stderr, "\n");
598789Sahrens 
599789Sahrens 	abort();	/* think of it as a "user-level crash dump" */
600789Sahrens }
601789Sahrens 
602789Sahrens void
603789Sahrens panic(const char *fmt, ...)
604789Sahrens {
605789Sahrens 	va_list adx;
606789Sahrens 
607789Sahrens 	va_start(adx, fmt);
608789Sahrens 	vpanic(fmt, adx);
609789Sahrens 	va_end(adx);
610789Sahrens }
611789Sahrens 
6123713Sahrens void
6133713Sahrens vcmn_err(int ce, const char *fmt, va_list adx)
6143713Sahrens {
6153713Sahrens 	if (ce == CE_PANIC)
6163713Sahrens 		vpanic(fmt, adx);
6173713Sahrens 	if (ce != CE_NOTE) {	/* suppress noise in userland stress testing */
6183713Sahrens 		(void) fprintf(stderr, "%s", ce_prefix[ce]);
6193713Sahrens 		(void) vfprintf(stderr, fmt, adx);
6203713Sahrens 		(void) fprintf(stderr, "%s", ce_suffix[ce]);
6213713Sahrens 	}
6223713Sahrens }
6233713Sahrens 
624789Sahrens /*PRINTFLIKE2*/
625789Sahrens void
626789Sahrens cmn_err(int ce, const char *fmt, ...)
627789Sahrens {
628789Sahrens 	va_list adx;
629789Sahrens 
630789Sahrens 	va_start(adx, fmt);
6313713Sahrens 	vcmn_err(ce, fmt, adx);
632789Sahrens 	va_end(adx);
633789Sahrens }
634789Sahrens 
635789Sahrens /*
636789Sahrens  * =========================================================================
6371544Seschrock  * kobj interfaces
6381544Seschrock  * =========================================================================
6391544Seschrock  */
6401544Seschrock struct _buf *
6411544Seschrock kobj_open_file(char *name)
6421544Seschrock {
6431544Seschrock 	struct _buf *file;
6441544Seschrock 	vnode_t *vp;
6451544Seschrock 
6461544Seschrock 	/* set vp as the _fd field of the file */
6475331Samw 	if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir,
6485331Samw 	    -1) != 0)
6491544Seschrock 		return ((void *)-1UL);
6501544Seschrock 
6511544Seschrock 	file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
6521544Seschrock 	file->_fd = (intptr_t)vp;
6531544Seschrock 	return (file);
6541544Seschrock }
6551544Seschrock 
6561544Seschrock int
6571544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
6581544Seschrock {
6591544Seschrock 	ssize_t resid;
6601544Seschrock 
6611544Seschrock 	vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
6621544Seschrock 	    UIO_SYSSPACE, 0, 0, 0, &resid);
6631544Seschrock 
6643912Slling 	return (size - resid);
6651544Seschrock }
6661544Seschrock 
6671544Seschrock void
6681544Seschrock kobj_close_file(struct _buf *file)
6691544Seschrock {
6701544Seschrock 	vn_close((vnode_t *)file->_fd);
6711544Seschrock 	umem_free(file, sizeof (struct _buf));
6721544Seschrock }
6731544Seschrock 
6741544Seschrock int
6753912Slling kobj_get_filesize(struct _buf *file, uint64_t *size)
6761544Seschrock {
6771544Seschrock 	struct stat64 st;
6783912Slling 	vnode_t *vp = (vnode_t *)file->_fd;
6793912Slling 
6801544Seschrock 	if (fstat64(vp->v_fd, &st) == -1) {
6811544Seschrock 		vn_close(vp);
6821544Seschrock 		return (errno);
6831544Seschrock 	}
6843912Slling 	*size = st.st_size;
6851544Seschrock 	return (0);
6861544Seschrock }
6871544Seschrock 
6881544Seschrock /*
6891544Seschrock  * =========================================================================
690789Sahrens  * misc routines
691789Sahrens  * =========================================================================
692789Sahrens  */
693789Sahrens 
694789Sahrens void
695789Sahrens delay(clock_t ticks)
696789Sahrens {
697789Sahrens 	poll(0, 0, ticks * (1000 / hz));
698789Sahrens }
699789Sahrens 
700789Sahrens /*
701789Sahrens  * Find highest one bit set.
702789Sahrens  *	Returns bit number + 1 of highest bit that is set, otherwise returns 0.
703789Sahrens  * High order bit is 31 (or 63 in _LP64 kernel).
704789Sahrens  */
705789Sahrens int
706789Sahrens highbit(ulong_t i)
707789Sahrens {
708789Sahrens 	register int h = 1;
709789Sahrens 
710789Sahrens 	if (i == 0)
711789Sahrens 		return (0);
712789Sahrens #ifdef _LP64
713789Sahrens 	if (i & 0xffffffff00000000ul) {
714789Sahrens 		h += 32; i >>= 32;
715789Sahrens 	}
716789Sahrens #endif
717789Sahrens 	if (i & 0xffff0000) {
718789Sahrens 		h += 16; i >>= 16;
719789Sahrens 	}
720789Sahrens 	if (i & 0xff00) {
721789Sahrens 		h += 8; i >>= 8;
722789Sahrens 	}
723789Sahrens 	if (i & 0xf0) {
724789Sahrens 		h += 4; i >>= 4;
725789Sahrens 	}
726789Sahrens 	if (i & 0xc) {
727789Sahrens 		h += 2; i >>= 2;
728789Sahrens 	}
729789Sahrens 	if (i & 0x2) {
730789Sahrens 		h += 1;
731789Sahrens 	}
732789Sahrens 	return (h);
733789Sahrens }
734789Sahrens 
7355688Sbonwick static int random_fd = -1, urandom_fd = -1;
7365688Sbonwick 
737789Sahrens static int
7385688Sbonwick random_get_bytes_common(uint8_t *ptr, size_t len, int fd)
739789Sahrens {
740789Sahrens 	size_t resid = len;
741789Sahrens 	ssize_t bytes;
742789Sahrens 
743789Sahrens 	ASSERT(fd != -1);
744789Sahrens 
745789Sahrens 	while (resid != 0) {
746789Sahrens 		bytes = read(fd, ptr, resid);
7475688Sbonwick 		ASSERT3S(bytes, >=, 0);
748789Sahrens 		ptr += bytes;
749789Sahrens 		resid -= bytes;
750789Sahrens 	}
751789Sahrens 
752789Sahrens 	return (0);
753789Sahrens }
754789Sahrens 
755789Sahrens int
756789Sahrens random_get_bytes(uint8_t *ptr, size_t len)
757789Sahrens {
7585688Sbonwick 	return (random_get_bytes_common(ptr, len, random_fd));
759789Sahrens }
760789Sahrens 
761789Sahrens int
762789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len)
763789Sahrens {
7645688Sbonwick 	return (random_get_bytes_common(ptr, len, urandom_fd));
765789Sahrens }
766789Sahrens 
7673975Sek110237 int
7683975Sek110237 ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result)
7693975Sek110237 {
7703975Sek110237 	char *end;
7713975Sek110237 
7723975Sek110237 	*result = strtoul(hw_serial, &end, base);
7733975Sek110237 	if (*result == 0)
7743975Sek110237 		return (errno);
7753975Sek110237 	return (0);
7763975Sek110237 }
7773975Sek110237 
77811935SMark.Shellenbaum@Sun.COM int
77911935SMark.Shellenbaum@Sun.COM ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result)
78011935SMark.Shellenbaum@Sun.COM {
78111935SMark.Shellenbaum@Sun.COM 	char *end;
78211935SMark.Shellenbaum@Sun.COM 
78311935SMark.Shellenbaum@Sun.COM 	*result = strtoull(str, &end, base);
78411935SMark.Shellenbaum@Sun.COM 	if (*result == 0)
78511935SMark.Shellenbaum@Sun.COM 		return (errno);
78611935SMark.Shellenbaum@Sun.COM 	return (0);
78711935SMark.Shellenbaum@Sun.COM }
78811935SMark.Shellenbaum@Sun.COM 
789789Sahrens /*
790789Sahrens  * =========================================================================
791789Sahrens  * kernel emulation setup & teardown
792789Sahrens  * =========================================================================
793789Sahrens  */
794789Sahrens static int
795789Sahrens umem_out_of_memory(void)
796789Sahrens {
797789Sahrens 	char errmsg[] = "out of memory -- generating core dump\n";
798789Sahrens 
799789Sahrens 	write(fileno(stderr), errmsg, sizeof (errmsg));
800789Sahrens 	abort();
801789Sahrens 	return (0);
802789Sahrens }
803789Sahrens 
804789Sahrens void
805789Sahrens kernel_init(int mode)
806789Sahrens {
807789Sahrens 	umem_nofail_callback(umem_out_of_memory);
808789Sahrens 
809789Sahrens 	physmem = sysconf(_SC_PHYS_PAGES);
810789Sahrens 
811789Sahrens 	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
812789Sahrens 	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
813789Sahrens 
81410858SVictor.Latushkin@Sun.COM 	(void) snprintf(hw_serial, sizeof (hw_serial), "%ld",
81510858SVictor.Latushkin@Sun.COM 	    (mode & FWRITE) ? gethostid() : 0);
8163975Sek110237 
8175688Sbonwick 	VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1);
8185688Sbonwick 	VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1);
8195688Sbonwick 
8207837SMatthew.Ahrens@Sun.COM 	system_taskq_init();
8217837SMatthew.Ahrens@Sun.COM 
822789Sahrens 	spa_init(mode);
823789Sahrens }
824789Sahrens 
825789Sahrens void
826789Sahrens kernel_fini(void)
827789Sahrens {
828789Sahrens 	spa_fini();
8295688Sbonwick 
83010612SRicardo.M.Correia@Sun.COM 	system_taskq_fini();
83110612SRicardo.M.Correia@Sun.COM 
8325688Sbonwick 	close(random_fd);
8335688Sbonwick 	close(urandom_fd);
8345688Sbonwick 
8355688Sbonwick 	random_fd = -1;
8365688Sbonwick 	urandom_fd = -1;
837789Sahrens }
8383886Sahl 
8393886Sahl int
8403886Sahl z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen)
8413886Sahl {
8423886Sahl 	int ret;
8433886Sahl 	uLongf len = *dstlen;
8443886Sahl 
8453886Sahl 	if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK)
8463886Sahl 		*dstlen = (size_t)len;
8473886Sahl 
8483886Sahl 	return (ret);
8493886Sahl }
8503886Sahl 
8513886Sahl int
8523886Sahl z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen,
8533886Sahl     int level)
8543886Sahl {
8553886Sahl 	int ret;
8563886Sahl 	uLongf len = *dstlen;
8573886Sahl 
8583886Sahl 	if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK)
8593886Sahl 		*dstlen = (size_t)len;
8603886Sahl 
8613886Sahl 	return (ret);
8623886Sahl }
8634543Smarks 
8644543Smarks uid_t
8654543Smarks crgetuid(cred_t *cr)
8664543Smarks {
8674543Smarks 	return (0);
8684543Smarks }
8694543Smarks 
8704543Smarks gid_t
8714543Smarks crgetgid(cred_t *cr)
8724543Smarks {
8734543Smarks 	return (0);
8744543Smarks }
8754543Smarks 
8764543Smarks int
8774543Smarks crgetngroups(cred_t *cr)
8784543Smarks {
8794543Smarks 	return (0);
8804543Smarks }
8814543Smarks 
8824543Smarks gid_t *
8834543Smarks crgetgroups(cred_t *cr)
8844543Smarks {
8854543Smarks 	return (NULL);
8864543Smarks }
8874543Smarks 
8884543Smarks int
8894543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
8904543Smarks {
8914543Smarks 	return (0);
8924543Smarks }
8934543Smarks 
8944543Smarks int
8954543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
8964543Smarks {
8974543Smarks 	return (0);
8984543Smarks }
8994543Smarks 
9004543Smarks int
9014543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
9024543Smarks {
9034543Smarks 	return (0);
9044543Smarks }
9055959Smarks 
9065959Smarks ksiddomain_t *
9075959Smarks ksid_lookupdomain(const char *dom)
9085959Smarks {
9095959Smarks 	ksiddomain_t *kd;
9105959Smarks 
9115959Smarks 	kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL);
9125959Smarks 	kd->kd_name = spa_strdup(dom);
9135959Smarks 	return (kd);
9145959Smarks }
9155959Smarks 
9165959Smarks void
9175959Smarks ksiddomain_rele(ksiddomain_t *ksid)
9185959Smarks {
9195959Smarks 	spa_strfree(ksid->kd_name);
9205959Smarks 	umem_free(ksid, sizeof (ksiddomain_t));
9215959Smarks }
92210272SMatthew.Ahrens@Sun.COM 
92310272SMatthew.Ahrens@Sun.COM /*
92410272SMatthew.Ahrens@Sun.COM  * Do not change the length of the returned string; it must be freed
92510272SMatthew.Ahrens@Sun.COM  * with strfree().
92610272SMatthew.Ahrens@Sun.COM  */
92710272SMatthew.Ahrens@Sun.COM char *
92810272SMatthew.Ahrens@Sun.COM kmem_asprintf(const char *fmt, ...)
92910272SMatthew.Ahrens@Sun.COM {
93010272SMatthew.Ahrens@Sun.COM 	int size;
93110272SMatthew.Ahrens@Sun.COM 	va_list adx;
93210272SMatthew.Ahrens@Sun.COM 	char *buf;
93310272SMatthew.Ahrens@Sun.COM 
93410272SMatthew.Ahrens@Sun.COM 	va_start(adx, fmt);
93510272SMatthew.Ahrens@Sun.COM 	size = vsnprintf(NULL, 0, fmt, adx) + 1;
93610272SMatthew.Ahrens@Sun.COM 	va_end(adx);
93710272SMatthew.Ahrens@Sun.COM 
93810272SMatthew.Ahrens@Sun.COM 	buf = kmem_alloc(size, KM_SLEEP);
93910272SMatthew.Ahrens@Sun.COM 
94010272SMatthew.Ahrens@Sun.COM 	va_start(adx, fmt);
94110272SMatthew.Ahrens@Sun.COM 	size = vsnprintf(buf, size, fmt, adx);
94210272SMatthew.Ahrens@Sun.COM 	va_end(adx);
94310272SMatthew.Ahrens@Sun.COM 
94410272SMatthew.Ahrens@Sun.COM 	return (buf);
94510272SMatthew.Ahrens@Sun.COM }
94612527SChris.Kirby@oracle.com 
94712527SChris.Kirby@oracle.com /* ARGSUSED */
94812527SChris.Kirby@oracle.com int
949*12786SChris.Kirby@oracle.com zfs_onexit_fd_hold(int fd, minor_t *minorp)
950*12786SChris.Kirby@oracle.com {
951*12786SChris.Kirby@oracle.com 	*minorp = 0;
952*12786SChris.Kirby@oracle.com 	return (0);
953*12786SChris.Kirby@oracle.com }
954*12786SChris.Kirby@oracle.com 
955*12786SChris.Kirby@oracle.com /* ARGSUSED */
956*12786SChris.Kirby@oracle.com void
957*12786SChris.Kirby@oracle.com zfs_onexit_fd_rele(int fd)
958*12786SChris.Kirby@oracle.com {
959*12786SChris.Kirby@oracle.com }
960*12786SChris.Kirby@oracle.com 
961*12786SChris.Kirby@oracle.com /* ARGSUSED */
962*12786SChris.Kirby@oracle.com int
963*12786SChris.Kirby@oracle.com zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
96412527SChris.Kirby@oracle.com     uint64_t *action_handle)
96512527SChris.Kirby@oracle.com {
96612527SChris.Kirby@oracle.com 	return (0);
96712527SChris.Kirby@oracle.com }
96812527SChris.Kirby@oracle.com 
96912527SChris.Kirby@oracle.com /* ARGSUSED */
97012527SChris.Kirby@oracle.com int
971*12786SChris.Kirby@oracle.com zfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire)
97212527SChris.Kirby@oracle.com {
97312527SChris.Kirby@oracle.com 	return (0);
97412527SChris.Kirby@oracle.com }
97512527SChris.Kirby@oracle.com 
97612527SChris.Kirby@oracle.com /* ARGSUSED */
97712527SChris.Kirby@oracle.com int
978*12786SChris.Kirby@oracle.com zfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data)
97912527SChris.Kirby@oracle.com {
98012527SChris.Kirby@oracle.com 	return (0);
98112527SChris.Kirby@oracle.com }
982