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 /* 225959Smarks * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #include <assert.h> 273886Sahl #include <fcntl.h> 28789Sahrens #include <poll.h> 29789Sahrens #include <stdio.h> 30789Sahrens #include <stdlib.h> 313886Sahl #include <string.h> 323886Sahl #include <zlib.h> 33789Sahrens #include <sys/spa.h> 343886Sahl #include <sys/stat.h> 35789Sahrens #include <sys/processor.h> 363886Sahl #include <sys/zfs_context.h> 373886Sahl #include <sys/zmod.h> 383975Sek110237 #include <sys/utsname.h> 392856Snd150628 40789Sahrens /* 41789Sahrens * Emulation of kernel services in userland. 42789Sahrens */ 43789Sahrens 44789Sahrens uint64_t physmem; 45789Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234; 463975Sek110237 char hw_serial[11]; 473975Sek110237 483975Sek110237 struct utsname utsname = { 493975Sek110237 "userland", "libzpool", "1", "1", "na" 503975Sek110237 }; 51789Sahrens 52789Sahrens /* 53789Sahrens * ========================================================================= 54789Sahrens * threads 55789Sahrens * ========================================================================= 56789Sahrens */ 57789Sahrens /*ARGSUSED*/ 58789Sahrens kthread_t * 59789Sahrens zk_thread_create(void (*func)(), void *arg) 60789Sahrens { 61789Sahrens thread_t tid; 62789Sahrens 63789Sahrens VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED, 64789Sahrens &tid) == 0); 65789Sahrens 66789Sahrens return ((void *)(uintptr_t)tid); 67789Sahrens } 68789Sahrens 69789Sahrens /* 70789Sahrens * ========================================================================= 713403Sbmc * kstats 723403Sbmc * ========================================================================= 733403Sbmc */ 743403Sbmc /*ARGSUSED*/ 753403Sbmc kstat_t * 763403Sbmc kstat_create(char *module, int instance, char *name, char *class, 773403Sbmc uchar_t type, ulong_t ndata, uchar_t ks_flag) 783403Sbmc { 793403Sbmc return (NULL); 803403Sbmc } 813403Sbmc 823403Sbmc /*ARGSUSED*/ 833403Sbmc void 843403Sbmc kstat_install(kstat_t *ksp) 853403Sbmc {} 863403Sbmc 873403Sbmc /*ARGSUSED*/ 883403Sbmc void 893403Sbmc kstat_delete(kstat_t *ksp) 903403Sbmc {} 913403Sbmc 923403Sbmc /* 933403Sbmc * ========================================================================= 94789Sahrens * mutexes 95789Sahrens * ========================================================================= 96789Sahrens */ 97789Sahrens void 98789Sahrens zmutex_init(kmutex_t *mp) 99789Sahrens { 100789Sahrens mp->m_owner = NULL; 1014831Sgw25295 mp->initialized = B_TRUE; 102789Sahrens (void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL); 103789Sahrens } 104789Sahrens 105789Sahrens void 106789Sahrens zmutex_destroy(kmutex_t *mp) 107789Sahrens { 1084831Sgw25295 ASSERT(mp->initialized == B_TRUE); 109789Sahrens ASSERT(mp->m_owner == NULL); 110789Sahrens (void) _mutex_destroy(&(mp)->m_lock); 111789Sahrens mp->m_owner = (void *)-1UL; 1124831Sgw25295 mp->initialized = B_FALSE; 113789Sahrens } 114789Sahrens 115789Sahrens void 116789Sahrens mutex_enter(kmutex_t *mp) 117789Sahrens { 1184831Sgw25295 ASSERT(mp->initialized == B_TRUE); 119789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 120789Sahrens ASSERT(mp->m_owner != curthread); 1212856Snd150628 VERIFY(mutex_lock(&mp->m_lock) == 0); 122789Sahrens ASSERT(mp->m_owner == NULL); 123789Sahrens mp->m_owner = curthread; 124789Sahrens } 125789Sahrens 126789Sahrens int 127789Sahrens mutex_tryenter(kmutex_t *mp) 128789Sahrens { 1294831Sgw25295 ASSERT(mp->initialized == B_TRUE); 130789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 131789Sahrens if (0 == mutex_trylock(&mp->m_lock)) { 132789Sahrens ASSERT(mp->m_owner == NULL); 133789Sahrens mp->m_owner = curthread; 134789Sahrens return (1); 135789Sahrens } else { 136789Sahrens return (0); 137789Sahrens } 138789Sahrens } 139789Sahrens 140789Sahrens void 141789Sahrens mutex_exit(kmutex_t *mp) 142789Sahrens { 1434831Sgw25295 ASSERT(mp->initialized == B_TRUE); 144789Sahrens ASSERT(mutex_owner(mp) == curthread); 145789Sahrens mp->m_owner = NULL; 1462856Snd150628 VERIFY(mutex_unlock(&mp->m_lock) == 0); 147789Sahrens } 148789Sahrens 149789Sahrens void * 150789Sahrens mutex_owner(kmutex_t *mp) 151789Sahrens { 1524831Sgw25295 ASSERT(mp->initialized == B_TRUE); 153789Sahrens return (mp->m_owner); 154789Sahrens } 155789Sahrens 156789Sahrens /* 157789Sahrens * ========================================================================= 158789Sahrens * rwlocks 159789Sahrens * ========================================================================= 160789Sahrens */ 161789Sahrens /*ARGSUSED*/ 162789Sahrens void 163789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg) 164789Sahrens { 165789Sahrens rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL); 166789Sahrens rwlp->rw_owner = NULL; 1674831Sgw25295 rwlp->initialized = B_TRUE; 168789Sahrens } 169789Sahrens 170789Sahrens void 171789Sahrens rw_destroy(krwlock_t *rwlp) 172789Sahrens { 173789Sahrens rwlock_destroy(&rwlp->rw_lock); 174789Sahrens rwlp->rw_owner = (void *)-1UL; 1754831Sgw25295 rwlp->initialized = B_FALSE; 176789Sahrens } 177789Sahrens 178789Sahrens void 179789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw) 180789Sahrens { 181789Sahrens ASSERT(!RW_LOCK_HELD(rwlp)); 1824831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 183789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 184789Sahrens ASSERT(rwlp->rw_owner != curthread); 185789Sahrens 186789Sahrens if (rw == RW_READER) 1876689Smaybee VERIFY(rw_rdlock(&rwlp->rw_lock) == 0); 188789Sahrens else 1896689Smaybee VERIFY(rw_wrlock(&rwlp->rw_lock) == 0); 190789Sahrens 191789Sahrens rwlp->rw_owner = curthread; 192789Sahrens } 193789Sahrens 194789Sahrens void 195789Sahrens rw_exit(krwlock_t *rwlp) 196789Sahrens { 1974831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 198789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 199789Sahrens 200789Sahrens rwlp->rw_owner = NULL; 2016689Smaybee VERIFY(rw_unlock(&rwlp->rw_lock) == 0); 202789Sahrens } 203789Sahrens 204789Sahrens int 205789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw) 206789Sahrens { 207789Sahrens int rv; 208789Sahrens 2094831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 210789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 211789Sahrens 212789Sahrens if (rw == RW_READER) 213789Sahrens rv = rw_tryrdlock(&rwlp->rw_lock); 214789Sahrens else 215789Sahrens rv = rw_trywrlock(&rwlp->rw_lock); 216789Sahrens 217789Sahrens if (rv == 0) { 218789Sahrens rwlp->rw_owner = curthread; 219789Sahrens return (1); 220789Sahrens } 221789Sahrens 222789Sahrens return (0); 223789Sahrens } 224789Sahrens 225789Sahrens /*ARGSUSED*/ 226789Sahrens int 227789Sahrens rw_tryupgrade(krwlock_t *rwlp) 228789Sahrens { 2294831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 230789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 231789Sahrens 232789Sahrens return (0); 233789Sahrens } 234789Sahrens 235789Sahrens /* 236789Sahrens * ========================================================================= 237789Sahrens * condition variables 238789Sahrens * ========================================================================= 239789Sahrens */ 240789Sahrens /*ARGSUSED*/ 241789Sahrens void 242789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg) 243789Sahrens { 2442856Snd150628 VERIFY(cond_init(cv, type, NULL) == 0); 245789Sahrens } 246789Sahrens 247789Sahrens void 248789Sahrens cv_destroy(kcondvar_t *cv) 249789Sahrens { 2502856Snd150628 VERIFY(cond_destroy(cv) == 0); 251789Sahrens } 252789Sahrens 253789Sahrens void 254789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp) 255789Sahrens { 256789Sahrens ASSERT(mutex_owner(mp) == curthread); 257789Sahrens mp->m_owner = NULL; 2582856Snd150628 int ret = cond_wait(cv, &mp->m_lock); 2592856Snd150628 VERIFY(ret == 0 || ret == EINTR); 260789Sahrens mp->m_owner = curthread; 261789Sahrens } 262789Sahrens 263789Sahrens clock_t 264789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) 265789Sahrens { 266789Sahrens int error; 267789Sahrens timestruc_t ts; 268789Sahrens clock_t delta; 269789Sahrens 270789Sahrens top: 271789Sahrens delta = abstime - lbolt; 272789Sahrens if (delta <= 0) 273789Sahrens return (-1); 274789Sahrens 275789Sahrens ts.tv_sec = delta / hz; 276789Sahrens ts.tv_nsec = (delta % hz) * (NANOSEC / hz); 277789Sahrens 278789Sahrens ASSERT(mutex_owner(mp) == curthread); 279789Sahrens mp->m_owner = NULL; 280789Sahrens error = cond_reltimedwait(cv, &mp->m_lock, &ts); 281789Sahrens mp->m_owner = curthread; 282789Sahrens 283789Sahrens if (error == ETIME) 284789Sahrens return (-1); 285789Sahrens 286789Sahrens if (error == EINTR) 287789Sahrens goto top; 288789Sahrens 289789Sahrens ASSERT(error == 0); 290789Sahrens 291789Sahrens return (1); 292789Sahrens } 293789Sahrens 294789Sahrens void 295789Sahrens cv_signal(kcondvar_t *cv) 296789Sahrens { 2972856Snd150628 VERIFY(cond_signal(cv) == 0); 298789Sahrens } 299789Sahrens 300789Sahrens void 301789Sahrens cv_broadcast(kcondvar_t *cv) 302789Sahrens { 3032856Snd150628 VERIFY(cond_broadcast(cv) == 0); 304789Sahrens } 305789Sahrens 306789Sahrens /* 307789Sahrens * ========================================================================= 308789Sahrens * vnode operations 309789Sahrens * ========================================================================= 310789Sahrens */ 311789Sahrens /* 312789Sahrens * Note: for the xxxat() versions of these functions, we assume that the 313789Sahrens * starting vp is always rootdir (which is true for spa_directory.c, the only 314789Sahrens * ZFS consumer of these interfaces). We assert this is true, and then emulate 315789Sahrens * them by adding '/' in front of the path. 316789Sahrens */ 317789Sahrens 318789Sahrens /*ARGSUSED*/ 319789Sahrens int 320789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) 321789Sahrens { 322789Sahrens int fd; 323789Sahrens vnode_t *vp; 324789Sahrens int old_umask; 325789Sahrens char realpath[MAXPATHLEN]; 326789Sahrens struct stat64 st; 327789Sahrens 328789Sahrens /* 329789Sahrens * If we're accessing a real disk from userland, we need to use 330789Sahrens * the character interface to avoid caching. This is particularly 331789Sahrens * important if we're trying to look at a real in-kernel storage 332789Sahrens * pool from userland, e.g. via zdb, because otherwise we won't 333789Sahrens * see the changes occurring under the segmap cache. 334789Sahrens * On the other hand, the stupid character device returns zero 335789Sahrens * for its size. So -- gag -- we open the block device to get 336789Sahrens * its size, and remember it for subsequent VOP_GETATTR(). 337789Sahrens */ 338789Sahrens if (strncmp(path, "/dev/", 5) == 0) { 339789Sahrens char *dsk; 340789Sahrens fd = open64(path, O_RDONLY); 341789Sahrens if (fd == -1) 342789Sahrens return (errno); 343789Sahrens if (fstat64(fd, &st) == -1) { 344789Sahrens close(fd); 345789Sahrens return (errno); 346789Sahrens } 347789Sahrens close(fd); 348789Sahrens (void) sprintf(realpath, "%s", path); 349789Sahrens dsk = strstr(path, "/dsk/"); 350789Sahrens if (dsk != NULL) 351789Sahrens (void) sprintf(realpath + (dsk - path) + 1, "r%s", 352789Sahrens dsk + 1); 353789Sahrens } else { 354789Sahrens (void) sprintf(realpath, "%s", path); 355789Sahrens if (!(flags & FCREAT) && stat64(realpath, &st) == -1) 356789Sahrens return (errno); 357789Sahrens } 358789Sahrens 359789Sahrens if (flags & FCREAT) 360789Sahrens old_umask = umask(0); 361789Sahrens 362789Sahrens /* 363789Sahrens * The construct 'flags - FREAD' conveniently maps combinations of 364789Sahrens * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. 365789Sahrens */ 366789Sahrens fd = open64(realpath, flags - FREAD, mode); 367789Sahrens 368789Sahrens if (flags & FCREAT) 369789Sahrens (void) umask(old_umask); 370789Sahrens 371789Sahrens if (fd == -1) 372789Sahrens return (errno); 373789Sahrens 374789Sahrens if (fstat64(fd, &st) == -1) { 375789Sahrens close(fd); 376789Sahrens return (errno); 377789Sahrens } 378789Sahrens 379789Sahrens (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 380789Sahrens 381789Sahrens *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); 382789Sahrens 383789Sahrens vp->v_fd = fd; 384789Sahrens vp->v_size = st.st_size; 385789Sahrens vp->v_path = spa_strdup(path); 386789Sahrens 387789Sahrens return (0); 388789Sahrens } 389789Sahrens 3905331Samw /*ARGSUSED*/ 391789Sahrens int 392789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, 3935331Samw int x3, vnode_t *startvp, int fd) 394789Sahrens { 395789Sahrens char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); 396789Sahrens int ret; 397789Sahrens 398789Sahrens ASSERT(startvp == rootdir); 399789Sahrens (void) sprintf(realpath, "/%s", path); 400789Sahrens 4015331Samw /* fd ignored for now, need if want to simulate nbmand support */ 402789Sahrens ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); 403789Sahrens 404789Sahrens umem_free(realpath, strlen(path) + 2); 405789Sahrens 406789Sahrens return (ret); 407789Sahrens } 408789Sahrens 409789Sahrens /*ARGSUSED*/ 410789Sahrens int 411789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, 412789Sahrens int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) 413789Sahrens { 414789Sahrens ssize_t iolen, split; 415789Sahrens 416789Sahrens if (uio == UIO_READ) { 417789Sahrens iolen = pread64(vp->v_fd, addr, len, offset); 418789Sahrens } else { 419789Sahrens /* 420789Sahrens * To simulate partial disk writes, we split writes into two 421789Sahrens * system calls so that the process can be killed in between. 422789Sahrens */ 423789Sahrens split = (len > 0 ? rand() % len : 0); 424789Sahrens iolen = pwrite64(vp->v_fd, addr, split, offset); 425789Sahrens iolen += pwrite64(vp->v_fd, (char *)addr + split, 426789Sahrens len - split, offset + split); 427789Sahrens } 428789Sahrens 429789Sahrens if (iolen == -1) 430789Sahrens return (errno); 431789Sahrens if (residp) 432789Sahrens *residp = len - iolen; 433789Sahrens else if (iolen != len) 434789Sahrens return (EIO); 435789Sahrens return (0); 436789Sahrens } 437789Sahrens 438789Sahrens void 439789Sahrens vn_close(vnode_t *vp) 440789Sahrens { 441789Sahrens close(vp->v_fd); 442789Sahrens spa_strfree(vp->v_path); 443789Sahrens umem_free(vp, sizeof (vnode_t)); 444789Sahrens } 445789Sahrens 446789Sahrens #ifdef ZFS_DEBUG 447789Sahrens 448789Sahrens /* 449789Sahrens * ========================================================================= 450789Sahrens * Figure out which debugging statements to print 451789Sahrens * ========================================================================= 452789Sahrens */ 453789Sahrens 454789Sahrens static char *dprintf_string; 455789Sahrens static int dprintf_print_all; 456789Sahrens 457789Sahrens int 458789Sahrens dprintf_find_string(const char *string) 459789Sahrens { 460789Sahrens char *tmp_str = dprintf_string; 461789Sahrens int len = strlen(string); 462789Sahrens 463789Sahrens /* 464789Sahrens * Find out if this is a string we want to print. 465789Sahrens * String format: file1.c,function_name1,file2.c,file3.c 466789Sahrens */ 467789Sahrens 468789Sahrens while (tmp_str != NULL) { 469789Sahrens if (strncmp(tmp_str, string, len) == 0 && 470789Sahrens (tmp_str[len] == ',' || tmp_str[len] == '\0')) 471789Sahrens return (1); 472789Sahrens tmp_str = strchr(tmp_str, ','); 473789Sahrens if (tmp_str != NULL) 474789Sahrens tmp_str++; /* Get rid of , */ 475789Sahrens } 476789Sahrens return (0); 477789Sahrens } 478789Sahrens 479789Sahrens void 480789Sahrens dprintf_setup(int *argc, char **argv) 481789Sahrens { 482789Sahrens int i, j; 483789Sahrens 484789Sahrens /* 485789Sahrens * Debugging can be specified two ways: by setting the 486789Sahrens * environment variable ZFS_DEBUG, or by including a 487789Sahrens * "debug=..." argument on the command line. The command 488789Sahrens * line setting overrides the environment variable. 489789Sahrens */ 490789Sahrens 491789Sahrens for (i = 1; i < *argc; i++) { 492789Sahrens int len = strlen("debug="); 493789Sahrens /* First look for a command line argument */ 494789Sahrens if (strncmp("debug=", argv[i], len) == 0) { 495789Sahrens dprintf_string = argv[i] + len; 496789Sahrens /* Remove from args */ 497789Sahrens for (j = i; j < *argc; j++) 498789Sahrens argv[j] = argv[j+1]; 499789Sahrens argv[j] = NULL; 500789Sahrens (*argc)--; 501789Sahrens } 502789Sahrens } 503789Sahrens 504789Sahrens if (dprintf_string == NULL) { 505789Sahrens /* Look for ZFS_DEBUG environment variable */ 506789Sahrens dprintf_string = getenv("ZFS_DEBUG"); 507789Sahrens } 508789Sahrens 509789Sahrens /* 510789Sahrens * Are we just turning on all debugging? 511789Sahrens */ 512789Sahrens if (dprintf_find_string("on")) 513789Sahrens dprintf_print_all = 1; 514789Sahrens } 515789Sahrens 516789Sahrens /* 517789Sahrens * ========================================================================= 518789Sahrens * debug printfs 519789Sahrens * ========================================================================= 520789Sahrens */ 521789Sahrens void 522789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 523789Sahrens { 524789Sahrens const char *newfile; 525789Sahrens va_list adx; 526789Sahrens 527789Sahrens /* 528789Sahrens * Get rid of annoying "../common/" prefix to filename. 529789Sahrens */ 530789Sahrens newfile = strrchr(file, '/'); 531789Sahrens if (newfile != NULL) { 532789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 533789Sahrens } else { 534789Sahrens newfile = file; 535789Sahrens } 536789Sahrens 537789Sahrens if (dprintf_print_all || 538789Sahrens dprintf_find_string(newfile) || 539789Sahrens dprintf_find_string(func)) { 540789Sahrens /* Print out just the function name if requested */ 541789Sahrens flockfile(stdout); 542789Sahrens if (dprintf_find_string("pid")) 543789Sahrens (void) printf("%d ", getpid()); 544789Sahrens if (dprintf_find_string("tid")) 545789Sahrens (void) printf("%u ", thr_self()); 546789Sahrens if (dprintf_find_string("cpu")) 547789Sahrens (void) printf("%u ", getcpuid()); 548789Sahrens if (dprintf_find_string("time")) 549789Sahrens (void) printf("%llu ", gethrtime()); 550789Sahrens if (dprintf_find_string("long")) 551789Sahrens (void) printf("%s, line %d: ", newfile, line); 552789Sahrens (void) printf("%s: ", func); 553789Sahrens va_start(adx, fmt); 554789Sahrens (void) vprintf(fmt, adx); 555789Sahrens va_end(adx); 556789Sahrens funlockfile(stdout); 557789Sahrens } 558789Sahrens } 559789Sahrens 560789Sahrens #endif /* ZFS_DEBUG */ 561789Sahrens 562789Sahrens /* 563789Sahrens * ========================================================================= 564789Sahrens * cmn_err() and panic() 565789Sahrens * ========================================================================= 566789Sahrens */ 567789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 568789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 569789Sahrens 570789Sahrens void 571789Sahrens vpanic(const char *fmt, va_list adx) 572789Sahrens { 573789Sahrens (void) fprintf(stderr, "error: "); 574789Sahrens (void) vfprintf(stderr, fmt, adx); 575789Sahrens (void) fprintf(stderr, "\n"); 576789Sahrens 577789Sahrens abort(); /* think of it as a "user-level crash dump" */ 578789Sahrens } 579789Sahrens 580789Sahrens void 581789Sahrens panic(const char *fmt, ...) 582789Sahrens { 583789Sahrens va_list adx; 584789Sahrens 585789Sahrens va_start(adx, fmt); 586789Sahrens vpanic(fmt, adx); 587789Sahrens va_end(adx); 588789Sahrens } 589789Sahrens 5903713Sahrens void 5913713Sahrens vcmn_err(int ce, const char *fmt, va_list adx) 5923713Sahrens { 5933713Sahrens if (ce == CE_PANIC) 5943713Sahrens vpanic(fmt, adx); 5953713Sahrens if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ 5963713Sahrens (void) fprintf(stderr, "%s", ce_prefix[ce]); 5973713Sahrens (void) vfprintf(stderr, fmt, adx); 5983713Sahrens (void) fprintf(stderr, "%s", ce_suffix[ce]); 5993713Sahrens } 6003713Sahrens } 6013713Sahrens 602789Sahrens /*PRINTFLIKE2*/ 603789Sahrens void 604789Sahrens cmn_err(int ce, const char *fmt, ...) 605789Sahrens { 606789Sahrens va_list adx; 607789Sahrens 608789Sahrens va_start(adx, fmt); 6093713Sahrens vcmn_err(ce, fmt, adx); 610789Sahrens va_end(adx); 611789Sahrens } 612789Sahrens 613789Sahrens /* 614789Sahrens * ========================================================================= 6151544Seschrock * kobj interfaces 6161544Seschrock * ========================================================================= 6171544Seschrock */ 6181544Seschrock struct _buf * 6191544Seschrock kobj_open_file(char *name) 6201544Seschrock { 6211544Seschrock struct _buf *file; 6221544Seschrock vnode_t *vp; 6231544Seschrock 6241544Seschrock /* set vp as the _fd field of the file */ 6255331Samw if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir, 6265331Samw -1) != 0) 6271544Seschrock return ((void *)-1UL); 6281544Seschrock 6291544Seschrock file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 6301544Seschrock file->_fd = (intptr_t)vp; 6311544Seschrock return (file); 6321544Seschrock } 6331544Seschrock 6341544Seschrock int 6351544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 6361544Seschrock { 6371544Seschrock ssize_t resid; 6381544Seschrock 6391544Seschrock vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 6401544Seschrock UIO_SYSSPACE, 0, 0, 0, &resid); 6411544Seschrock 6423912Slling return (size - resid); 6431544Seschrock } 6441544Seschrock 6451544Seschrock void 6461544Seschrock kobj_close_file(struct _buf *file) 6471544Seschrock { 6481544Seschrock vn_close((vnode_t *)file->_fd); 6491544Seschrock umem_free(file, sizeof (struct _buf)); 6501544Seschrock } 6511544Seschrock 6521544Seschrock int 6533912Slling kobj_get_filesize(struct _buf *file, uint64_t *size) 6541544Seschrock { 6551544Seschrock struct stat64 st; 6563912Slling vnode_t *vp = (vnode_t *)file->_fd; 6573912Slling 6581544Seschrock if (fstat64(vp->v_fd, &st) == -1) { 6591544Seschrock vn_close(vp); 6601544Seschrock return (errno); 6611544Seschrock } 6623912Slling *size = st.st_size; 6631544Seschrock return (0); 6641544Seschrock } 6651544Seschrock 6661544Seschrock /* 6671544Seschrock * ========================================================================= 668789Sahrens * misc routines 669789Sahrens * ========================================================================= 670789Sahrens */ 671789Sahrens 672789Sahrens void 673789Sahrens delay(clock_t ticks) 674789Sahrens { 675789Sahrens poll(0, 0, ticks * (1000 / hz)); 676789Sahrens } 677789Sahrens 678789Sahrens /* 679789Sahrens * Find highest one bit set. 680789Sahrens * Returns bit number + 1 of highest bit that is set, otherwise returns 0. 681789Sahrens * High order bit is 31 (or 63 in _LP64 kernel). 682789Sahrens */ 683789Sahrens int 684789Sahrens highbit(ulong_t i) 685789Sahrens { 686789Sahrens register int h = 1; 687789Sahrens 688789Sahrens if (i == 0) 689789Sahrens return (0); 690789Sahrens #ifdef _LP64 691789Sahrens if (i & 0xffffffff00000000ul) { 692789Sahrens h += 32; i >>= 32; 693789Sahrens } 694789Sahrens #endif 695789Sahrens if (i & 0xffff0000) { 696789Sahrens h += 16; i >>= 16; 697789Sahrens } 698789Sahrens if (i & 0xff00) { 699789Sahrens h += 8; i >>= 8; 700789Sahrens } 701789Sahrens if (i & 0xf0) { 702789Sahrens h += 4; i >>= 4; 703789Sahrens } 704789Sahrens if (i & 0xc) { 705789Sahrens h += 2; i >>= 2; 706789Sahrens } 707789Sahrens if (i & 0x2) { 708789Sahrens h += 1; 709789Sahrens } 710789Sahrens return (h); 711789Sahrens } 712789Sahrens 7135688Sbonwick static int random_fd = -1, urandom_fd = -1; 7145688Sbonwick 715789Sahrens static int 7165688Sbonwick random_get_bytes_common(uint8_t *ptr, size_t len, int fd) 717789Sahrens { 718789Sahrens size_t resid = len; 719789Sahrens ssize_t bytes; 720789Sahrens 721789Sahrens ASSERT(fd != -1); 722789Sahrens 723789Sahrens while (resid != 0) { 724789Sahrens bytes = read(fd, ptr, resid); 7255688Sbonwick ASSERT3S(bytes, >=, 0); 726789Sahrens ptr += bytes; 727789Sahrens resid -= bytes; 728789Sahrens } 729789Sahrens 730789Sahrens return (0); 731789Sahrens } 732789Sahrens 733789Sahrens int 734789Sahrens random_get_bytes(uint8_t *ptr, size_t len) 735789Sahrens { 7365688Sbonwick return (random_get_bytes_common(ptr, len, random_fd)); 737789Sahrens } 738789Sahrens 739789Sahrens int 740789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len) 741789Sahrens { 7425688Sbonwick return (random_get_bytes_common(ptr, len, urandom_fd)); 743789Sahrens } 744789Sahrens 7453975Sek110237 int 7463975Sek110237 ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result) 7473975Sek110237 { 7483975Sek110237 char *end; 7493975Sek110237 7503975Sek110237 *result = strtoul(hw_serial, &end, base); 7513975Sek110237 if (*result == 0) 7523975Sek110237 return (errno); 7533975Sek110237 return (0); 7543975Sek110237 } 7553975Sek110237 756789Sahrens /* 757789Sahrens * ========================================================================= 758789Sahrens * kernel emulation setup & teardown 759789Sahrens * ========================================================================= 760789Sahrens */ 761789Sahrens static int 762789Sahrens umem_out_of_memory(void) 763789Sahrens { 764789Sahrens char errmsg[] = "out of memory -- generating core dump\n"; 765789Sahrens 766789Sahrens write(fileno(stderr), errmsg, sizeof (errmsg)); 767789Sahrens abort(); 768789Sahrens return (0); 769789Sahrens } 770789Sahrens 771789Sahrens void 772789Sahrens kernel_init(int mode) 773789Sahrens { 774789Sahrens umem_nofail_callback(umem_out_of_memory); 775789Sahrens 776789Sahrens physmem = sysconf(_SC_PHYS_PAGES); 777789Sahrens 778789Sahrens dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 779789Sahrens (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 780789Sahrens 7813975Sek110237 snprintf(hw_serial, sizeof (hw_serial), "%ld", gethostid()); 7823975Sek110237 7835688Sbonwick VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1); 7845688Sbonwick VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1); 7855688Sbonwick 786*7837SMatthew.Ahrens@Sun.COM system_taskq_init(); 787*7837SMatthew.Ahrens@Sun.COM 788789Sahrens spa_init(mode); 789789Sahrens } 790789Sahrens 791789Sahrens void 792789Sahrens kernel_fini(void) 793789Sahrens { 794789Sahrens spa_fini(); 7955688Sbonwick 7965688Sbonwick close(random_fd); 7975688Sbonwick close(urandom_fd); 7985688Sbonwick 7995688Sbonwick random_fd = -1; 8005688Sbonwick 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 8284543Smarks uid_t 8294543Smarks crgetuid(cred_t *cr) 8304543Smarks { 8314543Smarks return (0); 8324543Smarks } 8334543Smarks 8344543Smarks gid_t 8354543Smarks crgetgid(cred_t *cr) 8364543Smarks { 8374543Smarks return (0); 8384543Smarks } 8394543Smarks 8404543Smarks int 8414543Smarks crgetngroups(cred_t *cr) 8424543Smarks { 8434543Smarks return (0); 8444543Smarks } 8454543Smarks 8464543Smarks gid_t * 8474543Smarks crgetgroups(cred_t *cr) 8484543Smarks { 8494543Smarks return (NULL); 8504543Smarks } 8514543Smarks 8524543Smarks int 8534543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 8544543Smarks { 8554543Smarks return (0); 8564543Smarks } 8574543Smarks 8584543Smarks int 8594543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 8604543Smarks { 8614543Smarks return (0); 8624543Smarks } 8634543Smarks 8644543Smarks int 8654543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 8664543Smarks { 8674543Smarks return (0); 8684543Smarks } 8695959Smarks 8705959Smarks ksiddomain_t * 8715959Smarks ksid_lookupdomain(const char *dom) 8725959Smarks { 8735959Smarks ksiddomain_t *kd; 8745959Smarks 8755959Smarks kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL); 8765959Smarks kd->kd_name = spa_strdup(dom); 8775959Smarks return (kd); 8785959Smarks } 8795959Smarks 8805959Smarks void 8815959Smarks ksiddomain_rele(ksiddomain_t *ksid) 8825959Smarks { 8835959Smarks spa_strfree(ksid->kd_name); 8845959Smarks umem_free(ksid, sizeof (ksiddomain_t)); 8855959Smarks } 886