1168404Spjd/*
2168404Spjd * CDDL HEADER START
3168404Spjd *
4168404Spjd * The contents of this file are subject to the terms of the
5168404Spjd * Common Development and Distribution License (the "License").
6168404Spjd * You may not use this file except in compliance with the License.
7168404Spjd *
8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9168404Spjd * or http://www.opensolaris.org/os/licensing.
10168404Spjd * See the License for the specific language governing permissions
11168404Spjd * and limitations under the License.
12168404Spjd *
13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each
14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15168404Spjd * If applicable, add the following below this CDDL HEADER, with the
16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying
17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner]
18168404Spjd *
19168404Spjd * CDDL HEADER END
20168404Spjd */
21168404Spjd/*
22219089Spjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23289562Smav * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
24264669Sdelphij * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
25168404Spjd */
26168404Spjd
27168404Spjd#include <assert.h>
28168404Spjd#include <fcntl.h>
29168404Spjd#include <poll.h>
30168404Spjd#include <stdio.h>
31168404Spjd#include <stdlib.h>
32168404Spjd#include <string.h>
33168404Spjd#include <zlib.h>
34268084Sdelphij#include <libgen.h>
35168404Spjd#include <sys/spa.h>
36168404Spjd#include <sys/stat.h>
37168404Spjd#include <sys/processor.h>
38168404Spjd#include <sys/zfs_context.h>
39248571Smm#include <sys/rrwlock.h>
40168404Spjd#include <sys/zmod.h>
41168498Spjd#include <sys/utsname.h>
42219089Spjd#include <sys/systeminfo.h>
43168404Spjd
44168404Spjd/*
45168404Spjd * Emulation of kernel services in userland.
46168404Spjd */
47168404Spjd
48288340Savg#ifndef __FreeBSD__
49219089Spjdint aok;
50288340Savg#endif
51168404Spjduint64_t physmem;
52168404Spjdvnode_t *rootdir = (vnode_t *)0xabcd1234;
53219089Spjdchar hw_serial[HW_HOSTID_LEN];
54247265Smm#ifdef illumos
55247265Smmkmutex_t cpu_lock;
56247265Smm#endif
57168404Spjd
58268084Sdelphij/* If set, all blocks read will be copied to the specified directory. */
59268084Sdelphijchar *vn_dumpdir = NULL;
60268084Sdelphij
61168498Spjdstruct utsname utsname = {
62168498Spjd	"userland", "libzpool", "1", "1", "na"
63168498Spjd};
64168498Spjd
65219089Spjd/* this only exists to have its address taken */
66219089Spjdstruct proc p0;
67219089Spjd
68168404Spjd/*
69168404Spjd * =========================================================================
70168404Spjd * threads
71168404Spjd * =========================================================================
72168404Spjd */
73168404Spjd/*ARGSUSED*/
74168404Spjdkthread_t *
75168404Spjdzk_thread_create(void (*func)(), void *arg)
76168404Spjd{
77168404Spjd	thread_t tid;
78168404Spjd
79168404Spjd	VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
80168404Spjd	    &tid) == 0);
81168404Spjd
82168404Spjd	return ((void *)(uintptr_t)tid);
83168404Spjd}
84168404Spjd
85168404Spjd/*
86168404Spjd * =========================================================================
87168404Spjd * kstats
88168404Spjd * =========================================================================
89168404Spjd */
90168404Spjd/*ARGSUSED*/
91168404Spjdkstat_t *
92168404Spjdkstat_create(char *module, int instance, char *name, char *class,
93168404Spjd    uchar_t type, ulong_t ndata, uchar_t ks_flag)
94168404Spjd{
95168404Spjd	return (NULL);
96168404Spjd}
97168404Spjd
98168404Spjd/*ARGSUSED*/
99168404Spjdvoid
100321529Smavkstat_named_init(kstat_named_t *knp, const char *name, uchar_t type)
101321529Smav{}
102321529Smav
103321529Smav/*ARGSUSED*/
104321529Smavvoid
105168404Spjdkstat_install(kstat_t *ksp)
106168404Spjd{}
107168404Spjd
108168404Spjd/*ARGSUSED*/
109168404Spjdvoid
110168404Spjdkstat_delete(kstat_t *ksp)
111168404Spjd{}
112168404Spjd
113168404Spjd/*
114168404Spjd * =========================================================================
115168404Spjd * mutexes
116168404Spjd * =========================================================================
117168404Spjd */
118168404Spjdvoid
119168404Spjdzmutex_init(kmutex_t *mp)
120168404Spjd{
121168404Spjd	mp->m_owner = NULL;
122185029Spjd	mp->initialized = B_TRUE;
123168404Spjd	(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
124168404Spjd}
125168404Spjd
126168404Spjdvoid
127168404Spjdzmutex_destroy(kmutex_t *mp)
128168404Spjd{
129185029Spjd	ASSERT(mp->initialized == B_TRUE);
130168404Spjd	ASSERT(mp->m_owner == NULL);
131168404Spjd	(void) _mutex_destroy(&(mp)->m_lock);
132168404Spjd	mp->m_owner = (void *)-1UL;
133185029Spjd	mp->initialized = B_FALSE;
134168404Spjd}
135168404Spjd
136195515Spjdint
137195515Spjdzmutex_owned(kmutex_t *mp)
138195515Spjd{
139195515Spjd	ASSERT(mp->initialized == B_TRUE);
140195515Spjd
141195515Spjd	return (mp->m_owner == curthread);
142195515Spjd}
143195515Spjd
144168404Spjdvoid
145168404Spjdmutex_enter(kmutex_t *mp)
146168404Spjd{
147185029Spjd	ASSERT(mp->initialized == B_TRUE);
148168404Spjd	ASSERT(mp->m_owner != (void *)-1UL);
149168404Spjd	ASSERT(mp->m_owner != curthread);
150168404Spjd	VERIFY(mutex_lock(&mp->m_lock) == 0);
151168404Spjd	ASSERT(mp->m_owner == NULL);
152168404Spjd	mp->m_owner = curthread;
153168404Spjd}
154168404Spjd
155168404Spjdint
156168404Spjdmutex_tryenter(kmutex_t *mp)
157168404Spjd{
158185029Spjd	ASSERT(mp->initialized == B_TRUE);
159168404Spjd	ASSERT(mp->m_owner != (void *)-1UL);
160219089Spjd	if (0 == mutex_trylock(&mp->m_lock)) {
161168404Spjd		ASSERT(mp->m_owner == NULL);
162168404Spjd		mp->m_owner = curthread;
163168404Spjd		return (1);
164168404Spjd	} else {
165168404Spjd		return (0);
166168404Spjd	}
167168404Spjd}
168168404Spjd
169168404Spjdvoid
170168404Spjdmutex_exit(kmutex_t *mp)
171168404Spjd{
172185029Spjd	ASSERT(mp->initialized == B_TRUE);
173219089Spjd	ASSERT(mutex_owner(mp) == curthread);
174168404Spjd	mp->m_owner = NULL;
175168404Spjd	VERIFY(mutex_unlock(&mp->m_lock) == 0);
176168404Spjd}
177168404Spjd
178168404Spjdvoid *
179168404Spjdmutex_owner(kmutex_t *mp)
180168404Spjd{
181185029Spjd	ASSERT(mp->initialized == B_TRUE);
182168404Spjd	return (mp->m_owner);
183168404Spjd}
184168404Spjd
185168404Spjd/*
186168404Spjd * =========================================================================
187168404Spjd * rwlocks
188168404Spjd * =========================================================================
189168404Spjd */
190168404Spjd/*ARGSUSED*/
191168404Spjdvoid
192168404Spjdrw_init(krwlock_t *rwlp, char *name, int type, void *arg)
193168404Spjd{
194168404Spjd	rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
195168404Spjd	rwlp->rw_owner = NULL;
196185029Spjd	rwlp->initialized = B_TRUE;
197210044Spjd	rwlp->rw_count = 0;
198168404Spjd}
199168404Spjd
200168404Spjdvoid
201168404Spjdrw_destroy(krwlock_t *rwlp)
202168404Spjd{
203210044Spjd	ASSERT(rwlp->rw_count == 0);
204168404Spjd	rwlock_destroy(&rwlp->rw_lock);
205168404Spjd	rwlp->rw_owner = (void *)-1UL;
206185029Spjd	rwlp->initialized = B_FALSE;
207168404Spjd}
208168404Spjd
209168404Spjdvoid
210168404Spjdrw_enter(krwlock_t *rwlp, krw_t rw)
211168404Spjd{
212168404Spjd	//ASSERT(!RW_LOCK_HELD(rwlp));
213185029Spjd	ASSERT(rwlp->initialized == B_TRUE);
214168404Spjd	ASSERT(rwlp->rw_owner != (void *)-1UL);
215168404Spjd	ASSERT(rwlp->rw_owner != curthread);
216168404Spjd
217168404Spjd	if (rw == RW_READER) {
218185029Spjd		VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
219168404Spjd		ASSERT(rwlp->rw_count >= 0);
220168404Spjd		atomic_add_int(&rwlp->rw_count, 1);
221168404Spjd	} else {
222185029Spjd		VERIFY(rw_wrlock(&rwlp->rw_lock) == 0);
223168404Spjd		ASSERT(rwlp->rw_count == 0);
224168404Spjd		rwlp->rw_count = -1;
225168404Spjd		rwlp->rw_owner = curthread;
226168404Spjd	}
227168404Spjd}
228168404Spjd
229168404Spjdvoid
230168404Spjdrw_exit(krwlock_t *rwlp)
231168404Spjd{
232185029Spjd	ASSERT(rwlp->initialized == B_TRUE);
233168404Spjd	ASSERT(rwlp->rw_owner != (void *)-1UL);
234168404Spjd
235168404Spjd	if (rwlp->rw_owner == curthread) {
236168404Spjd		/* Write locked. */
237168404Spjd		ASSERT(rwlp->rw_count == -1);
238168404Spjd		rwlp->rw_count = 0;
239168404Spjd		rwlp->rw_owner = NULL;
240168404Spjd	} else {
241168404Spjd		/* Read locked. */
242168404Spjd		ASSERT(rwlp->rw_count > 0);
243168404Spjd		atomic_add_int(&rwlp->rw_count, -1);
244168404Spjd	}
245185029Spjd	VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
246168404Spjd}
247168404Spjd
248168404Spjdint
249168404Spjdrw_tryenter(krwlock_t *rwlp, krw_t rw)
250168404Spjd{
251168404Spjd	int rv;
252168404Spjd
253185029Spjd	ASSERT(rwlp->initialized == B_TRUE);
254168404Spjd	ASSERT(rwlp->rw_owner != (void *)-1UL);
255168404Spjd	ASSERT(rwlp->rw_owner != curthread);
256168404Spjd
257168404Spjd	if (rw == RW_READER)
258168404Spjd		rv = rw_tryrdlock(&rwlp->rw_lock);
259168404Spjd	else
260168404Spjd		rv = rw_trywrlock(&rwlp->rw_lock);
261168404Spjd
262168404Spjd	if (rv == 0) {
263168404Spjd		ASSERT(rwlp->rw_owner == NULL);
264168404Spjd		if (rw == RW_READER) {
265168404Spjd			ASSERT(rwlp->rw_count >= 0);
266168404Spjd			atomic_add_int(&rwlp->rw_count, 1);
267168404Spjd		} else {
268168404Spjd			ASSERT(rwlp->rw_count == 0);
269168404Spjd			rwlp->rw_count = -1;
270168404Spjd			rwlp->rw_owner = curthread;
271168404Spjd		}
272168404Spjd		return (1);
273168404Spjd	}
274168404Spjd
275168404Spjd	return (0);
276168404Spjd}
277168404Spjd
278168404Spjd/*ARGSUSED*/
279168404Spjdint
280168404Spjdrw_tryupgrade(krwlock_t *rwlp)
281168404Spjd{
282185029Spjd	ASSERT(rwlp->initialized == B_TRUE);
283168404Spjd	ASSERT(rwlp->rw_owner != (void *)-1UL);
284168404Spjd
285168404Spjd	return (0);
286168404Spjd}
287168404Spjd
288168404Spjdint
289168404Spjdrw_lock_held(krwlock_t *rwlp)
290168404Spjd{
291168404Spjd
292168404Spjd	return (rwlp->rw_count != 0);
293168404Spjd}
294168404Spjd
295168404Spjd/*
296168404Spjd * =========================================================================
297168404Spjd * condition variables
298168404Spjd * =========================================================================
299168404Spjd */
300168404Spjd/*ARGSUSED*/
301168404Spjdvoid
302168404Spjdcv_init(kcondvar_t *cv, char *name, int type, void *arg)
303168404Spjd{
304168404Spjd	VERIFY(cond_init(cv, name, NULL) == 0);
305168404Spjd}
306168404Spjd
307168404Spjdvoid
308168404Spjdcv_destroy(kcondvar_t *cv)
309168404Spjd{
310168404Spjd	VERIFY(cond_destroy(cv) == 0);
311168404Spjd}
312168404Spjd
313168404Spjdvoid
314168404Spjdcv_wait(kcondvar_t *cv, kmutex_t *mp)
315168404Spjd{
316168404Spjd	ASSERT(mutex_owner(mp) == curthread);
317168404Spjd	mp->m_owner = NULL;
318168404Spjd	int ret = cond_wait(cv, &mp->m_lock);
319168404Spjd	VERIFY(ret == 0 || ret == EINTR);
320168404Spjd	mp->m_owner = curthread;
321168404Spjd}
322168404Spjd
323168404Spjdclock_t
324168404Spjdcv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
325168404Spjd{
326168404Spjd	int error;
327168404Spjd	struct timespec ts;
328168404Spjd	struct timeval tv;
329168404Spjd	clock_t delta;
330168404Spjd
331219089Spjd	abstime += ddi_get_lbolt();
332168404Spjdtop:
333219089Spjd	delta = abstime - ddi_get_lbolt();
334168404Spjd	if (delta <= 0)
335168404Spjd		return (-1);
336168404Spjd
337168404Spjd	if (gettimeofday(&tv, NULL) != 0)
338168404Spjd		assert(!"gettimeofday() failed");
339168404Spjd
340168404Spjd	ts.tv_sec = tv.tv_sec + delta / hz;
341168404Spjd	ts.tv_nsec = tv.tv_usec * 1000 + (delta % hz) * (NANOSEC / hz);
342168404Spjd	ASSERT(ts.tv_nsec >= 0);
343168404Spjd
344214622Spjd	if (ts.tv_nsec >= NANOSEC) {
345168404Spjd		ts.tv_sec++;
346168404Spjd		ts.tv_nsec -= NANOSEC;
347168404Spjd	}
348168404Spjd
349168404Spjd	ASSERT(mutex_owner(mp) == curthread);
350168404Spjd	mp->m_owner = NULL;
351168404Spjd	error = pthread_cond_timedwait(cv, &mp->m_lock, &ts);
352168404Spjd	mp->m_owner = curthread;
353168404Spjd
354168404Spjd	if (error == EINTR)
355168404Spjd		goto top;
356168404Spjd
357168404Spjd	if (error == ETIMEDOUT)
358168404Spjd		return (-1);
359168404Spjd
360168404Spjd	ASSERT(error == 0);
361168404Spjd
362168404Spjd	return (1);
363168404Spjd}
364168404Spjd
365255437Sdelphij/*ARGSUSED*/
366255437Sdelphijclock_t
367255437Sdelphijcv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res,
368255437Sdelphij    int flag)
369255437Sdelphij{
370255437Sdelphij	int error;
371318909Smav	timespec_t ts;
372255437Sdelphij	hrtime_t delta;
373255437Sdelphij
374297508Smav	ASSERT(flag == 0 || flag == CALLOUT_FLAG_ABSOLUTE);
375255437Sdelphij
376255437Sdelphijtop:
377297508Smav	delta = tim;
378297508Smav	if (flag & CALLOUT_FLAG_ABSOLUTE)
379297508Smav		delta -= gethrtime();
380297508Smav
381255437Sdelphij	if (delta <= 0)
382255437Sdelphij		return (-1);
383255437Sdelphij
384318909Smav	clock_gettime(CLOCK_REALTIME, &ts);
385318909Smav	ts.tv_sec += delta / NANOSEC;
386318909Smav	ts.tv_nsec += delta % NANOSEC;
387318909Smav	if (ts.tv_nsec >= NANOSEC) {
388318909Smav		ts.tv_sec++;
389318909Smav		ts.tv_nsec -= NANOSEC;
390318909Smav	}
391255437Sdelphij
392255437Sdelphij	ASSERT(mutex_owner(mp) == curthread);
393255437Sdelphij	mp->m_owner = NULL;
394255437Sdelphij	error = pthread_cond_timedwait(cv, &mp->m_lock, &ts);
395255437Sdelphij	mp->m_owner = curthread;
396255437Sdelphij
397255437Sdelphij	if (error == ETIMEDOUT)
398255437Sdelphij		return (-1);
399255437Sdelphij
400255437Sdelphij	if (error == EINTR)
401255437Sdelphij		goto top;
402255437Sdelphij
403255437Sdelphij	ASSERT(error == 0);
404255437Sdelphij
405255437Sdelphij	return (1);
406255437Sdelphij}
407255437Sdelphij
408168404Spjdvoid
409168404Spjdcv_signal(kcondvar_t *cv)
410168404Spjd{
411168404Spjd	VERIFY(cond_signal(cv) == 0);
412168404Spjd}
413168404Spjd
414168404Spjdvoid
415168404Spjdcv_broadcast(kcondvar_t *cv)
416168404Spjd{
417168404Spjd	VERIFY(cond_broadcast(cv) == 0);
418168404Spjd}
419168404Spjd
420168404Spjd/*
421168404Spjd * =========================================================================
422168404Spjd * vnode operations
423168404Spjd * =========================================================================
424168404Spjd */
425168404Spjd/*
426168404Spjd * Note: for the xxxat() versions of these functions, we assume that the
427168404Spjd * starting vp is always rootdir (which is true for spa_directory.c, the only
428168404Spjd * ZFS consumer of these interfaces).  We assert this is true, and then emulate
429168404Spjd * them by adding '/' in front of the path.
430168404Spjd */
431168404Spjd
432168404Spjd/*ARGSUSED*/
433168404Spjdint
434168404Spjdvn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
435168404Spjd{
436168404Spjd	int fd;
437268084Sdelphij	int dump_fd;
438168404Spjd	vnode_t *vp;
439168404Spjd	int old_umask;
440168404Spjd	char realpath[MAXPATHLEN];
441168404Spjd	struct stat64 st;
442168404Spjd
443168404Spjd	/*
444168404Spjd	 * If we're accessing a real disk from userland, we need to use
445168404Spjd	 * the character interface to avoid caching.  This is particularly
446168404Spjd	 * important if we're trying to look at a real in-kernel storage
447168404Spjd	 * pool from userland, e.g. via zdb, because otherwise we won't
448168404Spjd	 * see the changes occurring under the segmap cache.
449168404Spjd	 * On the other hand, the stupid character device returns zero
450168404Spjd	 * for its size.  So -- gag -- we open the block device to get
451168404Spjd	 * its size, and remember it for subsequent VOP_GETATTR().
452168404Spjd	 */
453168404Spjd	if (strncmp(path, "/dev/", 5) == 0) {
454168404Spjd		char *dsk;
455168404Spjd		fd = open64(path, O_RDONLY);
456168404Spjd		if (fd == -1)
457168404Spjd			return (errno);
458168404Spjd		if (fstat64(fd, &st) == -1) {
459168404Spjd			close(fd);
460168404Spjd			return (errno);
461168404Spjd		}
462168404Spjd		close(fd);
463168404Spjd		(void) sprintf(realpath, "%s", path);
464168404Spjd		dsk = strstr(path, "/dsk/");
465168404Spjd		if (dsk != NULL)
466168404Spjd			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
467168404Spjd			    dsk + 1);
468168404Spjd	} else {
469168404Spjd		(void) sprintf(realpath, "%s", path);
470168404Spjd		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
471168404Spjd			return (errno);
472168404Spjd	}
473168404Spjd
474168404Spjd	if (flags & FCREAT)
475168404Spjd		old_umask = umask(0);
476168404Spjd
477168404Spjd	/*
478168404Spjd	 * The construct 'flags - FREAD' conveniently maps combinations of
479168404Spjd	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
480168404Spjd	 */
481168404Spjd	fd = open64(realpath, flags - FREAD, mode);
482168404Spjd
483168404Spjd	if (flags & FCREAT)
484168404Spjd		(void) umask(old_umask);
485168404Spjd
486268084Sdelphij	if (vn_dumpdir != NULL) {
487268084Sdelphij		char dumppath[MAXPATHLEN];
488268084Sdelphij		(void) snprintf(dumppath, sizeof (dumppath),
489268084Sdelphij		    "%s/%s", vn_dumpdir, basename(realpath));
490268084Sdelphij		dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666);
491268084Sdelphij		if (dump_fd == -1)
492268084Sdelphij			return (errno);
493268084Sdelphij	} else {
494268084Sdelphij		dump_fd = -1;
495268084Sdelphij	}
496268084Sdelphij
497168404Spjd	if (fd == -1)
498168404Spjd		return (errno);
499168404Spjd
500168404Spjd	if (fstat64(fd, &st) == -1) {
501168404Spjd		close(fd);
502168404Spjd		return (errno);
503168404Spjd	}
504168404Spjd
505168404Spjd	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
506168404Spjd
507168404Spjd	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
508168404Spjd
509168404Spjd	vp->v_fd = fd;
510219089Spjd	vp->v_size = st.st_size;
511168404Spjd	vp->v_path = spa_strdup(path);
512268084Sdelphij	vp->v_dump_fd = dump_fd;
513168404Spjd
514168404Spjd	return (0);
515168404Spjd}
516168404Spjd
517185029Spjd/*ARGSUSED*/
518168404Spjdint
519168404Spjdvn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
520185029Spjd    int x3, vnode_t *startvp, int fd)
521168404Spjd{
522168404Spjd	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
523168404Spjd	int ret;
524168404Spjd
525168404Spjd	ASSERT(startvp == rootdir);
526168404Spjd	(void) sprintf(realpath, "/%s", path);
527168404Spjd
528185029Spjd	/* fd ignored for now, need if want to simulate nbmand support */
529168404Spjd	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
530168404Spjd
531168404Spjd	umem_free(realpath, strlen(path) + 2);
532168404Spjd
533168404Spjd	return (ret);
534168404Spjd}
535168404Spjd
536168404Spjd/*ARGSUSED*/
537168404Spjdint
538168404Spjdvn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
539289562Smav    int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
540168404Spjd{
541168404Spjd	ssize_t iolen, split;
542168404Spjd
543168404Spjd	if (uio == UIO_READ) {
544168404Spjd		iolen = pread64(vp->v_fd, addr, len, offset);
545268084Sdelphij		if (vp->v_dump_fd != -1) {
546268084Sdelphij			int status =
547268084Sdelphij			    pwrite64(vp->v_dump_fd, addr, iolen, offset);
548268084Sdelphij			ASSERT(status != -1);
549268084Sdelphij		}
550168404Spjd	} else {
551168404Spjd		/*
552168404Spjd		 * To simulate partial disk writes, we split writes into two
553168404Spjd		 * system calls so that the process can be killed in between.
554168404Spjd		 */
555236884Smm		int sectors = len >> SPA_MINBLOCKSHIFT;
556236884Smm		split = (sectors > 0 ? rand() % sectors : 0) <<
557236884Smm		    SPA_MINBLOCKSHIFT;
558168404Spjd		iolen = pwrite64(vp->v_fd, addr, split, offset);
559168404Spjd		iolen += pwrite64(vp->v_fd, (char *)addr + split,
560168404Spjd		    len - split, offset + split);
561168404Spjd	}
562168404Spjd
563168404Spjd	if (iolen == -1)
564168404Spjd		return (errno);
565168404Spjd	if (residp)
566168404Spjd		*residp = len - iolen;
567168404Spjd	else if (iolen != len)
568168404Spjd		return (EIO);
569168404Spjd	return (0);
570168404Spjd}
571168404Spjd
572168404Spjdvoid
573185029Spjdvn_close(vnode_t *vp, int openflag, cred_t *cr, kthread_t *td)
574168404Spjd{
575168404Spjd	close(vp->v_fd);
576268084Sdelphij	if (vp->v_dump_fd != -1)
577268084Sdelphij		close(vp->v_dump_fd);
578168404Spjd	spa_strfree(vp->v_path);
579168404Spjd	umem_free(vp, sizeof (vnode_t));
580168404Spjd}
581168404Spjd
582219089Spjd/*
583219089Spjd * At a minimum we need to update the size since vdev_reopen()
584219089Spjd * will no longer call vn_openat().
585219089Spjd */
586219089Spjdint
587219089Spjdfop_getattr(vnode_t *vp, vattr_t *vap)
588219089Spjd{
589219089Spjd	struct stat64 st;
590219089Spjd
591219089Spjd	if (fstat64(vp->v_fd, &st) == -1) {
592219089Spjd		close(vp->v_fd);
593219089Spjd		return (errno);
594219089Spjd	}
595219089Spjd
596219089Spjd	vap->va_size = st.st_size;
597219089Spjd	return (0);
598219089Spjd}
599219089Spjd
600168404Spjd#ifdef ZFS_DEBUG
601168404Spjd
602168404Spjd/*
603168404Spjd * =========================================================================
604168404Spjd * Figure out which debugging statements to print
605168404Spjd * =========================================================================
606168404Spjd */
607168404Spjd
608168404Spjdstatic char *dprintf_string;
609168404Spjdstatic int dprintf_print_all;
610168404Spjd
611168404Spjdint
612168404Spjddprintf_find_string(const char *string)
613168404Spjd{
614168404Spjd	char *tmp_str = dprintf_string;
615168404Spjd	int len = strlen(string);
616168404Spjd
617168404Spjd	/*
618168404Spjd	 * Find out if this is a string we want to print.
619168404Spjd	 * String format: file1.c,function_name1,file2.c,file3.c
620168404Spjd	 */
621168404Spjd
622168404Spjd	while (tmp_str != NULL) {
623168404Spjd		if (strncmp(tmp_str, string, len) == 0 &&
624168404Spjd		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
625168404Spjd			return (1);
626168404Spjd		tmp_str = strchr(tmp_str, ',');
627168404Spjd		if (tmp_str != NULL)
628168404Spjd			tmp_str++; /* Get rid of , */
629168404Spjd	}
630168404Spjd	return (0);
631168404Spjd}
632168404Spjd
633168404Spjdvoid
634168404Spjddprintf_setup(int *argc, char **argv)
635168404Spjd{
636168404Spjd	int i, j;
637168404Spjd
638168404Spjd	/*
639168404Spjd	 * Debugging can be specified two ways: by setting the
640168404Spjd	 * environment variable ZFS_DEBUG, or by including a
641168404Spjd	 * "debug=..."  argument on the command line.  The command
642168404Spjd	 * line setting overrides the environment variable.
643168404Spjd	 */
644168404Spjd
645168404Spjd	for (i = 1; i < *argc; i++) {
646168404Spjd		int len = strlen("debug=");
647168404Spjd		/* First look for a command line argument */
648168404Spjd		if (strncmp("debug=", argv[i], len) == 0) {
649168404Spjd			dprintf_string = argv[i] + len;
650168404Spjd			/* Remove from args */
651168404Spjd			for (j = i; j < *argc; j++)
652168404Spjd				argv[j] = argv[j+1];
653168404Spjd			argv[j] = NULL;
654168404Spjd			(*argc)--;
655168404Spjd		}
656168404Spjd	}
657168404Spjd
658168404Spjd	if (dprintf_string == NULL) {
659168404Spjd		/* Look for ZFS_DEBUG environment variable */
660168404Spjd		dprintf_string = getenv("ZFS_DEBUG");
661168404Spjd	}
662168404Spjd
663168404Spjd	/*
664168404Spjd	 * Are we just turning on all debugging?
665168404Spjd	 */
666168404Spjd	if (dprintf_find_string("on"))
667168404Spjd		dprintf_print_all = 1;
668271533Sdelphij
669271533Sdelphij	if (dprintf_string != NULL)
670271533Sdelphij		zfs_flags |= ZFS_DEBUG_DPRINTF;
671168404Spjd}
672168404Spjd
673254591Sgibbsint
674254591Sgibbssysctl_handle_64(SYSCTL_HANDLER_ARGS)
675254591Sgibbs{
676254591Sgibbs	return (0);
677254591Sgibbs}
678254591Sgibbs
679168404Spjd/*
680168404Spjd * =========================================================================
681168404Spjd * debug printfs
682168404Spjd * =========================================================================
683168404Spjd */
684168404Spjdvoid
685168404Spjd__dprintf(const char *file, const char *func, int line, const char *fmt, ...)
686168404Spjd{
687168404Spjd	const char *newfile;
688168404Spjd	va_list adx;
689168404Spjd
690168404Spjd	/*
691168404Spjd	 * Get rid of annoying "../common/" prefix to filename.
692168404Spjd	 */
693168404Spjd	newfile = strrchr(file, '/');
694168404Spjd	if (newfile != NULL) {
695168404Spjd		newfile = newfile + 1; /* Get rid of leading / */
696168404Spjd	} else {
697168404Spjd		newfile = file;
698168404Spjd	}
699168404Spjd
700168404Spjd	if (dprintf_print_all ||
701168404Spjd	    dprintf_find_string(newfile) ||
702168404Spjd	    dprintf_find_string(func)) {
703168404Spjd		/* Print out just the function name if requested */
704168404Spjd		flockfile(stdout);
705168404Spjd		if (dprintf_find_string("pid"))
706168404Spjd			(void) printf("%d ", getpid());
707168404Spjd		if (dprintf_find_string("tid"))
708269730Ssbruno			(void) printf("%lu ", thr_self());
709168404Spjd#if 0
710168404Spjd		if (dprintf_find_string("cpu"))
711168404Spjd			(void) printf("%u ", getcpuid());
712168404Spjd#endif
713168404Spjd		if (dprintf_find_string("time"))
714168404Spjd			(void) printf("%llu ", gethrtime());
715168404Spjd		if (dprintf_find_string("long"))
716168404Spjd			(void) printf("%s, line %d: ", newfile, line);
717168404Spjd		(void) printf("%s: ", func);
718168404Spjd		va_start(adx, fmt);
719168404Spjd		(void) vprintf(fmt, adx);
720168404Spjd		va_end(adx);
721168404Spjd		funlockfile(stdout);
722168404Spjd	}
723168404Spjd}
724168404Spjd
725168404Spjd#endif /* ZFS_DEBUG */
726168404Spjd
727168404Spjd/*
728168404Spjd * =========================================================================
729168404Spjd * cmn_err() and panic()
730168404Spjd * =========================================================================
731168404Spjd */
732168404Spjdstatic char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
733168404Spjdstatic char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
734168404Spjd
735168404Spjdvoid
736168404Spjdvpanic(const char *fmt, va_list adx)
737168404Spjd{
738324586Savg	char buf[512];
739324586Savg	(void) vsnprintf(buf, 512, fmt, adx);
740324586Savg	assfail(buf, NULL, 0);
741325534Savg	abort(); /* necessary to make vpanic meet noreturn requirements */
742168404Spjd}
743168404Spjd
744168404Spjdvoid
745168404Spjdpanic(const char *fmt, ...)
746168404Spjd{
747168404Spjd	va_list adx;
748168404Spjd
749168404Spjd	va_start(adx, fmt);
750168404Spjd	vpanic(fmt, adx);
751168404Spjd	va_end(adx);
752168404Spjd}
753168404Spjd
754168404Spjdvoid
755168404Spjdvcmn_err(int ce, const char *fmt, va_list adx)
756168404Spjd{
757168404Spjd	if (ce == CE_PANIC)
758168404Spjd		vpanic(fmt, adx);
759168404Spjd	if (ce != CE_NOTE) {	/* suppress noise in userland stress testing */
760168404Spjd		(void) fprintf(stderr, "%s", ce_prefix[ce]);
761168404Spjd		(void) vfprintf(stderr, fmt, adx);
762168404Spjd		(void) fprintf(stderr, "%s", ce_suffix[ce]);
763168404Spjd	}
764168404Spjd}
765168404Spjd
766168404Spjd/*PRINTFLIKE2*/
767168404Spjdvoid
768168404Spjdcmn_err(int ce, const char *fmt, ...)
769168404Spjd{
770168404Spjd	va_list adx;
771168404Spjd
772168404Spjd	va_start(adx, fmt);
773168404Spjd	vcmn_err(ce, fmt, adx);
774168404Spjd	va_end(adx);
775168404Spjd}
776168404Spjd
777168404Spjd/*
778168404Spjd * =========================================================================
779168404Spjd * kobj interfaces
780168404Spjd * =========================================================================
781168404Spjd */
782168404Spjdstruct _buf *
783168404Spjdkobj_open_file(char *name)
784168404Spjd{
785168404Spjd	struct _buf *file;
786168404Spjd	vnode_t *vp;
787168404Spjd
788168404Spjd	/* set vp as the _fd field of the file */
789185029Spjd	if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir,
790185029Spjd	    -1) != 0)
791168404Spjd		return ((void *)-1UL);
792168404Spjd
793168404Spjd	file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
794168404Spjd	file->_fd = (intptr_t)vp;
795168404Spjd	return (file);
796168404Spjd}
797168404Spjd
798168404Spjdint
799168404Spjdkobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
800168404Spjd{
801168404Spjd	ssize_t resid;
802168404Spjd
803168404Spjd	vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
804168404Spjd	    UIO_SYSSPACE, 0, 0, 0, &resid);
805168404Spjd
806168404Spjd	return (size - resid);
807168404Spjd}
808168404Spjd
809168404Spjdvoid
810168404Spjdkobj_close_file(struct _buf *file)
811168404Spjd{
812185029Spjd	vn_close((vnode_t *)file->_fd, 0, NULL, NULL);
813168404Spjd	umem_free(file, sizeof (struct _buf));
814168404Spjd}
815168404Spjd
816168404Spjdint
817168404Spjdkobj_get_filesize(struct _buf *file, uint64_t *size)
818168404Spjd{
819168404Spjd	struct stat64 st;
820168404Spjd	vnode_t *vp = (vnode_t *)file->_fd;
821168404Spjd
822168404Spjd	if (fstat64(vp->v_fd, &st) == -1) {
823185029Spjd		vn_close(vp, 0, NULL, NULL);
824168404Spjd		return (errno);
825168404Spjd	}
826168404Spjd	*size = st.st_size;
827168404Spjd	return (0);
828168404Spjd}
829168404Spjd
830168404Spjd/*
831168404Spjd * =========================================================================
832168404Spjd * misc routines
833168404Spjd * =========================================================================
834168404Spjd */
835168404Spjd
836168404Spjdvoid
837168404Spjddelay(clock_t ticks)
838168404Spjd{
839168404Spjd	poll(0, 0, ticks * (1000 / hz));
840168404Spjd}
841168404Spjd
842168404Spjd#if 0
843168404Spjd/*
844168404Spjd * Find highest one bit set.
845168404Spjd *	Returns bit number + 1 of highest bit that is set, otherwise returns 0.
846168404Spjd */
847168404Spjdint
848264669Sdelphijhighbit64(uint64_t i)
849168404Spjd{
850264669Sdelphij	int h = 1;
851168404Spjd
852168404Spjd	if (i == 0)
853168404Spjd		return (0);
854264669Sdelphij	if (i & 0xffffffff00000000ULL) {
855168404Spjd		h += 32; i >>= 32;
856168404Spjd	}
857168404Spjd	if (i & 0xffff0000) {
858168404Spjd		h += 16; i >>= 16;
859168404Spjd	}
860168404Spjd	if (i & 0xff00) {
861168404Spjd		h += 8; i >>= 8;
862168404Spjd	}
863168404Spjd	if (i & 0xf0) {
864168404Spjd		h += 4; i >>= 4;
865168404Spjd	}
866168404Spjd	if (i & 0xc) {
867168404Spjd		h += 2; i >>= 2;
868168404Spjd	}
869168404Spjd	if (i & 0x2) {
870168404Spjd		h += 1;
871168404Spjd	}
872168404Spjd	return (h);
873168404Spjd}
874168404Spjd#endif
875168404Spjd
876185029Spjdstatic int random_fd = -1, urandom_fd = -1;
877185029Spjd
878168404Spjdstatic int
879185029Spjdrandom_get_bytes_common(uint8_t *ptr, size_t len, int fd)
880168404Spjd{
881168404Spjd	size_t resid = len;
882168404Spjd	ssize_t bytes;
883168404Spjd
884168404Spjd	ASSERT(fd != -1);
885168404Spjd
886168404Spjd	while (resid != 0) {
887168404Spjd		bytes = read(fd, ptr, resid);
888185029Spjd		ASSERT3S(bytes, >=, 0);
889168404Spjd		ptr += bytes;
890168404Spjd		resid -= bytes;
891168404Spjd	}
892168404Spjd
893168404Spjd	return (0);
894168404Spjd}
895168404Spjd
896168404Spjdint
897168404Spjdrandom_get_bytes(uint8_t *ptr, size_t len)
898168404Spjd{
899185029Spjd	return (random_get_bytes_common(ptr, len, random_fd));
900168404Spjd}
901168404Spjd
902168404Spjdint
903168404Spjdrandom_get_pseudo_bytes(uint8_t *ptr, size_t len)
904168404Spjd{
905185029Spjd	return (random_get_bytes_common(ptr, len, urandom_fd));
906168404Spjd}
907168404Spjd
908168498Spjdint
909168498Spjdddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result)
910168498Spjd{
911168498Spjd	char *end;
912168498Spjd
913168498Spjd	*result = strtoul(hw_serial, &end, base);
914168498Spjd	if (*result == 0)
915168498Spjd		return (errno);
916168498Spjd	return (0);
917168498Spjd}
918168498Spjd
919219089Spjdint
920219089Spjdddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result)
921219089Spjd{
922219089Spjd	char *end;
923219089Spjd
924219089Spjd	*result = strtoull(str, &end, base);
925219089Spjd	if (*result == 0)
926219089Spjd		return (errno);
927219089Spjd	return (0);
928219089Spjd}
929219089Spjd
930247265Smm#ifdef illumos
931247265Smm/* ARGSUSED */
932247265Smmcyclic_id_t
933247265Smmcyclic_add(cyc_handler_t *hdlr, cyc_time_t *when)
934247265Smm{
935247265Smm	return (1);
936247265Smm}
937247265Smm
938247265Smm/* ARGSUSED */
939247265Smmvoid
940247265Smmcyclic_remove(cyclic_id_t id)
941247265Smm{
942247265Smm}
943247265Smm
944247265Smm/* ARGSUSED */
945247265Smmint
946247265Smmcyclic_reprogram(cyclic_id_t id, hrtime_t expiration)
947247265Smm{
948247265Smm	return (1);
949247265Smm}
950247265Smm#endif
951247265Smm
952168404Spjd/*
953168404Spjd * =========================================================================
954168404Spjd * kernel emulation setup & teardown
955168404Spjd * =========================================================================
956168404Spjd */
957168404Spjdstatic int
958168404Spjdumem_out_of_memory(void)
959168404Spjd{
960168404Spjd	char errmsg[] = "out of memory -- generating core dump\n";
961168404Spjd
962168404Spjd	write(fileno(stderr), errmsg, sizeof (errmsg));
963168404Spjd	abort();
964168404Spjd	return (0);
965168404Spjd}
966168404Spjd
967168404Spjdvoid
968168404Spjdkernel_init(int mode)
969168404Spjd{
970248571Smm	extern uint_t rrw_tsd_key;
971248571Smm
972168404Spjd	umem_nofail_callback(umem_out_of_memory);
973168404Spjd
974168404Spjd	physmem = sysconf(_SC_PHYS_PAGES);
975168404Spjd
976168404Spjd	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
977168404Spjd	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
978168404Spjd
979219089Spjd	(void) snprintf(hw_serial, sizeof (hw_serial), "%lu",
980219089Spjd	    (mode & FWRITE) ? (unsigned long)gethostid() : 0);
981168498Spjd
982185029Spjd	VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1);
983185029Spjd	VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1);
984185029Spjd
985208047Smm	system_taskq_init();
986208047Smm
987247265Smm#ifdef illumos
988247265Smm	mutex_init(&cpu_lock, NULL, MUTEX_DEFAULT, NULL);
989247265Smm#endif
990247265Smm
991168404Spjd	spa_init(mode);
992248571Smm
993248571Smm	tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
994168404Spjd}
995168404Spjd
996168404Spjdvoid
997168404Spjdkernel_fini(void)
998168404Spjd{
999168404Spjd	spa_fini();
1000185029Spjd
1001219089Spjd	system_taskq_fini();
1002219089Spjd
1003185029Spjd	close(random_fd);
1004185029Spjd	close(urandom_fd);
1005185029Spjd
1006185029Spjd	random_fd = -1;
1007185029Spjd	urandom_fd = -1;
1008168404Spjd}
1009168404Spjd
1010332536Smav/* ARGSUSED */
1011332536Smavuint32_t
1012332536Smavzone_get_hostid(void *zonep)
1013332536Smav{
1014332536Smav	/*
1015332536Smav	 * We're emulating the system's hostid in userland.
1016332536Smav	 */
1017332536Smav	return (strtoul(hw_serial, NULL, 10));
1018332536Smav}
1019332536Smav
1020168404Spjdint
1021168404Spjdz_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen)
1022168404Spjd{
1023168404Spjd	int ret;
1024168404Spjd	uLongf len = *dstlen;
1025168404Spjd
1026168404Spjd	if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK)
1027168404Spjd		*dstlen = (size_t)len;
1028168404Spjd
1029168404Spjd	return (ret);
1030168404Spjd}
1031168404Spjd
1032168404Spjdint
1033168404Spjdz_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen,
1034168404Spjd    int level)
1035168404Spjd{
1036168404Spjd	int ret;
1037168404Spjd	uLongf len = *dstlen;
1038168404Spjd
1039168404Spjd	if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK)
1040168404Spjd		*dstlen = (size_t)len;
1041168404Spjd
1042168404Spjd	return (ret);
1043168404Spjd}
1044185029Spjd
1045185029Spjduid_t
1046185029Spjdcrgetuid(cred_t *cr)
1047185029Spjd{
1048185029Spjd	return (0);
1049185029Spjd}
1050185029Spjd
1051248571Smmuid_t
1052248571Smmcrgetruid(cred_t *cr)
1053248571Smm{
1054248571Smm	return (0);
1055248571Smm}
1056248571Smm
1057185029Spjdgid_t
1058185029Spjdcrgetgid(cred_t *cr)
1059185029Spjd{
1060185029Spjd	return (0);
1061185029Spjd}
1062185029Spjd
1063185029Spjdint
1064185029Spjdcrgetngroups(cred_t *cr)
1065185029Spjd{
1066185029Spjd	return (0);
1067185029Spjd}
1068185029Spjd
1069185029Spjdgid_t *
1070185029Spjdcrgetgroups(cred_t *cr)
1071185029Spjd{
1072185029Spjd	return (NULL);
1073185029Spjd}
1074185029Spjd
1075185029Spjdint
1076185029Spjdzfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
1077185029Spjd{
1078185029Spjd	return (0);
1079185029Spjd}
1080185029Spjd
1081185029Spjdint
1082185029Spjdzfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
1083185029Spjd{
1084185029Spjd	return (0);
1085185029Spjd}
1086185029Spjd
1087185029Spjdint
1088185029Spjdzfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
1089185029Spjd{
1090185029Spjd	return (0);
1091185029Spjd}
1092185029Spjd
1093185029Spjdksiddomain_t *
1094185029Spjdksid_lookupdomain(const char *dom)
1095185029Spjd{
1096185029Spjd	ksiddomain_t *kd;
1097185029Spjd
1098185029Spjd	kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL);
1099185029Spjd	kd->kd_name = spa_strdup(dom);
1100185029Spjd	return (kd);
1101185029Spjd}
1102185029Spjd
1103185029Spjdvoid
1104185029Spjdksiddomain_rele(ksiddomain_t *ksid)
1105185029Spjd{
1106185029Spjd	spa_strfree(ksid->kd_name);
1107185029Spjd	umem_free(ksid, sizeof (ksiddomain_t));
1108185029Spjd}
1109219089Spjd
1110219089Spjd/*
1111219089Spjd * Do not change the length of the returned string; it must be freed
1112219089Spjd * with strfree().
1113219089Spjd */
1114219089Spjdchar *
1115219089Spjdkmem_asprintf(const char *fmt, ...)
1116219089Spjd{
1117219089Spjd	int size;
1118219089Spjd	va_list adx;
1119219089Spjd	char *buf;
1120219089Spjd
1121219089Spjd	va_start(adx, fmt);
1122219089Spjd	size = vsnprintf(NULL, 0, fmt, adx) + 1;
1123219089Spjd	va_end(adx);
1124219089Spjd
1125219089Spjd	buf = kmem_alloc(size, KM_SLEEP);
1126219089Spjd
1127219089Spjd	va_start(adx, fmt);
1128219089Spjd	size = vsnprintf(buf, size, fmt, adx);
1129219089Spjd	va_end(adx);
1130219089Spjd
1131219089Spjd	return (buf);
1132219089Spjd}
1133219089Spjd
1134219089Spjd/* ARGSUSED */
1135219089Spjdint
1136219089Spjdzfs_onexit_fd_hold(int fd, minor_t *minorp)
1137219089Spjd{
1138219089Spjd	*minorp = 0;
1139219089Spjd	return (0);
1140219089Spjd}
1141219089Spjd
1142219089Spjd/* ARGSUSED */
1143219089Spjdvoid
1144219089Spjdzfs_onexit_fd_rele(int fd)
1145219089Spjd{
1146219089Spjd}
1147219089Spjd
1148219089Spjd/* ARGSUSED */
1149219089Spjdint
1150219089Spjdzfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
1151219089Spjd    uint64_t *action_handle)
1152219089Spjd{
1153219089Spjd	return (0);
1154219089Spjd}
1155219089Spjd
1156219089Spjd/* ARGSUSED */
1157219089Spjdint
1158219089Spjdzfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire)
1159219089Spjd{
1160219089Spjd	return (0);
1161219089Spjd}
1162219089Spjd
1163219089Spjd/* ARGSUSED */
1164219089Spjdint
1165219089Spjdzfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data)
1166219089Spjd{
1167219089Spjd	return (0);
1168219089Spjd}
1169219089Spjd
1170219089Spjd#ifdef __FreeBSD__
1171219089Spjd/* ARGSUSED */
1172219089Spjdint
1173219089Spjdzvol_create_minors(const char *name)
1174219089Spjd{
1175219089Spjd	return (0);
1176219089Spjd}
1177219089Spjd#endif
1178260138Sdelphij
1179260138Sdelphij#ifdef illumos
1180260138Sdelphijvoid
1181260138Sdelphijbioinit(buf_t *bp)
1182260138Sdelphij{
1183260138Sdelphij	bzero(bp, sizeof (buf_t));
1184260138Sdelphij}
1185260138Sdelphij
1186260138Sdelphijvoid
1187260138Sdelphijbiodone(buf_t *bp)
1188260138Sdelphij{
1189260138Sdelphij	if (bp->b_iodone != NULL) {
1190260138Sdelphij		(*(bp->b_iodone))(bp);
1191260138Sdelphij		return;
1192260138Sdelphij	}
1193260138Sdelphij	ASSERT((bp->b_flags & B_DONE) == 0);
1194260138Sdelphij	bp->b_flags |= B_DONE;
1195260138Sdelphij}
1196260138Sdelphij
1197260138Sdelphijvoid
1198260138Sdelphijbioerror(buf_t *bp, int error)
1199260138Sdelphij{
1200260138Sdelphij	ASSERT(bp != NULL);
1201260138Sdelphij	ASSERT(error >= 0);
1202260138Sdelphij
1203260138Sdelphij	if (error != 0) {
1204260138Sdelphij		bp->b_flags |= B_ERROR;
1205260138Sdelphij	} else {
1206260138Sdelphij		bp->b_flags &= ~B_ERROR;
1207260138Sdelphij	}
1208260138Sdelphij	bp->b_error = error;
1209260138Sdelphij}
1210260138Sdelphij
1211260138Sdelphij
1212260138Sdelphijint
1213260138Sdelphijgeterror(struct buf *bp)
1214260138Sdelphij{
1215260138Sdelphij	int error = 0;
1216260138Sdelphij
1217260138Sdelphij	if (bp->b_flags & B_ERROR) {
1218260138Sdelphij		error = bp->b_error;
1219260138Sdelphij		if (!error)
1220260138Sdelphij			error = EIO;
1221260138Sdelphij	}
1222260138Sdelphij	return (error);
1223260138Sdelphij}
1224260138Sdelphij#endif
1225