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 /* 22*3403Sbmc * Copyright 2007 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 392856Snd150628 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 * ========================================================================= 66*3403Sbmc * kstats 67*3403Sbmc * ========================================================================= 68*3403Sbmc */ 69*3403Sbmc /*ARGSUSED*/ 70*3403Sbmc kstat_t * 71*3403Sbmc kstat_create(char *module, int instance, char *name, char *class, 72*3403Sbmc uchar_t type, ulong_t ndata, uchar_t ks_flag) 73*3403Sbmc { 74*3403Sbmc return (NULL); 75*3403Sbmc } 76*3403Sbmc 77*3403Sbmc /*ARGSUSED*/ 78*3403Sbmc void 79*3403Sbmc kstat_install(kstat_t *ksp) 80*3403Sbmc {} 81*3403Sbmc 82*3403Sbmc /*ARGSUSED*/ 83*3403Sbmc void 84*3403Sbmc kstat_delete(kstat_t *ksp) 85*3403Sbmc {} 86*3403Sbmc 87*3403Sbmc /* 88*3403Sbmc * ========================================================================= 89789Sahrens * mutexes 90789Sahrens * ========================================================================= 91789Sahrens */ 92789Sahrens void 93789Sahrens zmutex_init(kmutex_t *mp) 94789Sahrens { 95789Sahrens mp->m_owner = NULL; 96789Sahrens (void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL); 97789Sahrens } 98789Sahrens 99789Sahrens void 100789Sahrens zmutex_destroy(kmutex_t *mp) 101789Sahrens { 102789Sahrens ASSERT(mp->m_owner == NULL); 103789Sahrens (void) _mutex_destroy(&(mp)->m_lock); 104789Sahrens mp->m_owner = (void *)-1UL; 105789Sahrens } 106789Sahrens 107789Sahrens void 108789Sahrens mutex_enter(kmutex_t *mp) 109789Sahrens { 110789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 111789Sahrens ASSERT(mp->m_owner != curthread); 1122856Snd150628 VERIFY(mutex_lock(&mp->m_lock) == 0); 113789Sahrens ASSERT(mp->m_owner == NULL); 114789Sahrens mp->m_owner = curthread; 115789Sahrens } 116789Sahrens 117789Sahrens int 118789Sahrens mutex_tryenter(kmutex_t *mp) 119789Sahrens { 120789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 121789Sahrens if (0 == mutex_trylock(&mp->m_lock)) { 122789Sahrens ASSERT(mp->m_owner == NULL); 123789Sahrens mp->m_owner = curthread; 124789Sahrens return (1); 125789Sahrens } else { 126789Sahrens return (0); 127789Sahrens } 128789Sahrens } 129789Sahrens 130789Sahrens void 131789Sahrens mutex_exit(kmutex_t *mp) 132789Sahrens { 133789Sahrens ASSERT(mutex_owner(mp) == curthread); 134789Sahrens mp->m_owner = NULL; 1352856Snd150628 VERIFY(mutex_unlock(&mp->m_lock) == 0); 136789Sahrens } 137789Sahrens 138789Sahrens void * 139789Sahrens mutex_owner(kmutex_t *mp) 140789Sahrens { 141789Sahrens return (mp->m_owner); 142789Sahrens } 143789Sahrens 144789Sahrens /* 145789Sahrens * ========================================================================= 146789Sahrens * rwlocks 147789Sahrens * ========================================================================= 148789Sahrens */ 149789Sahrens /*ARGSUSED*/ 150789Sahrens void 151789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg) 152789Sahrens { 153789Sahrens rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL); 154789Sahrens rwlp->rw_owner = NULL; 155789Sahrens } 156789Sahrens 157789Sahrens void 158789Sahrens rw_destroy(krwlock_t *rwlp) 159789Sahrens { 160789Sahrens rwlock_destroy(&rwlp->rw_lock); 161789Sahrens rwlp->rw_owner = (void *)-1UL; 162789Sahrens } 163789Sahrens 164789Sahrens void 165789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw) 166789Sahrens { 167789Sahrens ASSERT(!RW_LOCK_HELD(rwlp)); 168789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 169789Sahrens ASSERT(rwlp->rw_owner != curthread); 170789Sahrens 171789Sahrens if (rw == RW_READER) 172789Sahrens (void) rw_rdlock(&rwlp->rw_lock); 173789Sahrens else 174789Sahrens (void) rw_wrlock(&rwlp->rw_lock); 175789Sahrens 176789Sahrens rwlp->rw_owner = curthread; 177789Sahrens } 178789Sahrens 179789Sahrens void 180789Sahrens rw_exit(krwlock_t *rwlp) 181789Sahrens { 182789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 183789Sahrens 184789Sahrens rwlp->rw_owner = NULL; 185789Sahrens (void) rw_unlock(&rwlp->rw_lock); 186789Sahrens } 187789Sahrens 188789Sahrens int 189789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw) 190789Sahrens { 191789Sahrens int rv; 192789Sahrens 193789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 194789Sahrens 195789Sahrens if (rw == RW_READER) 196789Sahrens rv = rw_tryrdlock(&rwlp->rw_lock); 197789Sahrens else 198789Sahrens rv = rw_trywrlock(&rwlp->rw_lock); 199789Sahrens 200789Sahrens if (rv == 0) { 201789Sahrens rwlp->rw_owner = curthread; 202789Sahrens return (1); 203789Sahrens } 204789Sahrens 205789Sahrens return (0); 206789Sahrens } 207789Sahrens 208789Sahrens /*ARGSUSED*/ 209789Sahrens int 210789Sahrens rw_tryupgrade(krwlock_t *rwlp) 211789Sahrens { 212789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 213789Sahrens 214789Sahrens return (0); 215789Sahrens } 216789Sahrens 217789Sahrens /* 218789Sahrens * ========================================================================= 219789Sahrens * condition variables 220789Sahrens * ========================================================================= 221789Sahrens */ 222789Sahrens /*ARGSUSED*/ 223789Sahrens void 224789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg) 225789Sahrens { 2262856Snd150628 VERIFY(cond_init(cv, type, NULL) == 0); 227789Sahrens } 228789Sahrens 229789Sahrens void 230789Sahrens cv_destroy(kcondvar_t *cv) 231789Sahrens { 2322856Snd150628 VERIFY(cond_destroy(cv) == 0); 233789Sahrens } 234789Sahrens 235789Sahrens void 236789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp) 237789Sahrens { 238789Sahrens ASSERT(mutex_owner(mp) == curthread); 239789Sahrens mp->m_owner = NULL; 2402856Snd150628 int ret = cond_wait(cv, &mp->m_lock); 2412856Snd150628 VERIFY(ret == 0 || ret == EINTR); 242789Sahrens mp->m_owner = curthread; 243789Sahrens } 244789Sahrens 245789Sahrens clock_t 246789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) 247789Sahrens { 248789Sahrens int error; 249789Sahrens timestruc_t ts; 250789Sahrens clock_t delta; 251789Sahrens 252789Sahrens top: 253789Sahrens delta = abstime - lbolt; 254789Sahrens if (delta <= 0) 255789Sahrens return (-1); 256789Sahrens 257789Sahrens ts.tv_sec = delta / hz; 258789Sahrens ts.tv_nsec = (delta % hz) * (NANOSEC / hz); 259789Sahrens 260789Sahrens ASSERT(mutex_owner(mp) == curthread); 261789Sahrens mp->m_owner = NULL; 262789Sahrens error = cond_reltimedwait(cv, &mp->m_lock, &ts); 263789Sahrens mp->m_owner = curthread; 264789Sahrens 265789Sahrens if (error == ETIME) 266789Sahrens return (-1); 267789Sahrens 268789Sahrens if (error == EINTR) 269789Sahrens goto top; 270789Sahrens 271789Sahrens ASSERT(error == 0); 272789Sahrens 273789Sahrens return (1); 274789Sahrens } 275789Sahrens 276789Sahrens void 277789Sahrens cv_signal(kcondvar_t *cv) 278789Sahrens { 2792856Snd150628 VERIFY(cond_signal(cv) == 0); 280789Sahrens } 281789Sahrens 282789Sahrens void 283789Sahrens cv_broadcast(kcondvar_t *cv) 284789Sahrens { 2852856Snd150628 VERIFY(cond_broadcast(cv) == 0); 286789Sahrens } 287789Sahrens 288789Sahrens /* 289789Sahrens * ========================================================================= 290789Sahrens * vnode operations 291789Sahrens * ========================================================================= 292789Sahrens */ 293789Sahrens /* 294789Sahrens * Note: for the xxxat() versions of these functions, we assume that the 295789Sahrens * starting vp is always rootdir (which is true for spa_directory.c, the only 296789Sahrens * ZFS consumer of these interfaces). We assert this is true, and then emulate 297789Sahrens * them by adding '/' in front of the path. 298789Sahrens */ 299789Sahrens 300789Sahrens /*ARGSUSED*/ 301789Sahrens int 302789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) 303789Sahrens { 304789Sahrens int fd; 305789Sahrens vnode_t *vp; 306789Sahrens int old_umask; 307789Sahrens char realpath[MAXPATHLEN]; 308789Sahrens struct stat64 st; 309789Sahrens 310789Sahrens /* 311789Sahrens * If we're accessing a real disk from userland, we need to use 312789Sahrens * the character interface to avoid caching. This is particularly 313789Sahrens * important if we're trying to look at a real in-kernel storage 314789Sahrens * pool from userland, e.g. via zdb, because otherwise we won't 315789Sahrens * see the changes occurring under the segmap cache. 316789Sahrens * On the other hand, the stupid character device returns zero 317789Sahrens * for its size. So -- gag -- we open the block device to get 318789Sahrens * its size, and remember it for subsequent VOP_GETATTR(). 319789Sahrens */ 320789Sahrens if (strncmp(path, "/dev/", 5) == 0) { 321789Sahrens char *dsk; 322789Sahrens fd = open64(path, O_RDONLY); 323789Sahrens if (fd == -1) 324789Sahrens return (errno); 325789Sahrens if (fstat64(fd, &st) == -1) { 326789Sahrens close(fd); 327789Sahrens return (errno); 328789Sahrens } 329789Sahrens close(fd); 330789Sahrens (void) sprintf(realpath, "%s", path); 331789Sahrens dsk = strstr(path, "/dsk/"); 332789Sahrens if (dsk != NULL) 333789Sahrens (void) sprintf(realpath + (dsk - path) + 1, "r%s", 334789Sahrens dsk + 1); 335789Sahrens } else { 336789Sahrens (void) sprintf(realpath, "%s", path); 337789Sahrens if (!(flags & FCREAT) && stat64(realpath, &st) == -1) 338789Sahrens return (errno); 339789Sahrens } 340789Sahrens 341789Sahrens if (flags & FCREAT) 342789Sahrens old_umask = umask(0); 343789Sahrens 344789Sahrens /* 345789Sahrens * The construct 'flags - FREAD' conveniently maps combinations of 346789Sahrens * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. 347789Sahrens */ 348789Sahrens fd = open64(realpath, flags - FREAD, mode); 349789Sahrens 350789Sahrens if (flags & FCREAT) 351789Sahrens (void) umask(old_umask); 352789Sahrens 353789Sahrens if (fd == -1) 354789Sahrens return (errno); 355789Sahrens 356789Sahrens if (fstat64(fd, &st) == -1) { 357789Sahrens close(fd); 358789Sahrens return (errno); 359789Sahrens } 360789Sahrens 361789Sahrens (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 362789Sahrens 363789Sahrens *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); 364789Sahrens 365789Sahrens vp->v_fd = fd; 366789Sahrens vp->v_size = st.st_size; 367789Sahrens vp->v_path = spa_strdup(path); 368789Sahrens 369789Sahrens return (0); 370789Sahrens } 371789Sahrens 372789Sahrens int 373789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, 374789Sahrens int x3, vnode_t *startvp) 375789Sahrens { 376789Sahrens char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); 377789Sahrens int ret; 378789Sahrens 379789Sahrens ASSERT(startvp == rootdir); 380789Sahrens (void) sprintf(realpath, "/%s", path); 381789Sahrens 382789Sahrens ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); 383789Sahrens 384789Sahrens umem_free(realpath, strlen(path) + 2); 385789Sahrens 386789Sahrens return (ret); 387789Sahrens } 388789Sahrens 389789Sahrens /*ARGSUSED*/ 390789Sahrens int 391789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, 392789Sahrens int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) 393789Sahrens { 394789Sahrens ssize_t iolen, split; 395789Sahrens 396789Sahrens if (uio == UIO_READ) { 397789Sahrens iolen = pread64(vp->v_fd, addr, len, offset); 398789Sahrens } else { 399789Sahrens /* 400789Sahrens * To simulate partial disk writes, we split writes into two 401789Sahrens * system calls so that the process can be killed in between. 402789Sahrens */ 403789Sahrens split = (len > 0 ? rand() % len : 0); 404789Sahrens iolen = pwrite64(vp->v_fd, addr, split, offset); 405789Sahrens iolen += pwrite64(vp->v_fd, (char *)addr + split, 406789Sahrens len - split, offset + split); 407789Sahrens } 408789Sahrens 409789Sahrens if (iolen == -1) 410789Sahrens return (errno); 411789Sahrens if (residp) 412789Sahrens *residp = len - iolen; 413789Sahrens else if (iolen != len) 414789Sahrens return (EIO); 415789Sahrens return (0); 416789Sahrens } 417789Sahrens 418789Sahrens void 419789Sahrens vn_close(vnode_t *vp) 420789Sahrens { 421789Sahrens close(vp->v_fd); 422789Sahrens spa_strfree(vp->v_path); 423789Sahrens umem_free(vp, sizeof (vnode_t)); 424789Sahrens } 425789Sahrens 426789Sahrens #ifdef ZFS_DEBUG 427789Sahrens 428789Sahrens /* 429789Sahrens * ========================================================================= 430789Sahrens * Figure out which debugging statements to print 431789Sahrens * ========================================================================= 432789Sahrens */ 433789Sahrens 434789Sahrens static char *dprintf_string; 435789Sahrens static int dprintf_print_all; 436789Sahrens 437789Sahrens int 438789Sahrens dprintf_find_string(const char *string) 439789Sahrens { 440789Sahrens char *tmp_str = dprintf_string; 441789Sahrens int len = strlen(string); 442789Sahrens 443789Sahrens /* 444789Sahrens * Find out if this is a string we want to print. 445789Sahrens * String format: file1.c,function_name1,file2.c,file3.c 446789Sahrens */ 447789Sahrens 448789Sahrens while (tmp_str != NULL) { 449789Sahrens if (strncmp(tmp_str, string, len) == 0 && 450789Sahrens (tmp_str[len] == ',' || tmp_str[len] == '\0')) 451789Sahrens return (1); 452789Sahrens tmp_str = strchr(tmp_str, ','); 453789Sahrens if (tmp_str != NULL) 454789Sahrens tmp_str++; /* Get rid of , */ 455789Sahrens } 456789Sahrens return (0); 457789Sahrens } 458789Sahrens 459789Sahrens void 460789Sahrens dprintf_setup(int *argc, char **argv) 461789Sahrens { 462789Sahrens int i, j; 463789Sahrens 464789Sahrens /* 465789Sahrens * Debugging can be specified two ways: by setting the 466789Sahrens * environment variable ZFS_DEBUG, or by including a 467789Sahrens * "debug=..." argument on the command line. The command 468789Sahrens * line setting overrides the environment variable. 469789Sahrens */ 470789Sahrens 471789Sahrens for (i = 1; i < *argc; i++) { 472789Sahrens int len = strlen("debug="); 473789Sahrens /* First look for a command line argument */ 474789Sahrens if (strncmp("debug=", argv[i], len) == 0) { 475789Sahrens dprintf_string = argv[i] + len; 476789Sahrens /* Remove from args */ 477789Sahrens for (j = i; j < *argc; j++) 478789Sahrens argv[j] = argv[j+1]; 479789Sahrens argv[j] = NULL; 480789Sahrens (*argc)--; 481789Sahrens } 482789Sahrens } 483789Sahrens 484789Sahrens if (dprintf_string == NULL) { 485789Sahrens /* Look for ZFS_DEBUG environment variable */ 486789Sahrens dprintf_string = getenv("ZFS_DEBUG"); 487789Sahrens } 488789Sahrens 489789Sahrens /* 490789Sahrens * Are we just turning on all debugging? 491789Sahrens */ 492789Sahrens if (dprintf_find_string("on")) 493789Sahrens dprintf_print_all = 1; 494789Sahrens } 495789Sahrens 496789Sahrens /* 497789Sahrens * ========================================================================= 498789Sahrens * debug printfs 499789Sahrens * ========================================================================= 500789Sahrens */ 501789Sahrens void 502789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 503789Sahrens { 504789Sahrens const char *newfile; 505789Sahrens va_list adx; 506789Sahrens 507789Sahrens /* 508789Sahrens * Get rid of annoying "../common/" prefix to filename. 509789Sahrens */ 510789Sahrens newfile = strrchr(file, '/'); 511789Sahrens if (newfile != NULL) { 512789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 513789Sahrens } else { 514789Sahrens newfile = file; 515789Sahrens } 516789Sahrens 517789Sahrens if (dprintf_print_all || 518789Sahrens dprintf_find_string(newfile) || 519789Sahrens dprintf_find_string(func)) { 520789Sahrens /* Print out just the function name if requested */ 521789Sahrens flockfile(stdout); 522789Sahrens if (dprintf_find_string("pid")) 523789Sahrens (void) printf("%d ", getpid()); 524789Sahrens if (dprintf_find_string("tid")) 525789Sahrens (void) printf("%u ", thr_self()); 526789Sahrens if (dprintf_find_string("cpu")) 527789Sahrens (void) printf("%u ", getcpuid()); 528789Sahrens if (dprintf_find_string("time")) 529789Sahrens (void) printf("%llu ", gethrtime()); 530789Sahrens if (dprintf_find_string("long")) 531789Sahrens (void) printf("%s, line %d: ", newfile, line); 532789Sahrens (void) printf("%s: ", func); 533789Sahrens va_start(adx, fmt); 534789Sahrens (void) vprintf(fmt, adx); 535789Sahrens va_end(adx); 536789Sahrens funlockfile(stdout); 537789Sahrens } 538789Sahrens } 539789Sahrens 540789Sahrens #endif /* ZFS_DEBUG */ 541789Sahrens 542789Sahrens /* 543789Sahrens * ========================================================================= 544789Sahrens * cmn_err() and panic() 545789Sahrens * ========================================================================= 546789Sahrens */ 547789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 548789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 549789Sahrens 550789Sahrens void 551789Sahrens vpanic(const char *fmt, va_list adx) 552789Sahrens { 553789Sahrens (void) fprintf(stderr, "error: "); 554789Sahrens (void) vfprintf(stderr, fmt, adx); 555789Sahrens (void) fprintf(stderr, "\n"); 556789Sahrens 557789Sahrens abort(); /* think of it as a "user-level crash dump" */ 558789Sahrens } 559789Sahrens 560789Sahrens void 561789Sahrens panic(const char *fmt, ...) 562789Sahrens { 563789Sahrens va_list adx; 564789Sahrens 565789Sahrens va_start(adx, fmt); 566789Sahrens vpanic(fmt, adx); 567789Sahrens va_end(adx); 568789Sahrens } 569789Sahrens 570789Sahrens /*PRINTFLIKE2*/ 571789Sahrens void 572789Sahrens cmn_err(int ce, const char *fmt, ...) 573789Sahrens { 574789Sahrens va_list adx; 575789Sahrens 576789Sahrens va_start(adx, fmt); 577789Sahrens if (ce == CE_PANIC) 578789Sahrens vpanic(fmt, adx); 579789Sahrens if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ 580789Sahrens (void) fprintf(stderr, "%s", ce_prefix[ce]); 581789Sahrens (void) vfprintf(stderr, fmt, adx); 582789Sahrens (void) fprintf(stderr, "%s", ce_suffix[ce]); 583789Sahrens } 584789Sahrens va_end(adx); 585789Sahrens } 586789Sahrens 587789Sahrens /* 588789Sahrens * ========================================================================= 5891544Seschrock * kobj interfaces 5901544Seschrock * ========================================================================= 5911544Seschrock */ 5921544Seschrock struct _buf * 5931544Seschrock kobj_open_file(char *name) 5941544Seschrock { 5951544Seschrock struct _buf *file; 5961544Seschrock vnode_t *vp; 5971544Seschrock 5981544Seschrock /* set vp as the _fd field of the file */ 5991544Seschrock if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir) != 0) 6001544Seschrock return ((void *)-1UL); 6011544Seschrock 6021544Seschrock file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 6031544Seschrock file->_fd = (intptr_t)vp; 6041544Seschrock return (file); 6051544Seschrock } 6061544Seschrock 6071544Seschrock int 6081544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 6091544Seschrock { 6101544Seschrock ssize_t resid; 6111544Seschrock 6121544Seschrock vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 6131544Seschrock UIO_SYSSPACE, 0, 0, 0, &resid); 6141544Seschrock 6151544Seschrock return (0); 6161544Seschrock } 6171544Seschrock 6181544Seschrock void 6191544Seschrock kobj_close_file(struct _buf *file) 6201544Seschrock { 6211544Seschrock vn_close((vnode_t *)file->_fd); 6221544Seschrock umem_free(file, sizeof (struct _buf)); 6231544Seschrock } 6241544Seschrock 6251544Seschrock int 6261544Seschrock kobj_fstat(intptr_t fd, struct bootstat *bst) 6271544Seschrock { 6281544Seschrock struct stat64 st; 6291544Seschrock vnode_t *vp = (vnode_t *)fd; 6301544Seschrock if (fstat64(vp->v_fd, &st) == -1) { 6311544Seschrock vn_close(vp); 6321544Seschrock return (errno); 6331544Seschrock } 6341544Seschrock bst->st_size = (uint64_t)st.st_size; 6351544Seschrock return (0); 6361544Seschrock } 6371544Seschrock 6381544Seschrock /* 6391544Seschrock * ========================================================================= 640789Sahrens * misc routines 641789Sahrens * ========================================================================= 642789Sahrens */ 643789Sahrens 644789Sahrens void 645789Sahrens delay(clock_t ticks) 646789Sahrens { 647789Sahrens poll(0, 0, ticks * (1000 / hz)); 648789Sahrens } 649789Sahrens 650789Sahrens /* 651789Sahrens * Find highest one bit set. 652789Sahrens * Returns bit number + 1 of highest bit that is set, otherwise returns 0. 653789Sahrens * High order bit is 31 (or 63 in _LP64 kernel). 654789Sahrens */ 655789Sahrens int 656789Sahrens highbit(ulong_t i) 657789Sahrens { 658789Sahrens register int h = 1; 659789Sahrens 660789Sahrens if (i == 0) 661789Sahrens return (0); 662789Sahrens #ifdef _LP64 663789Sahrens if (i & 0xffffffff00000000ul) { 664789Sahrens h += 32; i >>= 32; 665789Sahrens } 666789Sahrens #endif 667789Sahrens if (i & 0xffff0000) { 668789Sahrens h += 16; i >>= 16; 669789Sahrens } 670789Sahrens if (i & 0xff00) { 671789Sahrens h += 8; i >>= 8; 672789Sahrens } 673789Sahrens if (i & 0xf0) { 674789Sahrens h += 4; i >>= 4; 675789Sahrens } 676789Sahrens if (i & 0xc) { 677789Sahrens h += 2; i >>= 2; 678789Sahrens } 679789Sahrens if (i & 0x2) { 680789Sahrens h += 1; 681789Sahrens } 682789Sahrens return (h); 683789Sahrens } 684789Sahrens 685789Sahrens static int 686789Sahrens random_get_bytes_common(uint8_t *ptr, size_t len, char *devname) 687789Sahrens { 688789Sahrens int fd = open(devname, O_RDONLY); 689789Sahrens size_t resid = len; 690789Sahrens ssize_t bytes; 691789Sahrens 692789Sahrens ASSERT(fd != -1); 693789Sahrens 694789Sahrens while (resid != 0) { 695789Sahrens bytes = read(fd, ptr, resid); 696789Sahrens ASSERT(bytes >= 0); 697789Sahrens ptr += bytes; 698789Sahrens resid -= bytes; 699789Sahrens } 700789Sahrens 701789Sahrens close(fd); 702789Sahrens 703789Sahrens return (0); 704789Sahrens } 705789Sahrens 706789Sahrens int 707789Sahrens random_get_bytes(uint8_t *ptr, size_t len) 708789Sahrens { 709789Sahrens return (random_get_bytes_common(ptr, len, "/dev/random")); 710789Sahrens } 711789Sahrens 712789Sahrens int 713789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len) 714789Sahrens { 715789Sahrens return (random_get_bytes_common(ptr, len, "/dev/urandom")); 716789Sahrens } 717789Sahrens 718789Sahrens /* 719789Sahrens * ========================================================================= 720789Sahrens * kernel emulation setup & teardown 721789Sahrens * ========================================================================= 722789Sahrens */ 723789Sahrens static int 724789Sahrens umem_out_of_memory(void) 725789Sahrens { 726789Sahrens char errmsg[] = "out of memory -- generating core dump\n"; 727789Sahrens 728789Sahrens write(fileno(stderr), errmsg, sizeof (errmsg)); 729789Sahrens abort(); 730789Sahrens return (0); 731789Sahrens } 732789Sahrens 733789Sahrens void 734789Sahrens kernel_init(int mode) 735789Sahrens { 736789Sahrens umem_nofail_callback(umem_out_of_memory); 737789Sahrens 738789Sahrens physmem = sysconf(_SC_PHYS_PAGES); 739789Sahrens 740789Sahrens dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 741789Sahrens (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 742789Sahrens 743789Sahrens spa_init(mode); 744789Sahrens } 745789Sahrens 746789Sahrens void 747789Sahrens kernel_fini(void) 748789Sahrens { 749789Sahrens spa_fini(); 750789Sahrens } 751