1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 5*1544Seschrock * Common Development and Distribution License (the "License"). 6*1544Seschrock * 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 /* 22*1544Seschrock * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens #include <assert.h> 29789Sahrens #include <sys/zfs_context.h> 30789Sahrens #include <poll.h> 31789Sahrens #include <string.h> 32789Sahrens #include <stdio.h> 33789Sahrens #include <stdlib.h> 34789Sahrens #include <fcntl.h> 35789Sahrens #include <sys/stat.h> 36789Sahrens #include <sys/spa.h> 37789Sahrens #include <sys/processor.h> 38789Sahrens 39789Sahrens /* 40789Sahrens * Emulation of kernel services in userland. 41789Sahrens */ 42789Sahrens 43789Sahrens uint64_t physmem; 44789Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234; 45*1544Seschrock int modrootloaded = 0; 46789Sahrens 47789Sahrens /* 48789Sahrens * ========================================================================= 49789Sahrens * threads 50789Sahrens * ========================================================================= 51789Sahrens */ 52789Sahrens /*ARGSUSED*/ 53789Sahrens kthread_t * 54789Sahrens zk_thread_create(void (*func)(), void *arg) 55789Sahrens { 56789Sahrens thread_t tid; 57789Sahrens 58789Sahrens VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED, 59789Sahrens &tid) == 0); 60789Sahrens 61789Sahrens return ((void *)(uintptr_t)tid); 62789Sahrens } 63789Sahrens 64789Sahrens /* 65789Sahrens * ========================================================================= 66789Sahrens * mutexes 67789Sahrens * ========================================================================= 68789Sahrens */ 69789Sahrens void 70789Sahrens zmutex_init(kmutex_t *mp) 71789Sahrens { 72789Sahrens mp->m_owner = NULL; 73789Sahrens (void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL); 74789Sahrens } 75789Sahrens 76789Sahrens void 77789Sahrens zmutex_destroy(kmutex_t *mp) 78789Sahrens { 79789Sahrens ASSERT(mp->m_owner == NULL); 80789Sahrens (void) _mutex_destroy(&(mp)->m_lock); 81789Sahrens mp->m_owner = (void *)-1UL; 82789Sahrens } 83789Sahrens 84789Sahrens void 85789Sahrens mutex_enter(kmutex_t *mp) 86789Sahrens { 87789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 88789Sahrens ASSERT(mp->m_owner != curthread); 89789Sahrens (void) mutex_lock(&mp->m_lock); 90789Sahrens ASSERT(mp->m_owner == NULL); 91789Sahrens mp->m_owner = curthread; 92789Sahrens } 93789Sahrens 94789Sahrens int 95789Sahrens mutex_tryenter(kmutex_t *mp) 96789Sahrens { 97789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 98789Sahrens if (0 == mutex_trylock(&mp->m_lock)) { 99789Sahrens ASSERT(mp->m_owner == NULL); 100789Sahrens mp->m_owner = curthread; 101789Sahrens return (1); 102789Sahrens } else { 103789Sahrens return (0); 104789Sahrens } 105789Sahrens } 106789Sahrens 107789Sahrens void 108789Sahrens mutex_exit(kmutex_t *mp) 109789Sahrens { 110789Sahrens ASSERT(mutex_owner(mp) == curthread); 111789Sahrens mp->m_owner = NULL; 112789Sahrens (void) mutex_unlock(&mp->m_lock); 113789Sahrens } 114789Sahrens 115789Sahrens void * 116789Sahrens mutex_owner(kmutex_t *mp) 117789Sahrens { 118789Sahrens return (mp->m_owner); 119789Sahrens } 120789Sahrens 121789Sahrens /* 122789Sahrens * ========================================================================= 123789Sahrens * rwlocks 124789Sahrens * ========================================================================= 125789Sahrens */ 126789Sahrens /*ARGSUSED*/ 127789Sahrens void 128789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg) 129789Sahrens { 130789Sahrens rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL); 131789Sahrens rwlp->rw_owner = NULL; 132789Sahrens } 133789Sahrens 134789Sahrens void 135789Sahrens rw_destroy(krwlock_t *rwlp) 136789Sahrens { 137789Sahrens rwlock_destroy(&rwlp->rw_lock); 138789Sahrens rwlp->rw_owner = (void *)-1UL; 139789Sahrens } 140789Sahrens 141789Sahrens void 142789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw) 143789Sahrens { 144789Sahrens ASSERT(!RW_LOCK_HELD(rwlp)); 145789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 146789Sahrens ASSERT(rwlp->rw_owner != curthread); 147789Sahrens 148789Sahrens if (rw == RW_READER) 149789Sahrens (void) rw_rdlock(&rwlp->rw_lock); 150789Sahrens else 151789Sahrens (void) rw_wrlock(&rwlp->rw_lock); 152789Sahrens 153789Sahrens rwlp->rw_owner = curthread; 154789Sahrens } 155789Sahrens 156789Sahrens void 157789Sahrens rw_exit(krwlock_t *rwlp) 158789Sahrens { 159789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 160789Sahrens 161789Sahrens rwlp->rw_owner = NULL; 162789Sahrens (void) rw_unlock(&rwlp->rw_lock); 163789Sahrens } 164789Sahrens 165789Sahrens int 166789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw) 167789Sahrens { 168789Sahrens int rv; 169789Sahrens 170789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 171789Sahrens 172789Sahrens if (rw == RW_READER) 173789Sahrens rv = rw_tryrdlock(&rwlp->rw_lock); 174789Sahrens else 175789Sahrens rv = rw_trywrlock(&rwlp->rw_lock); 176789Sahrens 177789Sahrens if (rv == 0) { 178789Sahrens rwlp->rw_owner = curthread; 179789Sahrens return (1); 180789Sahrens } 181789Sahrens 182789Sahrens return (0); 183789Sahrens } 184789Sahrens 185789Sahrens /*ARGSUSED*/ 186789Sahrens int 187789Sahrens rw_tryupgrade(krwlock_t *rwlp) 188789Sahrens { 189789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 190789Sahrens 191789Sahrens return (0); 192789Sahrens } 193789Sahrens 194789Sahrens /* 195789Sahrens * ========================================================================= 196789Sahrens * condition variables 197789Sahrens * ========================================================================= 198789Sahrens */ 199789Sahrens /*ARGSUSED*/ 200789Sahrens void 201789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg) 202789Sahrens { 203789Sahrens (void) cond_init(cv, type, NULL); 204789Sahrens } 205789Sahrens 206789Sahrens void 207789Sahrens cv_destroy(kcondvar_t *cv) 208789Sahrens { 209789Sahrens (void) cond_destroy(cv); 210789Sahrens } 211789Sahrens 212789Sahrens void 213789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp) 214789Sahrens { 215789Sahrens ASSERT(mutex_owner(mp) == curthread); 216789Sahrens mp->m_owner = NULL; 217789Sahrens (void) cond_wait(cv, &mp->m_lock); 218789Sahrens mp->m_owner = curthread; 219789Sahrens } 220789Sahrens 221789Sahrens clock_t 222789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) 223789Sahrens { 224789Sahrens int error; 225789Sahrens timestruc_t ts; 226789Sahrens clock_t delta; 227789Sahrens 228789Sahrens top: 229789Sahrens delta = abstime - lbolt; 230789Sahrens if (delta <= 0) 231789Sahrens return (-1); 232789Sahrens 233789Sahrens ts.tv_sec = delta / hz; 234789Sahrens ts.tv_nsec = (delta % hz) * (NANOSEC / hz); 235789Sahrens 236789Sahrens ASSERT(mutex_owner(mp) == curthread); 237789Sahrens mp->m_owner = NULL; 238789Sahrens error = cond_reltimedwait(cv, &mp->m_lock, &ts); 239789Sahrens mp->m_owner = curthread; 240789Sahrens 241789Sahrens if (error == ETIME) 242789Sahrens return (-1); 243789Sahrens 244789Sahrens if (error == EINTR) 245789Sahrens goto top; 246789Sahrens 247789Sahrens ASSERT(error == 0); 248789Sahrens 249789Sahrens return (1); 250789Sahrens } 251789Sahrens 252789Sahrens void 253789Sahrens cv_signal(kcondvar_t *cv) 254789Sahrens { 255789Sahrens (void) cond_signal(cv); 256789Sahrens } 257789Sahrens 258789Sahrens void 259789Sahrens cv_broadcast(kcondvar_t *cv) 260789Sahrens { 261789Sahrens (void) cond_broadcast(cv); 262789Sahrens } 263789Sahrens 264789Sahrens /* 265789Sahrens * ========================================================================= 266789Sahrens * vnode operations 267789Sahrens * ========================================================================= 268789Sahrens */ 269789Sahrens /* 270789Sahrens * Note: for the xxxat() versions of these functions, we assume that the 271789Sahrens * starting vp is always rootdir (which is true for spa_directory.c, the only 272789Sahrens * ZFS consumer of these interfaces). We assert this is true, and then emulate 273789Sahrens * them by adding '/' in front of the path. 274789Sahrens */ 275789Sahrens 276789Sahrens /*ARGSUSED*/ 277789Sahrens int 278789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) 279789Sahrens { 280789Sahrens int fd; 281789Sahrens vnode_t *vp; 282789Sahrens int old_umask; 283789Sahrens char realpath[MAXPATHLEN]; 284789Sahrens struct stat64 st; 285789Sahrens 286789Sahrens /* 287789Sahrens * If we're accessing a real disk from userland, we need to use 288789Sahrens * the character interface to avoid caching. This is particularly 289789Sahrens * important if we're trying to look at a real in-kernel storage 290789Sahrens * pool from userland, e.g. via zdb, because otherwise we won't 291789Sahrens * see the changes occurring under the segmap cache. 292789Sahrens * On the other hand, the stupid character device returns zero 293789Sahrens * for its size. So -- gag -- we open the block device to get 294789Sahrens * its size, and remember it for subsequent VOP_GETATTR(). 295789Sahrens */ 296789Sahrens if (strncmp(path, "/dev/", 5) == 0) { 297789Sahrens char *dsk; 298789Sahrens fd = open64(path, O_RDONLY); 299789Sahrens if (fd == -1) 300789Sahrens return (errno); 301789Sahrens if (fstat64(fd, &st) == -1) { 302789Sahrens close(fd); 303789Sahrens return (errno); 304789Sahrens } 305789Sahrens close(fd); 306789Sahrens (void) sprintf(realpath, "%s", path); 307789Sahrens dsk = strstr(path, "/dsk/"); 308789Sahrens if (dsk != NULL) 309789Sahrens (void) sprintf(realpath + (dsk - path) + 1, "r%s", 310789Sahrens dsk + 1); 311789Sahrens } else { 312789Sahrens (void) sprintf(realpath, "%s", path); 313789Sahrens if (!(flags & FCREAT) && stat64(realpath, &st) == -1) 314789Sahrens return (errno); 315789Sahrens } 316789Sahrens 317789Sahrens if (flags & FCREAT) 318789Sahrens old_umask = umask(0); 319789Sahrens 320789Sahrens /* 321789Sahrens * The construct 'flags - FREAD' conveniently maps combinations of 322789Sahrens * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. 323789Sahrens */ 324789Sahrens fd = open64(realpath, flags - FREAD, mode); 325789Sahrens 326789Sahrens if (flags & FCREAT) 327789Sahrens (void) umask(old_umask); 328789Sahrens 329789Sahrens if (fd == -1) 330789Sahrens return (errno); 331789Sahrens 332789Sahrens if (fstat64(fd, &st) == -1) { 333789Sahrens close(fd); 334789Sahrens return (errno); 335789Sahrens } 336789Sahrens 337789Sahrens (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 338789Sahrens 339789Sahrens *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); 340789Sahrens 341789Sahrens vp->v_fd = fd; 342789Sahrens vp->v_size = st.st_size; 343789Sahrens vp->v_path = spa_strdup(path); 344789Sahrens 345789Sahrens return (0); 346789Sahrens } 347789Sahrens 348789Sahrens int 349789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, 350789Sahrens int x3, vnode_t *startvp) 351789Sahrens { 352789Sahrens char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); 353789Sahrens int ret; 354789Sahrens 355789Sahrens ASSERT(startvp == rootdir); 356789Sahrens (void) sprintf(realpath, "/%s", path); 357789Sahrens 358789Sahrens ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); 359789Sahrens 360789Sahrens umem_free(realpath, strlen(path) + 2); 361789Sahrens 362789Sahrens return (ret); 363789Sahrens } 364789Sahrens 365789Sahrens /*ARGSUSED*/ 366789Sahrens int 367789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, 368789Sahrens int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) 369789Sahrens { 370789Sahrens ssize_t iolen, split; 371789Sahrens 372789Sahrens if (uio == UIO_READ) { 373789Sahrens iolen = pread64(vp->v_fd, addr, len, offset); 374789Sahrens } else { 375789Sahrens /* 376789Sahrens * To simulate partial disk writes, we split writes into two 377789Sahrens * system calls so that the process can be killed in between. 378789Sahrens */ 379789Sahrens split = (len > 0 ? rand() % len : 0); 380789Sahrens iolen = pwrite64(vp->v_fd, addr, split, offset); 381789Sahrens iolen += pwrite64(vp->v_fd, (char *)addr + split, 382789Sahrens len - split, offset + split); 383789Sahrens } 384789Sahrens 385789Sahrens if (iolen == -1) 386789Sahrens return (errno); 387789Sahrens if (residp) 388789Sahrens *residp = len - iolen; 389789Sahrens else if (iolen != len) 390789Sahrens return (EIO); 391789Sahrens return (0); 392789Sahrens } 393789Sahrens 394789Sahrens void 395789Sahrens vn_close(vnode_t *vp) 396789Sahrens { 397789Sahrens close(vp->v_fd); 398789Sahrens spa_strfree(vp->v_path); 399789Sahrens umem_free(vp, sizeof (vnode_t)); 400789Sahrens } 401789Sahrens 402789Sahrens #ifdef ZFS_DEBUG 403789Sahrens 404789Sahrens /* 405789Sahrens * ========================================================================= 406789Sahrens * Figure out which debugging statements to print 407789Sahrens * ========================================================================= 408789Sahrens */ 409789Sahrens 410789Sahrens static char *dprintf_string; 411789Sahrens static int dprintf_print_all; 412789Sahrens 413789Sahrens int 414789Sahrens dprintf_find_string(const char *string) 415789Sahrens { 416789Sahrens char *tmp_str = dprintf_string; 417789Sahrens int len = strlen(string); 418789Sahrens 419789Sahrens /* 420789Sahrens * Find out if this is a string we want to print. 421789Sahrens * String format: file1.c,function_name1,file2.c,file3.c 422789Sahrens */ 423789Sahrens 424789Sahrens while (tmp_str != NULL) { 425789Sahrens if (strncmp(tmp_str, string, len) == 0 && 426789Sahrens (tmp_str[len] == ',' || tmp_str[len] == '\0')) 427789Sahrens return (1); 428789Sahrens tmp_str = strchr(tmp_str, ','); 429789Sahrens if (tmp_str != NULL) 430789Sahrens tmp_str++; /* Get rid of , */ 431789Sahrens } 432789Sahrens return (0); 433789Sahrens } 434789Sahrens 435789Sahrens void 436789Sahrens dprintf_setup(int *argc, char **argv) 437789Sahrens { 438789Sahrens int i, j; 439789Sahrens 440789Sahrens /* 441789Sahrens * Debugging can be specified two ways: by setting the 442789Sahrens * environment variable ZFS_DEBUG, or by including a 443789Sahrens * "debug=..." argument on the command line. The command 444789Sahrens * line setting overrides the environment variable. 445789Sahrens */ 446789Sahrens 447789Sahrens for (i = 1; i < *argc; i++) { 448789Sahrens int len = strlen("debug="); 449789Sahrens /* First look for a command line argument */ 450789Sahrens if (strncmp("debug=", argv[i], len) == 0) { 451789Sahrens dprintf_string = argv[i] + len; 452789Sahrens /* Remove from args */ 453789Sahrens for (j = i; j < *argc; j++) 454789Sahrens argv[j] = argv[j+1]; 455789Sahrens argv[j] = NULL; 456789Sahrens (*argc)--; 457789Sahrens } 458789Sahrens } 459789Sahrens 460789Sahrens if (dprintf_string == NULL) { 461789Sahrens /* Look for ZFS_DEBUG environment variable */ 462789Sahrens dprintf_string = getenv("ZFS_DEBUG"); 463789Sahrens } 464789Sahrens 465789Sahrens /* 466789Sahrens * Are we just turning on all debugging? 467789Sahrens */ 468789Sahrens if (dprintf_find_string("on")) 469789Sahrens dprintf_print_all = 1; 470789Sahrens } 471789Sahrens 472789Sahrens /* 473789Sahrens * ========================================================================= 474789Sahrens * debug printfs 475789Sahrens * ========================================================================= 476789Sahrens */ 477789Sahrens void 478789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 479789Sahrens { 480789Sahrens const char *newfile; 481789Sahrens va_list adx; 482789Sahrens 483789Sahrens /* 484789Sahrens * Get rid of annoying "../common/" prefix to filename. 485789Sahrens */ 486789Sahrens newfile = strrchr(file, '/'); 487789Sahrens if (newfile != NULL) { 488789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 489789Sahrens } else { 490789Sahrens newfile = file; 491789Sahrens } 492789Sahrens 493789Sahrens if (dprintf_print_all || 494789Sahrens dprintf_find_string(newfile) || 495789Sahrens dprintf_find_string(func)) { 496789Sahrens /* Print out just the function name if requested */ 497789Sahrens flockfile(stdout); 498789Sahrens if (dprintf_find_string("pid")) 499789Sahrens (void) printf("%d ", getpid()); 500789Sahrens if (dprintf_find_string("tid")) 501789Sahrens (void) printf("%u ", thr_self()); 502789Sahrens if (dprintf_find_string("cpu")) 503789Sahrens (void) printf("%u ", getcpuid()); 504789Sahrens if (dprintf_find_string("time")) 505789Sahrens (void) printf("%llu ", gethrtime()); 506789Sahrens if (dprintf_find_string("long")) 507789Sahrens (void) printf("%s, line %d: ", newfile, line); 508789Sahrens (void) printf("%s: ", func); 509789Sahrens va_start(adx, fmt); 510789Sahrens (void) vprintf(fmt, adx); 511789Sahrens va_end(adx); 512789Sahrens funlockfile(stdout); 513789Sahrens } 514789Sahrens } 515789Sahrens 516789Sahrens #endif /* ZFS_DEBUG */ 517789Sahrens 518789Sahrens /* 519789Sahrens * ========================================================================= 520789Sahrens * cmn_err() and panic() 521789Sahrens * ========================================================================= 522789Sahrens */ 523789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 524789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 525789Sahrens 526789Sahrens void 527789Sahrens vpanic(const char *fmt, va_list adx) 528789Sahrens { 529789Sahrens (void) fprintf(stderr, "error: "); 530789Sahrens (void) vfprintf(stderr, fmt, adx); 531789Sahrens (void) fprintf(stderr, "\n"); 532789Sahrens 533789Sahrens abort(); /* think of it as a "user-level crash dump" */ 534789Sahrens } 535789Sahrens 536789Sahrens void 537789Sahrens panic(const char *fmt, ...) 538789Sahrens { 539789Sahrens va_list adx; 540789Sahrens 541789Sahrens va_start(adx, fmt); 542789Sahrens vpanic(fmt, adx); 543789Sahrens va_end(adx); 544789Sahrens } 545789Sahrens 546789Sahrens /*PRINTFLIKE2*/ 547789Sahrens void 548789Sahrens cmn_err(int ce, const char *fmt, ...) 549789Sahrens { 550789Sahrens va_list adx; 551789Sahrens 552789Sahrens va_start(adx, fmt); 553789Sahrens if (ce == CE_PANIC) 554789Sahrens vpanic(fmt, adx); 555789Sahrens if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ 556789Sahrens (void) fprintf(stderr, "%s", ce_prefix[ce]); 557789Sahrens (void) vfprintf(stderr, fmt, adx); 558789Sahrens (void) fprintf(stderr, "%s", ce_suffix[ce]); 559789Sahrens } 560789Sahrens va_end(adx); 561789Sahrens } 562789Sahrens 563789Sahrens /* 564789Sahrens * ========================================================================= 565*1544Seschrock * kobj interfaces 566*1544Seschrock * ========================================================================= 567*1544Seschrock */ 568*1544Seschrock struct _buf * 569*1544Seschrock kobj_open_file(char *name) 570*1544Seschrock { 571*1544Seschrock struct _buf *file; 572*1544Seschrock vnode_t *vp; 573*1544Seschrock 574*1544Seschrock /* set vp as the _fd field of the file */ 575*1544Seschrock if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir) != 0) 576*1544Seschrock return ((void *)-1UL); 577*1544Seschrock 578*1544Seschrock file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 579*1544Seschrock file->_fd = (intptr_t)vp; 580*1544Seschrock return (file); 581*1544Seschrock } 582*1544Seschrock 583*1544Seschrock int 584*1544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 585*1544Seschrock { 586*1544Seschrock ssize_t resid; 587*1544Seschrock 588*1544Seschrock vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 589*1544Seschrock UIO_SYSSPACE, 0, 0, 0, &resid); 590*1544Seschrock 591*1544Seschrock return (0); 592*1544Seschrock } 593*1544Seschrock 594*1544Seschrock void 595*1544Seschrock kobj_close_file(struct _buf *file) 596*1544Seschrock { 597*1544Seschrock vn_close((vnode_t *)file->_fd); 598*1544Seschrock umem_free(file, sizeof (struct _buf)); 599*1544Seschrock } 600*1544Seschrock 601*1544Seschrock int 602*1544Seschrock kobj_fstat(intptr_t fd, struct bootstat *bst) 603*1544Seschrock { 604*1544Seschrock struct stat64 st; 605*1544Seschrock vnode_t *vp = (vnode_t *)fd; 606*1544Seschrock if (fstat64(vp->v_fd, &st) == -1) { 607*1544Seschrock vn_close(vp); 608*1544Seschrock return (errno); 609*1544Seschrock } 610*1544Seschrock bst->st_size = (uint64_t)st.st_size; 611*1544Seschrock return (0); 612*1544Seschrock } 613*1544Seschrock 614*1544Seschrock /* 615*1544Seschrock * ========================================================================= 616789Sahrens * misc routines 617789Sahrens * ========================================================================= 618789Sahrens */ 619789Sahrens 620789Sahrens void 621789Sahrens delay(clock_t ticks) 622789Sahrens { 623789Sahrens poll(0, 0, ticks * (1000 / hz)); 624789Sahrens } 625789Sahrens 626789Sahrens /* 627789Sahrens * Find highest one bit set. 628789Sahrens * Returns bit number + 1 of highest bit that is set, otherwise returns 0. 629789Sahrens * High order bit is 31 (or 63 in _LP64 kernel). 630789Sahrens */ 631789Sahrens int 632789Sahrens highbit(ulong_t i) 633789Sahrens { 634789Sahrens register int h = 1; 635789Sahrens 636789Sahrens if (i == 0) 637789Sahrens return (0); 638789Sahrens #ifdef _LP64 639789Sahrens if (i & 0xffffffff00000000ul) { 640789Sahrens h += 32; i >>= 32; 641789Sahrens } 642789Sahrens #endif 643789Sahrens if (i & 0xffff0000) { 644789Sahrens h += 16; i >>= 16; 645789Sahrens } 646789Sahrens if (i & 0xff00) { 647789Sahrens h += 8; i >>= 8; 648789Sahrens } 649789Sahrens if (i & 0xf0) { 650789Sahrens h += 4; i >>= 4; 651789Sahrens } 652789Sahrens if (i & 0xc) { 653789Sahrens h += 2; i >>= 2; 654789Sahrens } 655789Sahrens if (i & 0x2) { 656789Sahrens h += 1; 657789Sahrens } 658789Sahrens return (h); 659789Sahrens } 660789Sahrens 661789Sahrens static int 662789Sahrens random_get_bytes_common(uint8_t *ptr, size_t len, char *devname) 663789Sahrens { 664789Sahrens int fd = open(devname, O_RDONLY); 665789Sahrens size_t resid = len; 666789Sahrens ssize_t bytes; 667789Sahrens 668789Sahrens ASSERT(fd != -1); 669789Sahrens 670789Sahrens while (resid != 0) { 671789Sahrens bytes = read(fd, ptr, resid); 672789Sahrens ASSERT(bytes >= 0); 673789Sahrens ptr += bytes; 674789Sahrens resid -= bytes; 675789Sahrens } 676789Sahrens 677789Sahrens close(fd); 678789Sahrens 679789Sahrens return (0); 680789Sahrens } 681789Sahrens 682789Sahrens int 683789Sahrens random_get_bytes(uint8_t *ptr, size_t len) 684789Sahrens { 685789Sahrens return (random_get_bytes_common(ptr, len, "/dev/random")); 686789Sahrens } 687789Sahrens 688789Sahrens int 689789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len) 690789Sahrens { 691789Sahrens return (random_get_bytes_common(ptr, len, "/dev/urandom")); 692789Sahrens } 693789Sahrens 694789Sahrens /* 695789Sahrens * ========================================================================= 696789Sahrens * kernel emulation setup & teardown 697789Sahrens * ========================================================================= 698789Sahrens */ 699789Sahrens static int 700789Sahrens umem_out_of_memory(void) 701789Sahrens { 702789Sahrens char errmsg[] = "out of memory -- generating core dump\n"; 703789Sahrens 704789Sahrens write(fileno(stderr), errmsg, sizeof (errmsg)); 705789Sahrens abort(); 706789Sahrens return (0); 707789Sahrens } 708789Sahrens 709789Sahrens void 710789Sahrens kernel_init(int mode) 711789Sahrens { 712789Sahrens umem_nofail_callback(umem_out_of_memory); 713789Sahrens 714789Sahrens physmem = sysconf(_SC_PHYS_PAGES); 715789Sahrens 716789Sahrens dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 717789Sahrens (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 718789Sahrens 719789Sahrens spa_init(mode); 720789Sahrens } 721789Sahrens 722789Sahrens void 723789Sahrens kernel_fini(void) 724789Sahrens { 725789Sahrens spa_fini(); 726789Sahrens } 727