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> 403975Sek110237 #include <sys/utsname.h> 412856Snd150628 42789Sahrens /* 43789Sahrens * Emulation of kernel services in userland. 44789Sahrens */ 45789Sahrens 46789Sahrens uint64_t physmem; 47789Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234; 483975Sek110237 char hw_serial[11]; 493975Sek110237 503975Sek110237 struct utsname utsname = { 513975Sek110237 "userland", "libzpool", "1", "1", "na" 523975Sek110237 }; 53789Sahrens 54789Sahrens /* 55789Sahrens * ========================================================================= 56789Sahrens * threads 57789Sahrens * ========================================================================= 58789Sahrens */ 59789Sahrens /*ARGSUSED*/ 60789Sahrens kthread_t * 61789Sahrens zk_thread_create(void (*func)(), void *arg) 62789Sahrens { 63789Sahrens thread_t tid; 64789Sahrens 65789Sahrens VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED, 66789Sahrens &tid) == 0); 67789Sahrens 68789Sahrens return ((void *)(uintptr_t)tid); 69789Sahrens } 70789Sahrens 71789Sahrens /* 72789Sahrens * ========================================================================= 733403Sbmc * kstats 743403Sbmc * ========================================================================= 753403Sbmc */ 763403Sbmc /*ARGSUSED*/ 773403Sbmc kstat_t * 783403Sbmc kstat_create(char *module, int instance, char *name, char *class, 793403Sbmc uchar_t type, ulong_t ndata, uchar_t ks_flag) 803403Sbmc { 813403Sbmc return (NULL); 823403Sbmc } 833403Sbmc 843403Sbmc /*ARGSUSED*/ 853403Sbmc void 863403Sbmc kstat_install(kstat_t *ksp) 873403Sbmc {} 883403Sbmc 893403Sbmc /*ARGSUSED*/ 903403Sbmc void 913403Sbmc kstat_delete(kstat_t *ksp) 923403Sbmc {} 933403Sbmc 943403Sbmc /* 953403Sbmc * ========================================================================= 96789Sahrens * mutexes 97789Sahrens * ========================================================================= 98789Sahrens */ 99789Sahrens void 100789Sahrens zmutex_init(kmutex_t *mp) 101789Sahrens { 102789Sahrens mp->m_owner = NULL; 1034831Sgw25295 mp->initialized = B_TRUE; 104789Sahrens (void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL); 105789Sahrens } 106789Sahrens 107789Sahrens void 108789Sahrens zmutex_destroy(kmutex_t *mp) 109789Sahrens { 1104831Sgw25295 ASSERT(mp->initialized == B_TRUE); 111789Sahrens ASSERT(mp->m_owner == NULL); 112789Sahrens (void) _mutex_destroy(&(mp)->m_lock); 113789Sahrens mp->m_owner = (void *)-1UL; 1144831Sgw25295 mp->initialized = B_FALSE; 115789Sahrens } 116789Sahrens 117789Sahrens void 118789Sahrens mutex_enter(kmutex_t *mp) 119789Sahrens { 1204831Sgw25295 ASSERT(mp->initialized == B_TRUE); 121789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 122789Sahrens ASSERT(mp->m_owner != curthread); 1232856Snd150628 VERIFY(mutex_lock(&mp->m_lock) == 0); 124789Sahrens ASSERT(mp->m_owner == NULL); 125789Sahrens mp->m_owner = curthread; 126789Sahrens } 127789Sahrens 128789Sahrens int 129789Sahrens mutex_tryenter(kmutex_t *mp) 130789Sahrens { 1314831Sgw25295 ASSERT(mp->initialized == B_TRUE); 132789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 133789Sahrens if (0 == mutex_trylock(&mp->m_lock)) { 134789Sahrens ASSERT(mp->m_owner == NULL); 135789Sahrens mp->m_owner = curthread; 136789Sahrens return (1); 137789Sahrens } else { 138789Sahrens return (0); 139789Sahrens } 140789Sahrens } 141789Sahrens 142789Sahrens void 143789Sahrens mutex_exit(kmutex_t *mp) 144789Sahrens { 1454831Sgw25295 ASSERT(mp->initialized == B_TRUE); 146789Sahrens ASSERT(mutex_owner(mp) == curthread); 147789Sahrens mp->m_owner = NULL; 1482856Snd150628 VERIFY(mutex_unlock(&mp->m_lock) == 0); 149789Sahrens } 150789Sahrens 151789Sahrens void * 152789Sahrens mutex_owner(kmutex_t *mp) 153789Sahrens { 1544831Sgw25295 ASSERT(mp->initialized == B_TRUE); 155789Sahrens return (mp->m_owner); 156789Sahrens } 157789Sahrens 158789Sahrens /* 159789Sahrens * ========================================================================= 160789Sahrens * rwlocks 161789Sahrens * ========================================================================= 162789Sahrens */ 163789Sahrens /*ARGSUSED*/ 164789Sahrens void 165789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg) 166789Sahrens { 167789Sahrens rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL); 168789Sahrens rwlp->rw_owner = NULL; 1694831Sgw25295 rwlp->initialized = B_TRUE; 170789Sahrens } 171789Sahrens 172789Sahrens void 173789Sahrens rw_destroy(krwlock_t *rwlp) 174789Sahrens { 175789Sahrens rwlock_destroy(&rwlp->rw_lock); 176789Sahrens rwlp->rw_owner = (void *)-1UL; 1774831Sgw25295 rwlp->initialized = B_FALSE; 178789Sahrens } 179789Sahrens 180789Sahrens void 181789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw) 182789Sahrens { 183789Sahrens ASSERT(!RW_LOCK_HELD(rwlp)); 1844831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 185789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 186789Sahrens ASSERT(rwlp->rw_owner != curthread); 187789Sahrens 188789Sahrens if (rw == RW_READER) 189789Sahrens (void) rw_rdlock(&rwlp->rw_lock); 190789Sahrens else 191789Sahrens (void) rw_wrlock(&rwlp->rw_lock); 192789Sahrens 193789Sahrens rwlp->rw_owner = curthread; 194789Sahrens } 195789Sahrens 196789Sahrens void 197789Sahrens rw_exit(krwlock_t *rwlp) 198789Sahrens { 1994831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 200789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 201789Sahrens 202789Sahrens rwlp->rw_owner = NULL; 203789Sahrens (void) rw_unlock(&rwlp->rw_lock); 204789Sahrens } 205789Sahrens 206789Sahrens int 207789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw) 208789Sahrens { 209789Sahrens int rv; 210789Sahrens 2114831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 212789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 213789Sahrens 214789Sahrens if (rw == RW_READER) 215789Sahrens rv = rw_tryrdlock(&rwlp->rw_lock); 216789Sahrens else 217789Sahrens rv = rw_trywrlock(&rwlp->rw_lock); 218789Sahrens 219789Sahrens if (rv == 0) { 220789Sahrens rwlp->rw_owner = curthread; 221789Sahrens return (1); 222789Sahrens } 223789Sahrens 224789Sahrens return (0); 225789Sahrens } 226789Sahrens 227789Sahrens /*ARGSUSED*/ 228789Sahrens int 229789Sahrens rw_tryupgrade(krwlock_t *rwlp) 230789Sahrens { 2314831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 232789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 233789Sahrens 234789Sahrens return (0); 235789Sahrens } 236789Sahrens 237789Sahrens /* 238789Sahrens * ========================================================================= 239789Sahrens * condition variables 240789Sahrens * ========================================================================= 241789Sahrens */ 242789Sahrens /*ARGSUSED*/ 243789Sahrens void 244789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg) 245789Sahrens { 2462856Snd150628 VERIFY(cond_init(cv, type, NULL) == 0); 247789Sahrens } 248789Sahrens 249789Sahrens void 250789Sahrens cv_destroy(kcondvar_t *cv) 251789Sahrens { 2522856Snd150628 VERIFY(cond_destroy(cv) == 0); 253789Sahrens } 254789Sahrens 255789Sahrens void 256789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp) 257789Sahrens { 258789Sahrens ASSERT(mutex_owner(mp) == curthread); 259789Sahrens mp->m_owner = NULL; 2602856Snd150628 int ret = cond_wait(cv, &mp->m_lock); 2612856Snd150628 VERIFY(ret == 0 || ret == EINTR); 262789Sahrens mp->m_owner = curthread; 263789Sahrens } 264789Sahrens 265789Sahrens clock_t 266789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) 267789Sahrens { 268789Sahrens int error; 269789Sahrens timestruc_t ts; 270789Sahrens clock_t delta; 271789Sahrens 272789Sahrens top: 273789Sahrens delta = abstime - lbolt; 274789Sahrens if (delta <= 0) 275789Sahrens return (-1); 276789Sahrens 277789Sahrens ts.tv_sec = delta / hz; 278789Sahrens ts.tv_nsec = (delta % hz) * (NANOSEC / hz); 279789Sahrens 280789Sahrens ASSERT(mutex_owner(mp) == curthread); 281789Sahrens mp->m_owner = NULL; 282789Sahrens error = cond_reltimedwait(cv, &mp->m_lock, &ts); 283789Sahrens mp->m_owner = curthread; 284789Sahrens 285789Sahrens if (error == ETIME) 286789Sahrens return (-1); 287789Sahrens 288789Sahrens if (error == EINTR) 289789Sahrens goto top; 290789Sahrens 291789Sahrens ASSERT(error == 0); 292789Sahrens 293789Sahrens return (1); 294789Sahrens } 295789Sahrens 296789Sahrens void 297789Sahrens cv_signal(kcondvar_t *cv) 298789Sahrens { 2992856Snd150628 VERIFY(cond_signal(cv) == 0); 300789Sahrens } 301789Sahrens 302789Sahrens void 303789Sahrens cv_broadcast(kcondvar_t *cv) 304789Sahrens { 3052856Snd150628 VERIFY(cond_broadcast(cv) == 0); 306789Sahrens } 307789Sahrens 308789Sahrens /* 309789Sahrens * ========================================================================= 310789Sahrens * vnode operations 311789Sahrens * ========================================================================= 312789Sahrens */ 313789Sahrens /* 314789Sahrens * Note: for the xxxat() versions of these functions, we assume that the 315789Sahrens * starting vp is always rootdir (which is true for spa_directory.c, the only 316789Sahrens * ZFS consumer of these interfaces). We assert this is true, and then emulate 317789Sahrens * them by adding '/' in front of the path. 318789Sahrens */ 319789Sahrens 320789Sahrens /*ARGSUSED*/ 321789Sahrens int 322789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) 323789Sahrens { 324789Sahrens int fd; 325789Sahrens vnode_t *vp; 326789Sahrens int old_umask; 327789Sahrens char realpath[MAXPATHLEN]; 328789Sahrens struct stat64 st; 329789Sahrens 330789Sahrens /* 331789Sahrens * If we're accessing a real disk from userland, we need to use 332789Sahrens * the character interface to avoid caching. This is particularly 333789Sahrens * important if we're trying to look at a real in-kernel storage 334789Sahrens * pool from userland, e.g. via zdb, because otherwise we won't 335789Sahrens * see the changes occurring under the segmap cache. 336789Sahrens * On the other hand, the stupid character device returns zero 337789Sahrens * for its size. So -- gag -- we open the block device to get 338789Sahrens * its size, and remember it for subsequent VOP_GETATTR(). 339789Sahrens */ 340789Sahrens if (strncmp(path, "/dev/", 5) == 0) { 341789Sahrens char *dsk; 342789Sahrens fd = open64(path, O_RDONLY); 343789Sahrens if (fd == -1) 344789Sahrens return (errno); 345789Sahrens if (fstat64(fd, &st) == -1) { 346789Sahrens close(fd); 347789Sahrens return (errno); 348789Sahrens } 349789Sahrens close(fd); 350789Sahrens (void) sprintf(realpath, "%s", path); 351789Sahrens dsk = strstr(path, "/dsk/"); 352789Sahrens if (dsk != NULL) 353789Sahrens (void) sprintf(realpath + (dsk - path) + 1, "r%s", 354789Sahrens dsk + 1); 355789Sahrens } else { 356789Sahrens (void) sprintf(realpath, "%s", path); 357789Sahrens if (!(flags & FCREAT) && stat64(realpath, &st) == -1) 358789Sahrens return (errno); 359789Sahrens } 360789Sahrens 361789Sahrens if (flags & FCREAT) 362789Sahrens old_umask = umask(0); 363789Sahrens 364789Sahrens /* 365789Sahrens * The construct 'flags - FREAD' conveniently maps combinations of 366789Sahrens * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. 367789Sahrens */ 368789Sahrens fd = open64(realpath, flags - FREAD, mode); 369789Sahrens 370789Sahrens if (flags & FCREAT) 371789Sahrens (void) umask(old_umask); 372789Sahrens 373789Sahrens if (fd == -1) 374789Sahrens return (errno); 375789Sahrens 376789Sahrens if (fstat64(fd, &st) == -1) { 377789Sahrens close(fd); 378789Sahrens return (errno); 379789Sahrens } 380789Sahrens 381789Sahrens (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 382789Sahrens 383789Sahrens *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); 384789Sahrens 385789Sahrens vp->v_fd = fd; 386789Sahrens vp->v_size = st.st_size; 387789Sahrens vp->v_path = spa_strdup(path); 388789Sahrens 389789Sahrens return (0); 390789Sahrens } 391789Sahrens 3925331Samw /*ARGSUSED*/ 393789Sahrens int 394789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, 3955331Samw int x3, vnode_t *startvp, int fd) 396789Sahrens { 397789Sahrens char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); 398789Sahrens int ret; 399789Sahrens 400789Sahrens ASSERT(startvp == rootdir); 401789Sahrens (void) sprintf(realpath, "/%s", path); 402789Sahrens 4035331Samw /* fd ignored for now, need if want to simulate nbmand support */ 404789Sahrens ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); 405789Sahrens 406789Sahrens umem_free(realpath, strlen(path) + 2); 407789Sahrens 408789Sahrens return (ret); 409789Sahrens } 410789Sahrens 411789Sahrens /*ARGSUSED*/ 412789Sahrens int 413789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, 414789Sahrens int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) 415789Sahrens { 416789Sahrens ssize_t iolen, split; 417789Sahrens 418789Sahrens if (uio == UIO_READ) { 419789Sahrens iolen = pread64(vp->v_fd, addr, len, offset); 420789Sahrens } else { 421789Sahrens /* 422789Sahrens * To simulate partial disk writes, we split writes into two 423789Sahrens * system calls so that the process can be killed in between. 424789Sahrens */ 425789Sahrens split = (len > 0 ? rand() % len : 0); 426789Sahrens iolen = pwrite64(vp->v_fd, addr, split, offset); 427789Sahrens iolen += pwrite64(vp->v_fd, (char *)addr + split, 428789Sahrens len - split, offset + split); 429789Sahrens } 430789Sahrens 431789Sahrens if (iolen == -1) 432789Sahrens return (errno); 433789Sahrens if (residp) 434789Sahrens *residp = len - iolen; 435789Sahrens else if (iolen != len) 436789Sahrens return (EIO); 437789Sahrens return (0); 438789Sahrens } 439789Sahrens 440789Sahrens void 441789Sahrens vn_close(vnode_t *vp) 442789Sahrens { 443789Sahrens close(vp->v_fd); 444789Sahrens spa_strfree(vp->v_path); 445789Sahrens umem_free(vp, sizeof (vnode_t)); 446789Sahrens } 447789Sahrens 448789Sahrens #ifdef ZFS_DEBUG 449789Sahrens 450789Sahrens /* 451789Sahrens * ========================================================================= 452789Sahrens * Figure out which debugging statements to print 453789Sahrens * ========================================================================= 454789Sahrens */ 455789Sahrens 456789Sahrens static char *dprintf_string; 457789Sahrens static int dprintf_print_all; 458789Sahrens 459789Sahrens int 460789Sahrens dprintf_find_string(const char *string) 461789Sahrens { 462789Sahrens char *tmp_str = dprintf_string; 463789Sahrens int len = strlen(string); 464789Sahrens 465789Sahrens /* 466789Sahrens * Find out if this is a string we want to print. 467789Sahrens * String format: file1.c,function_name1,file2.c,file3.c 468789Sahrens */ 469789Sahrens 470789Sahrens while (tmp_str != NULL) { 471789Sahrens if (strncmp(tmp_str, string, len) == 0 && 472789Sahrens (tmp_str[len] == ',' || tmp_str[len] == '\0')) 473789Sahrens return (1); 474789Sahrens tmp_str = strchr(tmp_str, ','); 475789Sahrens if (tmp_str != NULL) 476789Sahrens tmp_str++; /* Get rid of , */ 477789Sahrens } 478789Sahrens return (0); 479789Sahrens } 480789Sahrens 481789Sahrens void 482789Sahrens dprintf_setup(int *argc, char **argv) 483789Sahrens { 484789Sahrens int i, j; 485789Sahrens 486789Sahrens /* 487789Sahrens * Debugging can be specified two ways: by setting the 488789Sahrens * environment variable ZFS_DEBUG, or by including a 489789Sahrens * "debug=..." argument on the command line. The command 490789Sahrens * line setting overrides the environment variable. 491789Sahrens */ 492789Sahrens 493789Sahrens for (i = 1; i < *argc; i++) { 494789Sahrens int len = strlen("debug="); 495789Sahrens /* First look for a command line argument */ 496789Sahrens if (strncmp("debug=", argv[i], len) == 0) { 497789Sahrens dprintf_string = argv[i] + len; 498789Sahrens /* Remove from args */ 499789Sahrens for (j = i; j < *argc; j++) 500789Sahrens argv[j] = argv[j+1]; 501789Sahrens argv[j] = NULL; 502789Sahrens (*argc)--; 503789Sahrens } 504789Sahrens } 505789Sahrens 506789Sahrens if (dprintf_string == NULL) { 507789Sahrens /* Look for ZFS_DEBUG environment variable */ 508789Sahrens dprintf_string = getenv("ZFS_DEBUG"); 509789Sahrens } 510789Sahrens 511789Sahrens /* 512789Sahrens * Are we just turning on all debugging? 513789Sahrens */ 514789Sahrens if (dprintf_find_string("on")) 515789Sahrens dprintf_print_all = 1; 516789Sahrens } 517789Sahrens 518789Sahrens /* 519789Sahrens * ========================================================================= 520789Sahrens * debug printfs 521789Sahrens * ========================================================================= 522789Sahrens */ 523789Sahrens void 524789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 525789Sahrens { 526789Sahrens const char *newfile; 527789Sahrens va_list adx; 528789Sahrens 529789Sahrens /* 530789Sahrens * Get rid of annoying "../common/" prefix to filename. 531789Sahrens */ 532789Sahrens newfile = strrchr(file, '/'); 533789Sahrens if (newfile != NULL) { 534789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 535789Sahrens } else { 536789Sahrens newfile = file; 537789Sahrens } 538789Sahrens 539789Sahrens if (dprintf_print_all || 540789Sahrens dprintf_find_string(newfile) || 541789Sahrens dprintf_find_string(func)) { 542789Sahrens /* Print out just the function name if requested */ 543789Sahrens flockfile(stdout); 544789Sahrens if (dprintf_find_string("pid")) 545789Sahrens (void) printf("%d ", getpid()); 546789Sahrens if (dprintf_find_string("tid")) 547789Sahrens (void) printf("%u ", thr_self()); 548789Sahrens if (dprintf_find_string("cpu")) 549789Sahrens (void) printf("%u ", getcpuid()); 550789Sahrens if (dprintf_find_string("time")) 551789Sahrens (void) printf("%llu ", gethrtime()); 552789Sahrens if (dprintf_find_string("long")) 553789Sahrens (void) printf("%s, line %d: ", newfile, line); 554789Sahrens (void) printf("%s: ", func); 555789Sahrens va_start(adx, fmt); 556789Sahrens (void) vprintf(fmt, adx); 557789Sahrens va_end(adx); 558789Sahrens funlockfile(stdout); 559789Sahrens } 560789Sahrens } 561789Sahrens 562789Sahrens #endif /* ZFS_DEBUG */ 563789Sahrens 564789Sahrens /* 565789Sahrens * ========================================================================= 566789Sahrens * cmn_err() and panic() 567789Sahrens * ========================================================================= 568789Sahrens */ 569789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 570789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 571789Sahrens 572789Sahrens void 573789Sahrens vpanic(const char *fmt, va_list adx) 574789Sahrens { 575789Sahrens (void) fprintf(stderr, "error: "); 576789Sahrens (void) vfprintf(stderr, fmt, adx); 577789Sahrens (void) fprintf(stderr, "\n"); 578789Sahrens 579789Sahrens abort(); /* think of it as a "user-level crash dump" */ 580789Sahrens } 581789Sahrens 582789Sahrens void 583789Sahrens panic(const char *fmt, ...) 584789Sahrens { 585789Sahrens va_list adx; 586789Sahrens 587789Sahrens va_start(adx, fmt); 588789Sahrens vpanic(fmt, adx); 589789Sahrens va_end(adx); 590789Sahrens } 591789Sahrens 5923713Sahrens void 5933713Sahrens vcmn_err(int ce, const char *fmt, va_list adx) 5943713Sahrens { 5953713Sahrens if (ce == CE_PANIC) 5963713Sahrens vpanic(fmt, adx); 5973713Sahrens if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ 5983713Sahrens (void) fprintf(stderr, "%s", ce_prefix[ce]); 5993713Sahrens (void) vfprintf(stderr, fmt, adx); 6003713Sahrens (void) fprintf(stderr, "%s", ce_suffix[ce]); 6013713Sahrens } 6023713Sahrens } 6033713Sahrens 604789Sahrens /*PRINTFLIKE2*/ 605789Sahrens void 606789Sahrens cmn_err(int ce, const char *fmt, ...) 607789Sahrens { 608789Sahrens va_list adx; 609789Sahrens 610789Sahrens va_start(adx, fmt); 6113713Sahrens vcmn_err(ce, fmt, adx); 612789Sahrens va_end(adx); 613789Sahrens } 614789Sahrens 615789Sahrens /* 616789Sahrens * ========================================================================= 6171544Seschrock * kobj interfaces 6181544Seschrock * ========================================================================= 6191544Seschrock */ 6201544Seschrock struct _buf * 6211544Seschrock kobj_open_file(char *name) 6221544Seschrock { 6231544Seschrock struct _buf *file; 6241544Seschrock vnode_t *vp; 6251544Seschrock 6261544Seschrock /* set vp as the _fd field of the file */ 6275331Samw if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir, 6285331Samw -1) != 0) 6291544Seschrock return ((void *)-1UL); 6301544Seschrock 6311544Seschrock file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 6321544Seschrock file->_fd = (intptr_t)vp; 6331544Seschrock return (file); 6341544Seschrock } 6351544Seschrock 6361544Seschrock int 6371544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 6381544Seschrock { 6391544Seschrock ssize_t resid; 6401544Seschrock 6411544Seschrock vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 6421544Seschrock UIO_SYSSPACE, 0, 0, 0, &resid); 6431544Seschrock 6443912Slling return (size - resid); 6451544Seschrock } 6461544Seschrock 6471544Seschrock void 6481544Seschrock kobj_close_file(struct _buf *file) 6491544Seschrock { 6501544Seschrock vn_close((vnode_t *)file->_fd); 6511544Seschrock umem_free(file, sizeof (struct _buf)); 6521544Seschrock } 6531544Seschrock 6541544Seschrock int 6553912Slling kobj_get_filesize(struct _buf *file, uint64_t *size) 6561544Seschrock { 6571544Seschrock struct stat64 st; 6583912Slling vnode_t *vp = (vnode_t *)file->_fd; 6593912Slling 6601544Seschrock if (fstat64(vp->v_fd, &st) == -1) { 6611544Seschrock vn_close(vp); 6621544Seschrock return (errno); 6631544Seschrock } 6643912Slling *size = st.st_size; 6651544Seschrock return (0); 6661544Seschrock } 6671544Seschrock 6681544Seschrock /* 6691544Seschrock * ========================================================================= 670789Sahrens * misc routines 671789Sahrens * ========================================================================= 672789Sahrens */ 673789Sahrens 674789Sahrens void 675789Sahrens delay(clock_t ticks) 676789Sahrens { 677789Sahrens poll(0, 0, ticks * (1000 / hz)); 678789Sahrens } 679789Sahrens 680789Sahrens /* 681789Sahrens * Find highest one bit set. 682789Sahrens * Returns bit number + 1 of highest bit that is set, otherwise returns 0. 683789Sahrens * High order bit is 31 (or 63 in _LP64 kernel). 684789Sahrens */ 685789Sahrens int 686789Sahrens highbit(ulong_t i) 687789Sahrens { 688789Sahrens register int h = 1; 689789Sahrens 690789Sahrens if (i == 0) 691789Sahrens return (0); 692789Sahrens #ifdef _LP64 693789Sahrens if (i & 0xffffffff00000000ul) { 694789Sahrens h += 32; i >>= 32; 695789Sahrens } 696789Sahrens #endif 697789Sahrens if (i & 0xffff0000) { 698789Sahrens h += 16; i >>= 16; 699789Sahrens } 700789Sahrens if (i & 0xff00) { 701789Sahrens h += 8; i >>= 8; 702789Sahrens } 703789Sahrens if (i & 0xf0) { 704789Sahrens h += 4; i >>= 4; 705789Sahrens } 706789Sahrens if (i & 0xc) { 707789Sahrens h += 2; i >>= 2; 708789Sahrens } 709789Sahrens if (i & 0x2) { 710789Sahrens h += 1; 711789Sahrens } 712789Sahrens return (h); 713789Sahrens } 714789Sahrens 715*5688Sbonwick static int random_fd = -1, urandom_fd = -1; 716*5688Sbonwick 717789Sahrens static int 718*5688Sbonwick random_get_bytes_common(uint8_t *ptr, size_t len, int fd) 719789Sahrens { 720789Sahrens size_t resid = len; 721789Sahrens ssize_t bytes; 722789Sahrens 723789Sahrens ASSERT(fd != -1); 724789Sahrens 725789Sahrens while (resid != 0) { 726789Sahrens bytes = read(fd, ptr, resid); 727*5688Sbonwick ASSERT3S(bytes, >=, 0); 728789Sahrens ptr += bytes; 729789Sahrens resid -= bytes; 730789Sahrens } 731789Sahrens 732789Sahrens return (0); 733789Sahrens } 734789Sahrens 735789Sahrens int 736789Sahrens random_get_bytes(uint8_t *ptr, size_t len) 737789Sahrens { 738*5688Sbonwick return (random_get_bytes_common(ptr, len, random_fd)); 739789Sahrens } 740789Sahrens 741789Sahrens int 742789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len) 743789Sahrens { 744*5688Sbonwick return (random_get_bytes_common(ptr, len, urandom_fd)); 745789Sahrens } 746789Sahrens 7473975Sek110237 int 7483975Sek110237 ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result) 7493975Sek110237 { 7503975Sek110237 char *end; 7513975Sek110237 7523975Sek110237 *result = strtoul(hw_serial, &end, base); 7533975Sek110237 if (*result == 0) 7543975Sek110237 return (errno); 7553975Sek110237 return (0); 7563975Sek110237 } 7573975Sek110237 758789Sahrens /* 759789Sahrens * ========================================================================= 760789Sahrens * kernel emulation setup & teardown 761789Sahrens * ========================================================================= 762789Sahrens */ 763789Sahrens static int 764789Sahrens umem_out_of_memory(void) 765789Sahrens { 766789Sahrens char errmsg[] = "out of memory -- generating core dump\n"; 767789Sahrens 768789Sahrens write(fileno(stderr), errmsg, sizeof (errmsg)); 769789Sahrens abort(); 770789Sahrens return (0); 771789Sahrens } 772789Sahrens 773789Sahrens void 774789Sahrens kernel_init(int mode) 775789Sahrens { 776789Sahrens umem_nofail_callback(umem_out_of_memory); 777789Sahrens 778789Sahrens physmem = sysconf(_SC_PHYS_PAGES); 779789Sahrens 780789Sahrens dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 781789Sahrens (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 782789Sahrens 7833975Sek110237 snprintf(hw_serial, sizeof (hw_serial), "%ld", gethostid()); 7843975Sek110237 785*5688Sbonwick VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1); 786*5688Sbonwick VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1); 787*5688Sbonwick 788789Sahrens spa_init(mode); 789789Sahrens } 790789Sahrens 791789Sahrens void 792789Sahrens kernel_fini(void) 793789Sahrens { 794789Sahrens spa_fini(); 795*5688Sbonwick 796*5688Sbonwick close(random_fd); 797*5688Sbonwick close(urandom_fd); 798*5688Sbonwick 799*5688Sbonwick random_fd = -1; 800*5688Sbonwick urandom_fd = -1; 801789Sahrens } 8023886Sahl 8033886Sahl int 8043886Sahl z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 8053886Sahl { 8063886Sahl int ret; 8073886Sahl uLongf len = *dstlen; 8083886Sahl 8093886Sahl if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK) 8103886Sahl *dstlen = (size_t)len; 8113886Sahl 8123886Sahl return (ret); 8133886Sahl } 8143886Sahl 8153886Sahl int 8163886Sahl z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen, 8173886Sahl int level) 8183886Sahl { 8193886Sahl int ret; 8203886Sahl uLongf len = *dstlen; 8213886Sahl 8223886Sahl if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK) 8233886Sahl *dstlen = (size_t)len; 8243886Sahl 8253886Sahl return (ret); 8263886Sahl } 8274543Smarks 8285331Samw /*ARGSUSED*/ 8295331Samw size_t u8_textprep_str(char *i, size_t *il, char *o, size_t *ol, int nf, 8305331Samw size_t vers, int *err) 8315331Samw { 8325331Samw *err = EINVAL; 8335331Samw return ((size_t)-1); 8345331Samw } 8355331Samw 8364543Smarks uid_t 8374543Smarks crgetuid(cred_t *cr) 8384543Smarks { 8394543Smarks return (0); 8404543Smarks } 8414543Smarks 8424543Smarks gid_t 8434543Smarks crgetgid(cred_t *cr) 8444543Smarks { 8454543Smarks return (0); 8464543Smarks } 8474543Smarks 8484543Smarks int 8494543Smarks crgetngroups(cred_t *cr) 8504543Smarks { 8514543Smarks return (0); 8524543Smarks } 8534543Smarks 8544543Smarks gid_t * 8554543Smarks crgetgroups(cred_t *cr) 8564543Smarks { 8574543Smarks return (NULL); 8584543Smarks } 8594543Smarks 8604543Smarks int 8614543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 8624543Smarks { 8634543Smarks return (0); 8644543Smarks } 8654543Smarks 8664543Smarks int 8674543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 8684543Smarks { 8694543Smarks return (0); 8704543Smarks } 8714543Smarks 8724543Smarks int 8734543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 8744543Smarks { 8754543Smarks return (0); 8764543Smarks } 877