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