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