kernel.c revision 254591
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25#include <assert.h>
26#include <fcntl.h>
27#include <poll.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <zlib.h>
32#include <sys/spa.h>
33#include <sys/stat.h>
34#include <sys/processor.h>
35#include <sys/zfs_context.h>
36#include <sys/rrwlock.h>
37#include <sys/zmod.h>
38#include <sys/utsname.h>
39#include <sys/systeminfo.h>
40
41/*
42 * Emulation of kernel services in userland.
43 */
44
45int aok;
46uint64_t physmem;
47vnode_t *rootdir = (vnode_t *)0xabcd1234;
48char hw_serial[HW_HOSTID_LEN];
49#ifdef illumos
50kmutex_t cpu_lock;
51#endif
52
53struct utsname utsname = {
54	"userland", "libzpool", "1", "1", "na"
55};
56
57/* this only exists to have its address taken */
58struct proc p0;
59
60/*
61 * =========================================================================
62 * threads
63 * =========================================================================
64 */
65/*ARGSUSED*/
66kthread_t *
67zk_thread_create(void (*func)(), void *arg)
68{
69	thread_t tid;
70
71	VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
72	    &tid) == 0);
73
74	return ((void *)(uintptr_t)tid);
75}
76
77/*
78 * =========================================================================
79 * kstats
80 * =========================================================================
81 */
82/*ARGSUSED*/
83kstat_t *
84kstat_create(char *module, int instance, char *name, char *class,
85    uchar_t type, ulong_t ndata, uchar_t ks_flag)
86{
87	return (NULL);
88}
89
90/*ARGSUSED*/
91void
92kstat_install(kstat_t *ksp)
93{}
94
95/*ARGSUSED*/
96void
97kstat_delete(kstat_t *ksp)
98{}
99
100/*
101 * =========================================================================
102 * mutexes
103 * =========================================================================
104 */
105void
106zmutex_init(kmutex_t *mp)
107{
108	mp->m_owner = NULL;
109	mp->initialized = B_TRUE;
110	(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
111}
112
113void
114zmutex_destroy(kmutex_t *mp)
115{
116	ASSERT(mp->initialized == B_TRUE);
117	ASSERT(mp->m_owner == NULL);
118	(void) _mutex_destroy(&(mp)->m_lock);
119	mp->m_owner = (void *)-1UL;
120	mp->initialized = B_FALSE;
121}
122
123int
124zmutex_owned(kmutex_t *mp)
125{
126	ASSERT(mp->initialized == B_TRUE);
127
128	return (mp->m_owner == curthread);
129}
130
131void
132mutex_enter(kmutex_t *mp)
133{
134	ASSERT(mp->initialized == B_TRUE);
135	ASSERT(mp->m_owner != (void *)-1UL);
136	ASSERT(mp->m_owner != curthread);
137	VERIFY(mutex_lock(&mp->m_lock) == 0);
138	ASSERT(mp->m_owner == NULL);
139	mp->m_owner = curthread;
140}
141
142int
143mutex_tryenter(kmutex_t *mp)
144{
145	ASSERT(mp->initialized == B_TRUE);
146	ASSERT(mp->m_owner != (void *)-1UL);
147	if (0 == mutex_trylock(&mp->m_lock)) {
148		ASSERT(mp->m_owner == NULL);
149		mp->m_owner = curthread;
150		return (1);
151	} else {
152		return (0);
153	}
154}
155
156void
157mutex_exit(kmutex_t *mp)
158{
159	ASSERT(mp->initialized == B_TRUE);
160	ASSERT(mutex_owner(mp) == curthread);
161	mp->m_owner = NULL;
162	VERIFY(mutex_unlock(&mp->m_lock) == 0);
163}
164
165void *
166mutex_owner(kmutex_t *mp)
167{
168	ASSERT(mp->initialized == B_TRUE);
169	return (mp->m_owner);
170}
171
172/*
173 * =========================================================================
174 * rwlocks
175 * =========================================================================
176 */
177/*ARGSUSED*/
178void
179rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
180{
181	rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
182	rwlp->rw_owner = NULL;
183	rwlp->initialized = B_TRUE;
184	rwlp->rw_count = 0;
185}
186
187void
188rw_destroy(krwlock_t *rwlp)
189{
190	ASSERT(rwlp->rw_count == 0);
191	rwlock_destroy(&rwlp->rw_lock);
192	rwlp->rw_owner = (void *)-1UL;
193	rwlp->initialized = B_FALSE;
194}
195
196void
197rw_enter(krwlock_t *rwlp, krw_t rw)
198{
199	//ASSERT(!RW_LOCK_HELD(rwlp));
200	ASSERT(rwlp->initialized == B_TRUE);
201	ASSERT(rwlp->rw_owner != (void *)-1UL);
202	ASSERT(rwlp->rw_owner != curthread);
203
204	if (rw == RW_READER) {
205		VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
206		ASSERT(rwlp->rw_count >= 0);
207		atomic_add_int(&rwlp->rw_count, 1);
208	} else {
209		VERIFY(rw_wrlock(&rwlp->rw_lock) == 0);
210		ASSERT(rwlp->rw_count == 0);
211		rwlp->rw_count = -1;
212		rwlp->rw_owner = curthread;
213	}
214}
215
216void
217rw_exit(krwlock_t *rwlp)
218{
219	ASSERT(rwlp->initialized == B_TRUE);
220	ASSERT(rwlp->rw_owner != (void *)-1UL);
221
222	if (rwlp->rw_owner == curthread) {
223		/* Write locked. */
224		ASSERT(rwlp->rw_count == -1);
225		rwlp->rw_count = 0;
226		rwlp->rw_owner = NULL;
227	} else {
228		/* Read locked. */
229		ASSERT(rwlp->rw_count > 0);
230		atomic_add_int(&rwlp->rw_count, -1);
231	}
232	VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
233}
234
235int
236rw_tryenter(krwlock_t *rwlp, krw_t rw)
237{
238	int rv;
239
240	ASSERT(rwlp->initialized == B_TRUE);
241	ASSERT(rwlp->rw_owner != (void *)-1UL);
242	ASSERT(rwlp->rw_owner != curthread);
243
244	if (rw == RW_READER)
245		rv = rw_tryrdlock(&rwlp->rw_lock);
246	else
247		rv = rw_trywrlock(&rwlp->rw_lock);
248
249	if (rv == 0) {
250		ASSERT(rwlp->rw_owner == NULL);
251		if (rw == RW_READER) {
252			ASSERT(rwlp->rw_count >= 0);
253			atomic_add_int(&rwlp->rw_count, 1);
254		} else {
255			ASSERT(rwlp->rw_count == 0);
256			rwlp->rw_count = -1;
257			rwlp->rw_owner = curthread;
258		}
259		return (1);
260	}
261
262	return (0);
263}
264
265/*ARGSUSED*/
266int
267rw_tryupgrade(krwlock_t *rwlp)
268{
269	ASSERT(rwlp->initialized == B_TRUE);
270	ASSERT(rwlp->rw_owner != (void *)-1UL);
271
272	return (0);
273}
274
275int
276rw_lock_held(krwlock_t *rwlp)
277{
278
279	return (rwlp->rw_count != 0);
280}
281
282/*
283 * =========================================================================
284 * condition variables
285 * =========================================================================
286 */
287/*ARGSUSED*/
288void
289cv_init(kcondvar_t *cv, char *name, int type, void *arg)
290{
291	VERIFY(cond_init(cv, name, NULL) == 0);
292}
293
294void
295cv_destroy(kcondvar_t *cv)
296{
297	VERIFY(cond_destroy(cv) == 0);
298}
299
300void
301cv_wait(kcondvar_t *cv, kmutex_t *mp)
302{
303	ASSERT(mutex_owner(mp) == curthread);
304	mp->m_owner = NULL;
305	int ret = cond_wait(cv, &mp->m_lock);
306	VERIFY(ret == 0 || ret == EINTR);
307	mp->m_owner = curthread;
308}
309
310clock_t
311cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
312{
313	int error;
314	struct timespec ts;
315	struct timeval tv;
316	clock_t delta;
317
318	abstime += ddi_get_lbolt();
319top:
320	delta = abstime - ddi_get_lbolt();
321	if (delta <= 0)
322		return (-1);
323
324	if (gettimeofday(&tv, NULL) != 0)
325		assert(!"gettimeofday() failed");
326
327	ts.tv_sec = tv.tv_sec + delta / hz;
328	ts.tv_nsec = tv.tv_usec * 1000 + (delta % hz) * (NANOSEC / hz);
329	ASSERT(ts.tv_nsec >= 0);
330
331	if (ts.tv_nsec >= NANOSEC) {
332		ts.tv_sec++;
333		ts.tv_nsec -= NANOSEC;
334	}
335
336	ASSERT(mutex_owner(mp) == curthread);
337	mp->m_owner = NULL;
338	error = pthread_cond_timedwait(cv, &mp->m_lock, &ts);
339	mp->m_owner = curthread;
340
341	if (error == EINTR)
342		goto top;
343
344	if (error == ETIMEDOUT)
345		return (-1);
346
347	ASSERT(error == 0);
348
349	return (1);
350}
351
352void
353cv_signal(kcondvar_t *cv)
354{
355	VERIFY(cond_signal(cv) == 0);
356}
357
358void
359cv_broadcast(kcondvar_t *cv)
360{
361	VERIFY(cond_broadcast(cv) == 0);
362}
363
364/*
365 * =========================================================================
366 * vnode operations
367 * =========================================================================
368 */
369/*
370 * Note: for the xxxat() versions of these functions, we assume that the
371 * starting vp is always rootdir (which is true for spa_directory.c, the only
372 * ZFS consumer of these interfaces).  We assert this is true, and then emulate
373 * them by adding '/' in front of the path.
374 */
375
376/*ARGSUSED*/
377int
378vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
379{
380	int fd;
381	vnode_t *vp;
382	int old_umask;
383	char realpath[MAXPATHLEN];
384	struct stat64 st;
385
386	/*
387	 * If we're accessing a real disk from userland, we need to use
388	 * the character interface to avoid caching.  This is particularly
389	 * important if we're trying to look at a real in-kernel storage
390	 * pool from userland, e.g. via zdb, because otherwise we won't
391	 * see the changes occurring under the segmap cache.
392	 * On the other hand, the stupid character device returns zero
393	 * for its size.  So -- gag -- we open the block device to get
394	 * its size, and remember it for subsequent VOP_GETATTR().
395	 */
396	if (strncmp(path, "/dev/", 5) == 0) {
397		char *dsk;
398		fd = open64(path, O_RDONLY);
399		if (fd == -1)
400			return (errno);
401		if (fstat64(fd, &st) == -1) {
402			close(fd);
403			return (errno);
404		}
405		close(fd);
406		(void) sprintf(realpath, "%s", path);
407		dsk = strstr(path, "/dsk/");
408		if (dsk != NULL)
409			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
410			    dsk + 1);
411	} else {
412		(void) sprintf(realpath, "%s", path);
413		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
414			return (errno);
415	}
416
417	if (flags & FCREAT)
418		old_umask = umask(0);
419
420	/*
421	 * The construct 'flags - FREAD' conveniently maps combinations of
422	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
423	 */
424	fd = open64(realpath, flags - FREAD, mode);
425
426	if (flags & FCREAT)
427		(void) umask(old_umask);
428
429	if (fd == -1)
430		return (errno);
431
432	if (fstat64(fd, &st) == -1) {
433		close(fd);
434		return (errno);
435	}
436
437	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
438
439	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
440
441	vp->v_fd = fd;
442	vp->v_size = st.st_size;
443	vp->v_path = spa_strdup(path);
444
445	return (0);
446}
447
448/*ARGSUSED*/
449int
450vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
451    int x3, vnode_t *startvp, int fd)
452{
453	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
454	int ret;
455
456	ASSERT(startvp == rootdir);
457	(void) sprintf(realpath, "/%s", path);
458
459	/* fd ignored for now, need if want to simulate nbmand support */
460	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
461
462	umem_free(realpath, strlen(path) + 2);
463
464	return (ret);
465}
466
467/*ARGSUSED*/
468int
469vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
470	int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
471{
472	ssize_t iolen, split;
473
474	if (uio == UIO_READ) {
475		iolen = pread64(vp->v_fd, addr, len, offset);
476	} else {
477		/*
478		 * To simulate partial disk writes, we split writes into two
479		 * system calls so that the process can be killed in between.
480		 */
481		int sectors = len >> SPA_MINBLOCKSHIFT;
482		split = (sectors > 0 ? rand() % sectors : 0) <<
483		    SPA_MINBLOCKSHIFT;
484		iolen = pwrite64(vp->v_fd, addr, split, offset);
485		iolen += pwrite64(vp->v_fd, (char *)addr + split,
486		    len - split, offset + split);
487	}
488
489	if (iolen == -1)
490		return (errno);
491	if (residp)
492		*residp = len - iolen;
493	else if (iolen != len)
494		return (EIO);
495	return (0);
496}
497
498void
499vn_close(vnode_t *vp, int openflag, cred_t *cr, kthread_t *td)
500{
501	close(vp->v_fd);
502	spa_strfree(vp->v_path);
503	umem_free(vp, sizeof (vnode_t));
504}
505
506/*
507 * At a minimum we need to update the size since vdev_reopen()
508 * will no longer call vn_openat().
509 */
510int
511fop_getattr(vnode_t *vp, vattr_t *vap)
512{
513	struct stat64 st;
514
515	if (fstat64(vp->v_fd, &st) == -1) {
516		close(vp->v_fd);
517		return (errno);
518	}
519
520	vap->va_size = st.st_size;
521	return (0);
522}
523
524#ifdef ZFS_DEBUG
525
526/*
527 * =========================================================================
528 * Figure out which debugging statements to print
529 * =========================================================================
530 */
531
532static char *dprintf_string;
533static int dprintf_print_all;
534
535int
536dprintf_find_string(const char *string)
537{
538	char *tmp_str = dprintf_string;
539	int len = strlen(string);
540
541	/*
542	 * Find out if this is a string we want to print.
543	 * String format: file1.c,function_name1,file2.c,file3.c
544	 */
545
546	while (tmp_str != NULL) {
547		if (strncmp(tmp_str, string, len) == 0 &&
548		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
549			return (1);
550		tmp_str = strchr(tmp_str, ',');
551		if (tmp_str != NULL)
552			tmp_str++; /* Get rid of , */
553	}
554	return (0);
555}
556
557void
558dprintf_setup(int *argc, char **argv)
559{
560	int i, j;
561
562	/*
563	 * Debugging can be specified two ways: by setting the
564	 * environment variable ZFS_DEBUG, or by including a
565	 * "debug=..."  argument on the command line.  The command
566	 * line setting overrides the environment variable.
567	 */
568
569	for (i = 1; i < *argc; i++) {
570		int len = strlen("debug=");
571		/* First look for a command line argument */
572		if (strncmp("debug=", argv[i], len) == 0) {
573			dprintf_string = argv[i] + len;
574			/* Remove from args */
575			for (j = i; j < *argc; j++)
576				argv[j] = argv[j+1];
577			argv[j] = NULL;
578			(*argc)--;
579		}
580	}
581
582	if (dprintf_string == NULL) {
583		/* Look for ZFS_DEBUG environment variable */
584		dprintf_string = getenv("ZFS_DEBUG");
585	}
586
587	/*
588	 * Are we just turning on all debugging?
589	 */
590	if (dprintf_find_string("on"))
591		dprintf_print_all = 1;
592}
593
594int
595sysctl_handle_64(SYSCTL_HANDLER_ARGS)
596{
597	return (0);
598}
599
600/*
601 * =========================================================================
602 * debug printfs
603 * =========================================================================
604 */
605void
606__dprintf(const char *file, const char *func, int line, const char *fmt, ...)
607{
608	const char *newfile;
609	va_list adx;
610
611	/*
612	 * Get rid of annoying "../common/" prefix to filename.
613	 */
614	newfile = strrchr(file, '/');
615	if (newfile != NULL) {
616		newfile = newfile + 1; /* Get rid of leading / */
617	} else {
618		newfile = file;
619	}
620
621	if (dprintf_print_all ||
622	    dprintf_find_string(newfile) ||
623	    dprintf_find_string(func)) {
624		/* Print out just the function name if requested */
625		flockfile(stdout);
626		if (dprintf_find_string("pid"))
627			(void) printf("%d ", getpid());
628		if (dprintf_find_string("tid"))
629			(void) printf("%u ", thr_self());
630#if 0
631		if (dprintf_find_string("cpu"))
632			(void) printf("%u ", getcpuid());
633#endif
634		if (dprintf_find_string("time"))
635			(void) printf("%llu ", gethrtime());
636		if (dprintf_find_string("long"))
637			(void) printf("%s, line %d: ", newfile, line);
638		(void) printf("%s: ", func);
639		va_start(adx, fmt);
640		(void) vprintf(fmt, adx);
641		va_end(adx);
642		funlockfile(stdout);
643	}
644}
645
646#endif /* ZFS_DEBUG */
647
648/*
649 * =========================================================================
650 * cmn_err() and panic()
651 * =========================================================================
652 */
653static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
654static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
655
656void
657vpanic(const char *fmt, va_list adx)
658{
659	(void) fprintf(stderr, "error: ");
660	(void) vfprintf(stderr, fmt, adx);
661	(void) fprintf(stderr, "\n");
662
663	abort();	/* think of it as a "user-level crash dump" */
664}
665
666void
667panic(const char *fmt, ...)
668{
669	va_list adx;
670
671	va_start(adx, fmt);
672	vpanic(fmt, adx);
673	va_end(adx);
674}
675
676void
677vcmn_err(int ce, const char *fmt, va_list adx)
678{
679	if (ce == CE_PANIC)
680		vpanic(fmt, adx);
681	if (ce != CE_NOTE) {	/* suppress noise in userland stress testing */
682		(void) fprintf(stderr, "%s", ce_prefix[ce]);
683		(void) vfprintf(stderr, fmt, adx);
684		(void) fprintf(stderr, "%s", ce_suffix[ce]);
685	}
686}
687
688/*PRINTFLIKE2*/
689void
690cmn_err(int ce, const char *fmt, ...)
691{
692	va_list adx;
693
694	va_start(adx, fmt);
695	vcmn_err(ce, fmt, adx);
696	va_end(adx);
697}
698
699/*
700 * =========================================================================
701 * kobj interfaces
702 * =========================================================================
703 */
704struct _buf *
705kobj_open_file(char *name)
706{
707	struct _buf *file;
708	vnode_t *vp;
709
710	/* set vp as the _fd field of the file */
711	if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir,
712	    -1) != 0)
713		return ((void *)-1UL);
714
715	file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
716	file->_fd = (intptr_t)vp;
717	return (file);
718}
719
720int
721kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
722{
723	ssize_t resid;
724
725	vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
726	    UIO_SYSSPACE, 0, 0, 0, &resid);
727
728	return (size - resid);
729}
730
731void
732kobj_close_file(struct _buf *file)
733{
734	vn_close((vnode_t *)file->_fd, 0, NULL, NULL);
735	umem_free(file, sizeof (struct _buf));
736}
737
738int
739kobj_get_filesize(struct _buf *file, uint64_t *size)
740{
741	struct stat64 st;
742	vnode_t *vp = (vnode_t *)file->_fd;
743
744	if (fstat64(vp->v_fd, &st) == -1) {
745		vn_close(vp, 0, NULL, NULL);
746		return (errno);
747	}
748	*size = st.st_size;
749	return (0);
750}
751
752/*
753 * =========================================================================
754 * misc routines
755 * =========================================================================
756 */
757
758void
759delay(clock_t ticks)
760{
761	poll(0, 0, ticks * (1000 / hz));
762}
763
764#if 0
765/*
766 * Find highest one bit set.
767 *	Returns bit number + 1 of highest bit that is set, otherwise returns 0.
768 * High order bit is 31 (or 63 in _LP64 kernel).
769 */
770int
771highbit(ulong_t i)
772{
773	register int h = 1;
774
775	if (i == 0)
776		return (0);
777#ifdef _LP64
778	if (i & 0xffffffff00000000ul) {
779		h += 32; i >>= 32;
780	}
781#endif
782	if (i & 0xffff0000) {
783		h += 16; i >>= 16;
784	}
785	if (i & 0xff00) {
786		h += 8; i >>= 8;
787	}
788	if (i & 0xf0) {
789		h += 4; i >>= 4;
790	}
791	if (i & 0xc) {
792		h += 2; i >>= 2;
793	}
794	if (i & 0x2) {
795		h += 1;
796	}
797	return (h);
798}
799#endif
800
801static int random_fd = -1, urandom_fd = -1;
802
803static int
804random_get_bytes_common(uint8_t *ptr, size_t len, int fd)
805{
806	size_t resid = len;
807	ssize_t bytes;
808
809	ASSERT(fd != -1);
810
811	while (resid != 0) {
812		bytes = read(fd, ptr, resid);
813		ASSERT3S(bytes, >=, 0);
814		ptr += bytes;
815		resid -= bytes;
816	}
817
818	return (0);
819}
820
821int
822random_get_bytes(uint8_t *ptr, size_t len)
823{
824	return (random_get_bytes_common(ptr, len, random_fd));
825}
826
827int
828random_get_pseudo_bytes(uint8_t *ptr, size_t len)
829{
830	return (random_get_bytes_common(ptr, len, urandom_fd));
831}
832
833int
834ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result)
835{
836	char *end;
837
838	*result = strtoul(hw_serial, &end, base);
839	if (*result == 0)
840		return (errno);
841	return (0);
842}
843
844int
845ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result)
846{
847	char *end;
848
849	*result = strtoull(str, &end, base);
850	if (*result == 0)
851		return (errno);
852	return (0);
853}
854
855#ifdef illumos
856/* ARGSUSED */
857cyclic_id_t
858cyclic_add(cyc_handler_t *hdlr, cyc_time_t *when)
859{
860	return (1);
861}
862
863/* ARGSUSED */
864void
865cyclic_remove(cyclic_id_t id)
866{
867}
868
869/* ARGSUSED */
870int
871cyclic_reprogram(cyclic_id_t id, hrtime_t expiration)
872{
873	return (1);
874}
875#endif
876
877/*
878 * =========================================================================
879 * kernel emulation setup & teardown
880 * =========================================================================
881 */
882static int
883umem_out_of_memory(void)
884{
885	char errmsg[] = "out of memory -- generating core dump\n";
886
887	write(fileno(stderr), errmsg, sizeof (errmsg));
888	abort();
889	return (0);
890}
891
892void
893kernel_init(int mode)
894{
895	extern uint_t rrw_tsd_key;
896
897	umem_nofail_callback(umem_out_of_memory);
898
899	physmem = sysconf(_SC_PHYS_PAGES);
900
901	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
902	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
903
904	(void) snprintf(hw_serial, sizeof (hw_serial), "%lu",
905	    (mode & FWRITE) ? (unsigned long)gethostid() : 0);
906
907	VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1);
908	VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1);
909
910	system_taskq_init();
911
912#ifdef illumos
913	mutex_init(&cpu_lock, NULL, MUTEX_DEFAULT, NULL);
914#endif
915
916	spa_init(mode);
917
918	tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
919}
920
921void
922kernel_fini(void)
923{
924	spa_fini();
925
926	system_taskq_fini();
927
928	close(random_fd);
929	close(urandom_fd);
930
931	random_fd = -1;
932	urandom_fd = -1;
933}
934
935int
936z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen)
937{
938	int ret;
939	uLongf len = *dstlen;
940
941	if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK)
942		*dstlen = (size_t)len;
943
944	return (ret);
945}
946
947int
948z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen,
949    int level)
950{
951	int ret;
952	uLongf len = *dstlen;
953
954	if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK)
955		*dstlen = (size_t)len;
956
957	return (ret);
958}
959
960uid_t
961crgetuid(cred_t *cr)
962{
963	return (0);
964}
965
966uid_t
967crgetruid(cred_t *cr)
968{
969	return (0);
970}
971
972gid_t
973crgetgid(cred_t *cr)
974{
975	return (0);
976}
977
978int
979crgetngroups(cred_t *cr)
980{
981	return (0);
982}
983
984gid_t *
985crgetgroups(cred_t *cr)
986{
987	return (NULL);
988}
989
990int
991zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
992{
993	return (0);
994}
995
996int
997zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
998{
999	return (0);
1000}
1001
1002int
1003zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
1004{
1005	return (0);
1006}
1007
1008ksiddomain_t *
1009ksid_lookupdomain(const char *dom)
1010{
1011	ksiddomain_t *kd;
1012
1013	kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL);
1014	kd->kd_name = spa_strdup(dom);
1015	return (kd);
1016}
1017
1018void
1019ksiddomain_rele(ksiddomain_t *ksid)
1020{
1021	spa_strfree(ksid->kd_name);
1022	umem_free(ksid, sizeof (ksiddomain_t));
1023}
1024
1025/*
1026 * Do not change the length of the returned string; it must be freed
1027 * with strfree().
1028 */
1029char *
1030kmem_asprintf(const char *fmt, ...)
1031{
1032	int size;
1033	va_list adx;
1034	char *buf;
1035
1036	va_start(adx, fmt);
1037	size = vsnprintf(NULL, 0, fmt, adx) + 1;
1038	va_end(adx);
1039
1040	buf = kmem_alloc(size, KM_SLEEP);
1041
1042	va_start(adx, fmt);
1043	size = vsnprintf(buf, size, fmt, adx);
1044	va_end(adx);
1045
1046	return (buf);
1047}
1048
1049/* ARGSUSED */
1050int
1051zfs_onexit_fd_hold(int fd, minor_t *minorp)
1052{
1053	*minorp = 0;
1054	return (0);
1055}
1056
1057/* ARGSUSED */
1058void
1059zfs_onexit_fd_rele(int fd)
1060{
1061}
1062
1063/* ARGSUSED */
1064int
1065zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
1066    uint64_t *action_handle)
1067{
1068	return (0);
1069}
1070
1071/* ARGSUSED */
1072int
1073zfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire)
1074{
1075	return (0);
1076}
1077
1078/* ARGSUSED */
1079int
1080zfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data)
1081{
1082	return (0);
1083}
1084
1085#ifdef __FreeBSD__
1086/* ARGSUSED */
1087int
1088zvol_create_minors(const char *name)
1089{
1090	return (0);
1091}
1092#endif
1093