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