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.
23168404Spjd */
24168404Spjd
25168404Spjd#include <assert.h>
26168404Spjd#include <fcntl.h>
27168404Spjd#include <poll.h>
28168404Spjd#include <stdio.h>
29168404Spjd#include <stdlib.h>
30168404Spjd#include <string.h>
31168404Spjd#include <zlib.h>
32168404Spjd#include <sys/spa.h>
33168404Spjd#include <sys/stat.h>
34168404Spjd#include <sys/processor.h>
35168404Spjd#include <sys/zfs_context.h>
36248571Smm#include <sys/rrwlock.h>
37168404Spjd#include <sys/zmod.h>
38168498Spjd#include <sys/utsname.h>
39219089Spjd#include <sys/systeminfo.h>
40168404Spjd
41168404Spjd/*
42168404Spjd * Emulation of kernel services in userland.
43168404Spjd */
44168404Spjd
45219089Spjdint aok;
46168404Spjduint64_t physmem;
47168404Spjdvnode_t *rootdir = (vnode_t *)0xabcd1234;
48219089Spjdchar hw_serial[HW_HOSTID_LEN];
49247265Smm#ifdef illumos
50247265Smmkmutex_t cpu_lock;
51247265Smm#endif
52168404Spjd
53168498Spjdstruct utsname utsname = {
54168498Spjd	"userland", "libzpool", "1", "1", "na"
55168498Spjd};
56168498Spjd
57219089Spjd/* this only exists to have its address taken */
58219089Spjdstruct proc p0;
59219089Spjd
60168404Spjd/*
61168404Spjd * =========================================================================
62168404Spjd * threads
63168404Spjd * =========================================================================
64168404Spjd */
65168404Spjd/*ARGSUSED*/
66168404Spjdkthread_t *
67168404Spjdzk_thread_create(void (*func)(), void *arg)
68168404Spjd{
69168404Spjd	thread_t tid;
70168404Spjd
71168404Spjd	VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
72168404Spjd	    &tid) == 0);
73168404Spjd
74168404Spjd	return ((void *)(uintptr_t)tid);
75168404Spjd}
76168404Spjd
77168404Spjd/*
78168404Spjd * =========================================================================
79168404Spjd * kstats
80168404Spjd * =========================================================================
81168404Spjd */
82168404Spjd/*ARGSUSED*/
83168404Spjdkstat_t *
84168404Spjdkstat_create(char *module, int instance, char *name, char *class,
85168404Spjd    uchar_t type, ulong_t ndata, uchar_t ks_flag)
86168404Spjd{
87168404Spjd	return (NULL);
88168404Spjd}
89168404Spjd
90168404Spjd/*ARGSUSED*/
91168404Spjdvoid
92168404Spjdkstat_install(kstat_t *ksp)
93168404Spjd{}
94168404Spjd
95168404Spjd/*ARGSUSED*/
96168404Spjdvoid
97168404Spjdkstat_delete(kstat_t *ksp)
98168404Spjd{}
99168404Spjd
100168404Spjd/*
101168404Spjd * =========================================================================
102168404Spjd * mutexes
103168404Spjd * =========================================================================
104168404Spjd */
105168404Spjdvoid
106168404Spjdzmutex_init(kmutex_t *mp)
107168404Spjd{
108168404Spjd	mp->m_owner = NULL;
109185029Spjd	mp->initialized = B_TRUE;
110168404Spjd	(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
111168404Spjd}
112168404Spjd
113168404Spjdvoid
114168404Spjdzmutex_destroy(kmutex_t *mp)
115168404Spjd{
116185029Spjd	ASSERT(mp->initialized == B_TRUE);
117168404Spjd	ASSERT(mp->m_owner == NULL);
118168404Spjd	(void) _mutex_destroy(&(mp)->m_lock);
119168404Spjd	mp->m_owner = (void *)-1UL;
120185029Spjd	mp->initialized = B_FALSE;
121168404Spjd}
122168404Spjd
123195515Spjdint
124195515Spjdzmutex_owned(kmutex_t *mp)
125195515Spjd{
126195515Spjd	ASSERT(mp->initialized == B_TRUE);
127195515Spjd
128195515Spjd	return (mp->m_owner == curthread);
129195515Spjd}
130195515Spjd
131168404Spjdvoid
132168404Spjdmutex_enter(kmutex_t *mp)
133168404Spjd{
134185029Spjd	ASSERT(mp->initialized == B_TRUE);
135168404Spjd	ASSERT(mp->m_owner != (void *)-1UL);
136168404Spjd	ASSERT(mp->m_owner != curthread);
137168404Spjd	VERIFY(mutex_lock(&mp->m_lock) == 0);
138168404Spjd	ASSERT(mp->m_owner == NULL);
139168404Spjd	mp->m_owner = curthread;
140168404Spjd}
141168404Spjd
142168404Spjdint
143168404Spjdmutex_tryenter(kmutex_t *mp)
144168404Spjd{
145185029Spjd	ASSERT(mp->initialized == B_TRUE);
146168404Spjd	ASSERT(mp->m_owner != (void *)-1UL);
147219089Spjd	if (0 == mutex_trylock(&mp->m_lock)) {
148168404Spjd		ASSERT(mp->m_owner == NULL);
149168404Spjd		mp->m_owner = curthread;
150168404Spjd		return (1);
151168404Spjd	} else {
152168404Spjd		return (0);
153168404Spjd	}
154168404Spjd}
155168404Spjd
156168404Spjdvoid
157168404Spjdmutex_exit(kmutex_t *mp)
158168404Spjd{
159185029Spjd	ASSERT(mp->initialized == B_TRUE);
160219089Spjd	ASSERT(mutex_owner(mp) == curthread);
161168404Spjd	mp->m_owner = NULL;
162168404Spjd	VERIFY(mutex_unlock(&mp->m_lock) == 0);
163168404Spjd}
164168404Spjd
165168404Spjdvoid *
166168404Spjdmutex_owner(kmutex_t *mp)
167168404Spjd{
168185029Spjd	ASSERT(mp->initialized == B_TRUE);
169168404Spjd	return (mp->m_owner);
170168404Spjd}
171168404Spjd
172168404Spjd/*
173168404Spjd * =========================================================================
174168404Spjd * rwlocks
175168404Spjd * =========================================================================
176168404Spjd */
177168404Spjd/*ARGSUSED*/
178168404Spjdvoid
179168404Spjdrw_init(krwlock_t *rwlp, char *name, int type, void *arg)
180168404Spjd{
181168404Spjd	rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
182168404Spjd	rwlp->rw_owner = NULL;
183185029Spjd	rwlp->initialized = B_TRUE;
184210044Spjd	rwlp->rw_count = 0;
185168404Spjd}
186168404Spjd
187168404Spjdvoid
188168404Spjdrw_destroy(krwlock_t *rwlp)
189168404Spjd{
190210044Spjd	ASSERT(rwlp->rw_count == 0);
191168404Spjd	rwlock_destroy(&rwlp->rw_lock);
192168404Spjd	rwlp->rw_owner = (void *)-1UL;
193185029Spjd	rwlp->initialized = B_FALSE;
194168404Spjd}
195168404Spjd
196168404Spjdvoid
197168404Spjdrw_enter(krwlock_t *rwlp, krw_t rw)
198168404Spjd{
199168404Spjd	//ASSERT(!RW_LOCK_HELD(rwlp));
200185029Spjd	ASSERT(rwlp->initialized == B_TRUE);
201168404Spjd	ASSERT(rwlp->rw_owner != (void *)-1UL);
202168404Spjd	ASSERT(rwlp->rw_owner != curthread);
203168404Spjd
204168404Spjd	if (rw == RW_READER) {
205185029Spjd		VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
206168404Spjd		ASSERT(rwlp->rw_count >= 0);
207168404Spjd		atomic_add_int(&rwlp->rw_count, 1);
208168404Spjd	} else {
209185029Spjd		VERIFY(rw_wrlock(&rwlp->rw_lock) == 0);
210168404Spjd		ASSERT(rwlp->rw_count == 0);
211168404Spjd		rwlp->rw_count = -1;
212168404Spjd		rwlp->rw_owner = curthread;
213168404Spjd	}
214168404Spjd}
215168404Spjd
216168404Spjdvoid
217168404Spjdrw_exit(krwlock_t *rwlp)
218168404Spjd{
219185029Spjd	ASSERT(rwlp->initialized == B_TRUE);
220168404Spjd	ASSERT(rwlp->rw_owner != (void *)-1UL);
221168404Spjd
222168404Spjd	if (rwlp->rw_owner == curthread) {
223168404Spjd		/* Write locked. */
224168404Spjd		ASSERT(rwlp->rw_count == -1);
225168404Spjd		rwlp->rw_count = 0;
226168404Spjd		rwlp->rw_owner = NULL;
227168404Spjd	} else {
228168404Spjd		/* Read locked. */
229168404Spjd		ASSERT(rwlp->rw_count > 0);
230168404Spjd		atomic_add_int(&rwlp->rw_count, -1);
231168404Spjd	}
232185029Spjd	VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
233168404Spjd}
234168404Spjd
235168404Spjdint
236168404Spjdrw_tryenter(krwlock_t *rwlp, krw_t rw)
237168404Spjd{
238168404Spjd	int rv;
239168404Spjd
240185029Spjd	ASSERT(rwlp->initialized == B_TRUE);
241168404Spjd	ASSERT(rwlp->rw_owner != (void *)-1UL);
242168404Spjd	ASSERT(rwlp->rw_owner != curthread);
243168404Spjd
244168404Spjd	if (rw == RW_READER)
245168404Spjd		rv = rw_tryrdlock(&rwlp->rw_lock);
246168404Spjd	else
247168404Spjd		rv = rw_trywrlock(&rwlp->rw_lock);
248168404Spjd
249168404Spjd	if (rv == 0) {
250168404Spjd		ASSERT(rwlp->rw_owner == NULL);
251168404Spjd		if (rw == RW_READER) {
252168404Spjd			ASSERT(rwlp->rw_count >= 0);
253168404Spjd			atomic_add_int(&rwlp->rw_count, 1);
254168404Spjd		} else {
255168404Spjd			ASSERT(rwlp->rw_count == 0);
256168404Spjd			rwlp->rw_count = -1;
257168404Spjd			rwlp->rw_owner = curthread;
258168404Spjd		}
259168404Spjd		return (1);
260168404Spjd	}
261168404Spjd
262168404Spjd	return (0);
263168404Spjd}
264168404Spjd
265168404Spjd/*ARGSUSED*/
266168404Spjdint
267168404Spjdrw_tryupgrade(krwlock_t *rwlp)
268168404Spjd{
269185029Spjd	ASSERT(rwlp->initialized == B_TRUE);
270168404Spjd	ASSERT(rwlp->rw_owner != (void *)-1UL);
271168404Spjd
272168404Spjd	return (0);
273168404Spjd}
274168404Spjd
275168404Spjdint
276168404Spjdrw_lock_held(krwlock_t *rwlp)
277168404Spjd{
278168404Spjd
279168404Spjd	return (rwlp->rw_count != 0);
280168404Spjd}
281168404Spjd
282168404Spjd/*
283168404Spjd * =========================================================================
284168404Spjd * condition variables
285168404Spjd * =========================================================================
286168404Spjd */
287168404Spjd/*ARGSUSED*/
288168404Spjdvoid
289168404Spjdcv_init(kcondvar_t *cv, char *name, int type, void *arg)
290168404Spjd{
291168404Spjd	VERIFY(cond_init(cv, name, NULL) == 0);
292168404Spjd}
293168404Spjd
294168404Spjdvoid
295168404Spjdcv_destroy(kcondvar_t *cv)
296168404Spjd{
297168404Spjd	VERIFY(cond_destroy(cv) == 0);
298168404Spjd}
299168404Spjd
300168404Spjdvoid
301168404Spjdcv_wait(kcondvar_t *cv, kmutex_t *mp)
302168404Spjd{
303168404Spjd	ASSERT(mutex_owner(mp) == curthread);
304168404Spjd	mp->m_owner = NULL;
305168404Spjd	int ret = cond_wait(cv, &mp->m_lock);
306168404Spjd	VERIFY(ret == 0 || ret == EINTR);
307168404Spjd	mp->m_owner = curthread;
308168404Spjd}
309168404Spjd
310168404Spjdclock_t
311168404Spjdcv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
312168404Spjd{
313168404Spjd	int error;
314168404Spjd	struct timespec ts;
315168404Spjd	struct timeval tv;
316168404Spjd	clock_t delta;
317168404Spjd
318219089Spjd	abstime += ddi_get_lbolt();
319168404Spjdtop:
320219089Spjd	delta = abstime - ddi_get_lbolt();
321168404Spjd	if (delta <= 0)
322168404Spjd		return (-1);
323168404Spjd
324168404Spjd	if (gettimeofday(&tv, NULL) != 0)
325168404Spjd		assert(!"gettimeofday() failed");
326168404Spjd
327168404Spjd	ts.tv_sec = tv.tv_sec + delta / hz;
328168404Spjd	ts.tv_nsec = tv.tv_usec * 1000 + (delta % hz) * (NANOSEC / hz);
329168404Spjd	ASSERT(ts.tv_nsec >= 0);
330168404Spjd
331214622Spjd	if (ts.tv_nsec >= NANOSEC) {
332168404Spjd		ts.tv_sec++;
333168404Spjd		ts.tv_nsec -= NANOSEC;
334168404Spjd	}
335168404Spjd
336168404Spjd	ASSERT(mutex_owner(mp) == curthread);
337168404Spjd	mp->m_owner = NULL;
338168404Spjd	error = pthread_cond_timedwait(cv, &mp->m_lock, &ts);
339168404Spjd	mp->m_owner = curthread;
340168404Spjd
341168404Spjd	if (error == EINTR)
342168404Spjd		goto top;
343168404Spjd
344168404Spjd	if (error == ETIMEDOUT)
345168404Spjd		return (-1);
346168404Spjd
347168404Spjd	ASSERT(error == 0);
348168404Spjd
349168404Spjd	return (1);
350168404Spjd}
351168404Spjd
352255437Sdelphij/*ARGSUSED*/
353255437Sdelphijclock_t
354255437Sdelphijcv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res,
355255437Sdelphij    int flag)
356255437Sdelphij{
357255437Sdelphij	int error;
358255437Sdelphij	timestruc_t ts;
359255437Sdelphij	hrtime_t delta;
360255437Sdelphij
361255437Sdelphij	ASSERT(flag == 0);
362255437Sdelphij
363255437Sdelphijtop:
364255437Sdelphij	delta = tim - gethrtime();
365255437Sdelphij	if (delta <= 0)
366255437Sdelphij		return (-1);
367255437Sdelphij
368255437Sdelphij	ts.tv_sec = delta / NANOSEC;
369255437Sdelphij	ts.tv_nsec = delta % NANOSEC;
370255437Sdelphij
371255437Sdelphij	ASSERT(mutex_owner(mp) == curthread);
372255437Sdelphij	mp->m_owner = NULL;
373255437Sdelphij	error = pthread_cond_timedwait(cv, &mp->m_lock, &ts);
374255437Sdelphij	mp->m_owner = curthread;
375255437Sdelphij
376255437Sdelphij	if (error == ETIMEDOUT)
377255437Sdelphij		return (-1);
378255437Sdelphij
379255437Sdelphij	if (error == EINTR)
380255437Sdelphij		goto top;
381255437Sdelphij
382255437Sdelphij	ASSERT(error == 0);
383255437Sdelphij
384255437Sdelphij	return (1);
385255437Sdelphij}
386255437Sdelphij
387168404Spjdvoid
388168404Spjdcv_signal(kcondvar_t *cv)
389168404Spjd{
390168404Spjd	VERIFY(cond_signal(cv) == 0);
391168404Spjd}
392168404Spjd
393168404Spjdvoid
394168404Spjdcv_broadcast(kcondvar_t *cv)
395168404Spjd{
396168404Spjd	VERIFY(cond_broadcast(cv) == 0);
397168404Spjd}
398168404Spjd
399168404Spjd/*
400168404Spjd * =========================================================================
401168404Spjd * vnode operations
402168404Spjd * =========================================================================
403168404Spjd */
404168404Spjd/*
405168404Spjd * Note: for the xxxat() versions of these functions, we assume that the
406168404Spjd * starting vp is always rootdir (which is true for spa_directory.c, the only
407168404Spjd * ZFS consumer of these interfaces).  We assert this is true, and then emulate
408168404Spjd * them by adding '/' in front of the path.
409168404Spjd */
410168404Spjd
411168404Spjd/*ARGSUSED*/
412168404Spjdint
413168404Spjdvn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
414168404Spjd{
415168404Spjd	int fd;
416168404Spjd	vnode_t *vp;
417168404Spjd	int old_umask;
418168404Spjd	char realpath[MAXPATHLEN];
419168404Spjd	struct stat64 st;
420168404Spjd
421168404Spjd	/*
422168404Spjd	 * If we're accessing a real disk from userland, we need to use
423168404Spjd	 * the character interface to avoid caching.  This is particularly
424168404Spjd	 * important if we're trying to look at a real in-kernel storage
425168404Spjd	 * pool from userland, e.g. via zdb, because otherwise we won't
426168404Spjd	 * see the changes occurring under the segmap cache.
427168404Spjd	 * On the other hand, the stupid character device returns zero
428168404Spjd	 * for its size.  So -- gag -- we open the block device to get
429168404Spjd	 * its size, and remember it for subsequent VOP_GETATTR().
430168404Spjd	 */
431168404Spjd	if (strncmp(path, "/dev/", 5) == 0) {
432168404Spjd		char *dsk;
433168404Spjd		fd = open64(path, O_RDONLY);
434168404Spjd		if (fd == -1)
435168404Spjd			return (errno);
436168404Spjd		if (fstat64(fd, &st) == -1) {
437168404Spjd			close(fd);
438168404Spjd			return (errno);
439168404Spjd		}
440168404Spjd		close(fd);
441168404Spjd		(void) sprintf(realpath, "%s", path);
442168404Spjd		dsk = strstr(path, "/dsk/");
443168404Spjd		if (dsk != NULL)
444168404Spjd			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
445168404Spjd			    dsk + 1);
446168404Spjd	} else {
447168404Spjd		(void) sprintf(realpath, "%s", path);
448168404Spjd		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
449168404Spjd			return (errno);
450168404Spjd	}
451168404Spjd
452168404Spjd	if (flags & FCREAT)
453168404Spjd		old_umask = umask(0);
454168404Spjd
455168404Spjd	/*
456168404Spjd	 * The construct 'flags - FREAD' conveniently maps combinations of
457168404Spjd	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
458168404Spjd	 */
459168404Spjd	fd = open64(realpath, flags - FREAD, mode);
460168404Spjd
461168404Spjd	if (flags & FCREAT)
462168404Spjd		(void) umask(old_umask);
463168404Spjd
464168404Spjd	if (fd == -1)
465168404Spjd		return (errno);
466168404Spjd
467168404Spjd	if (fstat64(fd, &st) == -1) {
468168404Spjd		close(fd);
469168404Spjd		return (errno);
470168404Spjd	}
471168404Spjd
472168404Spjd	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
473168404Spjd
474168404Spjd	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
475168404Spjd
476168404Spjd	vp->v_fd = fd;
477219089Spjd	vp->v_size = st.st_size;
478168404Spjd	vp->v_path = spa_strdup(path);
479168404Spjd
480168404Spjd	return (0);
481168404Spjd}
482168404Spjd
483185029Spjd/*ARGSUSED*/
484168404Spjdint
485168404Spjdvn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
486185029Spjd    int x3, vnode_t *startvp, int fd)
487168404Spjd{
488168404Spjd	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
489168404Spjd	int ret;
490168404Spjd
491168404Spjd	ASSERT(startvp == rootdir);
492168404Spjd	(void) sprintf(realpath, "/%s", path);
493168404Spjd
494185029Spjd	/* fd ignored for now, need if want to simulate nbmand support */
495168404Spjd	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
496168404Spjd
497168404Spjd	umem_free(realpath, strlen(path) + 2);
498168404Spjd
499168404Spjd	return (ret);
500168404Spjd}
501168404Spjd
502168404Spjd/*ARGSUSED*/
503168404Spjdint
504168404Spjdvn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
505168404Spjd	int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
506168404Spjd{
507168404Spjd	ssize_t iolen, split;
508168404Spjd
509168404Spjd	if (uio == UIO_READ) {
510168404Spjd		iolen = pread64(vp->v_fd, addr, len, offset);
511168404Spjd	} else {
512168404Spjd		/*
513168404Spjd		 * To simulate partial disk writes, we split writes into two
514168404Spjd		 * system calls so that the process can be killed in between.
515168404Spjd		 */
516236884Smm		int sectors = len >> SPA_MINBLOCKSHIFT;
517236884Smm		split = (sectors > 0 ? rand() % sectors : 0) <<
518236884Smm		    SPA_MINBLOCKSHIFT;
519168404Spjd		iolen = pwrite64(vp->v_fd, addr, split, offset);
520168404Spjd		iolen += pwrite64(vp->v_fd, (char *)addr + split,
521168404Spjd		    len - split, offset + split);
522168404Spjd	}
523168404Spjd
524168404Spjd	if (iolen == -1)
525168404Spjd		return (errno);
526168404Spjd	if (residp)
527168404Spjd		*residp = len - iolen;
528168404Spjd	else if (iolen != len)
529168404Spjd		return (EIO);
530168404Spjd	return (0);
531168404Spjd}
532168404Spjd
533168404Spjdvoid
534185029Spjdvn_close(vnode_t *vp, int openflag, cred_t *cr, kthread_t *td)
535168404Spjd{
536168404Spjd	close(vp->v_fd);
537168404Spjd	spa_strfree(vp->v_path);
538168404Spjd	umem_free(vp, sizeof (vnode_t));
539168404Spjd}
540168404Spjd
541219089Spjd/*
542219089Spjd * At a minimum we need to update the size since vdev_reopen()
543219089Spjd * will no longer call vn_openat().
544219089Spjd */
545219089Spjdint
546219089Spjdfop_getattr(vnode_t *vp, vattr_t *vap)
547219089Spjd{
548219089Spjd	struct stat64 st;
549219089Spjd
550219089Spjd	if (fstat64(vp->v_fd, &st) == -1) {
551219089Spjd		close(vp->v_fd);
552219089Spjd		return (errno);
553219089Spjd	}
554219089Spjd
555219089Spjd	vap->va_size = st.st_size;
556219089Spjd	return (0);
557219089Spjd}
558219089Spjd
559168404Spjd#ifdef ZFS_DEBUG
560168404Spjd
561168404Spjd/*
562168404Spjd * =========================================================================
563168404Spjd * Figure out which debugging statements to print
564168404Spjd * =========================================================================
565168404Spjd */
566168404Spjd
567168404Spjdstatic char *dprintf_string;
568168404Spjdstatic int dprintf_print_all;
569168404Spjd
570168404Spjdint
571168404Spjddprintf_find_string(const char *string)
572168404Spjd{
573168404Spjd	char *tmp_str = dprintf_string;
574168404Spjd	int len = strlen(string);
575168404Spjd
576168404Spjd	/*
577168404Spjd	 * Find out if this is a string we want to print.
578168404Spjd	 * String format: file1.c,function_name1,file2.c,file3.c
579168404Spjd	 */
580168404Spjd
581168404Spjd	while (tmp_str != NULL) {
582168404Spjd		if (strncmp(tmp_str, string, len) == 0 &&
583168404Spjd		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
584168404Spjd			return (1);
585168404Spjd		tmp_str = strchr(tmp_str, ',');
586168404Spjd		if (tmp_str != NULL)
587168404Spjd			tmp_str++; /* Get rid of , */
588168404Spjd	}
589168404Spjd	return (0);
590168404Spjd}
591168404Spjd
592168404Spjdvoid
593168404Spjddprintf_setup(int *argc, char **argv)
594168404Spjd{
595168404Spjd	int i, j;
596168404Spjd
597168404Spjd	/*
598168404Spjd	 * Debugging can be specified two ways: by setting the
599168404Spjd	 * environment variable ZFS_DEBUG, or by including a
600168404Spjd	 * "debug=..."  argument on the command line.  The command
601168404Spjd	 * line setting overrides the environment variable.
602168404Spjd	 */
603168404Spjd
604168404Spjd	for (i = 1; i < *argc; i++) {
605168404Spjd		int len = strlen("debug=");
606168404Spjd		/* First look for a command line argument */
607168404Spjd		if (strncmp("debug=", argv[i], len) == 0) {
608168404Spjd			dprintf_string = argv[i] + len;
609168404Spjd			/* Remove from args */
610168404Spjd			for (j = i; j < *argc; j++)
611168404Spjd				argv[j] = argv[j+1];
612168404Spjd			argv[j] = NULL;
613168404Spjd			(*argc)--;
614168404Spjd		}
615168404Spjd	}
616168404Spjd
617168404Spjd	if (dprintf_string == NULL) {
618168404Spjd		/* Look for ZFS_DEBUG environment variable */
619168404Spjd		dprintf_string = getenv("ZFS_DEBUG");
620168404Spjd	}
621168404Spjd
622168404Spjd	/*
623168404Spjd	 * Are we just turning on all debugging?
624168404Spjd	 */
625168404Spjd	if (dprintf_find_string("on"))
626168404Spjd		dprintf_print_all = 1;
627168404Spjd}
628168404Spjd
629254591Sgibbsint
630254591Sgibbssysctl_handle_64(SYSCTL_HANDLER_ARGS)
631254591Sgibbs{
632254591Sgibbs	return (0);
633254591Sgibbs}
634254591Sgibbs
635168404Spjd/*
636168404Spjd * =========================================================================
637168404Spjd * debug printfs
638168404Spjd * =========================================================================
639168404Spjd */
640168404Spjdvoid
641168404Spjd__dprintf(const char *file, const char *func, int line, const char *fmt, ...)
642168404Spjd{
643168404Spjd	const char *newfile;
644168404Spjd	va_list adx;
645168404Spjd
646168404Spjd	/*
647168404Spjd	 * Get rid of annoying "../common/" prefix to filename.
648168404Spjd	 */
649168404Spjd	newfile = strrchr(file, '/');
650168404Spjd	if (newfile != NULL) {
651168404Spjd		newfile = newfile + 1; /* Get rid of leading / */
652168404Spjd	} else {
653168404Spjd		newfile = file;
654168404Spjd	}
655168404Spjd
656168404Spjd	if (dprintf_print_all ||
657168404Spjd	    dprintf_find_string(newfile) ||
658168404Spjd	    dprintf_find_string(func)) {
659168404Spjd		/* Print out just the function name if requested */
660168404Spjd		flockfile(stdout);
661168404Spjd		if (dprintf_find_string("pid"))
662168404Spjd			(void) printf("%d ", getpid());
663168404Spjd		if (dprintf_find_string("tid"))
664168404Spjd			(void) printf("%u ", thr_self());
665168404Spjd#if 0
666168404Spjd		if (dprintf_find_string("cpu"))
667168404Spjd			(void) printf("%u ", getcpuid());
668168404Spjd#endif
669168404Spjd		if (dprintf_find_string("time"))
670168404Spjd			(void) printf("%llu ", gethrtime());
671168404Spjd		if (dprintf_find_string("long"))
672168404Spjd			(void) printf("%s, line %d: ", newfile, line);
673168404Spjd		(void) printf("%s: ", func);
674168404Spjd		va_start(adx, fmt);
675168404Spjd		(void) vprintf(fmt, adx);
676168404Spjd		va_end(adx);
677168404Spjd		funlockfile(stdout);
678168404Spjd	}
679168404Spjd}
680168404Spjd
681168404Spjd#endif /* ZFS_DEBUG */
682168404Spjd
683168404Spjd/*
684168404Spjd * =========================================================================
685168404Spjd * cmn_err() and panic()
686168404Spjd * =========================================================================
687168404Spjd */
688168404Spjdstatic char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
689168404Spjdstatic char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
690168404Spjd
691168404Spjdvoid
692168404Spjdvpanic(const char *fmt, va_list adx)
693168404Spjd{
694168404Spjd	(void) fprintf(stderr, "error: ");
695168404Spjd	(void) vfprintf(stderr, fmt, adx);
696168404Spjd	(void) fprintf(stderr, "\n");
697168404Spjd
698168404Spjd	abort();	/* think of it as a "user-level crash dump" */
699168404Spjd}
700168404Spjd
701168404Spjdvoid
702168404Spjdpanic(const char *fmt, ...)
703168404Spjd{
704168404Spjd	va_list adx;
705168404Spjd
706168404Spjd	va_start(adx, fmt);
707168404Spjd	vpanic(fmt, adx);
708168404Spjd	va_end(adx);
709168404Spjd}
710168404Spjd
711168404Spjdvoid
712168404Spjdvcmn_err(int ce, const char *fmt, va_list adx)
713168404Spjd{
714168404Spjd	if (ce == CE_PANIC)
715168404Spjd		vpanic(fmt, adx);
716168404Spjd	if (ce != CE_NOTE) {	/* suppress noise in userland stress testing */
717168404Spjd		(void) fprintf(stderr, "%s", ce_prefix[ce]);
718168404Spjd		(void) vfprintf(stderr, fmt, adx);
719168404Spjd		(void) fprintf(stderr, "%s", ce_suffix[ce]);
720168404Spjd	}
721168404Spjd}
722168404Spjd
723168404Spjd/*PRINTFLIKE2*/
724168404Spjdvoid
725168404Spjdcmn_err(int ce, const char *fmt, ...)
726168404Spjd{
727168404Spjd	va_list adx;
728168404Spjd
729168404Spjd	va_start(adx, fmt);
730168404Spjd	vcmn_err(ce, fmt, adx);
731168404Spjd	va_end(adx);
732168404Spjd}
733168404Spjd
734168404Spjd/*
735168404Spjd * =========================================================================
736168404Spjd * kobj interfaces
737168404Spjd * =========================================================================
738168404Spjd */
739168404Spjdstruct _buf *
740168404Spjdkobj_open_file(char *name)
741168404Spjd{
742168404Spjd	struct _buf *file;
743168404Spjd	vnode_t *vp;
744168404Spjd
745168404Spjd	/* set vp as the _fd field of the file */
746185029Spjd	if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir,
747185029Spjd	    -1) != 0)
748168404Spjd		return ((void *)-1UL);
749168404Spjd
750168404Spjd	file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
751168404Spjd	file->_fd = (intptr_t)vp;
752168404Spjd	return (file);
753168404Spjd}
754168404Spjd
755168404Spjdint
756168404Spjdkobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
757168404Spjd{
758168404Spjd	ssize_t resid;
759168404Spjd
760168404Spjd	vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
761168404Spjd	    UIO_SYSSPACE, 0, 0, 0, &resid);
762168404Spjd
763168404Spjd	return (size - resid);
764168404Spjd}
765168404Spjd
766168404Spjdvoid
767168404Spjdkobj_close_file(struct _buf *file)
768168404Spjd{
769185029Spjd	vn_close((vnode_t *)file->_fd, 0, NULL, NULL);
770168404Spjd	umem_free(file, sizeof (struct _buf));
771168404Spjd}
772168404Spjd
773168404Spjdint
774168404Spjdkobj_get_filesize(struct _buf *file, uint64_t *size)
775168404Spjd{
776168404Spjd	struct stat64 st;
777168404Spjd	vnode_t *vp = (vnode_t *)file->_fd;
778168404Spjd
779168404Spjd	if (fstat64(vp->v_fd, &st) == -1) {
780185029Spjd		vn_close(vp, 0, NULL, NULL);
781168404Spjd		return (errno);
782168404Spjd	}
783168404Spjd	*size = st.st_size;
784168404Spjd	return (0);
785168404Spjd}
786168404Spjd
787168404Spjd/*
788168404Spjd * =========================================================================
789168404Spjd * misc routines
790168404Spjd * =========================================================================
791168404Spjd */
792168404Spjd
793168404Spjdvoid
794168404Spjddelay(clock_t ticks)
795168404Spjd{
796168404Spjd	poll(0, 0, ticks * (1000 / hz));
797168404Spjd}
798168404Spjd
799168404Spjd#if 0
800168404Spjd/*
801168404Spjd * Find highest one bit set.
802168404Spjd *	Returns bit number + 1 of highest bit that is set, otherwise returns 0.
803168404Spjd * High order bit is 31 (or 63 in _LP64 kernel).
804168404Spjd */
805168404Spjdint
806168404Spjdhighbit(ulong_t i)
807168404Spjd{
808168404Spjd	register int h = 1;
809168404Spjd
810168404Spjd	if (i == 0)
811168404Spjd		return (0);
812168404Spjd#ifdef _LP64
813168404Spjd	if (i & 0xffffffff00000000ul) {
814168404Spjd		h += 32; i >>= 32;
815168404Spjd	}
816168404Spjd#endif
817168404Spjd	if (i & 0xffff0000) {
818168404Spjd		h += 16; i >>= 16;
819168404Spjd	}
820168404Spjd	if (i & 0xff00) {
821168404Spjd		h += 8; i >>= 8;
822168404Spjd	}
823168404Spjd	if (i & 0xf0) {
824168404Spjd		h += 4; i >>= 4;
825168404Spjd	}
826168404Spjd	if (i & 0xc) {
827168404Spjd		h += 2; i >>= 2;
828168404Spjd	}
829168404Spjd	if (i & 0x2) {
830168404Spjd		h += 1;
831168404Spjd	}
832168404Spjd	return (h);
833168404Spjd}
834168404Spjd#endif
835168404Spjd
836185029Spjdstatic int random_fd = -1, urandom_fd = -1;
837185029Spjd
838168404Spjdstatic int
839185029Spjdrandom_get_bytes_common(uint8_t *ptr, size_t len, int fd)
840168404Spjd{
841168404Spjd	size_t resid = len;
842168404Spjd	ssize_t bytes;
843168404Spjd
844168404Spjd	ASSERT(fd != -1);
845168404Spjd
846168404Spjd	while (resid != 0) {
847168404Spjd		bytes = read(fd, ptr, resid);
848185029Spjd		ASSERT3S(bytes, >=, 0);
849168404Spjd		ptr += bytes;
850168404Spjd		resid -= bytes;
851168404Spjd	}
852168404Spjd
853168404Spjd	return (0);
854168404Spjd}
855168404Spjd
856168404Spjdint
857168404Spjdrandom_get_bytes(uint8_t *ptr, size_t len)
858168404Spjd{
859185029Spjd	return (random_get_bytes_common(ptr, len, random_fd));
860168404Spjd}
861168404Spjd
862168404Spjdint
863168404Spjdrandom_get_pseudo_bytes(uint8_t *ptr, size_t len)
864168404Spjd{
865185029Spjd	return (random_get_bytes_common(ptr, len, urandom_fd));
866168404Spjd}
867168404Spjd
868168498Spjdint
869168498Spjdddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result)
870168498Spjd{
871168498Spjd	char *end;
872168498Spjd
873168498Spjd	*result = strtoul(hw_serial, &end, base);
874168498Spjd	if (*result == 0)
875168498Spjd		return (errno);
876168498Spjd	return (0);
877168498Spjd}
878168498Spjd
879219089Spjdint
880219089Spjdddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result)
881219089Spjd{
882219089Spjd	char *end;
883219089Spjd
884219089Spjd	*result = strtoull(str, &end, base);
885219089Spjd	if (*result == 0)
886219089Spjd		return (errno);
887219089Spjd	return (0);
888219089Spjd}
889219089Spjd
890247265Smm#ifdef illumos
891247265Smm/* ARGSUSED */
892247265Smmcyclic_id_t
893247265Smmcyclic_add(cyc_handler_t *hdlr, cyc_time_t *when)
894247265Smm{
895247265Smm	return (1);
896247265Smm}
897247265Smm
898247265Smm/* ARGSUSED */
899247265Smmvoid
900247265Smmcyclic_remove(cyclic_id_t id)
901247265Smm{
902247265Smm}
903247265Smm
904247265Smm/* ARGSUSED */
905247265Smmint
906247265Smmcyclic_reprogram(cyclic_id_t id, hrtime_t expiration)
907247265Smm{
908247265Smm	return (1);
909247265Smm}
910247265Smm#endif
911247265Smm
912168404Spjd/*
913168404Spjd * =========================================================================
914168404Spjd * kernel emulation setup & teardown
915168404Spjd * =========================================================================
916168404Spjd */
917168404Spjdstatic int
918168404Spjdumem_out_of_memory(void)
919168404Spjd{
920168404Spjd	char errmsg[] = "out of memory -- generating core dump\n";
921168404Spjd
922168404Spjd	write(fileno(stderr), errmsg, sizeof (errmsg));
923168404Spjd	abort();
924168404Spjd	return (0);
925168404Spjd}
926168404Spjd
927168404Spjdvoid
928168404Spjdkernel_init(int mode)
929168404Spjd{
930248571Smm	extern uint_t rrw_tsd_key;
931248571Smm
932168404Spjd	umem_nofail_callback(umem_out_of_memory);
933168404Spjd
934168404Spjd	physmem = sysconf(_SC_PHYS_PAGES);
935168404Spjd
936168404Spjd	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
937168404Spjd	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
938168404Spjd
939219089Spjd	(void) snprintf(hw_serial, sizeof (hw_serial), "%lu",
940219089Spjd	    (mode & FWRITE) ? (unsigned long)gethostid() : 0);
941168498Spjd
942185029Spjd	VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1);
943185029Spjd	VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1);
944185029Spjd
945208047Smm	system_taskq_init();
946208047Smm
947247265Smm#ifdef illumos
948247265Smm	mutex_init(&cpu_lock, NULL, MUTEX_DEFAULT, NULL);
949247265Smm#endif
950247265Smm
951168404Spjd	spa_init(mode);
952248571Smm
953248571Smm	tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
954168404Spjd}
955168404Spjd
956168404Spjdvoid
957168404Spjdkernel_fini(void)
958168404Spjd{
959168404Spjd	spa_fini();
960185029Spjd
961219089Spjd	system_taskq_fini();
962219089Spjd
963185029Spjd	close(random_fd);
964185029Spjd	close(urandom_fd);
965185029Spjd
966185029Spjd	random_fd = -1;
967185029Spjd	urandom_fd = -1;
968168404Spjd}
969168404Spjd
970168404Spjdint
971168404Spjdz_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen)
972168404Spjd{
973168404Spjd	int ret;
974168404Spjd	uLongf len = *dstlen;
975168404Spjd
976168404Spjd	if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK)
977168404Spjd		*dstlen = (size_t)len;
978168404Spjd
979168404Spjd	return (ret);
980168404Spjd}
981168404Spjd
982168404Spjdint
983168404Spjdz_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen,
984168404Spjd    int level)
985168404Spjd{
986168404Spjd	int ret;
987168404Spjd	uLongf len = *dstlen;
988168404Spjd
989168404Spjd	if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK)
990168404Spjd		*dstlen = (size_t)len;
991168404Spjd
992168404Spjd	return (ret);
993168404Spjd}
994185029Spjd
995185029Spjduid_t
996185029Spjdcrgetuid(cred_t *cr)
997185029Spjd{
998185029Spjd	return (0);
999185029Spjd}
1000185029Spjd
1001248571Smmuid_t
1002248571Smmcrgetruid(cred_t *cr)
1003248571Smm{
1004248571Smm	return (0);
1005248571Smm}
1006248571Smm
1007185029Spjdgid_t
1008185029Spjdcrgetgid(cred_t *cr)
1009185029Spjd{
1010185029Spjd	return (0);
1011185029Spjd}
1012185029Spjd
1013185029Spjdint
1014185029Spjdcrgetngroups(cred_t *cr)
1015185029Spjd{
1016185029Spjd	return (0);
1017185029Spjd}
1018185029Spjd
1019185029Spjdgid_t *
1020185029Spjdcrgetgroups(cred_t *cr)
1021185029Spjd{
1022185029Spjd	return (NULL);
1023185029Spjd}
1024185029Spjd
1025185029Spjdint
1026185029Spjdzfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
1027185029Spjd{
1028185029Spjd	return (0);
1029185029Spjd}
1030185029Spjd
1031185029Spjdint
1032185029Spjdzfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
1033185029Spjd{
1034185029Spjd	return (0);
1035185029Spjd}
1036185029Spjd
1037185029Spjdint
1038185029Spjdzfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
1039185029Spjd{
1040185029Spjd	return (0);
1041185029Spjd}
1042185029Spjd
1043185029Spjdksiddomain_t *
1044185029Spjdksid_lookupdomain(const char *dom)
1045185029Spjd{
1046185029Spjd	ksiddomain_t *kd;
1047185029Spjd
1048185029Spjd	kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL);
1049185029Spjd	kd->kd_name = spa_strdup(dom);
1050185029Spjd	return (kd);
1051185029Spjd}
1052185029Spjd
1053185029Spjdvoid
1054185029Spjdksiddomain_rele(ksiddomain_t *ksid)
1055185029Spjd{
1056185029Spjd	spa_strfree(ksid->kd_name);
1057185029Spjd	umem_free(ksid, sizeof (ksiddomain_t));
1058185029Spjd}
1059219089Spjd
1060219089Spjd/*
1061219089Spjd * Do not change the length of the returned string; it must be freed
1062219089Spjd * with strfree().
1063219089Spjd */
1064219089Spjdchar *
1065219089Spjdkmem_asprintf(const char *fmt, ...)
1066219089Spjd{
1067219089Spjd	int size;
1068219089Spjd	va_list adx;
1069219089Spjd	char *buf;
1070219089Spjd
1071219089Spjd	va_start(adx, fmt);
1072219089Spjd	size = vsnprintf(NULL, 0, fmt, adx) + 1;
1073219089Spjd	va_end(adx);
1074219089Spjd
1075219089Spjd	buf = kmem_alloc(size, KM_SLEEP);
1076219089Spjd
1077219089Spjd	va_start(adx, fmt);
1078219089Spjd	size = vsnprintf(buf, size, fmt, adx);
1079219089Spjd	va_end(adx);
1080219089Spjd
1081219089Spjd	return (buf);
1082219089Spjd}
1083219089Spjd
1084219089Spjd/* ARGSUSED */
1085219089Spjdint
1086219089Spjdzfs_onexit_fd_hold(int fd, minor_t *minorp)
1087219089Spjd{
1088219089Spjd	*minorp = 0;
1089219089Spjd	return (0);
1090219089Spjd}
1091219089Spjd
1092219089Spjd/* ARGSUSED */
1093219089Spjdvoid
1094219089Spjdzfs_onexit_fd_rele(int fd)
1095219089Spjd{
1096219089Spjd}
1097219089Spjd
1098219089Spjd/* ARGSUSED */
1099219089Spjdint
1100219089Spjdzfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
1101219089Spjd    uint64_t *action_handle)
1102219089Spjd{
1103219089Spjd	return (0);
1104219089Spjd}
1105219089Spjd
1106219089Spjd/* ARGSUSED */
1107219089Spjdint
1108219089Spjdzfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire)
1109219089Spjd{
1110219089Spjd	return (0);
1111219089Spjd}
1112219089Spjd
1113219089Spjd/* ARGSUSED */
1114219089Spjdint
1115219089Spjdzfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data)
1116219089Spjd{
1117219089Spjd	return (0);
1118219089Spjd}
1119219089Spjd
1120219089Spjd#ifdef __FreeBSD__
1121219089Spjd/* ARGSUSED */
1122219089Spjdint
1123219089Spjdzvol_create_minors(const char *name)
1124219089Spjd{
1125219089Spjd	return (0);
1126219089Spjd}
1127219089Spjd#endif
1128