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