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