]> git.proxmox.com Git - mirror_zfs.git/blame - lib/libzpool/kernel.c
Tag 0.7.0-rc4
[mirror_zfs.git] / lib / libzpool / kernel.c
CommitLineData
34dc7c2f
BB
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/*
572e2857 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
a0bd735a 23 * Copyright (c) 2016 Actifio, Inc. All rights reserved.
34dc7c2f
BB
24 */
25
34dc7c2f
BB
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>
9867e8be 33#include <libgen.h>
1e33ac1e 34#include <sys/signal.h>
34dc7c2f
BB
35#include <sys/spa.h>
36#include <sys/stat.h>
37#include <sys/processor.h>
38#include <sys/zfs_context.h>
13fe0198 39#include <sys/rrwlock.h>
34dc7c2f 40#include <sys/utsname.h>
d603ed6c 41#include <sys/time.h>
d164b209 42#include <sys/systeminfo.h>
1eeb4562 43#include <zfs_fletcher.h>
0b04990a 44#include <sys/crypto/icp.h>
34dc7c2f
BB
45
46/*
47 * Emulation of kernel services in userland.
48 */
49
428870ff 50int aok;
34dc7c2f
BB
51uint64_t physmem;
52vnode_t *rootdir = (vnode_t *)0xabcd1234;
d164b209 53char hw_serial[HW_HOSTID_LEN];
f0e324f2 54struct utsname hw_utsname;
ca67b33a 55vmem_t *zio_arena = NULL;
34dc7c2f 56
9867e8be
MA
57/* If set, all blocks read will be copied to the specified directory. */
58char *vn_dumpdir = NULL;
59
428870ff
BB
60/* this only exists to have its address taken */
61struct proc p0;
62
34dc7c2f
BB
63/*
64 * =========================================================================
65 * threads
66 * =========================================================================
67 */
1e33ac1e
BB
68
69pthread_cond_t kthread_cond = PTHREAD_COND_INITIALIZER;
70pthread_mutex_t kthread_lock = PTHREAD_MUTEX_INITIALIZER;
71pthread_key_t kthread_key;
72int kthread_nr = 0;
73
519129ff 74void
1e33ac1e
BB
75thread_init(void)
76{
77 kthread_t *kt;
78
79 VERIFY3S(pthread_key_create(&kthread_key, NULL), ==, 0);
80
81 /* Create entry for primary kthread */
d1d7e268 82 kt = umem_zalloc(sizeof (kthread_t), UMEM_NOFAIL);
1e33ac1e
BB
83 kt->t_tid = pthread_self();
84 kt->t_func = NULL;
85
86 VERIFY3S(pthread_setspecific(kthread_key, kt), ==, 0);
87
88 /* Only the main thread should be running at the moment */
89 ASSERT3S(kthread_nr, ==, 0);
90 kthread_nr = 1;
91}
92
519129ff 93void
1e33ac1e
BB
94thread_fini(void)
95{
96 kthread_t *kt = curthread;
97
98 ASSERT(pthread_equal(kt->t_tid, pthread_self()));
99 ASSERT3P(kt->t_func, ==, NULL);
100
d1d7e268 101 umem_free(kt, sizeof (kthread_t));
1e33ac1e
BB
102
103 /* Wait for all threads to exit via thread_exit() */
104 VERIFY3S(pthread_mutex_lock(&kthread_lock), ==, 0);
105
106 kthread_nr--; /* Main thread is exiting */
107
108 while (kthread_nr > 0)
206971d2 109 VERIFY0(pthread_cond_wait(&kthread_cond, &kthread_lock));
1e33ac1e
BB
110
111 ASSERT3S(kthread_nr, ==, 0);
112 VERIFY3S(pthread_mutex_unlock(&kthread_lock), ==, 0);
113
114 VERIFY3S(pthread_key_delete(kthread_key), ==, 0);
115}
116
34dc7c2f 117kthread_t *
1e33ac1e
BB
118zk_thread_current(void)
119{
120 kthread_t *kt = pthread_getspecific(kthread_key);
121
122 ASSERT3P(kt, !=, NULL);
123
d1d7e268 124 return (kt);
1e33ac1e
BB
125}
126
127void *
128zk_thread_helper(void *arg)
34dc7c2f 129{
02730c33 130 kthread_t *kt = (kthread_t *)arg;
1e33ac1e
BB
131
132 VERIFY3S(pthread_setspecific(kthread_key, kt), ==, 0);
34dc7c2f 133
1e33ac1e
BB
134 VERIFY3S(pthread_mutex_lock(&kthread_lock), ==, 0);
135 kthread_nr++;
136 VERIFY3S(pthread_mutex_unlock(&kthread_lock), ==, 0);
1229323d 137 (void) setpriority(PRIO_PROCESS, 0, kt->t_pri);
34dc7c2f 138
1e33ac1e 139 kt->t_tid = pthread_self();
02730c33 140 ((thread_func_arg_t)kt->t_func)(kt->t_arg);
1e33ac1e
BB
141
142 /* Unreachable, thread must exit with thread_exit() */
143 abort();
144
d1d7e268 145 return (NULL);
1e33ac1e
BB
146}
147
148kthread_t *
149zk_thread_create(caddr_t stk, size_t stksize, thread_func_t func, void *arg,
e2a65adb 150 uint64_t len, proc_t *pp, int state, pri_t pri, int detachstate)
1e33ac1e
BB
151{
152 kthread_t *kt;
153 pthread_attr_t attr;
aa0ac7ca 154 char *stkstr;
1e33ac1e 155
aa0ac7ca 156 ASSERT0(state & ~TS_RUN);
e2a65adb 157 ASSERT0(len);
1e33ac1e 158
d1d7e268 159 kt = umem_zalloc(sizeof (kthread_t), UMEM_NOFAIL);
1e33ac1e
BB
160 kt->t_func = func;
161 kt->t_arg = arg;
1229323d 162 kt->t_pri = pri;
1e33ac1e 163
aa0ac7ca
BB
164 VERIFY0(pthread_attr_init(&attr));
165 VERIFY0(pthread_attr_setdetachstate(&attr, detachstate));
166
1e33ac1e 167 /*
aa0ac7ca
BB
168 * We allow the default stack size in user space to be specified by
169 * setting the ZFS_STACK_SIZE environment variable. This allows us
170 * the convenience of observing and debugging stack overruns in
171 * user space. Explicitly specified stack sizes will be honored.
172 * The usage of ZFS_STACK_SIZE is discussed further in the
173 * ENVIRONMENT VARIABLES sections of the ztest(1) man page.
1e33ac1e 174 */
aa0ac7ca
BB
175 if (stksize == 0) {
176 stkstr = getenv("ZFS_STACK_SIZE");
177
178 if (stkstr == NULL)
179 stksize = TS_STACK_MAX;
180 else
181 stksize = MAX(atoi(stkstr), TS_STACK_MIN);
182 }
183
184 VERIFY3S(stksize, >, 0);
185 stksize = P2ROUNDUP(MAX(stksize, TS_STACK_MIN), PAGESIZE);
206971d2
DR
186 /*
187 * If this ever fails, it may be because the stack size is not a
188 * multiple of system page size.
189 */
aa0ac7ca
BB
190 VERIFY0(pthread_attr_setstacksize(&attr, stksize));
191 VERIFY0(pthread_attr_setguardsize(&attr, PAGESIZE));
192
193 VERIFY0(pthread_create(&kt->t_tid, &attr, &zk_thread_helper, kt));
194 VERIFY0(pthread_attr_destroy(&attr));
1e33ac1e 195
d1d7e268 196 return (kt);
1e33ac1e
BB
197}
198
199void
200zk_thread_exit(void)
201{
202 kthread_t *kt = curthread;
203
204 ASSERT(pthread_equal(kt->t_tid, pthread_self()));
205
d1d7e268 206 umem_free(kt, sizeof (kthread_t));
1e33ac1e 207
206971d2 208 VERIFY0(pthread_mutex_lock(&kthread_lock));
1e33ac1e 209 kthread_nr--;
206971d2 210 VERIFY0(pthread_mutex_unlock(&kthread_lock));
1e33ac1e 211
206971d2 212 VERIFY0(pthread_cond_broadcast(&kthread_cond));
1e33ac1e
BB
213 pthread_exit((void *)TS_MAGIC);
214}
215
216void
217zk_thread_join(kt_did_t tid)
218{
219 void *ret;
220
221 pthread_join((pthread_t)tid, &ret);
222 VERIFY3P(ret, ==, (void *)TS_MAGIC);
34dc7c2f
BB
223}
224
225/*
226 * =========================================================================
227 * kstats
228 * =========================================================================
229 */
230/*ARGSUSED*/
231kstat_t *
330847ff
MA
232kstat_create(const char *module, int instance, const char *name,
233 const char *class, uchar_t type, ulong_t ndata, uchar_t ks_flag)
34dc7c2f
BB
234{
235 return (NULL);
236}
237
238/*ARGSUSED*/
239void
240kstat_install(kstat_t *ksp)
241{}
242
243/*ARGSUSED*/
244void
245kstat_delete(kstat_t *ksp)
246{}
247
1421c891 248/*ARGSUSED*/
330847ff
MA
249void
250kstat_waitq_enter(kstat_io_t *kiop)
251{}
252
253/*ARGSUSED*/
254void
255kstat_waitq_exit(kstat_io_t *kiop)
256{}
257
258/*ARGSUSED*/
259void
260kstat_runq_enter(kstat_io_t *kiop)
261{}
262
263/*ARGSUSED*/
264void
265kstat_runq_exit(kstat_io_t *kiop)
266{}
267
268/*ARGSUSED*/
269void
270kstat_waitq_to_runq(kstat_io_t *kiop)
271{}
272
273/*ARGSUSED*/
274void
275kstat_runq_back_to_waitq(kstat_io_t *kiop)
276{}
277
1421c891
PS
278void
279kstat_set_raw_ops(kstat_t *ksp,
280 int (*headers)(char *buf, size_t size),
281 int (*data)(char *buf, size_t size, void *data),
282 void *(*addr)(kstat_t *ksp, loff_t index))
283{}
284
34dc7c2f
BB
285/*
286 * =========================================================================
287 * mutexes
288 * =========================================================================
289 */
1e33ac1e 290
34dc7c2f 291void
1e33ac1e 292mutex_init(kmutex_t *mp, char *name, int type, void *cookie)
34dc7c2f 293{
1e33ac1e
BB
294 ASSERT3S(type, ==, MUTEX_DEFAULT);
295 ASSERT3P(cookie, ==, NULL);
296 mp->m_owner = MTX_INIT;
297 mp->m_magic = MTX_MAGIC;
298 VERIFY3S(pthread_mutex_init(&mp->m_lock, NULL), ==, 0);
34dc7c2f
BB
299}
300
301void
1e33ac1e 302mutex_destroy(kmutex_t *mp)
34dc7c2f 303{
1e33ac1e
BB
304 ASSERT3U(mp->m_magic, ==, MTX_MAGIC);
305 ASSERT3P(mp->m_owner, ==, MTX_INIT);
340dfbe1 306 ASSERT0(pthread_mutex_destroy(&(mp)->m_lock));
1e33ac1e
BB
307 mp->m_owner = MTX_DEST;
308 mp->m_magic = 0;
34dc7c2f
BB
309}
310
311void
312mutex_enter(kmutex_t *mp)
313{
1e33ac1e
BB
314 ASSERT3U(mp->m_magic, ==, MTX_MAGIC);
315 ASSERT3P(mp->m_owner, !=, MTX_DEST);
316 ASSERT3P(mp->m_owner, !=, curthread);
317 VERIFY3S(pthread_mutex_lock(&mp->m_lock), ==, 0);
318 ASSERT3P(mp->m_owner, ==, MTX_INIT);
34dc7c2f
BB
319 mp->m_owner = curthread;
320}
321
322int
323mutex_tryenter(kmutex_t *mp)
324{
206971d2 325 int err;
1e33ac1e
BB
326 ASSERT3U(mp->m_magic, ==, MTX_MAGIC);
327 ASSERT3P(mp->m_owner, !=, MTX_DEST);
206971d2 328 if (0 == (err = pthread_mutex_trylock(&mp->m_lock))) {
1e33ac1e 329 ASSERT3P(mp->m_owner, ==, MTX_INIT);
34dc7c2f
BB
330 mp->m_owner = curthread;
331 return (1);
332 } else {
206971d2 333 VERIFY3S(err, ==, EBUSY);
34dc7c2f
BB
334 return (0);
335 }
336}
337
338void
339mutex_exit(kmutex_t *mp)
340{
1e33ac1e
BB
341 ASSERT3U(mp->m_magic, ==, MTX_MAGIC);
342 ASSERT3P(mutex_owner(mp), ==, curthread);
343 mp->m_owner = MTX_INIT;
344 VERIFY3S(pthread_mutex_unlock(&mp->m_lock), ==, 0);
34dc7c2f
BB
345}
346
347void *
348mutex_owner(kmutex_t *mp)
349{
1e33ac1e 350 ASSERT3U(mp->m_magic, ==, MTX_MAGIC);
34dc7c2f
BB
351 return (mp->m_owner);
352}
353
1e33ac1e
BB
354int
355mutex_held(kmutex_t *mp)
356{
357 return (mp->m_owner == curthread);
358}
359
34dc7c2f
BB
360/*
361 * =========================================================================
362 * rwlocks
363 * =========================================================================
364 */
1e33ac1e 365
34dc7c2f
BB
366void
367rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
368{
1e33ac1e
BB
369 ASSERT3S(type, ==, RW_DEFAULT);
370 ASSERT3P(arg, ==, NULL);
371 VERIFY3S(pthread_rwlock_init(&rwlp->rw_lock, NULL), ==, 0);
372 rwlp->rw_owner = RW_INIT;
373 rwlp->rw_wr_owner = RW_INIT;
374 rwlp->rw_readers = 0;
375 rwlp->rw_magic = RW_MAGIC;
34dc7c2f
BB
376}
377
378void
379rw_destroy(krwlock_t *rwlp)
380{
1e33ac1e 381 ASSERT3U(rwlp->rw_magic, ==, RW_MAGIC);
843b4aad 382 ASSERT(rwlp->rw_readers == 0 && rwlp->rw_wr_owner == RW_INIT);
1e33ac1e
BB
383 VERIFY3S(pthread_rwlock_destroy(&rwlp->rw_lock), ==, 0);
384 rwlp->rw_magic = 0;
34dc7c2f
BB
385}
386
387void
388rw_enter(krwlock_t *rwlp, krw_t rw)
389{
1e33ac1e
BB
390 ASSERT3U(rwlp->rw_magic, ==, RW_MAGIC);
391 ASSERT3P(rwlp->rw_owner, !=, curthread);
392 ASSERT3P(rwlp->rw_wr_owner, !=, curthread);
34dc7c2f 393
1e33ac1e
BB
394 if (rw == RW_READER) {
395 VERIFY3S(pthread_rwlock_rdlock(&rwlp->rw_lock), ==, 0);
396 ASSERT3P(rwlp->rw_wr_owner, ==, RW_INIT);
397
398 atomic_inc_uint(&rwlp->rw_readers);
399 } else {
400 VERIFY3S(pthread_rwlock_wrlock(&rwlp->rw_lock), ==, 0);
401 ASSERT3P(rwlp->rw_wr_owner, ==, RW_INIT);
402 ASSERT3U(rwlp->rw_readers, ==, 0);
403
404 rwlp->rw_wr_owner = curthread;
405 }
34dc7c2f
BB
406
407 rwlp->rw_owner = curthread;
408}
409
410void
411rw_exit(krwlock_t *rwlp)
412{
1e33ac1e
BB
413 ASSERT3U(rwlp->rw_magic, ==, RW_MAGIC);
414 ASSERT(RW_LOCK_HELD(rwlp));
415
416 if (RW_READ_HELD(rwlp))
417 atomic_dec_uint(&rwlp->rw_readers);
418 else
419 rwlp->rw_wr_owner = RW_INIT;
34dc7c2f 420
1e33ac1e
BB
421 rwlp->rw_owner = RW_INIT;
422 VERIFY3S(pthread_rwlock_unlock(&rwlp->rw_lock), ==, 0);
34dc7c2f
BB
423}
424
425int
426rw_tryenter(krwlock_t *rwlp, krw_t rw)
427{
428 int rv;
429
1e33ac1e 430 ASSERT3U(rwlp->rw_magic, ==, RW_MAGIC);
34dc7c2f
BB
431
432 if (rw == RW_READER)
1e33ac1e 433 rv = pthread_rwlock_tryrdlock(&rwlp->rw_lock);
34dc7c2f 434 else
1e33ac1e 435 rv = pthread_rwlock_trywrlock(&rwlp->rw_lock);
34dc7c2f
BB
436
437 if (rv == 0) {
1e33ac1e
BB
438 ASSERT3P(rwlp->rw_wr_owner, ==, RW_INIT);
439
440 if (rw == RW_READER)
441 atomic_inc_uint(&rwlp->rw_readers);
442 else {
443 ASSERT3U(rwlp->rw_readers, ==, 0);
444 rwlp->rw_wr_owner = curthread;
445 }
446
34dc7c2f
BB
447 rwlp->rw_owner = curthread;
448 return (1);
449 }
450
1e33ac1e
BB
451 VERIFY3S(rv, ==, EBUSY);
452
34dc7c2f
BB
453 return (0);
454}
455
34dc7c2f
BB
456int
457rw_tryupgrade(krwlock_t *rwlp)
458{
1e33ac1e 459 ASSERT3U(rwlp->rw_magic, ==, RW_MAGIC);
34dc7c2f
BB
460
461 return (0);
462}
463
464/*
465 * =========================================================================
466 * condition variables
467 * =========================================================================
468 */
1e33ac1e 469
34dc7c2f
BB
470void
471cv_init(kcondvar_t *cv, char *name, int type, void *arg)
472{
1e33ac1e
BB
473 ASSERT3S(type, ==, CV_DEFAULT);
474 cv->cv_magic = CV_MAGIC;
206971d2 475 VERIFY0(pthread_cond_init(&cv->cv, NULL));
34dc7c2f
BB
476}
477
478void
479cv_destroy(kcondvar_t *cv)
480{
1e33ac1e 481 ASSERT3U(cv->cv_magic, ==, CV_MAGIC);
206971d2 482 VERIFY0(pthread_cond_destroy(&cv->cv));
1e33ac1e 483 cv->cv_magic = 0;
34dc7c2f
BB
484}
485
486void
487cv_wait(kcondvar_t *cv, kmutex_t *mp)
488{
1e33ac1e
BB
489 ASSERT3U(cv->cv_magic, ==, CV_MAGIC);
490 ASSERT3P(mutex_owner(mp), ==, curthread);
491 mp->m_owner = MTX_INIT;
206971d2 492 VERIFY0(pthread_cond_wait(&cv->cv, &mp->m_lock));
34dc7c2f
BB
493 mp->m_owner = curthread;
494}
495
496clock_t
497cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
498{
499 int error;
1e33ac1e 500 struct timeval tv;
34dc7c2f
BB
501 timestruc_t ts;
502 clock_t delta;
503
1e33ac1e
BB
504 ASSERT3U(cv->cv_magic, ==, CV_MAGIC);
505
428870ff 506 delta = abstime - ddi_get_lbolt();
34dc7c2f
BB
507 if (delta <= 0)
508 return (-1);
509
1e33ac1e
BB
510 VERIFY(gettimeofday(&tv, NULL) == 0);
511
512 ts.tv_sec = tv.tv_sec + delta / hz;
67925abb 513 ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC + (delta % hz) * (NANOSEC / hz);
1e33ac1e
BB
514 if (ts.tv_nsec >= NANOSEC) {
515 ts.tv_sec++;
516 ts.tv_nsec -= NANOSEC;
517 }
34dc7c2f 518
1e33ac1e
BB
519 ASSERT3P(mutex_owner(mp), ==, curthread);
520 mp->m_owner = MTX_INIT;
521 error = pthread_cond_timedwait(&cv->cv, &mp->m_lock, &ts);
34dc7c2f
BB
522 mp->m_owner = curthread;
523
1e33ac1e 524 if (error == ETIMEDOUT)
34dc7c2f
BB
525 return (-1);
526
206971d2 527 VERIFY0(error);
34dc7c2f
BB
528
529 return (1);
530}
531
63fd3c6c
AL
532/*ARGSUSED*/
533clock_t
534cv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res,
535 int flag)
536{
537 int error;
67925abb 538 struct timeval tv;
63fd3c6c
AL
539 timestruc_t ts;
540 hrtime_t delta;
541
206971d2
DR
542 ASSERT(flag == 0 || flag == CALLOUT_FLAG_ABSOLUTE);
543
544 delta = tim;
545 if (flag & CALLOUT_FLAG_ABSOLUTE)
546 delta -= gethrtime();
63fd3c6c 547
63fd3c6c
AL
548 if (delta <= 0)
549 return (-1);
550
67925abb
BB
551 VERIFY(gettimeofday(&tv, NULL) == 0);
552
553 ts.tv_sec = tv.tv_sec + delta / NANOSEC;
554 ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC + (delta % NANOSEC);
555 if (ts.tv_nsec >= NANOSEC) {
556 ts.tv_sec++;
557 ts.tv_nsec -= NANOSEC;
558 }
63fd3c6c
AL
559
560 ASSERT(mutex_owner(mp) == curthread);
67925abb 561 mp->m_owner = MTX_INIT;
63fd3c6c
AL
562 error = pthread_cond_timedwait(&cv->cv, &mp->m_lock, &ts);
563 mp->m_owner = curthread;
564
206971d2 565 if (error == ETIMEDOUT)
63fd3c6c
AL
566 return (-1);
567
206971d2 568 VERIFY0(error);
63fd3c6c
AL
569
570 return (1);
571}
572
34dc7c2f
BB
573void
574cv_signal(kcondvar_t *cv)
575{
1e33ac1e 576 ASSERT3U(cv->cv_magic, ==, CV_MAGIC);
206971d2 577 VERIFY0(pthread_cond_signal(&cv->cv));
34dc7c2f
BB
578}
579
580void
581cv_broadcast(kcondvar_t *cv)
582{
1e33ac1e 583 ASSERT3U(cv->cv_magic, ==, CV_MAGIC);
206971d2 584 VERIFY0(pthread_cond_broadcast(&cv->cv));
34dc7c2f
BB
585}
586
587/*
588 * =========================================================================
589 * vnode operations
590 * =========================================================================
591 */
592/*
593 * Note: for the xxxat() versions of these functions, we assume that the
594 * starting vp is always rootdir (which is true for spa_directory.c, the only
595 * ZFS consumer of these interfaces). We assert this is true, and then emulate
596 * them by adding '/' in front of the path.
597 */
598
599/*ARGSUSED*/
600int
601vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
602{
e2c292bb 603 int fd = -1;
604 int dump_fd = -1;
34dc7c2f 605 vnode_t *vp;
a4914d38 606 int old_umask = 0;
5ae4e2c2 607 char *realpath;
34dc7c2f 608 struct stat64 st;
4d58b69d 609 int err;
34dc7c2f 610
5ae4e2c2
BB
611 realpath = umem_alloc(MAXPATHLEN, UMEM_NOFAIL);
612
34dc7c2f
BB
613 /*
614 * If we're accessing a real disk from userland, we need to use
615 * the character interface to avoid caching. This is particularly
616 * important if we're trying to look at a real in-kernel storage
617 * pool from userland, e.g. via zdb, because otherwise we won't
618 * see the changes occurring under the segmap cache.
619 * On the other hand, the stupid character device returns zero
620 * for its size. So -- gag -- we open the block device to get
621 * its size, and remember it for subsequent VOP_GETATTR().
622 */
d603ed6c 623#if defined(__sun__) || defined(__sun)
34dc7c2f 624 if (strncmp(path, "/dev/", 5) == 0) {
d603ed6c
BB
625#else
626 if (0) {
627#endif
34dc7c2f
BB
628 char *dsk;
629 fd = open64(path, O_RDONLY);
5ae4e2c2
BB
630 if (fd == -1) {
631 err = errno;
632 free(realpath);
633 return (err);
634 }
34dc7c2f 635 if (fstat64(fd, &st) == -1) {
5ae4e2c2 636 err = errno;
34dc7c2f 637 close(fd);
5ae4e2c2
BB
638 free(realpath);
639 return (err);
34dc7c2f
BB
640 }
641 close(fd);
642 (void) sprintf(realpath, "%s", path);
643 dsk = strstr(path, "/dsk/");
644 if (dsk != NULL)
645 (void) sprintf(realpath + (dsk - path) + 1, "r%s",
646 dsk + 1);
647 } else {
648 (void) sprintf(realpath, "%s", path);
5ae4e2c2
BB
649 if (!(flags & FCREAT) && stat64(realpath, &st) == -1) {
650 err = errno;
651 free(realpath);
652 return (err);
653 }
34dc7c2f
BB
654 }
655
d603ed6c
BB
656 if (!(flags & FCREAT) && S_ISBLK(st.st_mode)) {
657#ifdef __linux__
658 flags |= O_DIRECT;
659#endif
ada82581
BB
660 /* We shouldn't be writing to block devices in userspace */
661 VERIFY(!(flags & FWRITE));
d603ed6c
BB
662 }
663
34dc7c2f
BB
664 if (flags & FCREAT)
665 old_umask = umask(0);
666
667 /*
668 * The construct 'flags - FREAD' conveniently maps combinations of
669 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
670 */
671 fd = open64(realpath, flags - FREAD, mode);
470f12d6
G
672 if (fd == -1) {
673 err = errno;
674 free(realpath);
675 return (err);
676 }
34dc7c2f
BB
677
678 if (flags & FCREAT)
679 (void) umask(old_umask);
680
9867e8be
MA
681 if (vn_dumpdir != NULL) {
682 char *dumppath = umem_zalloc(MAXPATHLEN, UMEM_NOFAIL);
683 (void) snprintf(dumppath, MAXPATHLEN,
684 "%s/%s", vn_dumpdir, basename(realpath));
685 dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666);
686 umem_free(dumppath, MAXPATHLEN);
687 if (dump_fd == -1) {
688 err = errno;
689 free(realpath);
690 close(fd);
691 return (err);
692 }
693 } else {
694 dump_fd = -1;
695 }
696
697 free(realpath);
698
8d4e8140 699 if (fstat64_blk(fd, &st) == -1) {
4d58b69d 700 err = errno;
34dc7c2f 701 close(fd);
e2c292bb 702 if (dump_fd != -1)
703 close(dump_fd);
4d58b69d 704 return (err);
34dc7c2f
BB
705 }
706
707 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
708
709 *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
710
711 vp->v_fd = fd;
712 vp->v_size = st.st_size;
713 vp->v_path = spa_strdup(path);
9867e8be 714 vp->v_dump_fd = dump_fd;
34dc7c2f
BB
715
716 return (0);
717}
718
719/*ARGSUSED*/
720int
721vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
722 int x3, vnode_t *startvp, int fd)
723{
724 char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
725 int ret;
726
727 ASSERT(startvp == rootdir);
728 (void) sprintf(realpath, "/%s", path);
729
730 /* fd ignored for now, need if want to simulate nbmand support */
731 ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
732
733 umem_free(realpath, strlen(path) + 2);
734
735 return (ret);
736}
737
738/*ARGSUSED*/
739int
740vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
e9aa730c 741 int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
34dc7c2f 742{
4d58b69d 743 ssize_t rc, done = 0, split;
34dc7c2f
BB
744
745 if (uio == UIO_READ) {
4d58b69d 746 rc = pread64(vp->v_fd, addr, len, offset);
470f12d6 747 if (vp->v_dump_fd != -1 && rc != -1) {
928c58dd
BB
748 int status;
749 status = pwrite64(vp->v_dump_fd, addr, rc, offset);
9867e8be
MA
750 ASSERT(status != -1);
751 }
34dc7c2f
BB
752 } else {
753 /*
754 * To simulate partial disk writes, we split writes into two
755 * system calls so that the process can be killed in between.
756 */
9ae529ec
CS
757 int sectors = len >> SPA_MINBLOCKSHIFT;
758 split = (sectors > 0 ? rand() % sectors : 0) <<
759 SPA_MINBLOCKSHIFT;
4d58b69d
RC
760 rc = pwrite64(vp->v_fd, addr, split, offset);
761 if (rc != -1) {
762 done = rc;
763 rc = pwrite64(vp->v_fd, (char *)addr + split,
764 len - split, offset + split);
765 }
34dc7c2f
BB
766 }
767
d603ed6c
BB
768#ifdef __linux__
769 if (rc == -1 && errno == EINVAL) {
770 /*
771 * Under Linux, this most likely means an alignment issue
772 * (memory or disk) due to O_DIRECT, so we abort() in order to
773 * catch the offender.
774 */
d1d7e268 775 abort();
d603ed6c
BB
776 }
777#endif
4d58b69d 778 if (rc == -1)
34dc7c2f 779 return (errno);
4d58b69d
RC
780
781 done += rc;
782
34dc7c2f 783 if (residp)
4d58b69d
RC
784 *residp = len - done;
785 else if (done != len)
34dc7c2f
BB
786 return (EIO);
787 return (0);
788}
789
790void
791vn_close(vnode_t *vp)
792{
793 close(vp->v_fd);
9867e8be
MA
794 if (vp->v_dump_fd != -1)
795 close(vp->v_dump_fd);
34dc7c2f
BB
796 spa_strfree(vp->v_path);
797 umem_free(vp, sizeof (vnode_t));
798}
799
428870ff
BB
800/*
801 * At a minimum we need to update the size since vdev_reopen()
802 * will no longer call vn_openat().
803 */
804int
805fop_getattr(vnode_t *vp, vattr_t *vap)
806{
807 struct stat64 st;
8d4e8140 808 int err;
428870ff 809
8d4e8140
RC
810 if (fstat64_blk(vp->v_fd, &st) == -1) {
811 err = errno;
428870ff 812 close(vp->v_fd);
8d4e8140 813 return (err);
428870ff
BB
814 }
815
816 vap->va_size = st.st_size;
817 return (0);
818}
819
34dc7c2f
BB
820/*
821 * =========================================================================
822 * Figure out which debugging statements to print
823 * =========================================================================
824 */
825
826static char *dprintf_string;
827static int dprintf_print_all;
828
829int
830dprintf_find_string(const char *string)
831{
832 char *tmp_str = dprintf_string;
833 int len = strlen(string);
834
835 /*
836 * Find out if this is a string we want to print.
837 * String format: file1.c,function_name1,file2.c,file3.c
838 */
839
840 while (tmp_str != NULL) {
841 if (strncmp(tmp_str, string, len) == 0 &&
842 (tmp_str[len] == ',' || tmp_str[len] == '\0'))
843 return (1);
844 tmp_str = strchr(tmp_str, ',');
845 if (tmp_str != NULL)
846 tmp_str++; /* Get rid of , */
847 }
848 return (0);
849}
850
851void
852dprintf_setup(int *argc, char **argv)
853{
854 int i, j;
855
856 /*
857 * Debugging can be specified two ways: by setting the
858 * environment variable ZFS_DEBUG, or by including a
859 * "debug=..." argument on the command line. The command
860 * line setting overrides the environment variable.
861 */
862
863 for (i = 1; i < *argc; i++) {
864 int len = strlen("debug=");
865 /* First look for a command line argument */
866 if (strncmp("debug=", argv[i], len) == 0) {
867 dprintf_string = argv[i] + len;
868 /* Remove from args */
869 for (j = i; j < *argc; j++)
870 argv[j] = argv[j+1];
871 argv[j] = NULL;
872 (*argc)--;
873 }
874 }
875
876 if (dprintf_string == NULL) {
877 /* Look for ZFS_DEBUG environment variable */
878 dprintf_string = getenv("ZFS_DEBUG");
879 }
880
881 /*
882 * Are we just turning on all debugging?
883 */
884 if (dprintf_find_string("on"))
885 dprintf_print_all = 1;
308a451f
MA
886
887 if (dprintf_string != NULL)
888 zfs_flags |= ZFS_DEBUG_DPRINTF;
34dc7c2f
BB
889}
890
891/*
892 * =========================================================================
893 * debug printfs
894 * =========================================================================
895 */
896void
897__dprintf(const char *file, const char *func, int line, const char *fmt, ...)
898{
899 const char *newfile;
900 va_list adx;
901
902 /*
903 * Get rid of annoying "../common/" prefix to filename.
904 */
905 newfile = strrchr(file, '/');
906 if (newfile != NULL) {
907 newfile = newfile + 1; /* Get rid of leading / */
908 } else {
909 newfile = file;
910 }
911
912 if (dprintf_print_all ||
913 dprintf_find_string(newfile) ||
914 dprintf_find_string(func)) {
915 /* Print out just the function name if requested */
916 flockfile(stdout);
917 if (dprintf_find_string("pid"))
918 (void) printf("%d ", getpid());
919 if (dprintf_find_string("tid"))
02730c33 920 (void) printf("%u ", (uint_t)pthread_self());
34dc7c2f
BB
921 if (dprintf_find_string("cpu"))
922 (void) printf("%u ", getcpuid());
923 if (dprintf_find_string("time"))
924 (void) printf("%llu ", gethrtime());
925 if (dprintf_find_string("long"))
926 (void) printf("%s, line %d: ", newfile, line);
927 (void) printf("%s: ", func);
928 va_start(adx, fmt);
929 (void) vprintf(fmt, adx);
930 va_end(adx);
931 funlockfile(stdout);
932 }
933}
934
34dc7c2f
BB
935/*
936 * =========================================================================
937 * cmn_err() and panic()
938 * =========================================================================
939 */
940static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
941static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
942
943void
944vpanic(const char *fmt, va_list adx)
945{
946 (void) fprintf(stderr, "error: ");
947 (void) vfprintf(stderr, fmt, adx);
948 (void) fprintf(stderr, "\n");
949
950 abort(); /* think of it as a "user-level crash dump" */
951}
952
953void
954panic(const char *fmt, ...)
955{
956 va_list adx;
957
958 va_start(adx, fmt);
959 vpanic(fmt, adx);
960 va_end(adx);
961}
962
963void
964vcmn_err(int ce, const char *fmt, va_list adx)
965{
966 if (ce == CE_PANIC)
967 vpanic(fmt, adx);
968 if (ce != CE_NOTE) { /* suppress noise in userland stress testing */
969 (void) fprintf(stderr, "%s", ce_prefix[ce]);
970 (void) vfprintf(stderr, fmt, adx);
971 (void) fprintf(stderr, "%s", ce_suffix[ce]);
972 }
973}
974
975/*PRINTFLIKE2*/
976void
977cmn_err(int ce, const char *fmt, ...)
978{
979 va_list adx;
980
981 va_start(adx, fmt);
982 vcmn_err(ce, fmt, adx);
983 va_end(adx);
984}
985
986/*
987 * =========================================================================
988 * kobj interfaces
989 * =========================================================================
990 */
991struct _buf *
992kobj_open_file(char *name)
993{
994 struct _buf *file;
995 vnode_t *vp;
996
997 /* set vp as the _fd field of the file */
998 if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir,
999 -1) != 0)
1000 return ((void *)-1UL);
1001
1002 file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
1003 file->_fd = (intptr_t)vp;
1004 return (file);
1005}
1006
1007int
1008kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
1009{
689f093e 1010 ssize_t resid = 0;
34dc7c2f 1011
957dc932
RY
1012 if (vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
1013 UIO_SYSSPACE, 0, 0, 0, &resid) != 0)
1014 return (-1);
34dc7c2f
BB
1015
1016 return (size - resid);
1017}
1018
1019void
1020kobj_close_file(struct _buf *file)
1021{
1022 vn_close((vnode_t *)file->_fd);
1023 umem_free(file, sizeof (struct _buf));
1024}
1025
1026int
1027kobj_get_filesize(struct _buf *file, uint64_t *size)
1028{
1029 struct stat64 st;
1030 vnode_t *vp = (vnode_t *)file->_fd;
1031
1032 if (fstat64(vp->v_fd, &st) == -1) {
1033 vn_close(vp);
1034 return (errno);
1035 }
1036 *size = st.st_size;
1037 return (0);
1038}
1039
1040/*
1041 * =========================================================================
1042 * misc routines
1043 * =========================================================================
1044 */
1045
1046void
1047delay(clock_t ticks)
1048{
af4db70f 1049 (void) poll(0, 0, ticks * (1000 / hz));
34dc7c2f
BB
1050}
1051
1052/*
1053 * Find highest one bit set.
1054 * Returns bit number + 1 of highest bit that is set, otherwise returns 0.
1055 * High order bit is 31 (or 63 in _LP64 kernel).
1056 */
1057int
9bd274dd 1058highbit64(uint64_t i)
34dc7c2f
BB
1059{
1060 register int h = 1;
1061
1062 if (i == 0)
1063 return (0);
9bd274dd 1064 if (i & 0xffffffff00000000ULL) {
34dc7c2f
BB
1065 h += 32; i >>= 32;
1066 }
34dc7c2f
BB
1067 if (i & 0xffff0000) {
1068 h += 16; i >>= 16;
1069 }
1070 if (i & 0xff00) {
1071 h += 8; i >>= 8;
1072 }
1073 if (i & 0xf0) {
1074 h += 4; i >>= 4;
1075 }
1076 if (i & 0xc) {
1077 h += 2; i >>= 2;
1078 }
1079 if (i & 0x2) {
1080 h += 1;
1081 }
1082 return (h);
1083}
1084
193a37cb
TH
1085/*
1086 * Find lowest one bit set.
1087 * Returns bit number + 1 of lowest bit that is set, otherwise returns 0.
1088 * This is basically a reimplementation of ffsll(), which is GNU specific.
1089 */
1090int
1091lowbit64(uint64_t i)
1092{
1093 register int h = 64;
1094 if (i == 0)
1095 return (0);
1096
1097 if (i & 0x00000000ffffffffULL)
1098 h -= 32;
1099 else
1100 i >>= 32;
1101
1102 if (i & 0x0000ffff)
1103 h -= 16;
1104 else
1105 i >>= 16;
1106
1107 if (i & 0x00ff)
1108 h -= 8;
1109 else
1110 i >>= 8;
1111
1112 if (i & 0x0f)
1113 h -= 4;
1114 else
1115 i >>= 4;
1116
1117 if (i & 0x3)
1118 h -= 2;
1119 else
1120 i >>= 2;
1121
1122 if (i & 0x1)
1123 h -= 1;
1124
1125 return (h);
1126}
1127
0b04990a
TC
1128/*
1129 * Find highest one bit set.
1130 * Returns bit number + 1 of highest bit that is set, otherwise returns 0.
1131 * High order bit is 31 (or 63 in _LP64 kernel).
1132 */
1133int
1134highbit(ulong_t i)
1135{
1136register int h = 1;
1137
1138 if (i == 0)
1139 return (0);
1140#ifdef _LP64
1141 if (i & 0xffffffff00000000ul) {
1142 h += 32; i >>= 32;
1143 }
1144#endif
1145 if (i & 0xffff0000) {
1146 h += 16; i >>= 16;
1147 }
1148 if (i & 0xff00) {
1149 h += 8; i >>= 8;
1150 }
1151 if (i & 0xf0) {
1152 h += 4; i >>= 4;
1153 }
1154 if (i & 0xc) {
1155 h += 2; i >>= 2;
1156 }
1157 if (i & 0x2) {
1158 h += 1;
1159 }
1160 return (h);
1161}
1162
1163/*
1164 * Find lowest one bit set.
1165 * Returns bit number + 1 of lowest bit that is set, otherwise returns 0.
1166 * Low order bit is 0.
1167 */
1168int
1169lowbit(ulong_t i)
1170{
1171 register int h = 1;
1172
1173 if (i == 0)
1174 return (0);
1175
1176#ifdef _LP64
1177 if (!(i & 0xffffffff)) {
1178 h += 32; i >>= 32;
1179 }
1180#endif
1181 if (!(i & 0xffff)) {
1182 h += 16; i >>= 16;
1183 }
1184 if (!(i & 0xff)) {
1185 h += 8; i >>= 8;
1186 }
1187 if (!(i & 0xf)) {
1188 h += 4; i >>= 4;
1189 }
1190 if (!(i & 0x3)) {
1191 h += 2; i >>= 2;
1192 }
1193 if (!(i & 0x1)) {
1194 h += 1;
1195 }
1196 return (h);
1197}
193a37cb 1198
34dc7c2f
BB
1199static int random_fd = -1, urandom_fd = -1;
1200
0b04990a
TC
1201void
1202random_init(void)
1203{
1204 VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1);
1205 VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1);
1206}
1207
1208void
1209random_fini(void)
1210{
1211 close(random_fd);
1212 close(urandom_fd);
1213
1214 random_fd = -1;
1215 urandom_fd = -1;
1216}
1217
34dc7c2f
BB
1218static int
1219random_get_bytes_common(uint8_t *ptr, size_t len, int fd)
1220{
1221 size_t resid = len;
1222 ssize_t bytes;
1223
1224 ASSERT(fd != -1);
1225
1226 while (resid != 0) {
1227 bytes = read(fd, ptr, resid);
1228 ASSERT3S(bytes, >=, 0);
1229 ptr += bytes;
1230 resid -= bytes;
1231 }
1232
1233 return (0);
1234}
1235
1236int
1237random_get_bytes(uint8_t *ptr, size_t len)
1238{
1239 return (random_get_bytes_common(ptr, len, random_fd));
1240}
1241
1242int
1243random_get_pseudo_bytes(uint8_t *ptr, size_t len)
1244{
1245 return (random_get_bytes_common(ptr, len, urandom_fd));
1246}
1247
1248int
1249ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result)
1250{
1251 char *end;
1252
1253 *result = strtoul(hw_serial, &end, base);
1254 if (*result == 0)
1255 return (errno);
1256 return (0);
1257}
1258
428870ff
BB
1259int
1260ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result)
1261{
1262 char *end;
1263
1264 *result = strtoull(str, &end, base);
1265 if (*result == 0)
1266 return (errno);
1267 return (0);
1268}
1269
f0e324f2
BB
1270utsname_t *
1271utsname(void)
1272{
1273 return (&hw_utsname);
1274}
1275
34dc7c2f
BB
1276/*
1277 * =========================================================================
1278 * kernel emulation setup & teardown
1279 * =========================================================================
1280 */
1281static int
1282umem_out_of_memory(void)
1283{
1284 char errmsg[] = "out of memory -- generating core dump\n";
1285
0e5b68e0 1286 (void) fprintf(stderr, "%s", errmsg);
34dc7c2f
BB
1287 abort();
1288 return (0);
1289}
1290
53698a45
CC
1291static unsigned long
1292get_spl_hostid(void)
1293{
1294 FILE *f;
1295 unsigned long hostid;
1296
1297 f = fopen("/sys/module/spl/parameters/spl_hostid", "r");
1298 if (!f)
1299 return (0);
1300 if (fscanf(f, "%lu", &hostid) != 1)
1301 hostid = 0;
1302 fclose(f);
1303 return (hostid & 0xffffffff);
1304}
1305
1306unsigned long
1307get_system_hostid(void)
1308{
1309 unsigned long system_hostid = get_spl_hostid();
1310 if (system_hostid == 0)
1311 system_hostid = gethostid() & 0xffffffff;
1312 return (system_hostid);
1313}
1314
34dc7c2f
BB
1315void
1316kernel_init(int mode)
1317{
13fe0198
MA
1318 extern uint_t rrw_tsd_key;
1319
34dc7c2f
BB
1320 umem_nofail_callback(umem_out_of_memory);
1321
1322 physmem = sysconf(_SC_PHYS_PAGES);
1323
1324 dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
1325 (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
1326
428870ff 1327 (void) snprintf(hw_serial, sizeof (hw_serial), "%ld",
53698a45 1328 (mode & FWRITE) ? get_system_hostid() : 0);
34dc7c2f 1329
0b04990a
TC
1330 random_init();
1331
f0e324f2 1332 VERIFY0(uname(&hw_utsname));
34dc7c2f 1333
1e33ac1e 1334 thread_init();
b128c09f 1335 system_taskq_init();
0b04990a 1336 icp_init();
b128c09f 1337
34dc7c2f 1338 spa_init(mode);
13fe0198 1339
1eeb4562
JX
1340 fletcher_4_init();
1341
13fe0198 1342 tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
34dc7c2f
BB
1343}
1344
1345void
1346kernel_fini(void)
1347{
1eeb4562 1348 fletcher_4_fini();
34dc7c2f
BB
1349 spa_fini();
1350
0b04990a 1351 icp_fini();
428870ff 1352 system_taskq_fini();
1e33ac1e 1353 thread_fini();
428870ff 1354
0b04990a 1355 random_fini();
34dc7c2f
BB
1356}
1357
34dc7c2f
BB
1358uid_t
1359crgetuid(cred_t *cr)
1360{
1361 return (0);
1362}
1363
6f1ffb06
MA
1364uid_t
1365crgetruid(cred_t *cr)
1366{
1367 return (0);
1368}
1369
34dc7c2f
BB
1370gid_t
1371crgetgid(cred_t *cr)
1372{
1373 return (0);
1374}
1375
1376int
1377crgetngroups(cred_t *cr)
1378{
1379 return (0);
1380}
1381
1382gid_t *
1383crgetgroups(cred_t *cr)
1384{
1385 return (NULL);
1386}
1387
1388int
1389zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
1390{
1391 return (0);
1392}
1393
1394int
1395zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
1396{
1397 return (0);
1398}
1399
1400int
1401zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
1402{
1403 return (0);
1404}
1405
f74b821a
BB
1406int
1407secpolicy_zfs(const cred_t *cr)
1408{
1409 return (0);
1410}
1411
34dc7c2f
BB
1412ksiddomain_t *
1413ksid_lookupdomain(const char *dom)
1414{
1415 ksiddomain_t *kd;
1416
1417 kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL);
1418 kd->kd_name = spa_strdup(dom);
1419 return (kd);
1420}
1421
1422void
1423ksiddomain_rele(ksiddomain_t *ksid)
1424{
1425 spa_strfree(ksid->kd_name);
1426 umem_free(ksid, sizeof (ksiddomain_t));
1427}
428870ff 1428
428870ff 1429char *
00b46022 1430kmem_vasprintf(const char *fmt, va_list adx)
428870ff 1431{
00b46022
BB
1432 char *buf = NULL;
1433 va_list adx_copy;
428870ff 1434
00b46022
BB
1435 va_copy(adx_copy, adx);
1436 VERIFY(vasprintf(&buf, fmt, adx_copy) != -1);
1437 va_end(adx_copy);
428870ff 1438
00b46022
BB
1439 return (buf);
1440}
1441
1442char *
1443kmem_asprintf(const char *fmt, ...)
1444{
1445 char *buf = NULL;
1446 va_list adx;
428870ff
BB
1447
1448 va_start(adx, fmt);
00b46022 1449 VERIFY(vasprintf(&buf, fmt, adx) != -1);
428870ff
BB
1450 va_end(adx);
1451
1452 return (buf);
1453}
572e2857
BB
1454
1455/* ARGSUSED */
1456int
1457zfs_onexit_fd_hold(int fd, minor_t *minorp)
1458{
1459 *minorp = 0;
1460 return (0);
1461}
1462
1463/* ARGSUSED */
1464void
1465zfs_onexit_fd_rele(int fd)
1466{
1467}
1468
1469/* ARGSUSED */
1470int
1471zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
1472 uint64_t *action_handle)
1473{
1474 return (0);
1475}
1476
1477/* ARGSUSED */
1478int
1479zfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire)
1480{
1481 return (0);
1482}
1483
1484/* ARGSUSED */
1485int
1486zfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data)
1487{
1488 return (0);
1489}
92119cc2
BB
1490
1491fstrans_cookie_t
1492spl_fstrans_mark(void)
1493{
02730c33 1494 return ((fstrans_cookie_t)0);
92119cc2
BB
1495}
1496
1497void
1498spl_fstrans_unmark(fstrans_cookie_t cookie)
1499{
1500}
1501
1502int
1503spl_fstrans_check(void)
1504{
1505 return (0);
1506}
a0bd735a 1507
47dfff3b
MA
1508void *zvol_tag = "zvol_tag";
1509
a0bd735a
BP
1510void
1511zvol_create_minors(spa_t *spa, const char *name, boolean_t async)
1512{
1513}
1514
1515void
1516zvol_remove_minor(spa_t *spa, const char *name, boolean_t async)
1517{
1518}
1519
1520void
1521zvol_remove_minors(spa_t *spa, const char *name, boolean_t async)
1522{
1523}
1524
1525void
1526zvol_rename_minors(spa_t *spa, const char *oldname, const char *newname,
1527 boolean_t async)
1528{
1529}