1789Sahrens /*
2789Sahrens * CDDL HEADER START
3789Sahrens *
4789Sahrens * The contents of this file are subject to the terms of the
51544Seschrock * Common Development and Distribution License (the "License").
61544Seschrock * You may not use this file except in compliance with the License.
7789Sahrens *
8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9789Sahrens * or http://www.opensolaris.org/os/licensing.
10789Sahrens * See the License for the specific language governing permissions
11789Sahrens * and limitations under the License.
12789Sahrens *
13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each
14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15789Sahrens * If applicable, add the following below this CDDL HEADER, with the
16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying
17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner]
18789Sahrens *
19789Sahrens * CDDL HEADER END
20789Sahrens */
21789Sahrens /*
2212527SChris.Kirby@oracle.com * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23789Sahrens */
24789Sahrens
25789Sahrens #include <assert.h>
263886Sahl #include <fcntl.h>
27789Sahrens #include <poll.h>
28789Sahrens #include <stdio.h>
29789Sahrens #include <stdlib.h>
303886Sahl #include <string.h>
313886Sahl #include <zlib.h>
32789Sahrens #include <sys/spa.h>
333886Sahl #include <sys/stat.h>
34789Sahrens #include <sys/processor.h>
353886Sahl #include <sys/zfs_context.h>
363886Sahl #include <sys/zmod.h>
373975Sek110237 #include <sys/utsname.h>
388662SJordan.Vaughan@Sun.com #include <sys/systeminfo.h>
392856Snd150628
40789Sahrens /*
41789Sahrens * Emulation of kernel services in userland.
42789Sahrens */
43789Sahrens
4411726SVictor.Latushkin@Sun.COM int aok;
45789Sahrens uint64_t physmem;
46789Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234;
478662SJordan.Vaughan@Sun.com char hw_serial[HW_HOSTID_LEN];
483975Sek110237
493975Sek110237 struct utsname utsname = {
503975Sek110237 "userland", "libzpool", "1", "1", "na"
513975Sek110237 };
52789Sahrens
5311173SJonathan.Adams@Sun.COM /* this only exists to have its address taken */
5411173SJonathan.Adams@Sun.COM struct proc p0;
5511173SJonathan.Adams@Sun.COM
56789Sahrens /*
57789Sahrens * =========================================================================
58789Sahrens * threads
59789Sahrens * =========================================================================
60789Sahrens */
61789Sahrens /*ARGSUSED*/
62789Sahrens kthread_t *
zk_thread_create(void (* func)(),void * arg)63789Sahrens zk_thread_create(void (*func)(), void *arg)
64789Sahrens {
65789Sahrens thread_t tid;
66789Sahrens
67789Sahrens VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED,
68789Sahrens &tid) == 0);
69789Sahrens
70789Sahrens return ((void *)(uintptr_t)tid);
71789Sahrens }
72789Sahrens
73789Sahrens /*
74789Sahrens * =========================================================================
753403Sbmc * kstats
763403Sbmc * =========================================================================
773403Sbmc */
783403Sbmc /*ARGSUSED*/
793403Sbmc kstat_t *
kstat_create(char * module,int instance,char * name,char * class,uchar_t type,ulong_t ndata,uchar_t ks_flag)803403Sbmc kstat_create(char *module, int instance, char *name, char *class,
813403Sbmc uchar_t type, ulong_t ndata, uchar_t ks_flag)
823403Sbmc {
833403Sbmc return (NULL);
843403Sbmc }
853403Sbmc
863403Sbmc /*ARGSUSED*/
873403Sbmc void
kstat_install(kstat_t * ksp)883403Sbmc kstat_install(kstat_t *ksp)
893403Sbmc {}
903403Sbmc
913403Sbmc /*ARGSUSED*/
923403Sbmc void
kstat_delete(kstat_t * ksp)933403Sbmc kstat_delete(kstat_t *ksp)
943403Sbmc {}
953403Sbmc
963403Sbmc /*
973403Sbmc * =========================================================================
98789Sahrens * mutexes
99789Sahrens * =========================================================================
100789Sahrens */
101789Sahrens void
zmutex_init(kmutex_t * mp)102789Sahrens zmutex_init(kmutex_t *mp)
103789Sahrens {
104789Sahrens mp->m_owner = NULL;
1054831Sgw25295 mp->initialized = B_TRUE;
106789Sahrens (void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
107789Sahrens }
108789Sahrens
109789Sahrens void
zmutex_destroy(kmutex_t * mp)110789Sahrens zmutex_destroy(kmutex_t *mp)
111789Sahrens {
1124831Sgw25295 ASSERT(mp->initialized == B_TRUE);
113789Sahrens ASSERT(mp->m_owner == NULL);
114789Sahrens (void) _mutex_destroy(&(mp)->m_lock);
115789Sahrens mp->m_owner = (void *)-1UL;
1164831Sgw25295 mp->initialized = B_FALSE;
117789Sahrens }
118789Sahrens
119789Sahrens void
mutex_enter(kmutex_t * mp)120789Sahrens mutex_enter(kmutex_t *mp)
121789Sahrens {
1224831Sgw25295 ASSERT(mp->initialized == B_TRUE);
123789Sahrens ASSERT(mp->m_owner != (void *)-1UL);
124789Sahrens ASSERT(mp->m_owner != curthread);
1252856Snd150628 VERIFY(mutex_lock(&mp->m_lock) == 0);
126789Sahrens ASSERT(mp->m_owner == NULL);
127789Sahrens mp->m_owner = curthread;
128789Sahrens }
129789Sahrens
130789Sahrens int
mutex_tryenter(kmutex_t * mp)131789Sahrens mutex_tryenter(kmutex_t *mp)
132789Sahrens {
1334831Sgw25295 ASSERT(mp->initialized == B_TRUE);
134789Sahrens ASSERT(mp->m_owner != (void *)-1UL);
135789Sahrens if (0 == mutex_trylock(&mp->m_lock)) {
136789Sahrens ASSERT(mp->m_owner == NULL);
137789Sahrens mp->m_owner = curthread;
138789Sahrens return (1);
139789Sahrens } else {
140789Sahrens return (0);
141789Sahrens }
142789Sahrens }
143789Sahrens
144789Sahrens void
mutex_exit(kmutex_t * mp)145789Sahrens mutex_exit(kmutex_t *mp)
146789Sahrens {
1474831Sgw25295 ASSERT(mp->initialized == B_TRUE);
148789Sahrens ASSERT(mutex_owner(mp) == curthread);
149789Sahrens mp->m_owner = NULL;
1502856Snd150628 VERIFY(mutex_unlock(&mp->m_lock) == 0);
151789Sahrens }
152789Sahrens
153789Sahrens void *
mutex_owner(kmutex_t * mp)154789Sahrens mutex_owner(kmutex_t *mp)
155789Sahrens {
1564831Sgw25295 ASSERT(mp->initialized == B_TRUE);
157789Sahrens return (mp->m_owner);
158789Sahrens }
159789Sahrens
160789Sahrens /*
161789Sahrens * =========================================================================
162789Sahrens * rwlocks
163789Sahrens * =========================================================================
164789Sahrens */
165789Sahrens /*ARGSUSED*/
166789Sahrens void
rw_init(krwlock_t * rwlp,char * name,int type,void * arg)167789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
168789Sahrens {
169789Sahrens rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
170789Sahrens rwlp->rw_owner = NULL;
1714831Sgw25295 rwlp->initialized = B_TRUE;
172789Sahrens }
173789Sahrens
174789Sahrens void
rw_destroy(krwlock_t * rwlp)175789Sahrens rw_destroy(krwlock_t *rwlp)
176789Sahrens {
177789Sahrens rwlock_destroy(&rwlp->rw_lock);
178789Sahrens rwlp->rw_owner = (void *)-1UL;
1794831Sgw25295 rwlp->initialized = B_FALSE;
180789Sahrens }
181789Sahrens
182789Sahrens void
rw_enter(krwlock_t * rwlp,krw_t rw)183789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw)
184789Sahrens {
185789Sahrens ASSERT(!RW_LOCK_HELD(rwlp));
1864831Sgw25295 ASSERT(rwlp->initialized == B_TRUE);
187789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL);
188789Sahrens ASSERT(rwlp->rw_owner != curthread);
189789Sahrens
190789Sahrens if (rw == RW_READER)
1916689Smaybee VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
192789Sahrens else
1936689Smaybee VERIFY(rw_wrlock(&rwlp->rw_lock) == 0);
194789Sahrens
195789Sahrens rwlp->rw_owner = curthread;
196789Sahrens }
197789Sahrens
198789Sahrens void
rw_exit(krwlock_t * rwlp)199789Sahrens rw_exit(krwlock_t *rwlp)
200789Sahrens {
2014831Sgw25295 ASSERT(rwlp->initialized == B_TRUE);
202789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL);
203789Sahrens
204789Sahrens rwlp->rw_owner = NULL;
2056689Smaybee VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
206789Sahrens }
207789Sahrens
208789Sahrens int
rw_tryenter(krwlock_t * rwlp,krw_t rw)209789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw)
210789Sahrens {
211789Sahrens int rv;
212789Sahrens
2134831Sgw25295 ASSERT(rwlp->initialized == B_TRUE);
214789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL);
215789Sahrens
216789Sahrens if (rw == RW_READER)
217789Sahrens rv = rw_tryrdlock(&rwlp->rw_lock);
218789Sahrens else
219789Sahrens rv = rw_trywrlock(&rwlp->rw_lock);
220789Sahrens
221789Sahrens if (rv == 0) {
222789Sahrens rwlp->rw_owner = curthread;
223789Sahrens return (1);
224789Sahrens }
225789Sahrens
226789Sahrens return (0);
227789Sahrens }
228789Sahrens
229789Sahrens /*ARGSUSED*/
230789Sahrens int
rw_tryupgrade(krwlock_t * rwlp)231789Sahrens rw_tryupgrade(krwlock_t *rwlp)
232789Sahrens {
2334831Sgw25295 ASSERT(rwlp->initialized == B_TRUE);
234789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL);
235789Sahrens
236789Sahrens return (0);
237789Sahrens }
238789Sahrens
239789Sahrens /*
240789Sahrens * =========================================================================
241789Sahrens * condition variables
242789Sahrens * =========================================================================
243789Sahrens */
244789Sahrens /*ARGSUSED*/
245789Sahrens void
cv_init(kcondvar_t * cv,char * name,int type,void * arg)246789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg)
247789Sahrens {
2482856Snd150628 VERIFY(cond_init(cv, type, NULL) == 0);
249789Sahrens }
250789Sahrens
251789Sahrens void
cv_destroy(kcondvar_t * cv)252789Sahrens cv_destroy(kcondvar_t *cv)
253789Sahrens {
2542856Snd150628 VERIFY(cond_destroy(cv) == 0);
255789Sahrens }
256789Sahrens
257789Sahrens void
cv_wait(kcondvar_t * cv,kmutex_t * mp)258789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp)
259789Sahrens {
260789Sahrens ASSERT(mutex_owner(mp) == curthread);
261789Sahrens mp->m_owner = NULL;
2622856Snd150628 int ret = cond_wait(cv, &mp->m_lock);
2632856Snd150628 VERIFY(ret == 0 || ret == EINTR);
264789Sahrens mp->m_owner = curthread;
265789Sahrens }
266789Sahrens
267789Sahrens clock_t
cv_timedwait(kcondvar_t * cv,kmutex_t * mp,clock_t abstime)268789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
269789Sahrens {
270789Sahrens int error;
271789Sahrens timestruc_t ts;
272789Sahrens clock_t delta;
273789Sahrens
274789Sahrens top:
27511066Srafael.vanoni@sun.com delta = abstime - ddi_get_lbolt();
276789Sahrens if (delta <= 0)
277789Sahrens return (-1);
278789Sahrens
279789Sahrens ts.tv_sec = delta / hz;
280789Sahrens ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
281789Sahrens
282789Sahrens ASSERT(mutex_owner(mp) == curthread);
283789Sahrens mp->m_owner = NULL;
284789Sahrens error = cond_reltimedwait(cv, &mp->m_lock, &ts);
285789Sahrens mp->m_owner = curthread;
286789Sahrens
287789Sahrens if (error == ETIME)
288789Sahrens return (-1);
289789Sahrens
290789Sahrens if (error == EINTR)
291789Sahrens goto top;
292789Sahrens
293789Sahrens ASSERT(error == 0);
294789Sahrens
295789Sahrens return (1);
296789Sahrens }
297789Sahrens
298789Sahrens void
cv_signal(kcondvar_t * cv)299789Sahrens cv_signal(kcondvar_t *cv)
300789Sahrens {
3012856Snd150628 VERIFY(cond_signal(cv) == 0);
302789Sahrens }
303789Sahrens
304789Sahrens void
cv_broadcast(kcondvar_t * cv)305789Sahrens cv_broadcast(kcondvar_t *cv)
306789Sahrens {
3072856Snd150628 VERIFY(cond_broadcast(cv) == 0);
308789Sahrens }
309789Sahrens
310789Sahrens /*
311789Sahrens * =========================================================================
312789Sahrens * vnode operations
313789Sahrens * =========================================================================
314789Sahrens */
315789Sahrens /*
316789Sahrens * Note: for the xxxat() versions of these functions, we assume that the
317789Sahrens * starting vp is always rootdir (which is true for spa_directory.c, the only
318789Sahrens * ZFS consumer of these interfaces). We assert this is true, and then emulate
319789Sahrens * them by adding '/' in front of the path.
320789Sahrens */
321789Sahrens
322789Sahrens /*ARGSUSED*/
323789Sahrens int
vn_open(char * path,int x1,int flags,int mode,vnode_t ** vpp,int x2,int x3)324789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
325789Sahrens {
326789Sahrens int fd;
327789Sahrens vnode_t *vp;
328789Sahrens int old_umask;
329789Sahrens char realpath[MAXPATHLEN];
330789Sahrens struct stat64 st;
331789Sahrens
332789Sahrens /*
333789Sahrens * If we're accessing a real disk from userland, we need to use
334789Sahrens * the character interface to avoid caching. This is particularly
335789Sahrens * important if we're trying to look at a real in-kernel storage
336789Sahrens * pool from userland, e.g. via zdb, because otherwise we won't
337789Sahrens * see the changes occurring under the segmap cache.
338789Sahrens * On the other hand, the stupid character device returns zero
339789Sahrens * for its size. So -- gag -- we open the block device to get
340789Sahrens * its size, and remember it for subsequent VOP_GETATTR().
341789Sahrens */
342789Sahrens if (strncmp(path, "/dev/", 5) == 0) {
343789Sahrens char *dsk;
344789Sahrens fd = open64(path, O_RDONLY);
345789Sahrens if (fd == -1)
346789Sahrens return (errno);
347789Sahrens if (fstat64(fd, &st) == -1) {
348789Sahrens close(fd);
349789Sahrens return (errno);
350789Sahrens }
351789Sahrens close(fd);
352789Sahrens (void) sprintf(realpath, "%s", path);
353789Sahrens dsk = strstr(path, "/dsk/");
354789Sahrens if (dsk != NULL)
355789Sahrens (void) sprintf(realpath + (dsk - path) + 1, "r%s",
356789Sahrens dsk + 1);
357789Sahrens } else {
358789Sahrens (void) sprintf(realpath, "%s", path);
359789Sahrens if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
360789Sahrens return (errno);
361789Sahrens }
362789Sahrens
363789Sahrens if (flags & FCREAT)
364789Sahrens old_umask = umask(0);
365789Sahrens
366789Sahrens /*
367789Sahrens * The construct 'flags - FREAD' conveniently maps combinations of
368789Sahrens * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
369789Sahrens */
370789Sahrens fd = open64(realpath, flags - FREAD, mode);
371789Sahrens
372789Sahrens if (flags & FCREAT)
373789Sahrens (void) umask(old_umask);
374789Sahrens
375789Sahrens if (fd == -1)
376789Sahrens return (errno);
377789Sahrens
378789Sahrens if (fstat64(fd, &st) == -1) {
379789Sahrens close(fd);
380789Sahrens return (errno);
381789Sahrens }
382789Sahrens
383789Sahrens (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
384789Sahrens
385789Sahrens *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
386789Sahrens
387789Sahrens vp->v_fd = fd;
388789Sahrens vp->v_size = st.st_size;
389789Sahrens vp->v_path = spa_strdup(path);
390789Sahrens
391789Sahrens return (0);
392789Sahrens }
393789Sahrens
3945331Samw /*ARGSUSED*/
395789Sahrens int
vn_openat(char * path,int x1,int flags,int mode,vnode_t ** vpp,int x2,int x3,vnode_t * startvp,int fd)396789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
3975331Samw int x3, vnode_t *startvp, int fd)
398789Sahrens {
399789Sahrens char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
400789Sahrens int ret;
401789Sahrens
402789Sahrens ASSERT(startvp == rootdir);
403789Sahrens (void) sprintf(realpath, "/%s", path);
404789Sahrens
4055331Samw /* fd ignored for now, need if want to simulate nbmand support */
406789Sahrens ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
407789Sahrens
408789Sahrens umem_free(realpath, strlen(path) + 2);
409789Sahrens
410789Sahrens return (ret);
411789Sahrens }
412789Sahrens
413789Sahrens /*ARGSUSED*/
414789Sahrens int
vn_rdwr(int uio,vnode_t * vp,void * addr,ssize_t len,offset_t offset,int x1,int x2,rlim64_t x3,void * x4,ssize_t * residp)415789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
416789Sahrens int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
417789Sahrens {
418789Sahrens ssize_t iolen, split;
419789Sahrens
420789Sahrens if (uio == UIO_READ) {
421789Sahrens iolen = pread64(vp->v_fd, addr, len, offset);
422789Sahrens } else {
423789Sahrens /*
424789Sahrens * To simulate partial disk writes, we split writes into two
425789Sahrens * system calls so that the process can be killed in between.
426789Sahrens */
427789Sahrens split = (len > 0 ? rand() % len : 0);
428789Sahrens iolen = pwrite64(vp->v_fd, addr, split, offset);
429789Sahrens iolen += pwrite64(vp->v_fd, (char *)addr + split,
430789Sahrens len - split, offset + split);
431789Sahrens }
432789Sahrens
433789Sahrens if (iolen == -1)
434789Sahrens return (errno);
435789Sahrens if (residp)
436789Sahrens *residp = len - iolen;
437789Sahrens else if (iolen != len)
438789Sahrens return (EIO);
439789Sahrens return (0);
440789Sahrens }
441789Sahrens
442789Sahrens void
vn_close(vnode_t * vp)443789Sahrens vn_close(vnode_t *vp)
444789Sahrens {
445789Sahrens close(vp->v_fd);
446789Sahrens spa_strfree(vp->v_path);
447789Sahrens umem_free(vp, sizeof (vnode_t));
448789Sahrens }
449789Sahrens
45010850SGeorge.Wilson@Sun.COM /*
45110850SGeorge.Wilson@Sun.COM * At a minimum we need to update the size since vdev_reopen()
45210850SGeorge.Wilson@Sun.COM * will no longer call vn_openat().
45310850SGeorge.Wilson@Sun.COM */
45410850SGeorge.Wilson@Sun.COM int
fop_getattr(vnode_t * vp,vattr_t * vap)45510850SGeorge.Wilson@Sun.COM fop_getattr(vnode_t *vp, vattr_t *vap)
45610850SGeorge.Wilson@Sun.COM {
45710850SGeorge.Wilson@Sun.COM struct stat64 st;
45810850SGeorge.Wilson@Sun.COM
45910850SGeorge.Wilson@Sun.COM if (fstat64(vp->v_fd, &st) == -1) {
46010850SGeorge.Wilson@Sun.COM close(vp->v_fd);
46110850SGeorge.Wilson@Sun.COM return (errno);
46210850SGeorge.Wilson@Sun.COM }
46310850SGeorge.Wilson@Sun.COM
46410850SGeorge.Wilson@Sun.COM vap->va_size = st.st_size;
46510850SGeorge.Wilson@Sun.COM return (0);
46610850SGeorge.Wilson@Sun.COM }
46710850SGeorge.Wilson@Sun.COM
468789Sahrens #ifdef ZFS_DEBUG
469789Sahrens
470789Sahrens /*
471789Sahrens * =========================================================================
472789Sahrens * Figure out which debugging statements to print
473789Sahrens * =========================================================================
474789Sahrens */
475789Sahrens
476789Sahrens static char *dprintf_string;
477789Sahrens static int dprintf_print_all;
478789Sahrens
479789Sahrens int
dprintf_find_string(const char * string)480789Sahrens dprintf_find_string(const char *string)
481789Sahrens {
482789Sahrens char *tmp_str = dprintf_string;
483789Sahrens int len = strlen(string);
484789Sahrens
485789Sahrens /*
486789Sahrens * Find out if this is a string we want to print.
487789Sahrens * String format: file1.c,function_name1,file2.c,file3.c
488789Sahrens */
489789Sahrens
490789Sahrens while (tmp_str != NULL) {
491789Sahrens if (strncmp(tmp_str, string, len) == 0 &&
492789Sahrens (tmp_str[len] == ',' || tmp_str[len] == '\0'))
493789Sahrens return (1);
494789Sahrens tmp_str = strchr(tmp_str, ',');
495789Sahrens if (tmp_str != NULL)
496789Sahrens tmp_str++; /* Get rid of , */
497789Sahrens }
498789Sahrens return (0);
499789Sahrens }
500789Sahrens
501789Sahrens void
dprintf_setup(int * argc,char ** argv)502789Sahrens dprintf_setup(int *argc, char **argv)
503789Sahrens {
504789Sahrens int i, j;
505789Sahrens
506789Sahrens /*
507789Sahrens * Debugging can be specified two ways: by setting the
508789Sahrens * environment variable ZFS_DEBUG, or by including a
509789Sahrens * "debug=..." argument on the command line. The command
510789Sahrens * line setting overrides the environment variable.
511789Sahrens */
512789Sahrens
513789Sahrens for (i = 1; i < *argc; i++) {
514789Sahrens int len = strlen("debug=");
515789Sahrens /* First look for a command line argument */
516789Sahrens if (strncmp("debug=", argv[i], len) == 0) {
517789Sahrens dprintf_string = argv[i] + len;
518789Sahrens /* Remove from args */
519789Sahrens for (j = i; j < *argc; j++)
520789Sahrens argv[j] = argv[j+1];
521789Sahrens argv[j] = NULL;
522789Sahrens (*argc)--;
523789Sahrens }
524789Sahrens }
525789Sahrens
526789Sahrens if (dprintf_string == NULL) {
527789Sahrens /* Look for ZFS_DEBUG environment variable */
528789Sahrens dprintf_string = getenv("ZFS_DEBUG");
529789Sahrens }
530789Sahrens
531789Sahrens /*
532789Sahrens * Are we just turning on all debugging?
533789Sahrens */
534789Sahrens if (dprintf_find_string("on"))
535789Sahrens dprintf_print_all = 1;
536789Sahrens }
537789Sahrens
538789Sahrens /*
539789Sahrens * =========================================================================
540789Sahrens * debug printfs
541789Sahrens * =========================================================================
542789Sahrens */
543789Sahrens void
__dprintf(const char * file,const char * func,int line,const char * fmt,...)544789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
545789Sahrens {
546789Sahrens const char *newfile;
547789Sahrens va_list adx;
548789Sahrens
549789Sahrens /*
550789Sahrens * Get rid of annoying "../common/" prefix to filename.
551789Sahrens */
552789Sahrens newfile = strrchr(file, '/');
553789Sahrens if (newfile != NULL) {
554789Sahrens newfile = newfile + 1; /* Get rid of leading / */
555789Sahrens } else {
556789Sahrens newfile = file;
557789Sahrens }
558789Sahrens
559789Sahrens if (dprintf_print_all ||
560789Sahrens dprintf_find_string(newfile) ||
561789Sahrens dprintf_find_string(func)) {
562789Sahrens /* Print out just the function name if requested */
563789Sahrens flockfile(stdout);
564789Sahrens if (dprintf_find_string("pid"))
565789Sahrens (void) printf("%d ", getpid());
566789Sahrens if (dprintf_find_string("tid"))
567789Sahrens (void) printf("%u ", thr_self());
568789Sahrens if (dprintf_find_string("cpu"))
569789Sahrens (void) printf("%u ", getcpuid());
570789Sahrens if (dprintf_find_string("time"))
571789Sahrens (void) printf("%llu ", gethrtime());
572789Sahrens if (dprintf_find_string("long"))
573789Sahrens (void) printf("%s, line %d: ", newfile, line);
574789Sahrens (void) printf("%s: ", func);
575789Sahrens va_start(adx, fmt);
576789Sahrens (void) vprintf(fmt, adx);
577789Sahrens va_end(adx);
578789Sahrens funlockfile(stdout);
579789Sahrens }
580789Sahrens }
581789Sahrens
582789Sahrens #endif /* ZFS_DEBUG */
583789Sahrens
584789Sahrens /*
585789Sahrens * =========================================================================
586789Sahrens * cmn_err() and panic()
587789Sahrens * =========================================================================
588789Sahrens */
589789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
590789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
591789Sahrens
592789Sahrens void
vpanic(const char * fmt,va_list adx)593789Sahrens vpanic(const char *fmt, va_list adx)
594789Sahrens {
595789Sahrens (void) fprintf(stderr, "error: ");
596789Sahrens (void) vfprintf(stderr, fmt, adx);
597789Sahrens (void) fprintf(stderr, "\n");
598789Sahrens
599789Sahrens abort(); /* think of it as a "user-level crash dump" */
600789Sahrens }
601789Sahrens
602789Sahrens void
panic(const char * fmt,...)603789Sahrens panic(const char *fmt, ...)
604789Sahrens {
605789Sahrens va_list adx;
606789Sahrens
607789Sahrens va_start(adx, fmt);
608789Sahrens vpanic(fmt, adx);
609789Sahrens va_end(adx);
610789Sahrens }
611789Sahrens
6123713Sahrens void
vcmn_err(int ce,const char * fmt,va_list adx)6133713Sahrens vcmn_err(int ce, const char *fmt, va_list adx)
6143713Sahrens {
6153713Sahrens if (ce == CE_PANIC)
6163713Sahrens vpanic(fmt, adx);
6173713Sahrens if (ce != CE_NOTE) { /* suppress noise in userland stress testing */
6183713Sahrens (void) fprintf(stderr, "%s", ce_prefix[ce]);
6193713Sahrens (void) vfprintf(stderr, fmt, adx);
6203713Sahrens (void) fprintf(stderr, "%s", ce_suffix[ce]);
6213713Sahrens }
6223713Sahrens }
6233713Sahrens
624789Sahrens /*PRINTFLIKE2*/
625789Sahrens void
cmn_err(int ce,const char * fmt,...)626789Sahrens cmn_err(int ce, const char *fmt, ...)
627789Sahrens {
628789Sahrens va_list adx;
629789Sahrens
630789Sahrens va_start(adx, fmt);
6313713Sahrens vcmn_err(ce, fmt, adx);
632789Sahrens va_end(adx);
633789Sahrens }
634789Sahrens
635789Sahrens /*
636789Sahrens * =========================================================================
6371544Seschrock * kobj interfaces
6381544Seschrock * =========================================================================
6391544Seschrock */
6401544Seschrock struct _buf *
kobj_open_file(char * name)6411544Seschrock kobj_open_file(char *name)
6421544Seschrock {
6431544Seschrock struct _buf *file;
6441544Seschrock vnode_t *vp;
6451544Seschrock
6461544Seschrock /* set vp as the _fd field of the file */
6475331Samw if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir,
6485331Samw -1) != 0)
6491544Seschrock return ((void *)-1UL);
6501544Seschrock
6511544Seschrock file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
6521544Seschrock file->_fd = (intptr_t)vp;
6531544Seschrock return (file);
6541544Seschrock }
6551544Seschrock
6561544Seschrock int
kobj_read_file(struct _buf * file,char * buf,unsigned size,unsigned off)6571544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
6581544Seschrock {
6591544Seschrock ssize_t resid;
6601544Seschrock
6611544Seschrock vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
6621544Seschrock UIO_SYSSPACE, 0, 0, 0, &resid);
6631544Seschrock
6643912Slling return (size - resid);
6651544Seschrock }
6661544Seschrock
6671544Seschrock void
kobj_close_file(struct _buf * file)6681544Seschrock kobj_close_file(struct _buf *file)
6691544Seschrock {
6701544Seschrock vn_close((vnode_t *)file->_fd);
6711544Seschrock umem_free(file, sizeof (struct _buf));
6721544Seschrock }
6731544Seschrock
6741544Seschrock int
kobj_get_filesize(struct _buf * file,uint64_t * size)6753912Slling kobj_get_filesize(struct _buf *file, uint64_t *size)
6761544Seschrock {
6771544Seschrock struct stat64 st;
6783912Slling vnode_t *vp = (vnode_t *)file->_fd;
6793912Slling
6801544Seschrock if (fstat64(vp->v_fd, &st) == -1) {
6811544Seschrock vn_close(vp);
6821544Seschrock return (errno);
6831544Seschrock }
6843912Slling *size = st.st_size;
6851544Seschrock return (0);
6861544Seschrock }
6871544Seschrock
6881544Seschrock /*
6891544Seschrock * =========================================================================
690789Sahrens * misc routines
691789Sahrens * =========================================================================
692789Sahrens */
693789Sahrens
694789Sahrens void
delay(clock_t ticks)695789Sahrens delay(clock_t ticks)
696789Sahrens {
697789Sahrens poll(0, 0, ticks * (1000 / hz));
698789Sahrens }
699789Sahrens
700789Sahrens /*
701789Sahrens * Find highest one bit set.
702789Sahrens * Returns bit number + 1 of highest bit that is set, otherwise returns 0.
703789Sahrens * High order bit is 31 (or 63 in _LP64 kernel).
704789Sahrens */
705789Sahrens int
highbit(ulong_t i)706789Sahrens highbit(ulong_t i)
707789Sahrens {
708789Sahrens register int h = 1;
709789Sahrens
710789Sahrens if (i == 0)
711789Sahrens return (0);
712789Sahrens #ifdef _LP64
713789Sahrens if (i & 0xffffffff00000000ul) {
714789Sahrens h += 32; i >>= 32;
715789Sahrens }
716789Sahrens #endif
717789Sahrens if (i & 0xffff0000) {
718789Sahrens h += 16; i >>= 16;
719789Sahrens }
720789Sahrens if (i & 0xff00) {
721789Sahrens h += 8; i >>= 8;
722789Sahrens }
723789Sahrens if (i & 0xf0) {
724789Sahrens h += 4; i >>= 4;
725789Sahrens }
726789Sahrens if (i & 0xc) {
727789Sahrens h += 2; i >>= 2;
728789Sahrens }
729789Sahrens if (i & 0x2) {
730789Sahrens h += 1;
731789Sahrens }
732789Sahrens return (h);
733789Sahrens }
734789Sahrens
7355688Sbonwick static int random_fd = -1, urandom_fd = -1;
7365688Sbonwick
737789Sahrens static int
random_get_bytes_common(uint8_t * ptr,size_t len,int fd)7385688Sbonwick random_get_bytes_common(uint8_t *ptr, size_t len, int fd)
739789Sahrens {
740789Sahrens size_t resid = len;
741789Sahrens ssize_t bytes;
742789Sahrens
743789Sahrens ASSERT(fd != -1);
744789Sahrens
745789Sahrens while (resid != 0) {
746789Sahrens bytes = read(fd, ptr, resid);
7475688Sbonwick ASSERT3S(bytes, >=, 0);
748789Sahrens ptr += bytes;
749789Sahrens resid -= bytes;
750789Sahrens }
751789Sahrens
752789Sahrens return (0);
753789Sahrens }
754789Sahrens
755789Sahrens int
random_get_bytes(uint8_t * ptr,size_t len)756789Sahrens random_get_bytes(uint8_t *ptr, size_t len)
757789Sahrens {
7585688Sbonwick return (random_get_bytes_common(ptr, len, random_fd));
759789Sahrens }
760789Sahrens
761789Sahrens int
random_get_pseudo_bytes(uint8_t * ptr,size_t len)762789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len)
763789Sahrens {
7645688Sbonwick return (random_get_bytes_common(ptr, len, urandom_fd));
765789Sahrens }
766789Sahrens
7673975Sek110237 int
ddi_strtoul(const char * hw_serial,char ** nptr,int base,unsigned long * result)7683975Sek110237 ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result)
7693975Sek110237 {
7703975Sek110237 char *end;
7713975Sek110237
7723975Sek110237 *result = strtoul(hw_serial, &end, base);
7733975Sek110237 if (*result == 0)
7743975Sek110237 return (errno);
7753975Sek110237 return (0);
7763975Sek110237 }
7773975Sek110237
77811935SMark.Shellenbaum@Sun.COM int
ddi_strtoull(const char * str,char ** nptr,int base,u_longlong_t * result)77911935SMark.Shellenbaum@Sun.COM ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result)
78011935SMark.Shellenbaum@Sun.COM {
78111935SMark.Shellenbaum@Sun.COM char *end;
78211935SMark.Shellenbaum@Sun.COM
78311935SMark.Shellenbaum@Sun.COM *result = strtoull(str, &end, base);
78411935SMark.Shellenbaum@Sun.COM if (*result == 0)
78511935SMark.Shellenbaum@Sun.COM return (errno);
78611935SMark.Shellenbaum@Sun.COM return (0);
78711935SMark.Shellenbaum@Sun.COM }
78811935SMark.Shellenbaum@Sun.COM
789789Sahrens /*
790789Sahrens * =========================================================================
791789Sahrens * kernel emulation setup & teardown
792789Sahrens * =========================================================================
793789Sahrens */
794789Sahrens static int
umem_out_of_memory(void)795789Sahrens umem_out_of_memory(void)
796789Sahrens {
797789Sahrens char errmsg[] = "out of memory -- generating core dump\n";
798789Sahrens
799789Sahrens write(fileno(stderr), errmsg, sizeof (errmsg));
800789Sahrens abort();
801789Sahrens return (0);
802789Sahrens }
803789Sahrens
804789Sahrens void
kernel_init(int mode)805789Sahrens kernel_init(int mode)
806789Sahrens {
807789Sahrens umem_nofail_callback(umem_out_of_memory);
808789Sahrens
809789Sahrens physmem = sysconf(_SC_PHYS_PAGES);
810789Sahrens
811789Sahrens dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
812789Sahrens (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
813789Sahrens
81410858SVictor.Latushkin@Sun.COM (void) snprintf(hw_serial, sizeof (hw_serial), "%ld",
81510858SVictor.Latushkin@Sun.COM (mode & FWRITE) ? gethostid() : 0);
8163975Sek110237
8175688Sbonwick VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1);
8185688Sbonwick VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1);
8195688Sbonwick
8207837SMatthew.Ahrens@Sun.COM system_taskq_init();
8217837SMatthew.Ahrens@Sun.COM
822789Sahrens spa_init(mode);
823789Sahrens }
824789Sahrens
825789Sahrens void
kernel_fini(void)826789Sahrens kernel_fini(void)
827789Sahrens {
828789Sahrens spa_fini();
8295688Sbonwick
83010612SRicardo.M.Correia@Sun.COM system_taskq_fini();
83110612SRicardo.M.Correia@Sun.COM
8325688Sbonwick close(random_fd);
8335688Sbonwick close(urandom_fd);
8345688Sbonwick
8355688Sbonwick random_fd = -1;
8365688Sbonwick urandom_fd = -1;
837789Sahrens }
8383886Sahl
8393886Sahl int
z_uncompress(void * dst,size_t * dstlen,const void * src,size_t srclen)8403886Sahl z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen)
8413886Sahl {
8423886Sahl int ret;
8433886Sahl uLongf len = *dstlen;
8443886Sahl
8453886Sahl if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK)
8463886Sahl *dstlen = (size_t)len;
8473886Sahl
8483886Sahl return (ret);
8493886Sahl }
8503886Sahl
8513886Sahl int
z_compress_level(void * dst,size_t * dstlen,const void * src,size_t srclen,int level)8523886Sahl z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen,
8533886Sahl int level)
8543886Sahl {
8553886Sahl int ret;
8563886Sahl uLongf len = *dstlen;
8573886Sahl
8583886Sahl if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK)
8593886Sahl *dstlen = (size_t)len;
8603886Sahl
8613886Sahl return (ret);
8623886Sahl }
8634543Smarks
8644543Smarks uid_t
crgetuid(cred_t * cr)8654543Smarks crgetuid(cred_t *cr)
8664543Smarks {
8674543Smarks return (0);
8684543Smarks }
8694543Smarks
8704543Smarks gid_t
crgetgid(cred_t * cr)8714543Smarks crgetgid(cred_t *cr)
8724543Smarks {
8734543Smarks return (0);
8744543Smarks }
8754543Smarks
8764543Smarks int
crgetngroups(cred_t * cr)8774543Smarks crgetngroups(cred_t *cr)
8784543Smarks {
8794543Smarks return (0);
8804543Smarks }
8814543Smarks
8824543Smarks gid_t *
crgetgroups(cred_t * cr)8834543Smarks crgetgroups(cred_t *cr)
8844543Smarks {
8854543Smarks return (NULL);
8864543Smarks }
8874543Smarks
8884543Smarks int
zfs_secpolicy_snapshot_perms(const char * name,cred_t * cr)8894543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
8904543Smarks {
8914543Smarks return (0);
8924543Smarks }
8934543Smarks
8944543Smarks int
zfs_secpolicy_rename_perms(const char * from,const char * to,cred_t * cr)8954543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
8964543Smarks {
8974543Smarks return (0);
8984543Smarks }
8994543Smarks
9004543Smarks int
zfs_secpolicy_destroy_perms(const char * name,cred_t * cr)9014543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
9024543Smarks {
9034543Smarks return (0);
9044543Smarks }
9055959Smarks
9065959Smarks ksiddomain_t *
ksid_lookupdomain(const char * dom)9075959Smarks ksid_lookupdomain(const char *dom)
9085959Smarks {
9095959Smarks ksiddomain_t *kd;
9105959Smarks
9115959Smarks kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL);
9125959Smarks kd->kd_name = spa_strdup(dom);
9135959Smarks return (kd);
9145959Smarks }
9155959Smarks
9165959Smarks void
ksiddomain_rele(ksiddomain_t * ksid)9175959Smarks ksiddomain_rele(ksiddomain_t *ksid)
9185959Smarks {
9195959Smarks spa_strfree(ksid->kd_name);
9205959Smarks umem_free(ksid, sizeof (ksiddomain_t));
9215959Smarks }
92210272SMatthew.Ahrens@Sun.COM
92310272SMatthew.Ahrens@Sun.COM /*
92410272SMatthew.Ahrens@Sun.COM * Do not change the length of the returned string; it must be freed
92510272SMatthew.Ahrens@Sun.COM * with strfree().
92610272SMatthew.Ahrens@Sun.COM */
92710272SMatthew.Ahrens@Sun.COM char *
kmem_asprintf(const char * fmt,...)92810272SMatthew.Ahrens@Sun.COM kmem_asprintf(const char *fmt, ...)
92910272SMatthew.Ahrens@Sun.COM {
93010272SMatthew.Ahrens@Sun.COM int size;
93110272SMatthew.Ahrens@Sun.COM va_list adx;
93210272SMatthew.Ahrens@Sun.COM char *buf;
93310272SMatthew.Ahrens@Sun.COM
93410272SMatthew.Ahrens@Sun.COM va_start(adx, fmt);
93510272SMatthew.Ahrens@Sun.COM size = vsnprintf(NULL, 0, fmt, adx) + 1;
93610272SMatthew.Ahrens@Sun.COM va_end(adx);
93710272SMatthew.Ahrens@Sun.COM
93810272SMatthew.Ahrens@Sun.COM buf = kmem_alloc(size, KM_SLEEP);
93910272SMatthew.Ahrens@Sun.COM
94010272SMatthew.Ahrens@Sun.COM va_start(adx, fmt);
94110272SMatthew.Ahrens@Sun.COM size = vsnprintf(buf, size, fmt, adx);
94210272SMatthew.Ahrens@Sun.COM va_end(adx);
94310272SMatthew.Ahrens@Sun.COM
94410272SMatthew.Ahrens@Sun.COM return (buf);
94510272SMatthew.Ahrens@Sun.COM }
94612527SChris.Kirby@oracle.com
94712527SChris.Kirby@oracle.com /* ARGSUSED */
94812527SChris.Kirby@oracle.com int
zfs_onexit_fd_hold(int fd,minor_t * minorp)949*12786SChris.Kirby@oracle.com zfs_onexit_fd_hold(int fd, minor_t *minorp)
950*12786SChris.Kirby@oracle.com {
951*12786SChris.Kirby@oracle.com *minorp = 0;
952*12786SChris.Kirby@oracle.com return (0);
953*12786SChris.Kirby@oracle.com }
954*12786SChris.Kirby@oracle.com
955*12786SChris.Kirby@oracle.com /* ARGSUSED */
956*12786SChris.Kirby@oracle.com void
zfs_onexit_fd_rele(int fd)957*12786SChris.Kirby@oracle.com zfs_onexit_fd_rele(int fd)
958*12786SChris.Kirby@oracle.com {
959*12786SChris.Kirby@oracle.com }
960*12786SChris.Kirby@oracle.com
961*12786SChris.Kirby@oracle.com /* ARGSUSED */
962*12786SChris.Kirby@oracle.com int
zfs_onexit_add_cb(minor_t minor,void (* func)(void *),void * data,uint64_t * action_handle)963*12786SChris.Kirby@oracle.com zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
96412527SChris.Kirby@oracle.com uint64_t *action_handle)
96512527SChris.Kirby@oracle.com {
96612527SChris.Kirby@oracle.com return (0);
96712527SChris.Kirby@oracle.com }
96812527SChris.Kirby@oracle.com
96912527SChris.Kirby@oracle.com /* ARGSUSED */
97012527SChris.Kirby@oracle.com int
zfs_onexit_del_cb(minor_t minor,uint64_t action_handle,boolean_t fire)971*12786SChris.Kirby@oracle.com zfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire)
97212527SChris.Kirby@oracle.com {
97312527SChris.Kirby@oracle.com return (0);
97412527SChris.Kirby@oracle.com }
97512527SChris.Kirby@oracle.com
97612527SChris.Kirby@oracle.com /* ARGSUSED */
97712527SChris.Kirby@oracle.com int
zfs_onexit_cb_data(minor_t minor,uint64_t action_handle,void ** data)978*12786SChris.Kirby@oracle.com zfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data)
97912527SChris.Kirby@oracle.com {
98012527SChris.Kirby@oracle.com return (0);
98112527SChris.Kirby@oracle.com }
982