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 /* 221544Seschrock * 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 39*2856Snd150628 40789Sahrens /* 41789Sahrens * Emulation of kernel services in userland. 42789Sahrens */ 43789Sahrens 44789Sahrens uint64_t physmem; 45789Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234; 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); 89*2856Snd150628 VERIFY(mutex_lock(&mp->m_lock) == 0); 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; 112*2856Snd150628 VERIFY(mutex_unlock(&mp->m_lock) == 0); 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 { 203*2856Snd150628 VERIFY(cond_init(cv, type, NULL) == 0); 204789Sahrens } 205789Sahrens 206789Sahrens void 207789Sahrens cv_destroy(kcondvar_t *cv) 208789Sahrens { 209*2856Snd150628 VERIFY(cond_destroy(cv) == 0); 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; 217*2856Snd150628 int ret = cond_wait(cv, &mp->m_lock); 218*2856Snd150628 VERIFY(ret == 0 || ret == EINTR); 219789Sahrens mp->m_owner = curthread; 220789Sahrens } 221789Sahrens 222789Sahrens clock_t 223789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) 224789Sahrens { 225789Sahrens int error; 226789Sahrens timestruc_t ts; 227789Sahrens clock_t delta; 228789Sahrens 229789Sahrens top: 230789Sahrens delta = abstime - lbolt; 231789Sahrens if (delta <= 0) 232789Sahrens return (-1); 233789Sahrens 234789Sahrens ts.tv_sec = delta / hz; 235789Sahrens ts.tv_nsec = (delta % hz) * (NANOSEC / hz); 236789Sahrens 237789Sahrens ASSERT(mutex_owner(mp) == curthread); 238789Sahrens mp->m_owner = NULL; 239789Sahrens error = cond_reltimedwait(cv, &mp->m_lock, &ts); 240789Sahrens mp->m_owner = curthread; 241789Sahrens 242789Sahrens if (error == ETIME) 243789Sahrens return (-1); 244789Sahrens 245789Sahrens if (error == EINTR) 246789Sahrens goto top; 247789Sahrens 248789Sahrens ASSERT(error == 0); 249789Sahrens 250789Sahrens return (1); 251789Sahrens } 252789Sahrens 253789Sahrens void 254789Sahrens cv_signal(kcondvar_t *cv) 255789Sahrens { 256*2856Snd150628 VERIFY(cond_signal(cv) == 0); 257789Sahrens } 258789Sahrens 259789Sahrens void 260789Sahrens cv_broadcast(kcondvar_t *cv) 261789Sahrens { 262*2856Snd150628 VERIFY(cond_broadcast(cv) == 0); 263789Sahrens } 264789Sahrens 265789Sahrens /* 266789Sahrens * ========================================================================= 267789Sahrens * vnode operations 268789Sahrens * ========================================================================= 269789Sahrens */ 270789Sahrens /* 271789Sahrens * Note: for the xxxat() versions of these functions, we assume that the 272789Sahrens * starting vp is always rootdir (which is true for spa_directory.c, the only 273789Sahrens * ZFS consumer of these interfaces). We assert this is true, and then emulate 274789Sahrens * them by adding '/' in front of the path. 275789Sahrens */ 276789Sahrens 277789Sahrens /*ARGSUSED*/ 278789Sahrens int 279789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) 280789Sahrens { 281789Sahrens int fd; 282789Sahrens vnode_t *vp; 283789Sahrens int old_umask; 284789Sahrens char realpath[MAXPATHLEN]; 285789Sahrens struct stat64 st; 286789Sahrens 287789Sahrens /* 288789Sahrens * If we're accessing a real disk from userland, we need to use 289789Sahrens * the character interface to avoid caching. This is particularly 290789Sahrens * important if we're trying to look at a real in-kernel storage 291789Sahrens * pool from userland, e.g. via zdb, because otherwise we won't 292789Sahrens * see the changes occurring under the segmap cache. 293789Sahrens * On the other hand, the stupid character device returns zero 294789Sahrens * for its size. So -- gag -- we open the block device to get 295789Sahrens * its size, and remember it for subsequent VOP_GETATTR(). 296789Sahrens */ 297789Sahrens if (strncmp(path, "/dev/", 5) == 0) { 298789Sahrens char *dsk; 299789Sahrens fd = open64(path, O_RDONLY); 300789Sahrens if (fd == -1) 301789Sahrens return (errno); 302789Sahrens if (fstat64(fd, &st) == -1) { 303789Sahrens close(fd); 304789Sahrens return (errno); 305789Sahrens } 306789Sahrens close(fd); 307789Sahrens (void) sprintf(realpath, "%s", path); 308789Sahrens dsk = strstr(path, "/dsk/"); 309789Sahrens if (dsk != NULL) 310789Sahrens (void) sprintf(realpath + (dsk - path) + 1, "r%s", 311789Sahrens dsk + 1); 312789Sahrens } else { 313789Sahrens (void) sprintf(realpath, "%s", path); 314789Sahrens if (!(flags & FCREAT) && stat64(realpath, &st) == -1) 315789Sahrens return (errno); 316789Sahrens } 317789Sahrens 318789Sahrens if (flags & FCREAT) 319789Sahrens old_umask = umask(0); 320789Sahrens 321789Sahrens /* 322789Sahrens * The construct 'flags - FREAD' conveniently maps combinations of 323789Sahrens * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. 324789Sahrens */ 325789Sahrens fd = open64(realpath, flags - FREAD, mode); 326789Sahrens 327789Sahrens if (flags & FCREAT) 328789Sahrens (void) umask(old_umask); 329789Sahrens 330789Sahrens if (fd == -1) 331789Sahrens return (errno); 332789Sahrens 333789Sahrens if (fstat64(fd, &st) == -1) { 334789Sahrens close(fd); 335789Sahrens return (errno); 336789Sahrens } 337789Sahrens 338789Sahrens (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 339789Sahrens 340789Sahrens *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); 341789Sahrens 342789Sahrens vp->v_fd = fd; 343789Sahrens vp->v_size = st.st_size; 344789Sahrens vp->v_path = spa_strdup(path); 345789Sahrens 346789Sahrens return (0); 347789Sahrens } 348789Sahrens 349789Sahrens int 350789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, 351789Sahrens int x3, vnode_t *startvp) 352789Sahrens { 353789Sahrens char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); 354789Sahrens int ret; 355789Sahrens 356789Sahrens ASSERT(startvp == rootdir); 357789Sahrens (void) sprintf(realpath, "/%s", path); 358789Sahrens 359789Sahrens ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); 360789Sahrens 361789Sahrens umem_free(realpath, strlen(path) + 2); 362789Sahrens 363789Sahrens return (ret); 364789Sahrens } 365789Sahrens 366789Sahrens /*ARGSUSED*/ 367789Sahrens int 368789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, 369789Sahrens int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) 370789Sahrens { 371789Sahrens ssize_t iolen, split; 372789Sahrens 373789Sahrens if (uio == UIO_READ) { 374789Sahrens iolen = pread64(vp->v_fd, addr, len, offset); 375789Sahrens } else { 376789Sahrens /* 377789Sahrens * To simulate partial disk writes, we split writes into two 378789Sahrens * system calls so that the process can be killed in between. 379789Sahrens */ 380789Sahrens split = (len > 0 ? rand() % len : 0); 381789Sahrens iolen = pwrite64(vp->v_fd, addr, split, offset); 382789Sahrens iolen += pwrite64(vp->v_fd, (char *)addr + split, 383789Sahrens len - split, offset + split); 384789Sahrens } 385789Sahrens 386789Sahrens if (iolen == -1) 387789Sahrens return (errno); 388789Sahrens if (residp) 389789Sahrens *residp = len - iolen; 390789Sahrens else if (iolen != len) 391789Sahrens return (EIO); 392789Sahrens return (0); 393789Sahrens } 394789Sahrens 395789Sahrens void 396789Sahrens vn_close(vnode_t *vp) 397789Sahrens { 398789Sahrens close(vp->v_fd); 399789Sahrens spa_strfree(vp->v_path); 400789Sahrens umem_free(vp, sizeof (vnode_t)); 401789Sahrens } 402789Sahrens 403789Sahrens #ifdef ZFS_DEBUG 404789Sahrens 405789Sahrens /* 406789Sahrens * ========================================================================= 407789Sahrens * Figure out which debugging statements to print 408789Sahrens * ========================================================================= 409789Sahrens */ 410789Sahrens 411789Sahrens static char *dprintf_string; 412789Sahrens static int dprintf_print_all; 413789Sahrens 414789Sahrens int 415789Sahrens dprintf_find_string(const char *string) 416789Sahrens { 417789Sahrens char *tmp_str = dprintf_string; 418789Sahrens int len = strlen(string); 419789Sahrens 420789Sahrens /* 421789Sahrens * Find out if this is a string we want to print. 422789Sahrens * String format: file1.c,function_name1,file2.c,file3.c 423789Sahrens */ 424789Sahrens 425789Sahrens while (tmp_str != NULL) { 426789Sahrens if (strncmp(tmp_str, string, len) == 0 && 427789Sahrens (tmp_str[len] == ',' || tmp_str[len] == '\0')) 428789Sahrens return (1); 429789Sahrens tmp_str = strchr(tmp_str, ','); 430789Sahrens if (tmp_str != NULL) 431789Sahrens tmp_str++; /* Get rid of , */ 432789Sahrens } 433789Sahrens return (0); 434789Sahrens } 435789Sahrens 436789Sahrens void 437789Sahrens dprintf_setup(int *argc, char **argv) 438789Sahrens { 439789Sahrens int i, j; 440789Sahrens 441789Sahrens /* 442789Sahrens * Debugging can be specified two ways: by setting the 443789Sahrens * environment variable ZFS_DEBUG, or by including a 444789Sahrens * "debug=..." argument on the command line. The command 445789Sahrens * line setting overrides the environment variable. 446789Sahrens */ 447789Sahrens 448789Sahrens for (i = 1; i < *argc; i++) { 449789Sahrens int len = strlen("debug="); 450789Sahrens /* First look for a command line argument */ 451789Sahrens if (strncmp("debug=", argv[i], len) == 0) { 452789Sahrens dprintf_string = argv[i] + len; 453789Sahrens /* Remove from args */ 454789Sahrens for (j = i; j < *argc; j++) 455789Sahrens argv[j] = argv[j+1]; 456789Sahrens argv[j] = NULL; 457789Sahrens (*argc)--; 458789Sahrens } 459789Sahrens } 460789Sahrens 461789Sahrens if (dprintf_string == NULL) { 462789Sahrens /* Look for ZFS_DEBUG environment variable */ 463789Sahrens dprintf_string = getenv("ZFS_DEBUG"); 464789Sahrens } 465789Sahrens 466789Sahrens /* 467789Sahrens * Are we just turning on all debugging? 468789Sahrens */ 469789Sahrens if (dprintf_find_string("on")) 470789Sahrens dprintf_print_all = 1; 471789Sahrens } 472789Sahrens 473789Sahrens /* 474789Sahrens * ========================================================================= 475789Sahrens * debug printfs 476789Sahrens * ========================================================================= 477789Sahrens */ 478789Sahrens void 479789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 480789Sahrens { 481789Sahrens const char *newfile; 482789Sahrens va_list adx; 483789Sahrens 484789Sahrens /* 485789Sahrens * Get rid of annoying "../common/" prefix to filename. 486789Sahrens */ 487789Sahrens newfile = strrchr(file, '/'); 488789Sahrens if (newfile != NULL) { 489789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 490789Sahrens } else { 491789Sahrens newfile = file; 492789Sahrens } 493789Sahrens 494789Sahrens if (dprintf_print_all || 495789Sahrens dprintf_find_string(newfile) || 496789Sahrens dprintf_find_string(func)) { 497789Sahrens /* Print out just the function name if requested */ 498789Sahrens flockfile(stdout); 499789Sahrens if (dprintf_find_string("pid")) 500789Sahrens (void) printf("%d ", getpid()); 501789Sahrens if (dprintf_find_string("tid")) 502789Sahrens (void) printf("%u ", thr_self()); 503789Sahrens if (dprintf_find_string("cpu")) 504789Sahrens (void) printf("%u ", getcpuid()); 505789Sahrens if (dprintf_find_string("time")) 506789Sahrens (void) printf("%llu ", gethrtime()); 507789Sahrens if (dprintf_find_string("long")) 508789Sahrens (void) printf("%s, line %d: ", newfile, line); 509789Sahrens (void) printf("%s: ", func); 510789Sahrens va_start(adx, fmt); 511789Sahrens (void) vprintf(fmt, adx); 512789Sahrens va_end(adx); 513789Sahrens funlockfile(stdout); 514789Sahrens } 515789Sahrens } 516789Sahrens 517789Sahrens #endif /* ZFS_DEBUG */ 518789Sahrens 519789Sahrens /* 520789Sahrens * ========================================================================= 521789Sahrens * cmn_err() and panic() 522789Sahrens * ========================================================================= 523789Sahrens */ 524789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 525789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 526789Sahrens 527789Sahrens void 528789Sahrens vpanic(const char *fmt, va_list adx) 529789Sahrens { 530789Sahrens (void) fprintf(stderr, "error: "); 531789Sahrens (void) vfprintf(stderr, fmt, adx); 532789Sahrens (void) fprintf(stderr, "\n"); 533789Sahrens 534789Sahrens abort(); /* think of it as a "user-level crash dump" */ 535789Sahrens } 536789Sahrens 537789Sahrens void 538789Sahrens panic(const char *fmt, ...) 539789Sahrens { 540789Sahrens va_list adx; 541789Sahrens 542789Sahrens va_start(adx, fmt); 543789Sahrens vpanic(fmt, adx); 544789Sahrens va_end(adx); 545789Sahrens } 546789Sahrens 547789Sahrens /*PRINTFLIKE2*/ 548789Sahrens void 549789Sahrens cmn_err(int ce, const char *fmt, ...) 550789Sahrens { 551789Sahrens va_list adx; 552789Sahrens 553789Sahrens va_start(adx, fmt); 554789Sahrens if (ce == CE_PANIC) 555789Sahrens vpanic(fmt, adx); 556789Sahrens if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ 557789Sahrens (void) fprintf(stderr, "%s", ce_prefix[ce]); 558789Sahrens (void) vfprintf(stderr, fmt, adx); 559789Sahrens (void) fprintf(stderr, "%s", ce_suffix[ce]); 560789Sahrens } 561789Sahrens va_end(adx); 562789Sahrens } 563789Sahrens 564789Sahrens /* 565789Sahrens * ========================================================================= 5661544Seschrock * kobj interfaces 5671544Seschrock * ========================================================================= 5681544Seschrock */ 5691544Seschrock struct _buf * 5701544Seschrock kobj_open_file(char *name) 5711544Seschrock { 5721544Seschrock struct _buf *file; 5731544Seschrock vnode_t *vp; 5741544Seschrock 5751544Seschrock /* set vp as the _fd field of the file */ 5761544Seschrock if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir) != 0) 5771544Seschrock return ((void *)-1UL); 5781544Seschrock 5791544Seschrock file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 5801544Seschrock file->_fd = (intptr_t)vp; 5811544Seschrock return (file); 5821544Seschrock } 5831544Seschrock 5841544Seschrock int 5851544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 5861544Seschrock { 5871544Seschrock ssize_t resid; 5881544Seschrock 5891544Seschrock vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 5901544Seschrock UIO_SYSSPACE, 0, 0, 0, &resid); 5911544Seschrock 5921544Seschrock return (0); 5931544Seschrock } 5941544Seschrock 5951544Seschrock void 5961544Seschrock kobj_close_file(struct _buf *file) 5971544Seschrock { 5981544Seschrock vn_close((vnode_t *)file->_fd); 5991544Seschrock umem_free(file, sizeof (struct _buf)); 6001544Seschrock } 6011544Seschrock 6021544Seschrock int 6031544Seschrock kobj_fstat(intptr_t fd, struct bootstat *bst) 6041544Seschrock { 6051544Seschrock struct stat64 st; 6061544Seschrock vnode_t *vp = (vnode_t *)fd; 6071544Seschrock if (fstat64(vp->v_fd, &st) == -1) { 6081544Seschrock vn_close(vp); 6091544Seschrock return (errno); 6101544Seschrock } 6111544Seschrock bst->st_size = (uint64_t)st.st_size; 6121544Seschrock return (0); 6131544Seschrock } 6141544Seschrock 6151544Seschrock /* 6161544Seschrock * ========================================================================= 617789Sahrens * misc routines 618789Sahrens * ========================================================================= 619789Sahrens */ 620789Sahrens 621789Sahrens void 622789Sahrens delay(clock_t ticks) 623789Sahrens { 624789Sahrens poll(0, 0, ticks * (1000 / hz)); 625789Sahrens } 626789Sahrens 627789Sahrens /* 628789Sahrens * Find highest one bit set. 629789Sahrens * Returns bit number + 1 of highest bit that is set, otherwise returns 0. 630789Sahrens * High order bit is 31 (or 63 in _LP64 kernel). 631789Sahrens */ 632789Sahrens int 633789Sahrens highbit(ulong_t i) 634789Sahrens { 635789Sahrens register int h = 1; 636789Sahrens 637789Sahrens if (i == 0) 638789Sahrens return (0); 639789Sahrens #ifdef _LP64 640789Sahrens if (i & 0xffffffff00000000ul) { 641789Sahrens h += 32; i >>= 32; 642789Sahrens } 643789Sahrens #endif 644789Sahrens if (i & 0xffff0000) { 645789Sahrens h += 16; i >>= 16; 646789Sahrens } 647789Sahrens if (i & 0xff00) { 648789Sahrens h += 8; i >>= 8; 649789Sahrens } 650789Sahrens if (i & 0xf0) { 651789Sahrens h += 4; i >>= 4; 652789Sahrens } 653789Sahrens if (i & 0xc) { 654789Sahrens h += 2; i >>= 2; 655789Sahrens } 656789Sahrens if (i & 0x2) { 657789Sahrens h += 1; 658789Sahrens } 659789Sahrens return (h); 660789Sahrens } 661789Sahrens 662789Sahrens static int 663789Sahrens random_get_bytes_common(uint8_t *ptr, size_t len, char *devname) 664789Sahrens { 665789Sahrens int fd = open(devname, O_RDONLY); 666789Sahrens size_t resid = len; 667789Sahrens ssize_t bytes; 668789Sahrens 669789Sahrens ASSERT(fd != -1); 670789Sahrens 671789Sahrens while (resid != 0) { 672789Sahrens bytes = read(fd, ptr, resid); 673789Sahrens ASSERT(bytes >= 0); 674789Sahrens ptr += bytes; 675789Sahrens resid -= bytes; 676789Sahrens } 677789Sahrens 678789Sahrens close(fd); 679789Sahrens 680789Sahrens return (0); 681789Sahrens } 682789Sahrens 683789Sahrens int 684789Sahrens random_get_bytes(uint8_t *ptr, size_t len) 685789Sahrens { 686789Sahrens return (random_get_bytes_common(ptr, len, "/dev/random")); 687789Sahrens } 688789Sahrens 689789Sahrens int 690789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len) 691789Sahrens { 692789Sahrens return (random_get_bytes_common(ptr, len, "/dev/urandom")); 693789Sahrens } 694789Sahrens 695789Sahrens /* 696789Sahrens * ========================================================================= 697789Sahrens * kernel emulation setup & teardown 698789Sahrens * ========================================================================= 699789Sahrens */ 700789Sahrens static int 701789Sahrens umem_out_of_memory(void) 702789Sahrens { 703789Sahrens char errmsg[] = "out of memory -- generating core dump\n"; 704789Sahrens 705789Sahrens write(fileno(stderr), errmsg, sizeof (errmsg)); 706789Sahrens abort(); 707789Sahrens return (0); 708789Sahrens } 709789Sahrens 710789Sahrens void 711789Sahrens kernel_init(int mode) 712789Sahrens { 713789Sahrens umem_nofail_callback(umem_out_of_memory); 714789Sahrens 715789Sahrens physmem = sysconf(_SC_PHYS_PAGES); 716789Sahrens 717789Sahrens dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 718789Sahrens (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 719789Sahrens 720789Sahrens spa_init(mode); 721789Sahrens } 722789Sahrens 723789Sahrens void 724789Sahrens kernel_fini(void) 725789Sahrens { 726789Sahrens spa_fini(); 727789Sahrens } 728