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; 103789Sahrens (void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL); 104789Sahrens } 105789Sahrens 106789Sahrens void 107789Sahrens zmutex_destroy(kmutex_t *mp) 108789Sahrens { 109789Sahrens ASSERT(mp->m_owner == NULL); 110789Sahrens (void) _mutex_destroy(&(mp)->m_lock); 111789Sahrens mp->m_owner = (void *)-1UL; 112789Sahrens } 113789Sahrens 114789Sahrens void 115789Sahrens mutex_enter(kmutex_t *mp) 116789Sahrens { 117789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 118789Sahrens ASSERT(mp->m_owner != curthread); 1192856Snd150628 VERIFY(mutex_lock(&mp->m_lock) == 0); 120789Sahrens ASSERT(mp->m_owner == NULL); 121789Sahrens mp->m_owner = curthread; 122789Sahrens } 123789Sahrens 124789Sahrens int 125789Sahrens mutex_tryenter(kmutex_t *mp) 126789Sahrens { 127789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 128789Sahrens if (0 == mutex_trylock(&mp->m_lock)) { 129789Sahrens ASSERT(mp->m_owner == NULL); 130789Sahrens mp->m_owner = curthread; 131789Sahrens return (1); 132789Sahrens } else { 133789Sahrens return (0); 134789Sahrens } 135789Sahrens } 136789Sahrens 137789Sahrens void 138789Sahrens mutex_exit(kmutex_t *mp) 139789Sahrens { 140789Sahrens ASSERT(mutex_owner(mp) == curthread); 141789Sahrens mp->m_owner = NULL; 1422856Snd150628 VERIFY(mutex_unlock(&mp->m_lock) == 0); 143789Sahrens } 144789Sahrens 145789Sahrens void * 146789Sahrens mutex_owner(kmutex_t *mp) 147789Sahrens { 148789Sahrens return (mp->m_owner); 149789Sahrens } 150789Sahrens 151789Sahrens /* 152789Sahrens * ========================================================================= 153789Sahrens * rwlocks 154789Sahrens * ========================================================================= 155789Sahrens */ 156789Sahrens /*ARGSUSED*/ 157789Sahrens void 158789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg) 159789Sahrens { 160789Sahrens rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL); 161789Sahrens rwlp->rw_owner = NULL; 162789Sahrens } 163789Sahrens 164789Sahrens void 165789Sahrens rw_destroy(krwlock_t *rwlp) 166789Sahrens { 167789Sahrens rwlock_destroy(&rwlp->rw_lock); 168789Sahrens rwlp->rw_owner = (void *)-1UL; 169789Sahrens } 170789Sahrens 171789Sahrens void 172789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw) 173789Sahrens { 174789Sahrens ASSERT(!RW_LOCK_HELD(rwlp)); 175789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 176789Sahrens ASSERT(rwlp->rw_owner != curthread); 177789Sahrens 178789Sahrens if (rw == RW_READER) 179789Sahrens (void) rw_rdlock(&rwlp->rw_lock); 180789Sahrens else 181789Sahrens (void) rw_wrlock(&rwlp->rw_lock); 182789Sahrens 183789Sahrens rwlp->rw_owner = curthread; 184789Sahrens } 185789Sahrens 186789Sahrens void 187789Sahrens rw_exit(krwlock_t *rwlp) 188789Sahrens { 189789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 190789Sahrens 191789Sahrens rwlp->rw_owner = NULL; 192789Sahrens (void) rw_unlock(&rwlp->rw_lock); 193789Sahrens } 194789Sahrens 195789Sahrens int 196789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw) 197789Sahrens { 198789Sahrens int rv; 199789Sahrens 200789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 201789Sahrens 202789Sahrens if (rw == RW_READER) 203789Sahrens rv = rw_tryrdlock(&rwlp->rw_lock); 204789Sahrens else 205789Sahrens rv = rw_trywrlock(&rwlp->rw_lock); 206789Sahrens 207789Sahrens if (rv == 0) { 208789Sahrens rwlp->rw_owner = curthread; 209789Sahrens return (1); 210789Sahrens } 211789Sahrens 212789Sahrens return (0); 213789Sahrens } 214789Sahrens 215789Sahrens /*ARGSUSED*/ 216789Sahrens int 217789Sahrens rw_tryupgrade(krwlock_t *rwlp) 218789Sahrens { 219789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 220789Sahrens 221789Sahrens return (0); 222789Sahrens } 223789Sahrens 224789Sahrens /* 225789Sahrens * ========================================================================= 226789Sahrens * condition variables 227789Sahrens * ========================================================================= 228789Sahrens */ 229789Sahrens /*ARGSUSED*/ 230789Sahrens void 231789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg) 232789Sahrens { 2332856Snd150628 VERIFY(cond_init(cv, type, NULL) == 0); 234789Sahrens } 235789Sahrens 236789Sahrens void 237789Sahrens cv_destroy(kcondvar_t *cv) 238789Sahrens { 2392856Snd150628 VERIFY(cond_destroy(cv) == 0); 240789Sahrens } 241789Sahrens 242789Sahrens void 243789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp) 244789Sahrens { 245789Sahrens ASSERT(mutex_owner(mp) == curthread); 246789Sahrens mp->m_owner = NULL; 2472856Snd150628 int ret = cond_wait(cv, &mp->m_lock); 2482856Snd150628 VERIFY(ret == 0 || ret == EINTR); 249789Sahrens mp->m_owner = curthread; 250789Sahrens } 251789Sahrens 252789Sahrens clock_t 253789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) 254789Sahrens { 255789Sahrens int error; 256789Sahrens timestruc_t ts; 257789Sahrens clock_t delta; 258789Sahrens 259789Sahrens top: 260789Sahrens delta = abstime - lbolt; 261789Sahrens if (delta <= 0) 262789Sahrens return (-1); 263789Sahrens 264789Sahrens ts.tv_sec = delta / hz; 265789Sahrens ts.tv_nsec = (delta % hz) * (NANOSEC / hz); 266789Sahrens 267789Sahrens ASSERT(mutex_owner(mp) == curthread); 268789Sahrens mp->m_owner = NULL; 269789Sahrens error = cond_reltimedwait(cv, &mp->m_lock, &ts); 270789Sahrens mp->m_owner = curthread; 271789Sahrens 272789Sahrens if (error == ETIME) 273789Sahrens return (-1); 274789Sahrens 275789Sahrens if (error == EINTR) 276789Sahrens goto top; 277789Sahrens 278789Sahrens ASSERT(error == 0); 279789Sahrens 280789Sahrens return (1); 281789Sahrens } 282789Sahrens 283789Sahrens void 284789Sahrens cv_signal(kcondvar_t *cv) 285789Sahrens { 2862856Snd150628 VERIFY(cond_signal(cv) == 0); 287789Sahrens } 288789Sahrens 289789Sahrens void 290789Sahrens cv_broadcast(kcondvar_t *cv) 291789Sahrens { 2922856Snd150628 VERIFY(cond_broadcast(cv) == 0); 293789Sahrens } 294789Sahrens 295789Sahrens /* 296789Sahrens * ========================================================================= 297789Sahrens * vnode operations 298789Sahrens * ========================================================================= 299789Sahrens */ 300789Sahrens /* 301789Sahrens * Note: for the xxxat() versions of these functions, we assume that the 302789Sahrens * starting vp is always rootdir (which is true for spa_directory.c, the only 303789Sahrens * ZFS consumer of these interfaces). We assert this is true, and then emulate 304789Sahrens * them by adding '/' in front of the path. 305789Sahrens */ 306789Sahrens 307789Sahrens /*ARGSUSED*/ 308789Sahrens int 309789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) 310789Sahrens { 311789Sahrens int fd; 312789Sahrens vnode_t *vp; 313789Sahrens int old_umask; 314789Sahrens char realpath[MAXPATHLEN]; 315789Sahrens struct stat64 st; 316789Sahrens 317789Sahrens /* 318789Sahrens * If we're accessing a real disk from userland, we need to use 319789Sahrens * the character interface to avoid caching. This is particularly 320789Sahrens * important if we're trying to look at a real in-kernel storage 321789Sahrens * pool from userland, e.g. via zdb, because otherwise we won't 322789Sahrens * see the changes occurring under the segmap cache. 323789Sahrens * On the other hand, the stupid character device returns zero 324789Sahrens * for its size. So -- gag -- we open the block device to get 325789Sahrens * its size, and remember it for subsequent VOP_GETATTR(). 326789Sahrens */ 327789Sahrens if (strncmp(path, "/dev/", 5) == 0) { 328789Sahrens char *dsk; 329789Sahrens fd = open64(path, O_RDONLY); 330789Sahrens if (fd == -1) 331789Sahrens return (errno); 332789Sahrens if (fstat64(fd, &st) == -1) { 333789Sahrens close(fd); 334789Sahrens return (errno); 335789Sahrens } 336789Sahrens close(fd); 337789Sahrens (void) sprintf(realpath, "%s", path); 338789Sahrens dsk = strstr(path, "/dsk/"); 339789Sahrens if (dsk != NULL) 340789Sahrens (void) sprintf(realpath + (dsk - path) + 1, "r%s", 341789Sahrens dsk + 1); 342789Sahrens } else { 343789Sahrens (void) sprintf(realpath, "%s", path); 344789Sahrens if (!(flags & FCREAT) && stat64(realpath, &st) == -1) 345789Sahrens return (errno); 346789Sahrens } 347789Sahrens 348789Sahrens if (flags & FCREAT) 349789Sahrens old_umask = umask(0); 350789Sahrens 351789Sahrens /* 352789Sahrens * The construct 'flags - FREAD' conveniently maps combinations of 353789Sahrens * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. 354789Sahrens */ 355789Sahrens fd = open64(realpath, flags - FREAD, mode); 356789Sahrens 357789Sahrens if (flags & FCREAT) 358789Sahrens (void) umask(old_umask); 359789Sahrens 360789Sahrens if (fd == -1) 361789Sahrens return (errno); 362789Sahrens 363789Sahrens if (fstat64(fd, &st) == -1) { 364789Sahrens close(fd); 365789Sahrens return (errno); 366789Sahrens } 367789Sahrens 368789Sahrens (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 369789Sahrens 370789Sahrens *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); 371789Sahrens 372789Sahrens vp->v_fd = fd; 373789Sahrens vp->v_size = st.st_size; 374789Sahrens vp->v_path = spa_strdup(path); 375789Sahrens 376789Sahrens return (0); 377789Sahrens } 378789Sahrens 379789Sahrens int 380789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, 381789Sahrens int x3, vnode_t *startvp) 382789Sahrens { 383789Sahrens char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); 384789Sahrens int ret; 385789Sahrens 386789Sahrens ASSERT(startvp == rootdir); 387789Sahrens (void) sprintf(realpath, "/%s", path); 388789Sahrens 389789Sahrens ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); 390789Sahrens 391789Sahrens umem_free(realpath, strlen(path) + 2); 392789Sahrens 393789Sahrens return (ret); 394789Sahrens } 395789Sahrens 396789Sahrens /*ARGSUSED*/ 397789Sahrens int 398789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, 399789Sahrens int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) 400789Sahrens { 401789Sahrens ssize_t iolen, split; 402789Sahrens 403789Sahrens if (uio == UIO_READ) { 404789Sahrens iolen = pread64(vp->v_fd, addr, len, offset); 405789Sahrens } else { 406789Sahrens /* 407789Sahrens * To simulate partial disk writes, we split writes into two 408789Sahrens * system calls so that the process can be killed in between. 409789Sahrens */ 410789Sahrens split = (len > 0 ? rand() % len : 0); 411789Sahrens iolen = pwrite64(vp->v_fd, addr, split, offset); 412789Sahrens iolen += pwrite64(vp->v_fd, (char *)addr + split, 413789Sahrens len - split, offset + split); 414789Sahrens } 415789Sahrens 416789Sahrens if (iolen == -1) 417789Sahrens return (errno); 418789Sahrens if (residp) 419789Sahrens *residp = len - iolen; 420789Sahrens else if (iolen != len) 421789Sahrens return (EIO); 422789Sahrens return (0); 423789Sahrens } 424789Sahrens 425789Sahrens void 426789Sahrens vn_close(vnode_t *vp) 427789Sahrens { 428789Sahrens close(vp->v_fd); 429789Sahrens spa_strfree(vp->v_path); 430789Sahrens umem_free(vp, sizeof (vnode_t)); 431789Sahrens } 432789Sahrens 433789Sahrens #ifdef ZFS_DEBUG 434789Sahrens 435789Sahrens /* 436789Sahrens * ========================================================================= 437789Sahrens * Figure out which debugging statements to print 438789Sahrens * ========================================================================= 439789Sahrens */ 440789Sahrens 441789Sahrens static char *dprintf_string; 442789Sahrens static int dprintf_print_all; 443789Sahrens 444789Sahrens int 445789Sahrens dprintf_find_string(const char *string) 446789Sahrens { 447789Sahrens char *tmp_str = dprintf_string; 448789Sahrens int len = strlen(string); 449789Sahrens 450789Sahrens /* 451789Sahrens * Find out if this is a string we want to print. 452789Sahrens * String format: file1.c,function_name1,file2.c,file3.c 453789Sahrens */ 454789Sahrens 455789Sahrens while (tmp_str != NULL) { 456789Sahrens if (strncmp(tmp_str, string, len) == 0 && 457789Sahrens (tmp_str[len] == ',' || tmp_str[len] == '\0')) 458789Sahrens return (1); 459789Sahrens tmp_str = strchr(tmp_str, ','); 460789Sahrens if (tmp_str != NULL) 461789Sahrens tmp_str++; /* Get rid of , */ 462789Sahrens } 463789Sahrens return (0); 464789Sahrens } 465789Sahrens 466789Sahrens void 467789Sahrens dprintf_setup(int *argc, char **argv) 468789Sahrens { 469789Sahrens int i, j; 470789Sahrens 471789Sahrens /* 472789Sahrens * Debugging can be specified two ways: by setting the 473789Sahrens * environment variable ZFS_DEBUG, or by including a 474789Sahrens * "debug=..." argument on the command line. The command 475789Sahrens * line setting overrides the environment variable. 476789Sahrens */ 477789Sahrens 478789Sahrens for (i = 1; i < *argc; i++) { 479789Sahrens int len = strlen("debug="); 480789Sahrens /* First look for a command line argument */ 481789Sahrens if (strncmp("debug=", argv[i], len) == 0) { 482789Sahrens dprintf_string = argv[i] + len; 483789Sahrens /* Remove from args */ 484789Sahrens for (j = i; j < *argc; j++) 485789Sahrens argv[j] = argv[j+1]; 486789Sahrens argv[j] = NULL; 487789Sahrens (*argc)--; 488789Sahrens } 489789Sahrens } 490789Sahrens 491789Sahrens if (dprintf_string == NULL) { 492789Sahrens /* Look for ZFS_DEBUG environment variable */ 493789Sahrens dprintf_string = getenv("ZFS_DEBUG"); 494789Sahrens } 495789Sahrens 496789Sahrens /* 497789Sahrens * Are we just turning on all debugging? 498789Sahrens */ 499789Sahrens if (dprintf_find_string("on")) 500789Sahrens dprintf_print_all = 1; 501789Sahrens } 502789Sahrens 503789Sahrens /* 504789Sahrens * ========================================================================= 505789Sahrens * debug printfs 506789Sahrens * ========================================================================= 507789Sahrens */ 508789Sahrens void 509789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 510789Sahrens { 511789Sahrens const char *newfile; 512789Sahrens va_list adx; 513789Sahrens 514789Sahrens /* 515789Sahrens * Get rid of annoying "../common/" prefix to filename. 516789Sahrens */ 517789Sahrens newfile = strrchr(file, '/'); 518789Sahrens if (newfile != NULL) { 519789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 520789Sahrens } else { 521789Sahrens newfile = file; 522789Sahrens } 523789Sahrens 524789Sahrens if (dprintf_print_all || 525789Sahrens dprintf_find_string(newfile) || 526789Sahrens dprintf_find_string(func)) { 527789Sahrens /* Print out just the function name if requested */ 528789Sahrens flockfile(stdout); 529789Sahrens if (dprintf_find_string("pid")) 530789Sahrens (void) printf("%d ", getpid()); 531789Sahrens if (dprintf_find_string("tid")) 532789Sahrens (void) printf("%u ", thr_self()); 533789Sahrens if (dprintf_find_string("cpu")) 534789Sahrens (void) printf("%u ", getcpuid()); 535789Sahrens if (dprintf_find_string("time")) 536789Sahrens (void) printf("%llu ", gethrtime()); 537789Sahrens if (dprintf_find_string("long")) 538789Sahrens (void) printf("%s, line %d: ", newfile, line); 539789Sahrens (void) printf("%s: ", func); 540789Sahrens va_start(adx, fmt); 541789Sahrens (void) vprintf(fmt, adx); 542789Sahrens va_end(adx); 543789Sahrens funlockfile(stdout); 544789Sahrens } 545789Sahrens } 546789Sahrens 547789Sahrens #endif /* ZFS_DEBUG */ 548789Sahrens 549789Sahrens /* 550789Sahrens * ========================================================================= 551789Sahrens * cmn_err() and panic() 552789Sahrens * ========================================================================= 553789Sahrens */ 554789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 555789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 556789Sahrens 557789Sahrens void 558789Sahrens vpanic(const char *fmt, va_list adx) 559789Sahrens { 560789Sahrens (void) fprintf(stderr, "error: "); 561789Sahrens (void) vfprintf(stderr, fmt, adx); 562789Sahrens (void) fprintf(stderr, "\n"); 563789Sahrens 564789Sahrens abort(); /* think of it as a "user-level crash dump" */ 565789Sahrens } 566789Sahrens 567789Sahrens void 568789Sahrens panic(const char *fmt, ...) 569789Sahrens { 570789Sahrens va_list adx; 571789Sahrens 572789Sahrens va_start(adx, fmt); 573789Sahrens vpanic(fmt, adx); 574789Sahrens va_end(adx); 575789Sahrens } 576789Sahrens 5773713Sahrens void 5783713Sahrens vcmn_err(int ce, const char *fmt, va_list adx) 5793713Sahrens { 5803713Sahrens if (ce == CE_PANIC) 5813713Sahrens vpanic(fmt, adx); 5823713Sahrens if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ 5833713Sahrens (void) fprintf(stderr, "%s", ce_prefix[ce]); 5843713Sahrens (void) vfprintf(stderr, fmt, adx); 5853713Sahrens (void) fprintf(stderr, "%s", ce_suffix[ce]); 5863713Sahrens } 5873713Sahrens } 5883713Sahrens 589789Sahrens /*PRINTFLIKE2*/ 590789Sahrens void 591789Sahrens cmn_err(int ce, const char *fmt, ...) 592789Sahrens { 593789Sahrens va_list adx; 594789Sahrens 595789Sahrens va_start(adx, fmt); 5963713Sahrens vcmn_err(ce, fmt, adx); 597789Sahrens va_end(adx); 598789Sahrens } 599789Sahrens 600789Sahrens /* 601789Sahrens * ========================================================================= 6021544Seschrock * kobj interfaces 6031544Seschrock * ========================================================================= 6041544Seschrock */ 6051544Seschrock struct _buf * 6061544Seschrock kobj_open_file(char *name) 6071544Seschrock { 6081544Seschrock struct _buf *file; 6091544Seschrock vnode_t *vp; 6101544Seschrock 6111544Seschrock /* set vp as the _fd field of the file */ 6121544Seschrock if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir) != 0) 6131544Seschrock return ((void *)-1UL); 6141544Seschrock 6151544Seschrock file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 6161544Seschrock file->_fd = (intptr_t)vp; 6171544Seschrock return (file); 6181544Seschrock } 6191544Seschrock 6201544Seschrock int 6211544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 6221544Seschrock { 6231544Seschrock ssize_t resid; 6241544Seschrock 6251544Seschrock vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 6261544Seschrock UIO_SYSSPACE, 0, 0, 0, &resid); 6271544Seschrock 6283912Slling return (size - resid); 6291544Seschrock } 6301544Seschrock 6311544Seschrock void 6321544Seschrock kobj_close_file(struct _buf *file) 6331544Seschrock { 6341544Seschrock vn_close((vnode_t *)file->_fd); 6351544Seschrock umem_free(file, sizeof (struct _buf)); 6361544Seschrock } 6371544Seschrock 6381544Seschrock int 6393912Slling kobj_get_filesize(struct _buf *file, uint64_t *size) 6401544Seschrock { 6411544Seschrock struct stat64 st; 6423912Slling vnode_t *vp = (vnode_t *)file->_fd; 6433912Slling 6441544Seschrock if (fstat64(vp->v_fd, &st) == -1) { 6451544Seschrock vn_close(vp); 6461544Seschrock return (errno); 6471544Seschrock } 6483912Slling *size = st.st_size; 6491544Seschrock return (0); 6501544Seschrock } 6511544Seschrock 6521544Seschrock /* 6531544Seschrock * ========================================================================= 654789Sahrens * misc routines 655789Sahrens * ========================================================================= 656789Sahrens */ 657789Sahrens 658789Sahrens void 659789Sahrens delay(clock_t ticks) 660789Sahrens { 661789Sahrens poll(0, 0, ticks * (1000 / hz)); 662789Sahrens } 663789Sahrens 664789Sahrens /* 665789Sahrens * Find highest one bit set. 666789Sahrens * Returns bit number + 1 of highest bit that is set, otherwise returns 0. 667789Sahrens * High order bit is 31 (or 63 in _LP64 kernel). 668789Sahrens */ 669789Sahrens int 670789Sahrens highbit(ulong_t i) 671789Sahrens { 672789Sahrens register int h = 1; 673789Sahrens 674789Sahrens if (i == 0) 675789Sahrens return (0); 676789Sahrens #ifdef _LP64 677789Sahrens if (i & 0xffffffff00000000ul) { 678789Sahrens h += 32; i >>= 32; 679789Sahrens } 680789Sahrens #endif 681789Sahrens if (i & 0xffff0000) { 682789Sahrens h += 16; i >>= 16; 683789Sahrens } 684789Sahrens if (i & 0xff00) { 685789Sahrens h += 8; i >>= 8; 686789Sahrens } 687789Sahrens if (i & 0xf0) { 688789Sahrens h += 4; i >>= 4; 689789Sahrens } 690789Sahrens if (i & 0xc) { 691789Sahrens h += 2; i >>= 2; 692789Sahrens } 693789Sahrens if (i & 0x2) { 694789Sahrens h += 1; 695789Sahrens } 696789Sahrens return (h); 697789Sahrens } 698789Sahrens 699789Sahrens static int 700789Sahrens random_get_bytes_common(uint8_t *ptr, size_t len, char *devname) 701789Sahrens { 702789Sahrens int fd = open(devname, O_RDONLY); 703789Sahrens size_t resid = len; 704789Sahrens ssize_t bytes; 705789Sahrens 706789Sahrens ASSERT(fd != -1); 707789Sahrens 708789Sahrens while (resid != 0) { 709789Sahrens bytes = read(fd, ptr, resid); 710789Sahrens ASSERT(bytes >= 0); 711789Sahrens ptr += bytes; 712789Sahrens resid -= bytes; 713789Sahrens } 714789Sahrens 715789Sahrens close(fd); 716789Sahrens 717789Sahrens return (0); 718789Sahrens } 719789Sahrens 720789Sahrens int 721789Sahrens random_get_bytes(uint8_t *ptr, size_t len) 722789Sahrens { 723789Sahrens return (random_get_bytes_common(ptr, len, "/dev/random")); 724789Sahrens } 725789Sahrens 726789Sahrens int 727789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len) 728789Sahrens { 729789Sahrens return (random_get_bytes_common(ptr, len, "/dev/urandom")); 730789Sahrens } 731789Sahrens 7323975Sek110237 int 7333975Sek110237 ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result) 7343975Sek110237 { 7353975Sek110237 char *end; 7363975Sek110237 7373975Sek110237 *result = strtoul(hw_serial, &end, base); 7383975Sek110237 if (*result == 0) 7393975Sek110237 return (errno); 7403975Sek110237 return (0); 7413975Sek110237 } 7423975Sek110237 743789Sahrens /* 744789Sahrens * ========================================================================= 745789Sahrens * kernel emulation setup & teardown 746789Sahrens * ========================================================================= 747789Sahrens */ 748789Sahrens static int 749789Sahrens umem_out_of_memory(void) 750789Sahrens { 751789Sahrens char errmsg[] = "out of memory -- generating core dump\n"; 752789Sahrens 753789Sahrens write(fileno(stderr), errmsg, sizeof (errmsg)); 754789Sahrens abort(); 755789Sahrens return (0); 756789Sahrens } 757789Sahrens 758789Sahrens void 759789Sahrens kernel_init(int mode) 760789Sahrens { 761789Sahrens umem_nofail_callback(umem_out_of_memory); 762789Sahrens 763789Sahrens physmem = sysconf(_SC_PHYS_PAGES); 764789Sahrens 765789Sahrens dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 766789Sahrens (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 767789Sahrens 7683975Sek110237 snprintf(hw_serial, sizeof (hw_serial), "%ld", gethostid()); 7693975Sek110237 770789Sahrens spa_init(mode); 771789Sahrens } 772789Sahrens 773789Sahrens void 774789Sahrens kernel_fini(void) 775789Sahrens { 776789Sahrens spa_fini(); 777789Sahrens } 7783886Sahl 7793886Sahl int 7803886Sahl z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 7813886Sahl { 7823886Sahl int ret; 7833886Sahl uLongf len = *dstlen; 7843886Sahl 7853886Sahl if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK) 7863886Sahl *dstlen = (size_t)len; 7873886Sahl 7883886Sahl return (ret); 7893886Sahl } 7903886Sahl 7913886Sahl int 7923886Sahl z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen, 7933886Sahl int level) 7943886Sahl { 7953886Sahl int ret; 7963886Sahl uLongf len = *dstlen; 7973886Sahl 7983886Sahl if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK) 7993886Sahl *dstlen = (size_t)len; 8003886Sahl 8013886Sahl return (ret); 8023886Sahl } 803*4543Smarks 804*4543Smarks uid_t 805*4543Smarks crgetuid(cred_t *cr) 806*4543Smarks { 807*4543Smarks return (0); 808*4543Smarks } 809*4543Smarks 810*4543Smarks gid_t 811*4543Smarks crgetgid(cred_t *cr) 812*4543Smarks { 813*4543Smarks return (0); 814*4543Smarks } 815*4543Smarks 816*4543Smarks int 817*4543Smarks crgetngroups(cred_t *cr) 818*4543Smarks { 819*4543Smarks return (0); 820*4543Smarks } 821*4543Smarks 822*4543Smarks gid_t * 823*4543Smarks crgetgroups(cred_t *cr) 824*4543Smarks { 825*4543Smarks return (NULL); 826*4543Smarks } 827*4543Smarks 828*4543Smarks int 829*4543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 830*4543Smarks { 831*4543Smarks return (0); 832*4543Smarks } 833*4543Smarks 834*4543Smarks int 835*4543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 836*4543Smarks { 837*4543Smarks return (0); 838*4543Smarks } 839*4543Smarks 840*4543Smarks int 841*4543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 842*4543Smarks { 843*4543Smarks return (0); 844*4543Smarks } 845