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