xref: /illumos-gate/usr/src/lib/libzpool/common/kernel.c (revision fa9e4066f08beec538e775443c5be79dd423fcab)
1*fa9e4066Sahrens /*
2*fa9e4066Sahrens  * CDDL HEADER START
3*fa9e4066Sahrens  *
4*fa9e4066Sahrens  * The contents of this file are subject to the terms of the
5*fa9e4066Sahrens  * Common Development and Distribution License, Version 1.0 only
6*fa9e4066Sahrens  * (the "License").  You may not use this file except in compliance
7*fa9e4066Sahrens  * with the License.
8*fa9e4066Sahrens  *
9*fa9e4066Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*fa9e4066Sahrens  * or http://www.opensolaris.org/os/licensing.
11*fa9e4066Sahrens  * See the License for the specific language governing permissions
12*fa9e4066Sahrens  * and limitations under the License.
13*fa9e4066Sahrens  *
14*fa9e4066Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
15*fa9e4066Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*fa9e4066Sahrens  * If applicable, add the following below this CDDL HEADER, with the
17*fa9e4066Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
18*fa9e4066Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
19*fa9e4066Sahrens  *
20*fa9e4066Sahrens  * CDDL HEADER END
21*fa9e4066Sahrens  */
22*fa9e4066Sahrens /*
23*fa9e4066Sahrens  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*fa9e4066Sahrens  * Use is subject to license terms.
25*fa9e4066Sahrens  */
26*fa9e4066Sahrens 
27*fa9e4066Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*fa9e4066Sahrens 
29*fa9e4066Sahrens #include <assert.h>
30*fa9e4066Sahrens #include <sys/zfs_context.h>
31*fa9e4066Sahrens #include <poll.h>
32*fa9e4066Sahrens #include <string.h>
33*fa9e4066Sahrens #include <stdio.h>
34*fa9e4066Sahrens #include <stdlib.h>
35*fa9e4066Sahrens #include <fcntl.h>
36*fa9e4066Sahrens #include <sys/stat.h>
37*fa9e4066Sahrens #include <sys/spa.h>
38*fa9e4066Sahrens #include <sys/processor.h>
39*fa9e4066Sahrens 
40*fa9e4066Sahrens /*
41*fa9e4066Sahrens  * Emulation of kernel services in userland.
42*fa9e4066Sahrens  */
43*fa9e4066Sahrens 
44*fa9e4066Sahrens uint64_t physmem;
45*fa9e4066Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234;
46*fa9e4066Sahrens 
47*fa9e4066Sahrens /*
48*fa9e4066Sahrens  * =========================================================================
49*fa9e4066Sahrens  * threads
50*fa9e4066Sahrens  * =========================================================================
51*fa9e4066Sahrens  */
52*fa9e4066Sahrens /*ARGSUSED*/
53*fa9e4066Sahrens kthread_t *
54*fa9e4066Sahrens zk_thread_create(void (*func)(), void *arg)
55*fa9e4066Sahrens {
56*fa9e4066Sahrens 	thread_t tid;
57*fa9e4066Sahrens 
58*fa9e4066Sahrens 	VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
59*fa9e4066Sahrens 	    &tid) == 0);
60*fa9e4066Sahrens 
61*fa9e4066Sahrens 	return ((void *)(uintptr_t)tid);
62*fa9e4066Sahrens }
63*fa9e4066Sahrens 
64*fa9e4066Sahrens /*
65*fa9e4066Sahrens  * =========================================================================
66*fa9e4066Sahrens  * mutexes
67*fa9e4066Sahrens  * =========================================================================
68*fa9e4066Sahrens  */
69*fa9e4066Sahrens void
70*fa9e4066Sahrens zmutex_init(kmutex_t *mp)
71*fa9e4066Sahrens {
72*fa9e4066Sahrens 	mp->m_owner = NULL;
73*fa9e4066Sahrens 	(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
74*fa9e4066Sahrens }
75*fa9e4066Sahrens 
76*fa9e4066Sahrens void
77*fa9e4066Sahrens zmutex_destroy(kmutex_t *mp)
78*fa9e4066Sahrens {
79*fa9e4066Sahrens 	ASSERT(mp->m_owner == NULL);
80*fa9e4066Sahrens 	(void) _mutex_destroy(&(mp)->m_lock);
81*fa9e4066Sahrens 	mp->m_owner = (void *)-1UL;
82*fa9e4066Sahrens }
83*fa9e4066Sahrens 
84*fa9e4066Sahrens void
85*fa9e4066Sahrens mutex_enter(kmutex_t *mp)
86*fa9e4066Sahrens {
87*fa9e4066Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
88*fa9e4066Sahrens 	ASSERT(mp->m_owner != curthread);
89*fa9e4066Sahrens 	(void) mutex_lock(&mp->m_lock);
90*fa9e4066Sahrens 	ASSERT(mp->m_owner == NULL);
91*fa9e4066Sahrens 	mp->m_owner = curthread;
92*fa9e4066Sahrens }
93*fa9e4066Sahrens 
94*fa9e4066Sahrens int
95*fa9e4066Sahrens mutex_tryenter(kmutex_t *mp)
96*fa9e4066Sahrens {
97*fa9e4066Sahrens 	ASSERT(mp->m_owner != (void *)-1UL);
98*fa9e4066Sahrens 	if (0 == mutex_trylock(&mp->m_lock)) {
99*fa9e4066Sahrens 		ASSERT(mp->m_owner == NULL);
100*fa9e4066Sahrens 		mp->m_owner = curthread;
101*fa9e4066Sahrens 		return (1);
102*fa9e4066Sahrens 	} else {
103*fa9e4066Sahrens 		return (0);
104*fa9e4066Sahrens 	}
105*fa9e4066Sahrens }
106*fa9e4066Sahrens 
107*fa9e4066Sahrens void
108*fa9e4066Sahrens mutex_exit(kmutex_t *mp)
109*fa9e4066Sahrens {
110*fa9e4066Sahrens 	ASSERT(mutex_owner(mp) == curthread);
111*fa9e4066Sahrens 	mp->m_owner = NULL;
112*fa9e4066Sahrens 	(void) mutex_unlock(&mp->m_lock);
113*fa9e4066Sahrens }
114*fa9e4066Sahrens 
115*fa9e4066Sahrens void *
116*fa9e4066Sahrens mutex_owner(kmutex_t *mp)
117*fa9e4066Sahrens {
118*fa9e4066Sahrens 	return (mp->m_owner);
119*fa9e4066Sahrens }
120*fa9e4066Sahrens 
121*fa9e4066Sahrens /*
122*fa9e4066Sahrens  * =========================================================================
123*fa9e4066Sahrens  * rwlocks
124*fa9e4066Sahrens  * =========================================================================
125*fa9e4066Sahrens  */
126*fa9e4066Sahrens /*ARGSUSED*/
127*fa9e4066Sahrens void
128*fa9e4066Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
129*fa9e4066Sahrens {
130*fa9e4066Sahrens 	rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
131*fa9e4066Sahrens 	rwlp->rw_owner = NULL;
132*fa9e4066Sahrens }
133*fa9e4066Sahrens 
134*fa9e4066Sahrens void
135*fa9e4066Sahrens rw_destroy(krwlock_t *rwlp)
136*fa9e4066Sahrens {
137*fa9e4066Sahrens 	rwlock_destroy(&rwlp->rw_lock);
138*fa9e4066Sahrens 	rwlp->rw_owner = (void *)-1UL;
139*fa9e4066Sahrens }
140*fa9e4066Sahrens 
141*fa9e4066Sahrens void
142*fa9e4066Sahrens rw_enter(krwlock_t *rwlp, krw_t rw)
143*fa9e4066Sahrens {
144*fa9e4066Sahrens 	ASSERT(!RW_LOCK_HELD(rwlp));
145*fa9e4066Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
146*fa9e4066Sahrens 	ASSERT(rwlp->rw_owner != curthread);
147*fa9e4066Sahrens 
148*fa9e4066Sahrens 	if (rw == RW_READER)
149*fa9e4066Sahrens 		(void) rw_rdlock(&rwlp->rw_lock);
150*fa9e4066Sahrens 	else
151*fa9e4066Sahrens 		(void) rw_wrlock(&rwlp->rw_lock);
152*fa9e4066Sahrens 
153*fa9e4066Sahrens 	rwlp->rw_owner = curthread;
154*fa9e4066Sahrens }
155*fa9e4066Sahrens 
156*fa9e4066Sahrens void
157*fa9e4066Sahrens rw_exit(krwlock_t *rwlp)
158*fa9e4066Sahrens {
159*fa9e4066Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
160*fa9e4066Sahrens 
161*fa9e4066Sahrens 	rwlp->rw_owner = NULL;
162*fa9e4066Sahrens 	(void) rw_unlock(&rwlp->rw_lock);
163*fa9e4066Sahrens }
164*fa9e4066Sahrens 
165*fa9e4066Sahrens int
166*fa9e4066Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw)
167*fa9e4066Sahrens {
168*fa9e4066Sahrens 	int rv;
169*fa9e4066Sahrens 
170*fa9e4066Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
171*fa9e4066Sahrens 
172*fa9e4066Sahrens 	if (rw == RW_READER)
173*fa9e4066Sahrens 		rv = rw_tryrdlock(&rwlp->rw_lock);
174*fa9e4066Sahrens 	else
175*fa9e4066Sahrens 		rv = rw_trywrlock(&rwlp->rw_lock);
176*fa9e4066Sahrens 
177*fa9e4066Sahrens 	if (rv == 0) {
178*fa9e4066Sahrens 		rwlp->rw_owner = curthread;
179*fa9e4066Sahrens 		return (1);
180*fa9e4066Sahrens 	}
181*fa9e4066Sahrens 
182*fa9e4066Sahrens 	return (0);
183*fa9e4066Sahrens }
184*fa9e4066Sahrens 
185*fa9e4066Sahrens /*ARGSUSED*/
186*fa9e4066Sahrens int
187*fa9e4066Sahrens rw_tryupgrade(krwlock_t *rwlp)
188*fa9e4066Sahrens {
189*fa9e4066Sahrens 	ASSERT(rwlp->rw_owner != (void *)-1UL);
190*fa9e4066Sahrens 
191*fa9e4066Sahrens 	return (0);
192*fa9e4066Sahrens }
193*fa9e4066Sahrens 
194*fa9e4066Sahrens /*
195*fa9e4066Sahrens  * =========================================================================
196*fa9e4066Sahrens  * condition variables
197*fa9e4066Sahrens  * =========================================================================
198*fa9e4066Sahrens  */
199*fa9e4066Sahrens /*ARGSUSED*/
200*fa9e4066Sahrens void
201*fa9e4066Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg)
202*fa9e4066Sahrens {
203*fa9e4066Sahrens 	(void) cond_init(cv, type, NULL);
204*fa9e4066Sahrens }
205*fa9e4066Sahrens 
206*fa9e4066Sahrens void
207*fa9e4066Sahrens cv_destroy(kcondvar_t *cv)
208*fa9e4066Sahrens {
209*fa9e4066Sahrens 	(void) cond_destroy(cv);
210*fa9e4066Sahrens }
211*fa9e4066Sahrens 
212*fa9e4066Sahrens void
213*fa9e4066Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp)
214*fa9e4066Sahrens {
215*fa9e4066Sahrens 	ASSERT(mutex_owner(mp) == curthread);
216*fa9e4066Sahrens 	mp->m_owner = NULL;
217*fa9e4066Sahrens 	(void) cond_wait(cv, &mp->m_lock);
218*fa9e4066Sahrens 	mp->m_owner = curthread;
219*fa9e4066Sahrens }
220*fa9e4066Sahrens 
221*fa9e4066Sahrens clock_t
222*fa9e4066Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
223*fa9e4066Sahrens {
224*fa9e4066Sahrens 	int error;
225*fa9e4066Sahrens 	timestruc_t ts;
226*fa9e4066Sahrens 	clock_t delta;
227*fa9e4066Sahrens 
228*fa9e4066Sahrens top:
229*fa9e4066Sahrens 	delta = abstime - lbolt;
230*fa9e4066Sahrens 	if (delta <= 0)
231*fa9e4066Sahrens 		return (-1);
232*fa9e4066Sahrens 
233*fa9e4066Sahrens 	ts.tv_sec = delta / hz;
234*fa9e4066Sahrens 	ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
235*fa9e4066Sahrens 
236*fa9e4066Sahrens 	ASSERT(mutex_owner(mp) == curthread);
237*fa9e4066Sahrens 	mp->m_owner = NULL;
238*fa9e4066Sahrens 	error = cond_reltimedwait(cv, &mp->m_lock, &ts);
239*fa9e4066Sahrens 	mp->m_owner = curthread;
240*fa9e4066Sahrens 
241*fa9e4066Sahrens 	if (error == ETIME)
242*fa9e4066Sahrens 		return (-1);
243*fa9e4066Sahrens 
244*fa9e4066Sahrens 	if (error == EINTR)
245*fa9e4066Sahrens 		goto top;
246*fa9e4066Sahrens 
247*fa9e4066Sahrens 	ASSERT(error == 0);
248*fa9e4066Sahrens 
249*fa9e4066Sahrens 	return (1);
250*fa9e4066Sahrens }
251*fa9e4066Sahrens 
252*fa9e4066Sahrens void
253*fa9e4066Sahrens cv_signal(kcondvar_t *cv)
254*fa9e4066Sahrens {
255*fa9e4066Sahrens 	(void) cond_signal(cv);
256*fa9e4066Sahrens }
257*fa9e4066Sahrens 
258*fa9e4066Sahrens void
259*fa9e4066Sahrens cv_broadcast(kcondvar_t *cv)
260*fa9e4066Sahrens {
261*fa9e4066Sahrens 	(void) cond_broadcast(cv);
262*fa9e4066Sahrens }
263*fa9e4066Sahrens 
264*fa9e4066Sahrens /*
265*fa9e4066Sahrens  * =========================================================================
266*fa9e4066Sahrens  * vnode operations
267*fa9e4066Sahrens  * =========================================================================
268*fa9e4066Sahrens  */
269*fa9e4066Sahrens /*
270*fa9e4066Sahrens  * Note: for the xxxat() versions of these functions, we assume that the
271*fa9e4066Sahrens  * starting vp is always rootdir (which is true for spa_directory.c, the only
272*fa9e4066Sahrens  * ZFS consumer of these interfaces).  We assert this is true, and then emulate
273*fa9e4066Sahrens  * them by adding '/' in front of the path.
274*fa9e4066Sahrens  */
275*fa9e4066Sahrens 
276*fa9e4066Sahrens /*ARGSUSED*/
277*fa9e4066Sahrens int
278*fa9e4066Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
279*fa9e4066Sahrens {
280*fa9e4066Sahrens 	int fd;
281*fa9e4066Sahrens 	vnode_t *vp;
282*fa9e4066Sahrens 	int old_umask;
283*fa9e4066Sahrens 	char realpath[MAXPATHLEN];
284*fa9e4066Sahrens 	struct stat64 st;
285*fa9e4066Sahrens 
286*fa9e4066Sahrens 	/*
287*fa9e4066Sahrens 	 * If we're accessing a real disk from userland, we need to use
288*fa9e4066Sahrens 	 * the character interface to avoid caching.  This is particularly
289*fa9e4066Sahrens 	 * important if we're trying to look at a real in-kernel storage
290*fa9e4066Sahrens 	 * pool from userland, e.g. via zdb, because otherwise we won't
291*fa9e4066Sahrens 	 * see the changes occurring under the segmap cache.
292*fa9e4066Sahrens 	 * On the other hand, the stupid character device returns zero
293*fa9e4066Sahrens 	 * for its size.  So -- gag -- we open the block device to get
294*fa9e4066Sahrens 	 * its size, and remember it for subsequent VOP_GETATTR().
295*fa9e4066Sahrens 	 */
296*fa9e4066Sahrens 	if (strncmp(path, "/dev/", 5) == 0) {
297*fa9e4066Sahrens 		char *dsk;
298*fa9e4066Sahrens 		fd = open64(path, O_RDONLY);
299*fa9e4066Sahrens 		if (fd == -1)
300*fa9e4066Sahrens 			return (errno);
301*fa9e4066Sahrens 		if (fstat64(fd, &st) == -1) {
302*fa9e4066Sahrens 			close(fd);
303*fa9e4066Sahrens 			return (errno);
304*fa9e4066Sahrens 		}
305*fa9e4066Sahrens 		close(fd);
306*fa9e4066Sahrens 		(void) sprintf(realpath, "%s", path);
307*fa9e4066Sahrens 		dsk = strstr(path, "/dsk/");
308*fa9e4066Sahrens 		if (dsk != NULL)
309*fa9e4066Sahrens 			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
310*fa9e4066Sahrens 			    dsk + 1);
311*fa9e4066Sahrens 	} else {
312*fa9e4066Sahrens 		(void) sprintf(realpath, "%s", path);
313*fa9e4066Sahrens 		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
314*fa9e4066Sahrens 			return (errno);
315*fa9e4066Sahrens 	}
316*fa9e4066Sahrens 
317*fa9e4066Sahrens 	if (flags & FCREAT)
318*fa9e4066Sahrens 		old_umask = umask(0);
319*fa9e4066Sahrens 
320*fa9e4066Sahrens 	/*
321*fa9e4066Sahrens 	 * The construct 'flags - FREAD' conveniently maps combinations of
322*fa9e4066Sahrens 	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
323*fa9e4066Sahrens 	 */
324*fa9e4066Sahrens 	fd = open64(realpath, flags - FREAD, mode);
325*fa9e4066Sahrens 
326*fa9e4066Sahrens 	if (flags & FCREAT)
327*fa9e4066Sahrens 		(void) umask(old_umask);
328*fa9e4066Sahrens 
329*fa9e4066Sahrens 	if (fd == -1)
330*fa9e4066Sahrens 		return (errno);
331*fa9e4066Sahrens 
332*fa9e4066Sahrens 	if (fstat64(fd, &st) == -1) {
333*fa9e4066Sahrens 		close(fd);
334*fa9e4066Sahrens 		return (errno);
335*fa9e4066Sahrens 	}
336*fa9e4066Sahrens 
337*fa9e4066Sahrens 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
338*fa9e4066Sahrens 
339*fa9e4066Sahrens 	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
340*fa9e4066Sahrens 
341*fa9e4066Sahrens 	vp->v_fd = fd;
342*fa9e4066Sahrens 	vp->v_size = st.st_size;
343*fa9e4066Sahrens 	vp->v_path = spa_strdup(path);
344*fa9e4066Sahrens 
345*fa9e4066Sahrens 	return (0);
346*fa9e4066Sahrens }
347*fa9e4066Sahrens 
348*fa9e4066Sahrens int
349*fa9e4066Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
350*fa9e4066Sahrens     int x3, vnode_t *startvp)
351*fa9e4066Sahrens {
352*fa9e4066Sahrens 	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
353*fa9e4066Sahrens 	int ret;
354*fa9e4066Sahrens 
355*fa9e4066Sahrens 	ASSERT(startvp == rootdir);
356*fa9e4066Sahrens 	(void) sprintf(realpath, "/%s", path);
357*fa9e4066Sahrens 
358*fa9e4066Sahrens 	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
359*fa9e4066Sahrens 
360*fa9e4066Sahrens 	umem_free(realpath, strlen(path) + 2);
361*fa9e4066Sahrens 
362*fa9e4066Sahrens 	return (ret);
363*fa9e4066Sahrens }
364*fa9e4066Sahrens 
365*fa9e4066Sahrens /*ARGSUSED*/
366*fa9e4066Sahrens int
367*fa9e4066Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
368*fa9e4066Sahrens 	int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
369*fa9e4066Sahrens {
370*fa9e4066Sahrens 	ssize_t iolen, split;
371*fa9e4066Sahrens 
372*fa9e4066Sahrens 	if (uio == UIO_READ) {
373*fa9e4066Sahrens 		iolen = pread64(vp->v_fd, addr, len, offset);
374*fa9e4066Sahrens 	} else {
375*fa9e4066Sahrens 		/*
376*fa9e4066Sahrens 		 * To simulate partial disk writes, we split writes into two
377*fa9e4066Sahrens 		 * system calls so that the process can be killed in between.
378*fa9e4066Sahrens 		 */
379*fa9e4066Sahrens 		split = (len > 0 ? rand() % len : 0);
380*fa9e4066Sahrens 		iolen = pwrite64(vp->v_fd, addr, split, offset);
381*fa9e4066Sahrens 		iolen += pwrite64(vp->v_fd, (char *)addr + split,
382*fa9e4066Sahrens 		    len - split, offset + split);
383*fa9e4066Sahrens 	}
384*fa9e4066Sahrens 
385*fa9e4066Sahrens 	if (iolen == -1)
386*fa9e4066Sahrens 		return (errno);
387*fa9e4066Sahrens 	if (residp)
388*fa9e4066Sahrens 		*residp = len - iolen;
389*fa9e4066Sahrens 	else if (iolen != len)
390*fa9e4066Sahrens 		return (EIO);
391*fa9e4066Sahrens 	return (0);
392*fa9e4066Sahrens }
393*fa9e4066Sahrens 
394*fa9e4066Sahrens void
395*fa9e4066Sahrens vn_close(vnode_t *vp)
396*fa9e4066Sahrens {
397*fa9e4066Sahrens 	close(vp->v_fd);
398*fa9e4066Sahrens 	spa_strfree(vp->v_path);
399*fa9e4066Sahrens 	umem_free(vp, sizeof (vnode_t));
400*fa9e4066Sahrens }
401*fa9e4066Sahrens 
402*fa9e4066Sahrens #ifdef ZFS_DEBUG
403*fa9e4066Sahrens 
404*fa9e4066Sahrens /*
405*fa9e4066Sahrens  * =========================================================================
406*fa9e4066Sahrens  * Figure out which debugging statements to print
407*fa9e4066Sahrens  * =========================================================================
408*fa9e4066Sahrens  */
409*fa9e4066Sahrens 
410*fa9e4066Sahrens static char *dprintf_string;
411*fa9e4066Sahrens static int dprintf_print_all;
412*fa9e4066Sahrens 
413*fa9e4066Sahrens int
414*fa9e4066Sahrens dprintf_find_string(const char *string)
415*fa9e4066Sahrens {
416*fa9e4066Sahrens 	char *tmp_str = dprintf_string;
417*fa9e4066Sahrens 	int len = strlen(string);
418*fa9e4066Sahrens 
419*fa9e4066Sahrens 	/*
420*fa9e4066Sahrens 	 * Find out if this is a string we want to print.
421*fa9e4066Sahrens 	 * String format: file1.c,function_name1,file2.c,file3.c
422*fa9e4066Sahrens 	 */
423*fa9e4066Sahrens 
424*fa9e4066Sahrens 	while (tmp_str != NULL) {
425*fa9e4066Sahrens 		if (strncmp(tmp_str, string, len) == 0 &&
426*fa9e4066Sahrens 		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
427*fa9e4066Sahrens 			return (1);
428*fa9e4066Sahrens 		tmp_str = strchr(tmp_str, ',');
429*fa9e4066Sahrens 		if (tmp_str != NULL)
430*fa9e4066Sahrens 			tmp_str++; /* Get rid of , */
431*fa9e4066Sahrens 	}
432*fa9e4066Sahrens 	return (0);
433*fa9e4066Sahrens }
434*fa9e4066Sahrens 
435*fa9e4066Sahrens void
436*fa9e4066Sahrens dprintf_setup(int *argc, char **argv)
437*fa9e4066Sahrens {
438*fa9e4066Sahrens 	int i, j;
439*fa9e4066Sahrens 
440*fa9e4066Sahrens 	/*
441*fa9e4066Sahrens 	 * Debugging can be specified two ways: by setting the
442*fa9e4066Sahrens 	 * environment variable ZFS_DEBUG, or by including a
443*fa9e4066Sahrens 	 * "debug=..."  argument on the command line.  The command
444*fa9e4066Sahrens 	 * line setting overrides the environment variable.
445*fa9e4066Sahrens 	 */
446*fa9e4066Sahrens 
447*fa9e4066Sahrens 	for (i = 1; i < *argc; i++) {
448*fa9e4066Sahrens 		int len = strlen("debug=");
449*fa9e4066Sahrens 		/* First look for a command line argument */
450*fa9e4066Sahrens 		if (strncmp("debug=", argv[i], len) == 0) {
451*fa9e4066Sahrens 			dprintf_string = argv[i] + len;
452*fa9e4066Sahrens 			/* Remove from args */
453*fa9e4066Sahrens 			for (j = i; j < *argc; j++)
454*fa9e4066Sahrens 				argv[j] = argv[j+1];
455*fa9e4066Sahrens 			argv[j] = NULL;
456*fa9e4066Sahrens 			(*argc)--;
457*fa9e4066Sahrens 		}
458*fa9e4066Sahrens 	}
459*fa9e4066Sahrens 
460*fa9e4066Sahrens 	if (dprintf_string == NULL) {
461*fa9e4066Sahrens 		/* Look for ZFS_DEBUG environment variable */
462*fa9e4066Sahrens 		dprintf_string = getenv("ZFS_DEBUG");
463*fa9e4066Sahrens 	}
464*fa9e4066Sahrens 
465*fa9e4066Sahrens 	/*
466*fa9e4066Sahrens 	 * Are we just turning on all debugging?
467*fa9e4066Sahrens 	 */
468*fa9e4066Sahrens 	if (dprintf_find_string("on"))
469*fa9e4066Sahrens 		dprintf_print_all = 1;
470*fa9e4066Sahrens }
471*fa9e4066Sahrens 
472*fa9e4066Sahrens /*
473*fa9e4066Sahrens  * =========================================================================
474*fa9e4066Sahrens  * debug printfs
475*fa9e4066Sahrens  * =========================================================================
476*fa9e4066Sahrens  */
477*fa9e4066Sahrens void
478*fa9e4066Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
479*fa9e4066Sahrens {
480*fa9e4066Sahrens 	const char *newfile;
481*fa9e4066Sahrens 	va_list adx;
482*fa9e4066Sahrens 
483*fa9e4066Sahrens 	/*
484*fa9e4066Sahrens 	 * Get rid of annoying "../common/" prefix to filename.
485*fa9e4066Sahrens 	 */
486*fa9e4066Sahrens 	newfile = strrchr(file, '/');
487*fa9e4066Sahrens 	if (newfile != NULL) {
488*fa9e4066Sahrens 		newfile = newfile + 1; /* Get rid of leading / */
489*fa9e4066Sahrens 	} else {
490*fa9e4066Sahrens 		newfile = file;
491*fa9e4066Sahrens 	}
492*fa9e4066Sahrens 
493*fa9e4066Sahrens 	if (dprintf_print_all ||
494*fa9e4066Sahrens 	    dprintf_find_string(newfile) ||
495*fa9e4066Sahrens 	    dprintf_find_string(func)) {
496*fa9e4066Sahrens 		/* Print out just the function name if requested */
497*fa9e4066Sahrens 		flockfile(stdout);
498*fa9e4066Sahrens 		if (dprintf_find_string("pid"))
499*fa9e4066Sahrens 			(void) printf("%d ", getpid());
500*fa9e4066Sahrens 		if (dprintf_find_string("tid"))
501*fa9e4066Sahrens 			(void) printf("%u ", thr_self());
502*fa9e4066Sahrens 		if (dprintf_find_string("cpu"))
503*fa9e4066Sahrens 			(void) printf("%u ", getcpuid());
504*fa9e4066Sahrens 		if (dprintf_find_string("time"))
505*fa9e4066Sahrens 			(void) printf("%llu ", gethrtime());
506*fa9e4066Sahrens 		if (dprintf_find_string("long"))
507*fa9e4066Sahrens 			(void) printf("%s, line %d: ", newfile, line);
508*fa9e4066Sahrens 		(void) printf("%s: ", func);
509*fa9e4066Sahrens 		va_start(adx, fmt);
510*fa9e4066Sahrens 		(void) vprintf(fmt, adx);
511*fa9e4066Sahrens 		va_end(adx);
512*fa9e4066Sahrens 		funlockfile(stdout);
513*fa9e4066Sahrens 	}
514*fa9e4066Sahrens }
515*fa9e4066Sahrens 
516*fa9e4066Sahrens #endif /* ZFS_DEBUG */
517*fa9e4066Sahrens 
518*fa9e4066Sahrens /*
519*fa9e4066Sahrens  * =========================================================================
520*fa9e4066Sahrens  * cmn_err() and panic()
521*fa9e4066Sahrens  * =========================================================================
522*fa9e4066Sahrens  */
523*fa9e4066Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
524*fa9e4066Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
525*fa9e4066Sahrens 
526*fa9e4066Sahrens void
527*fa9e4066Sahrens vpanic(const char *fmt, va_list adx)
528*fa9e4066Sahrens {
529*fa9e4066Sahrens 	(void) fprintf(stderr, "error: ");
530*fa9e4066Sahrens 	(void) vfprintf(stderr, fmt, adx);
531*fa9e4066Sahrens 	(void) fprintf(stderr, "\n");
532*fa9e4066Sahrens 
533*fa9e4066Sahrens 	abort();	/* think of it as a "user-level crash dump" */
534*fa9e4066Sahrens }
535*fa9e4066Sahrens 
536*fa9e4066Sahrens void
537*fa9e4066Sahrens panic(const char *fmt, ...)
538*fa9e4066Sahrens {
539*fa9e4066Sahrens 	va_list adx;
540*fa9e4066Sahrens 
541*fa9e4066Sahrens 	va_start(adx, fmt);
542*fa9e4066Sahrens 	vpanic(fmt, adx);
543*fa9e4066Sahrens 	va_end(adx);
544*fa9e4066Sahrens }
545*fa9e4066Sahrens 
546*fa9e4066Sahrens /*PRINTFLIKE2*/
547*fa9e4066Sahrens void
548*fa9e4066Sahrens cmn_err(int ce, const char *fmt, ...)
549*fa9e4066Sahrens {
550*fa9e4066Sahrens 	va_list adx;
551*fa9e4066Sahrens 
552*fa9e4066Sahrens 	va_start(adx, fmt);
553*fa9e4066Sahrens 	if (ce == CE_PANIC)
554*fa9e4066Sahrens 		vpanic(fmt, adx);
555*fa9e4066Sahrens 	if (ce != CE_NOTE) {	/* suppress noise in userland stress testing */
556*fa9e4066Sahrens 		(void) fprintf(stderr, "%s", ce_prefix[ce]);
557*fa9e4066Sahrens 		(void) vfprintf(stderr, fmt, adx);
558*fa9e4066Sahrens 		(void) fprintf(stderr, "%s", ce_suffix[ce]);
559*fa9e4066Sahrens 	}
560*fa9e4066Sahrens 	va_end(adx);
561*fa9e4066Sahrens }
562*fa9e4066Sahrens 
563*fa9e4066Sahrens /*
564*fa9e4066Sahrens  * =========================================================================
565*fa9e4066Sahrens  * misc routines
566*fa9e4066Sahrens  * =========================================================================
567*fa9e4066Sahrens  */
568*fa9e4066Sahrens 
569*fa9e4066Sahrens void
570*fa9e4066Sahrens delay(clock_t ticks)
571*fa9e4066Sahrens {
572*fa9e4066Sahrens 	poll(0, 0, ticks * (1000 / hz));
573*fa9e4066Sahrens }
574*fa9e4066Sahrens 
575*fa9e4066Sahrens /*
576*fa9e4066Sahrens  * Find highest one bit set.
577*fa9e4066Sahrens  *	Returns bit number + 1 of highest bit that is set, otherwise returns 0.
578*fa9e4066Sahrens  * High order bit is 31 (or 63 in _LP64 kernel).
579*fa9e4066Sahrens  */
580*fa9e4066Sahrens int
581*fa9e4066Sahrens highbit(ulong_t i)
582*fa9e4066Sahrens {
583*fa9e4066Sahrens 	register int h = 1;
584*fa9e4066Sahrens 
585*fa9e4066Sahrens 	if (i == 0)
586*fa9e4066Sahrens 		return (0);
587*fa9e4066Sahrens #ifdef _LP64
588*fa9e4066Sahrens 	if (i & 0xffffffff00000000ul) {
589*fa9e4066Sahrens 		h += 32; i >>= 32;
590*fa9e4066Sahrens 	}
591*fa9e4066Sahrens #endif
592*fa9e4066Sahrens 	if (i & 0xffff0000) {
593*fa9e4066Sahrens 		h += 16; i >>= 16;
594*fa9e4066Sahrens 	}
595*fa9e4066Sahrens 	if (i & 0xff00) {
596*fa9e4066Sahrens 		h += 8; i >>= 8;
597*fa9e4066Sahrens 	}
598*fa9e4066Sahrens 	if (i & 0xf0) {
599*fa9e4066Sahrens 		h += 4; i >>= 4;
600*fa9e4066Sahrens 	}
601*fa9e4066Sahrens 	if (i & 0xc) {
602*fa9e4066Sahrens 		h += 2; i >>= 2;
603*fa9e4066Sahrens 	}
604*fa9e4066Sahrens 	if (i & 0x2) {
605*fa9e4066Sahrens 		h += 1;
606*fa9e4066Sahrens 	}
607*fa9e4066Sahrens 	return (h);
608*fa9e4066Sahrens }
609*fa9e4066Sahrens 
610*fa9e4066Sahrens static int
611*fa9e4066Sahrens random_get_bytes_common(uint8_t *ptr, size_t len, char *devname)
612*fa9e4066Sahrens {
613*fa9e4066Sahrens 	int fd = open(devname, O_RDONLY);
614*fa9e4066Sahrens 	size_t resid = len;
615*fa9e4066Sahrens 	ssize_t bytes;
616*fa9e4066Sahrens 
617*fa9e4066Sahrens 	ASSERT(fd != -1);
618*fa9e4066Sahrens 
619*fa9e4066Sahrens 	while (resid != 0) {
620*fa9e4066Sahrens 		bytes = read(fd, ptr, resid);
621*fa9e4066Sahrens 		ASSERT(bytes >= 0);
622*fa9e4066Sahrens 		ptr += bytes;
623*fa9e4066Sahrens 		resid -= bytes;
624*fa9e4066Sahrens 	}
625*fa9e4066Sahrens 
626*fa9e4066Sahrens 	close(fd);
627*fa9e4066Sahrens 
628*fa9e4066Sahrens 	return (0);
629*fa9e4066Sahrens }
630*fa9e4066Sahrens 
631*fa9e4066Sahrens int
632*fa9e4066Sahrens random_get_bytes(uint8_t *ptr, size_t len)
633*fa9e4066Sahrens {
634*fa9e4066Sahrens 	return (random_get_bytes_common(ptr, len, "/dev/random"));
635*fa9e4066Sahrens }
636*fa9e4066Sahrens 
637*fa9e4066Sahrens int
638*fa9e4066Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len)
639*fa9e4066Sahrens {
640*fa9e4066Sahrens 	return (random_get_bytes_common(ptr, len, "/dev/urandom"));
641*fa9e4066Sahrens }
642*fa9e4066Sahrens 
643*fa9e4066Sahrens /*
644*fa9e4066Sahrens  * =========================================================================
645*fa9e4066Sahrens  * kernel emulation setup & teardown
646*fa9e4066Sahrens  * =========================================================================
647*fa9e4066Sahrens  */
648*fa9e4066Sahrens static int
649*fa9e4066Sahrens umem_out_of_memory(void)
650*fa9e4066Sahrens {
651*fa9e4066Sahrens 	char errmsg[] = "out of memory -- generating core dump\n";
652*fa9e4066Sahrens 
653*fa9e4066Sahrens 	write(fileno(stderr), errmsg, sizeof (errmsg));
654*fa9e4066Sahrens 	abort();
655*fa9e4066Sahrens 	return (0);
656*fa9e4066Sahrens }
657*fa9e4066Sahrens 
658*fa9e4066Sahrens void
659*fa9e4066Sahrens kernel_init(int mode)
660*fa9e4066Sahrens {
661*fa9e4066Sahrens 	umem_nofail_callback(umem_out_of_memory);
662*fa9e4066Sahrens 
663*fa9e4066Sahrens 	physmem = sysconf(_SC_PHYS_PAGES);
664*fa9e4066Sahrens 
665*fa9e4066Sahrens 	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
666*fa9e4066Sahrens 	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
667*fa9e4066Sahrens 
668*fa9e4066Sahrens 	spa_init(mode);
669*fa9e4066Sahrens }
670*fa9e4066Sahrens 
671*fa9e4066Sahrens void
672*fa9e4066Sahrens kernel_fini(void)
673*fa9e4066Sahrens {
674*fa9e4066Sahrens 	spa_fini();
675*fa9e4066Sahrens }
676