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 /* 228662SJordan.Vaughan@Sun.com * Copyright 2009 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> 398662SJordan.Vaughan@Sun.com #include <sys/systeminfo.h> 402856Snd150628 41789Sahrens /* 42789Sahrens * Emulation of kernel services in userland. 43789Sahrens */ 44789Sahrens 45789Sahrens uint64_t physmem; 46789Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234; 478662SJordan.Vaughan@Sun.com char hw_serial[HW_HOSTID_LEN]; 483975Sek110237 493975Sek110237 struct utsname utsname = { 503975Sek110237 "userland", "libzpool", "1", "1", "na" 513975Sek110237 }; 52789Sahrens 53789Sahrens /* 54789Sahrens * ========================================================================= 55789Sahrens * threads 56789Sahrens * ========================================================================= 57789Sahrens */ 58789Sahrens /*ARGSUSED*/ 59789Sahrens kthread_t * 60789Sahrens zk_thread_create(void (*func)(), void *arg) 61789Sahrens { 62789Sahrens thread_t tid; 63789Sahrens 64789Sahrens VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED, 65789Sahrens &tid) == 0); 66789Sahrens 67789Sahrens return ((void *)(uintptr_t)tid); 68789Sahrens } 69789Sahrens 70789Sahrens /* 71789Sahrens * ========================================================================= 723403Sbmc * kstats 733403Sbmc * ========================================================================= 743403Sbmc */ 753403Sbmc /*ARGSUSED*/ 763403Sbmc kstat_t * 773403Sbmc kstat_create(char *module, int instance, char *name, char *class, 783403Sbmc uchar_t type, ulong_t ndata, uchar_t ks_flag) 793403Sbmc { 803403Sbmc return (NULL); 813403Sbmc } 823403Sbmc 833403Sbmc /*ARGSUSED*/ 843403Sbmc void 853403Sbmc kstat_install(kstat_t *ksp) 863403Sbmc {} 873403Sbmc 883403Sbmc /*ARGSUSED*/ 893403Sbmc void 903403Sbmc kstat_delete(kstat_t *ksp) 913403Sbmc {} 923403Sbmc 933403Sbmc /* 943403Sbmc * ========================================================================= 95789Sahrens * mutexes 96789Sahrens * ========================================================================= 97789Sahrens */ 98789Sahrens void 99789Sahrens zmutex_init(kmutex_t *mp) 100789Sahrens { 101789Sahrens mp->m_owner = NULL; 1024831Sgw25295 mp->initialized = B_TRUE; 103789Sahrens (void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL); 104789Sahrens } 105789Sahrens 106789Sahrens void 107789Sahrens zmutex_destroy(kmutex_t *mp) 108789Sahrens { 1094831Sgw25295 ASSERT(mp->initialized == B_TRUE); 110789Sahrens ASSERT(mp->m_owner == NULL); 111789Sahrens (void) _mutex_destroy(&(mp)->m_lock); 112789Sahrens mp->m_owner = (void *)-1UL; 1134831Sgw25295 mp->initialized = B_FALSE; 114789Sahrens } 115789Sahrens 116789Sahrens void 117789Sahrens mutex_enter(kmutex_t *mp) 118789Sahrens { 1194831Sgw25295 ASSERT(mp->initialized == B_TRUE); 120789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 121789Sahrens ASSERT(mp->m_owner != curthread); 1222856Snd150628 VERIFY(mutex_lock(&mp->m_lock) == 0); 123789Sahrens ASSERT(mp->m_owner == NULL); 124789Sahrens mp->m_owner = curthread; 125789Sahrens } 126789Sahrens 127789Sahrens int 128789Sahrens mutex_tryenter(kmutex_t *mp) 129789Sahrens { 1304831Sgw25295 ASSERT(mp->initialized == B_TRUE); 131789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 132789Sahrens if (0 == mutex_trylock(&mp->m_lock)) { 133789Sahrens ASSERT(mp->m_owner == NULL); 134789Sahrens mp->m_owner = curthread; 135789Sahrens return (1); 136789Sahrens } else { 137789Sahrens return (0); 138789Sahrens } 139789Sahrens } 140789Sahrens 141789Sahrens void 142789Sahrens mutex_exit(kmutex_t *mp) 143789Sahrens { 1444831Sgw25295 ASSERT(mp->initialized == B_TRUE); 145789Sahrens ASSERT(mutex_owner(mp) == curthread); 146789Sahrens mp->m_owner = NULL; 1472856Snd150628 VERIFY(mutex_unlock(&mp->m_lock) == 0); 148789Sahrens } 149789Sahrens 150789Sahrens void * 151789Sahrens mutex_owner(kmutex_t *mp) 152789Sahrens { 1534831Sgw25295 ASSERT(mp->initialized == B_TRUE); 154789Sahrens return (mp->m_owner); 155789Sahrens } 156789Sahrens 157789Sahrens /* 158789Sahrens * ========================================================================= 159789Sahrens * rwlocks 160789Sahrens * ========================================================================= 161789Sahrens */ 162789Sahrens /*ARGSUSED*/ 163789Sahrens void 164789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg) 165789Sahrens { 166789Sahrens rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL); 167789Sahrens rwlp->rw_owner = NULL; 1684831Sgw25295 rwlp->initialized = B_TRUE; 169789Sahrens } 170789Sahrens 171789Sahrens void 172789Sahrens rw_destroy(krwlock_t *rwlp) 173789Sahrens { 174789Sahrens rwlock_destroy(&rwlp->rw_lock); 175789Sahrens rwlp->rw_owner = (void *)-1UL; 1764831Sgw25295 rwlp->initialized = B_FALSE; 177789Sahrens } 178789Sahrens 179789Sahrens void 180789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw) 181789Sahrens { 182789Sahrens ASSERT(!RW_LOCK_HELD(rwlp)); 1834831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 184789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 185789Sahrens ASSERT(rwlp->rw_owner != curthread); 186789Sahrens 187789Sahrens if (rw == RW_READER) 1886689Smaybee VERIFY(rw_rdlock(&rwlp->rw_lock) == 0); 189789Sahrens else 1906689Smaybee VERIFY(rw_wrlock(&rwlp->rw_lock) == 0); 191789Sahrens 192789Sahrens rwlp->rw_owner = curthread; 193789Sahrens } 194789Sahrens 195789Sahrens void 196789Sahrens rw_exit(krwlock_t *rwlp) 197789Sahrens { 1984831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 199789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 200789Sahrens 201789Sahrens rwlp->rw_owner = NULL; 2026689Smaybee VERIFY(rw_unlock(&rwlp->rw_lock) == 0); 203789Sahrens } 204789Sahrens 205789Sahrens int 206789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw) 207789Sahrens { 208789Sahrens int rv; 209789Sahrens 2104831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 211789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 212789Sahrens 213789Sahrens if (rw == RW_READER) 214789Sahrens rv = rw_tryrdlock(&rwlp->rw_lock); 215789Sahrens else 216789Sahrens rv = rw_trywrlock(&rwlp->rw_lock); 217789Sahrens 218789Sahrens if (rv == 0) { 219789Sahrens rwlp->rw_owner = curthread; 220789Sahrens return (1); 221789Sahrens } 222789Sahrens 223789Sahrens return (0); 224789Sahrens } 225789Sahrens 226789Sahrens /*ARGSUSED*/ 227789Sahrens int 228789Sahrens rw_tryupgrade(krwlock_t *rwlp) 229789Sahrens { 2304831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 231789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 232789Sahrens 233789Sahrens return (0); 234789Sahrens } 235789Sahrens 236789Sahrens /* 237789Sahrens * ========================================================================= 238789Sahrens * condition variables 239789Sahrens * ========================================================================= 240789Sahrens */ 241789Sahrens /*ARGSUSED*/ 242789Sahrens void 243789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg) 244789Sahrens { 2452856Snd150628 VERIFY(cond_init(cv, type, NULL) == 0); 246789Sahrens } 247789Sahrens 248789Sahrens void 249789Sahrens cv_destroy(kcondvar_t *cv) 250789Sahrens { 2512856Snd150628 VERIFY(cond_destroy(cv) == 0); 252789Sahrens } 253789Sahrens 254789Sahrens void 255789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp) 256789Sahrens { 257789Sahrens ASSERT(mutex_owner(mp) == curthread); 258789Sahrens mp->m_owner = NULL; 2592856Snd150628 int ret = cond_wait(cv, &mp->m_lock); 2602856Snd150628 VERIFY(ret == 0 || ret == EINTR); 261789Sahrens mp->m_owner = curthread; 262789Sahrens } 263789Sahrens 264789Sahrens clock_t 265789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) 266789Sahrens { 267789Sahrens int error; 268789Sahrens timestruc_t ts; 269789Sahrens clock_t delta; 270789Sahrens 271789Sahrens top: 272789Sahrens delta = abstime - lbolt; 273789Sahrens if (delta <= 0) 274789Sahrens return (-1); 275789Sahrens 276789Sahrens ts.tv_sec = delta / hz; 277789Sahrens ts.tv_nsec = (delta % hz) * (NANOSEC / hz); 278789Sahrens 279789Sahrens ASSERT(mutex_owner(mp) == curthread); 280789Sahrens mp->m_owner = NULL; 281789Sahrens error = cond_reltimedwait(cv, &mp->m_lock, &ts); 282789Sahrens mp->m_owner = curthread; 283789Sahrens 284789Sahrens if (error == ETIME) 285789Sahrens return (-1); 286789Sahrens 287789Sahrens if (error == EINTR) 288789Sahrens goto top; 289789Sahrens 290789Sahrens ASSERT(error == 0); 291789Sahrens 292789Sahrens return (1); 293789Sahrens } 294789Sahrens 295789Sahrens void 296789Sahrens cv_signal(kcondvar_t *cv) 297789Sahrens { 2982856Snd150628 VERIFY(cond_signal(cv) == 0); 299789Sahrens } 300789Sahrens 301789Sahrens void 302789Sahrens cv_broadcast(kcondvar_t *cv) 303789Sahrens { 3042856Snd150628 VERIFY(cond_broadcast(cv) == 0); 305789Sahrens } 306789Sahrens 307789Sahrens /* 308789Sahrens * ========================================================================= 309789Sahrens * vnode operations 310789Sahrens * ========================================================================= 311789Sahrens */ 312789Sahrens /* 313789Sahrens * Note: for the xxxat() versions of these functions, we assume that the 314789Sahrens * starting vp is always rootdir (which is true for spa_directory.c, the only 315789Sahrens * ZFS consumer of these interfaces). We assert this is true, and then emulate 316789Sahrens * them by adding '/' in front of the path. 317789Sahrens */ 318789Sahrens 319789Sahrens /*ARGSUSED*/ 320789Sahrens int 321789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) 322789Sahrens { 323789Sahrens int fd; 324789Sahrens vnode_t *vp; 325789Sahrens int old_umask; 326789Sahrens char realpath[MAXPATHLEN]; 327789Sahrens struct stat64 st; 328789Sahrens 329789Sahrens /* 330789Sahrens * If we're accessing a real disk from userland, we need to use 331789Sahrens * the character interface to avoid caching. This is particularly 332789Sahrens * important if we're trying to look at a real in-kernel storage 333789Sahrens * pool from userland, e.g. via zdb, because otherwise we won't 334789Sahrens * see the changes occurring under the segmap cache. 335789Sahrens * On the other hand, the stupid character device returns zero 336789Sahrens * for its size. So -- gag -- we open the block device to get 337789Sahrens * its size, and remember it for subsequent VOP_GETATTR(). 338789Sahrens */ 339789Sahrens if (strncmp(path, "/dev/", 5) == 0) { 340789Sahrens char *dsk; 341789Sahrens fd = open64(path, O_RDONLY); 342789Sahrens if (fd == -1) 343789Sahrens return (errno); 344789Sahrens if (fstat64(fd, &st) == -1) { 345789Sahrens close(fd); 346789Sahrens return (errno); 347789Sahrens } 348789Sahrens close(fd); 349789Sahrens (void) sprintf(realpath, "%s", path); 350789Sahrens dsk = strstr(path, "/dsk/"); 351789Sahrens if (dsk != NULL) 352789Sahrens (void) sprintf(realpath + (dsk - path) + 1, "r%s", 353789Sahrens dsk + 1); 354789Sahrens } else { 355789Sahrens (void) sprintf(realpath, "%s", path); 356789Sahrens if (!(flags & FCREAT) && stat64(realpath, &st) == -1) 357789Sahrens return (errno); 358789Sahrens } 359789Sahrens 360789Sahrens if (flags & FCREAT) 361789Sahrens old_umask = umask(0); 362789Sahrens 363789Sahrens /* 364789Sahrens * The construct 'flags - FREAD' conveniently maps combinations of 365789Sahrens * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. 366789Sahrens */ 367789Sahrens fd = open64(realpath, flags - FREAD, mode); 368789Sahrens 369789Sahrens if (flags & FCREAT) 370789Sahrens (void) umask(old_umask); 371789Sahrens 372789Sahrens if (fd == -1) 373789Sahrens return (errno); 374789Sahrens 375789Sahrens if (fstat64(fd, &st) == -1) { 376789Sahrens close(fd); 377789Sahrens return (errno); 378789Sahrens } 379789Sahrens 380789Sahrens (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 381789Sahrens 382789Sahrens *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); 383789Sahrens 384789Sahrens vp->v_fd = fd; 385789Sahrens vp->v_size = st.st_size; 386789Sahrens vp->v_path = spa_strdup(path); 387789Sahrens 388789Sahrens return (0); 389789Sahrens } 390789Sahrens 3915331Samw /*ARGSUSED*/ 392789Sahrens int 393789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, 3945331Samw int x3, vnode_t *startvp, int fd) 395789Sahrens { 396789Sahrens char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); 397789Sahrens int ret; 398789Sahrens 399789Sahrens ASSERT(startvp == rootdir); 400789Sahrens (void) sprintf(realpath, "/%s", path); 401789Sahrens 4025331Samw /* fd ignored for now, need if want to simulate nbmand support */ 403789Sahrens ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); 404789Sahrens 405789Sahrens umem_free(realpath, strlen(path) + 2); 406789Sahrens 407789Sahrens return (ret); 408789Sahrens } 409789Sahrens 410789Sahrens /*ARGSUSED*/ 411789Sahrens int 412789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, 413789Sahrens int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) 414789Sahrens { 415789Sahrens ssize_t iolen, split; 416789Sahrens 417789Sahrens if (uio == UIO_READ) { 418789Sahrens iolen = pread64(vp->v_fd, addr, len, offset); 419789Sahrens } else { 420789Sahrens /* 421789Sahrens * To simulate partial disk writes, we split writes into two 422789Sahrens * system calls so that the process can be killed in between. 423789Sahrens */ 424789Sahrens split = (len > 0 ? rand() % len : 0); 425789Sahrens iolen = pwrite64(vp->v_fd, addr, split, offset); 426789Sahrens iolen += pwrite64(vp->v_fd, (char *)addr + split, 427789Sahrens len - split, offset + split); 428789Sahrens } 429789Sahrens 430789Sahrens if (iolen == -1) 431789Sahrens return (errno); 432789Sahrens if (residp) 433789Sahrens *residp = len - iolen; 434789Sahrens else if (iolen != len) 435789Sahrens return (EIO); 436789Sahrens return (0); 437789Sahrens } 438789Sahrens 439789Sahrens void 440789Sahrens vn_close(vnode_t *vp) 441789Sahrens { 442789Sahrens close(vp->v_fd); 443789Sahrens spa_strfree(vp->v_path); 444789Sahrens umem_free(vp, sizeof (vnode_t)); 445789Sahrens } 446789Sahrens 447*10850SGeorge.Wilson@Sun.COM /* 448*10850SGeorge.Wilson@Sun.COM * At a minimum we need to update the size since vdev_reopen() 449*10850SGeorge.Wilson@Sun.COM * will no longer call vn_openat(). 450*10850SGeorge.Wilson@Sun.COM */ 451*10850SGeorge.Wilson@Sun.COM int 452*10850SGeorge.Wilson@Sun.COM fop_getattr(vnode_t *vp, vattr_t *vap) 453*10850SGeorge.Wilson@Sun.COM { 454*10850SGeorge.Wilson@Sun.COM struct stat64 st; 455*10850SGeorge.Wilson@Sun.COM 456*10850SGeorge.Wilson@Sun.COM if (fstat64(vp->v_fd, &st) == -1) { 457*10850SGeorge.Wilson@Sun.COM close(vp->v_fd); 458*10850SGeorge.Wilson@Sun.COM return (errno); 459*10850SGeorge.Wilson@Sun.COM } 460*10850SGeorge.Wilson@Sun.COM 461*10850SGeorge.Wilson@Sun.COM vap->va_size = st.st_size; 462*10850SGeorge.Wilson@Sun.COM return (0); 463*10850SGeorge.Wilson@Sun.COM } 464*10850SGeorge.Wilson@Sun.COM 465789Sahrens #ifdef ZFS_DEBUG 466789Sahrens 467789Sahrens /* 468789Sahrens * ========================================================================= 469789Sahrens * Figure out which debugging statements to print 470789Sahrens * ========================================================================= 471789Sahrens */ 472789Sahrens 473789Sahrens static char *dprintf_string; 474789Sahrens static int dprintf_print_all; 475789Sahrens 476789Sahrens int 477789Sahrens dprintf_find_string(const char *string) 478789Sahrens { 479789Sahrens char *tmp_str = dprintf_string; 480789Sahrens int len = strlen(string); 481789Sahrens 482789Sahrens /* 483789Sahrens * Find out if this is a string we want to print. 484789Sahrens * String format: file1.c,function_name1,file2.c,file3.c 485789Sahrens */ 486789Sahrens 487789Sahrens while (tmp_str != NULL) { 488789Sahrens if (strncmp(tmp_str, string, len) == 0 && 489789Sahrens (tmp_str[len] == ',' || tmp_str[len] == '\0')) 490789Sahrens return (1); 491789Sahrens tmp_str = strchr(tmp_str, ','); 492789Sahrens if (tmp_str != NULL) 493789Sahrens tmp_str++; /* Get rid of , */ 494789Sahrens } 495789Sahrens return (0); 496789Sahrens } 497789Sahrens 498789Sahrens void 499789Sahrens dprintf_setup(int *argc, char **argv) 500789Sahrens { 501789Sahrens int i, j; 502789Sahrens 503789Sahrens /* 504789Sahrens * Debugging can be specified two ways: by setting the 505789Sahrens * environment variable ZFS_DEBUG, or by including a 506789Sahrens * "debug=..." argument on the command line. The command 507789Sahrens * line setting overrides the environment variable. 508789Sahrens */ 509789Sahrens 510789Sahrens for (i = 1; i < *argc; i++) { 511789Sahrens int len = strlen("debug="); 512789Sahrens /* First look for a command line argument */ 513789Sahrens if (strncmp("debug=", argv[i], len) == 0) { 514789Sahrens dprintf_string = argv[i] + len; 515789Sahrens /* Remove from args */ 516789Sahrens for (j = i; j < *argc; j++) 517789Sahrens argv[j] = argv[j+1]; 518789Sahrens argv[j] = NULL; 519789Sahrens (*argc)--; 520789Sahrens } 521789Sahrens } 522789Sahrens 523789Sahrens if (dprintf_string == NULL) { 524789Sahrens /* Look for ZFS_DEBUG environment variable */ 525789Sahrens dprintf_string = getenv("ZFS_DEBUG"); 526789Sahrens } 527789Sahrens 528789Sahrens /* 529789Sahrens * Are we just turning on all debugging? 530789Sahrens */ 531789Sahrens if (dprintf_find_string("on")) 532789Sahrens dprintf_print_all = 1; 533789Sahrens } 534789Sahrens 535789Sahrens /* 536789Sahrens * ========================================================================= 537789Sahrens * debug printfs 538789Sahrens * ========================================================================= 539789Sahrens */ 540789Sahrens void 541789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 542789Sahrens { 543789Sahrens const char *newfile; 544789Sahrens va_list adx; 545789Sahrens 546789Sahrens /* 547789Sahrens * Get rid of annoying "../common/" prefix to filename. 548789Sahrens */ 549789Sahrens newfile = strrchr(file, '/'); 550789Sahrens if (newfile != NULL) { 551789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 552789Sahrens } else { 553789Sahrens newfile = file; 554789Sahrens } 555789Sahrens 556789Sahrens if (dprintf_print_all || 557789Sahrens dprintf_find_string(newfile) || 558789Sahrens dprintf_find_string(func)) { 559789Sahrens /* Print out just the function name if requested */ 560789Sahrens flockfile(stdout); 561789Sahrens if (dprintf_find_string("pid")) 562789Sahrens (void) printf("%d ", getpid()); 563789Sahrens if (dprintf_find_string("tid")) 564789Sahrens (void) printf("%u ", thr_self()); 565789Sahrens if (dprintf_find_string("cpu")) 566789Sahrens (void) printf("%u ", getcpuid()); 567789Sahrens if (dprintf_find_string("time")) 568789Sahrens (void) printf("%llu ", gethrtime()); 569789Sahrens if (dprintf_find_string("long")) 570789Sahrens (void) printf("%s, line %d: ", newfile, line); 571789Sahrens (void) printf("%s: ", func); 572789Sahrens va_start(adx, fmt); 573789Sahrens (void) vprintf(fmt, adx); 574789Sahrens va_end(adx); 575789Sahrens funlockfile(stdout); 576789Sahrens } 577789Sahrens } 578789Sahrens 579789Sahrens #endif /* ZFS_DEBUG */ 580789Sahrens 581789Sahrens /* 582789Sahrens * ========================================================================= 583789Sahrens * cmn_err() and panic() 584789Sahrens * ========================================================================= 585789Sahrens */ 586789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 587789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 588789Sahrens 589789Sahrens void 590789Sahrens vpanic(const char *fmt, va_list adx) 591789Sahrens { 592789Sahrens (void) fprintf(stderr, "error: "); 593789Sahrens (void) vfprintf(stderr, fmt, adx); 594789Sahrens (void) fprintf(stderr, "\n"); 595789Sahrens 596789Sahrens abort(); /* think of it as a "user-level crash dump" */ 597789Sahrens } 598789Sahrens 599789Sahrens void 600789Sahrens panic(const char *fmt, ...) 601789Sahrens { 602789Sahrens va_list adx; 603789Sahrens 604789Sahrens va_start(adx, fmt); 605789Sahrens vpanic(fmt, adx); 606789Sahrens va_end(adx); 607789Sahrens } 608789Sahrens 6093713Sahrens void 6103713Sahrens vcmn_err(int ce, const char *fmt, va_list adx) 6113713Sahrens { 6123713Sahrens if (ce == CE_PANIC) 6133713Sahrens vpanic(fmt, adx); 6143713Sahrens if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ 6153713Sahrens (void) fprintf(stderr, "%s", ce_prefix[ce]); 6163713Sahrens (void) vfprintf(stderr, fmt, adx); 6173713Sahrens (void) fprintf(stderr, "%s", ce_suffix[ce]); 6183713Sahrens } 6193713Sahrens } 6203713Sahrens 621789Sahrens /*PRINTFLIKE2*/ 622789Sahrens void 623789Sahrens cmn_err(int ce, const char *fmt, ...) 624789Sahrens { 625789Sahrens va_list adx; 626789Sahrens 627789Sahrens va_start(adx, fmt); 6283713Sahrens vcmn_err(ce, fmt, adx); 629789Sahrens va_end(adx); 630789Sahrens } 631789Sahrens 632789Sahrens /* 633789Sahrens * ========================================================================= 6341544Seschrock * kobj interfaces 6351544Seschrock * ========================================================================= 6361544Seschrock */ 6371544Seschrock struct _buf * 6381544Seschrock kobj_open_file(char *name) 6391544Seschrock { 6401544Seschrock struct _buf *file; 6411544Seschrock vnode_t *vp; 6421544Seschrock 6431544Seschrock /* set vp as the _fd field of the file */ 6445331Samw if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir, 6455331Samw -1) != 0) 6461544Seschrock return ((void *)-1UL); 6471544Seschrock 6481544Seschrock file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 6491544Seschrock file->_fd = (intptr_t)vp; 6501544Seschrock return (file); 6511544Seschrock } 6521544Seschrock 6531544Seschrock int 6541544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 6551544Seschrock { 6561544Seschrock ssize_t resid; 6571544Seschrock 6581544Seschrock vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 6591544Seschrock UIO_SYSSPACE, 0, 0, 0, &resid); 6601544Seschrock 6613912Slling return (size - resid); 6621544Seschrock } 6631544Seschrock 6641544Seschrock void 6651544Seschrock kobj_close_file(struct _buf *file) 6661544Seschrock { 6671544Seschrock vn_close((vnode_t *)file->_fd); 6681544Seschrock umem_free(file, sizeof (struct _buf)); 6691544Seschrock } 6701544Seschrock 6711544Seschrock int 6723912Slling kobj_get_filesize(struct _buf *file, uint64_t *size) 6731544Seschrock { 6741544Seschrock struct stat64 st; 6753912Slling vnode_t *vp = (vnode_t *)file->_fd; 6763912Slling 6771544Seschrock if (fstat64(vp->v_fd, &st) == -1) { 6781544Seschrock vn_close(vp); 6791544Seschrock return (errno); 6801544Seschrock } 6813912Slling *size = st.st_size; 6821544Seschrock return (0); 6831544Seschrock } 6841544Seschrock 6851544Seschrock /* 6861544Seschrock * ========================================================================= 687789Sahrens * misc routines 688789Sahrens * ========================================================================= 689789Sahrens */ 690789Sahrens 691789Sahrens void 692789Sahrens delay(clock_t ticks) 693789Sahrens { 694789Sahrens poll(0, 0, ticks * (1000 / hz)); 695789Sahrens } 696789Sahrens 697789Sahrens /* 698789Sahrens * Find highest one bit set. 699789Sahrens * Returns bit number + 1 of highest bit that is set, otherwise returns 0. 700789Sahrens * High order bit is 31 (or 63 in _LP64 kernel). 701789Sahrens */ 702789Sahrens int 703789Sahrens highbit(ulong_t i) 704789Sahrens { 705789Sahrens register int h = 1; 706789Sahrens 707789Sahrens if (i == 0) 708789Sahrens return (0); 709789Sahrens #ifdef _LP64 710789Sahrens if (i & 0xffffffff00000000ul) { 711789Sahrens h += 32; i >>= 32; 712789Sahrens } 713789Sahrens #endif 714789Sahrens if (i & 0xffff0000) { 715789Sahrens h += 16; i >>= 16; 716789Sahrens } 717789Sahrens if (i & 0xff00) { 718789Sahrens h += 8; i >>= 8; 719789Sahrens } 720789Sahrens if (i & 0xf0) { 721789Sahrens h += 4; i >>= 4; 722789Sahrens } 723789Sahrens if (i & 0xc) { 724789Sahrens h += 2; i >>= 2; 725789Sahrens } 726789Sahrens if (i & 0x2) { 727789Sahrens h += 1; 728789Sahrens } 729789Sahrens return (h); 730789Sahrens } 731789Sahrens 7325688Sbonwick static int random_fd = -1, urandom_fd = -1; 7335688Sbonwick 734789Sahrens static int 7355688Sbonwick random_get_bytes_common(uint8_t *ptr, size_t len, int fd) 736789Sahrens { 737789Sahrens size_t resid = len; 738789Sahrens ssize_t bytes; 739789Sahrens 740789Sahrens ASSERT(fd != -1); 741789Sahrens 742789Sahrens while (resid != 0) { 743789Sahrens bytes = read(fd, ptr, resid); 7445688Sbonwick ASSERT3S(bytes, >=, 0); 745789Sahrens ptr += bytes; 746789Sahrens resid -= bytes; 747789Sahrens } 748789Sahrens 749789Sahrens return (0); 750789Sahrens } 751789Sahrens 752789Sahrens int 753789Sahrens random_get_bytes(uint8_t *ptr, size_t len) 754789Sahrens { 7555688Sbonwick return (random_get_bytes_common(ptr, len, random_fd)); 756789Sahrens } 757789Sahrens 758789Sahrens int 759789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len) 760789Sahrens { 7615688Sbonwick return (random_get_bytes_common(ptr, len, urandom_fd)); 762789Sahrens } 763789Sahrens 7643975Sek110237 int 7653975Sek110237 ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result) 7663975Sek110237 { 7673975Sek110237 char *end; 7683975Sek110237 7693975Sek110237 *result = strtoul(hw_serial, &end, base); 7703975Sek110237 if (*result == 0) 7713975Sek110237 return (errno); 7723975Sek110237 return (0); 7733975Sek110237 } 7743975Sek110237 775789Sahrens /* 776789Sahrens * ========================================================================= 777789Sahrens * kernel emulation setup & teardown 778789Sahrens * ========================================================================= 779789Sahrens */ 780789Sahrens static int 781789Sahrens umem_out_of_memory(void) 782789Sahrens { 783789Sahrens char errmsg[] = "out of memory -- generating core dump\n"; 784789Sahrens 785789Sahrens write(fileno(stderr), errmsg, sizeof (errmsg)); 786789Sahrens abort(); 787789Sahrens return (0); 788789Sahrens } 789789Sahrens 790789Sahrens void 791789Sahrens kernel_init(int mode) 792789Sahrens { 793789Sahrens umem_nofail_callback(umem_out_of_memory); 794789Sahrens 795789Sahrens physmem = sysconf(_SC_PHYS_PAGES); 796789Sahrens 797789Sahrens dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 798789Sahrens (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 799789Sahrens 8008662SJordan.Vaughan@Sun.com (void) snprintf(hw_serial, sizeof (hw_serial), "%ld", gethostid()); 8013975Sek110237 8025688Sbonwick VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1); 8035688Sbonwick VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1); 8045688Sbonwick 8057837SMatthew.Ahrens@Sun.COM system_taskq_init(); 8067837SMatthew.Ahrens@Sun.COM 807789Sahrens spa_init(mode); 808789Sahrens } 809789Sahrens 810789Sahrens void 811789Sahrens kernel_fini(void) 812789Sahrens { 813789Sahrens spa_fini(); 8145688Sbonwick 81510612SRicardo.M.Correia@Sun.COM system_taskq_fini(); 81610612SRicardo.M.Correia@Sun.COM 8175688Sbonwick close(random_fd); 8185688Sbonwick close(urandom_fd); 8195688Sbonwick 8205688Sbonwick random_fd = -1; 8215688Sbonwick urandom_fd = -1; 822789Sahrens } 8233886Sahl 8243886Sahl int 8253886Sahl z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 8263886Sahl { 8273886Sahl int ret; 8283886Sahl uLongf len = *dstlen; 8293886Sahl 8303886Sahl if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK) 8313886Sahl *dstlen = (size_t)len; 8323886Sahl 8333886Sahl return (ret); 8343886Sahl } 8353886Sahl 8363886Sahl int 8373886Sahl z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen, 8383886Sahl int level) 8393886Sahl { 8403886Sahl int ret; 8413886Sahl uLongf len = *dstlen; 8423886Sahl 8433886Sahl if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK) 8443886Sahl *dstlen = (size_t)len; 8453886Sahl 8463886Sahl return (ret); 8473886Sahl } 8484543Smarks 8494543Smarks uid_t 8504543Smarks crgetuid(cred_t *cr) 8514543Smarks { 8524543Smarks return (0); 8534543Smarks } 8544543Smarks 8554543Smarks gid_t 8564543Smarks crgetgid(cred_t *cr) 8574543Smarks { 8584543Smarks return (0); 8594543Smarks } 8604543Smarks 8614543Smarks int 8624543Smarks crgetngroups(cred_t *cr) 8634543Smarks { 8644543Smarks return (0); 8654543Smarks } 8664543Smarks 8674543Smarks gid_t * 8684543Smarks crgetgroups(cred_t *cr) 8694543Smarks { 8704543Smarks return (NULL); 8714543Smarks } 8724543Smarks 8734543Smarks int 8744543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 8754543Smarks { 8764543Smarks return (0); 8774543Smarks } 8784543Smarks 8794543Smarks int 8804543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 8814543Smarks { 8824543Smarks return (0); 8834543Smarks } 8844543Smarks 8854543Smarks int 8864543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 8874543Smarks { 8884543Smarks return (0); 8894543Smarks } 8905959Smarks 8915959Smarks ksiddomain_t * 8925959Smarks ksid_lookupdomain(const char *dom) 8935959Smarks { 8945959Smarks ksiddomain_t *kd; 8955959Smarks 8965959Smarks kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL); 8975959Smarks kd->kd_name = spa_strdup(dom); 8985959Smarks return (kd); 8995959Smarks } 9005959Smarks 9015959Smarks void 9025959Smarks ksiddomain_rele(ksiddomain_t *ksid) 9035959Smarks { 9045959Smarks spa_strfree(ksid->kd_name); 9055959Smarks umem_free(ksid, sizeof (ksiddomain_t)); 9065959Smarks } 90710272SMatthew.Ahrens@Sun.COM 90810272SMatthew.Ahrens@Sun.COM /* 90910272SMatthew.Ahrens@Sun.COM * Do not change the length of the returned string; it must be freed 91010272SMatthew.Ahrens@Sun.COM * with strfree(). 91110272SMatthew.Ahrens@Sun.COM */ 91210272SMatthew.Ahrens@Sun.COM char * 91310272SMatthew.Ahrens@Sun.COM kmem_asprintf(const char *fmt, ...) 91410272SMatthew.Ahrens@Sun.COM { 91510272SMatthew.Ahrens@Sun.COM int size; 91610272SMatthew.Ahrens@Sun.COM va_list adx; 91710272SMatthew.Ahrens@Sun.COM char *buf; 91810272SMatthew.Ahrens@Sun.COM 91910272SMatthew.Ahrens@Sun.COM va_start(adx, fmt); 92010272SMatthew.Ahrens@Sun.COM size = vsnprintf(NULL, 0, fmt, adx) + 1; 92110272SMatthew.Ahrens@Sun.COM va_end(adx); 92210272SMatthew.Ahrens@Sun.COM 92310272SMatthew.Ahrens@Sun.COM buf = kmem_alloc(size, KM_SLEEP); 92410272SMatthew.Ahrens@Sun.COM 92510272SMatthew.Ahrens@Sun.COM va_start(adx, fmt); 92610272SMatthew.Ahrens@Sun.COM size = vsnprintf(buf, size, fmt, adx); 92710272SMatthew.Ahrens@Sun.COM va_end(adx); 92810272SMatthew.Ahrens@Sun.COM 92910272SMatthew.Ahrens@Sun.COM return (buf); 93010272SMatthew.Ahrens@Sun.COM } 931