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 /* 2211726SVictor.Latushkin@Sun.COM * Copyright 2010 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 4511726SVictor.Latushkin@Sun.COM int aok; 46789Sahrens uint64_t physmem; 47789Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234; 488662SJordan.Vaughan@Sun.com char hw_serial[HW_HOSTID_LEN]; 493975Sek110237 503975Sek110237 struct utsname utsname = { 513975Sek110237 "userland", "libzpool", "1", "1", "na" 523975Sek110237 }; 53789Sahrens 5411173SJonathan.Adams@Sun.COM /* this only exists to have its address taken */ 5511173SJonathan.Adams@Sun.COM struct proc p0; 5611173SJonathan.Adams@Sun.COM 57789Sahrens /* 58789Sahrens * ========================================================================= 59789Sahrens * threads 60789Sahrens * ========================================================================= 61789Sahrens */ 62789Sahrens /*ARGSUSED*/ 63789Sahrens kthread_t * 64789Sahrens zk_thread_create(void (*func)(), void *arg) 65789Sahrens { 66789Sahrens thread_t tid; 67789Sahrens 68789Sahrens VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED, 69789Sahrens &tid) == 0); 70789Sahrens 71789Sahrens return ((void *)(uintptr_t)tid); 72789Sahrens } 73789Sahrens 74789Sahrens /* 75789Sahrens * ========================================================================= 763403Sbmc * kstats 773403Sbmc * ========================================================================= 783403Sbmc */ 793403Sbmc /*ARGSUSED*/ 803403Sbmc kstat_t * 813403Sbmc kstat_create(char *module, int instance, char *name, char *class, 823403Sbmc uchar_t type, ulong_t ndata, uchar_t ks_flag) 833403Sbmc { 843403Sbmc return (NULL); 853403Sbmc } 863403Sbmc 873403Sbmc /*ARGSUSED*/ 883403Sbmc void 893403Sbmc kstat_install(kstat_t *ksp) 903403Sbmc {} 913403Sbmc 923403Sbmc /*ARGSUSED*/ 933403Sbmc void 943403Sbmc kstat_delete(kstat_t *ksp) 953403Sbmc {} 963403Sbmc 973403Sbmc /* 983403Sbmc * ========================================================================= 99789Sahrens * mutexes 100789Sahrens * ========================================================================= 101789Sahrens */ 102789Sahrens void 103789Sahrens zmutex_init(kmutex_t *mp) 104789Sahrens { 105789Sahrens mp->m_owner = NULL; 1064831Sgw25295 mp->initialized = B_TRUE; 107789Sahrens (void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL); 108789Sahrens } 109789Sahrens 110789Sahrens void 111789Sahrens zmutex_destroy(kmutex_t *mp) 112789Sahrens { 1134831Sgw25295 ASSERT(mp->initialized == B_TRUE); 114789Sahrens ASSERT(mp->m_owner == NULL); 115789Sahrens (void) _mutex_destroy(&(mp)->m_lock); 116789Sahrens mp->m_owner = (void *)-1UL; 1174831Sgw25295 mp->initialized = B_FALSE; 118789Sahrens } 119789Sahrens 120789Sahrens void 121789Sahrens mutex_enter(kmutex_t *mp) 122789Sahrens { 1234831Sgw25295 ASSERT(mp->initialized == B_TRUE); 124789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 125789Sahrens ASSERT(mp->m_owner != curthread); 1262856Snd150628 VERIFY(mutex_lock(&mp->m_lock) == 0); 127789Sahrens ASSERT(mp->m_owner == NULL); 128789Sahrens mp->m_owner = curthread; 129789Sahrens } 130789Sahrens 131789Sahrens int 132789Sahrens mutex_tryenter(kmutex_t *mp) 133789Sahrens { 1344831Sgw25295 ASSERT(mp->initialized == B_TRUE); 135789Sahrens ASSERT(mp->m_owner != (void *)-1UL); 136789Sahrens if (0 == mutex_trylock(&mp->m_lock)) { 137789Sahrens ASSERT(mp->m_owner == NULL); 138789Sahrens mp->m_owner = curthread; 139789Sahrens return (1); 140789Sahrens } else { 141789Sahrens return (0); 142789Sahrens } 143789Sahrens } 144789Sahrens 145789Sahrens void 146789Sahrens mutex_exit(kmutex_t *mp) 147789Sahrens { 1484831Sgw25295 ASSERT(mp->initialized == B_TRUE); 149789Sahrens ASSERT(mutex_owner(mp) == curthread); 150789Sahrens mp->m_owner = NULL; 1512856Snd150628 VERIFY(mutex_unlock(&mp->m_lock) == 0); 152789Sahrens } 153789Sahrens 154789Sahrens void * 155789Sahrens mutex_owner(kmutex_t *mp) 156789Sahrens { 1574831Sgw25295 ASSERT(mp->initialized == B_TRUE); 158789Sahrens return (mp->m_owner); 159789Sahrens } 160789Sahrens 161789Sahrens /* 162789Sahrens * ========================================================================= 163789Sahrens * rwlocks 164789Sahrens * ========================================================================= 165789Sahrens */ 166789Sahrens /*ARGSUSED*/ 167789Sahrens void 168789Sahrens rw_init(krwlock_t *rwlp, char *name, int type, void *arg) 169789Sahrens { 170789Sahrens rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL); 171789Sahrens rwlp->rw_owner = NULL; 1724831Sgw25295 rwlp->initialized = B_TRUE; 173789Sahrens } 174789Sahrens 175789Sahrens void 176789Sahrens rw_destroy(krwlock_t *rwlp) 177789Sahrens { 178789Sahrens rwlock_destroy(&rwlp->rw_lock); 179789Sahrens rwlp->rw_owner = (void *)-1UL; 1804831Sgw25295 rwlp->initialized = B_FALSE; 181789Sahrens } 182789Sahrens 183789Sahrens void 184789Sahrens rw_enter(krwlock_t *rwlp, krw_t rw) 185789Sahrens { 186789Sahrens ASSERT(!RW_LOCK_HELD(rwlp)); 1874831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 188789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 189789Sahrens ASSERT(rwlp->rw_owner != curthread); 190789Sahrens 191789Sahrens if (rw == RW_READER) 1926689Smaybee VERIFY(rw_rdlock(&rwlp->rw_lock) == 0); 193789Sahrens else 1946689Smaybee VERIFY(rw_wrlock(&rwlp->rw_lock) == 0); 195789Sahrens 196789Sahrens rwlp->rw_owner = curthread; 197789Sahrens } 198789Sahrens 199789Sahrens void 200789Sahrens rw_exit(krwlock_t *rwlp) 201789Sahrens { 2024831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 203789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 204789Sahrens 205789Sahrens rwlp->rw_owner = NULL; 2066689Smaybee VERIFY(rw_unlock(&rwlp->rw_lock) == 0); 207789Sahrens } 208789Sahrens 209789Sahrens int 210789Sahrens rw_tryenter(krwlock_t *rwlp, krw_t rw) 211789Sahrens { 212789Sahrens int rv; 213789Sahrens 2144831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 215789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 216789Sahrens 217789Sahrens if (rw == RW_READER) 218789Sahrens rv = rw_tryrdlock(&rwlp->rw_lock); 219789Sahrens else 220789Sahrens rv = rw_trywrlock(&rwlp->rw_lock); 221789Sahrens 222789Sahrens if (rv == 0) { 223789Sahrens rwlp->rw_owner = curthread; 224789Sahrens return (1); 225789Sahrens } 226789Sahrens 227789Sahrens return (0); 228789Sahrens } 229789Sahrens 230789Sahrens /*ARGSUSED*/ 231789Sahrens int 232789Sahrens rw_tryupgrade(krwlock_t *rwlp) 233789Sahrens { 2344831Sgw25295 ASSERT(rwlp->initialized == B_TRUE); 235789Sahrens ASSERT(rwlp->rw_owner != (void *)-1UL); 236789Sahrens 237789Sahrens return (0); 238789Sahrens } 239789Sahrens 240789Sahrens /* 241789Sahrens * ========================================================================= 242789Sahrens * condition variables 243789Sahrens * ========================================================================= 244789Sahrens */ 245789Sahrens /*ARGSUSED*/ 246789Sahrens void 247789Sahrens cv_init(kcondvar_t *cv, char *name, int type, void *arg) 248789Sahrens { 2492856Snd150628 VERIFY(cond_init(cv, type, NULL) == 0); 250789Sahrens } 251789Sahrens 252789Sahrens void 253789Sahrens cv_destroy(kcondvar_t *cv) 254789Sahrens { 2552856Snd150628 VERIFY(cond_destroy(cv) == 0); 256789Sahrens } 257789Sahrens 258789Sahrens void 259789Sahrens cv_wait(kcondvar_t *cv, kmutex_t *mp) 260789Sahrens { 261789Sahrens ASSERT(mutex_owner(mp) == curthread); 262789Sahrens mp->m_owner = NULL; 2632856Snd150628 int ret = cond_wait(cv, &mp->m_lock); 2642856Snd150628 VERIFY(ret == 0 || ret == EINTR); 265789Sahrens mp->m_owner = curthread; 266789Sahrens } 267789Sahrens 268789Sahrens clock_t 269789Sahrens cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) 270789Sahrens { 271789Sahrens int error; 272789Sahrens timestruc_t ts; 273789Sahrens clock_t delta; 274789Sahrens 275789Sahrens top: 27611066Srafael.vanoni@sun.com delta = abstime - ddi_get_lbolt(); 277789Sahrens if (delta <= 0) 278789Sahrens return (-1); 279789Sahrens 280789Sahrens ts.tv_sec = delta / hz; 281789Sahrens ts.tv_nsec = (delta % hz) * (NANOSEC / hz); 282789Sahrens 283789Sahrens ASSERT(mutex_owner(mp) == curthread); 284789Sahrens mp->m_owner = NULL; 285789Sahrens error = cond_reltimedwait(cv, &mp->m_lock, &ts); 286789Sahrens mp->m_owner = curthread; 287789Sahrens 288789Sahrens if (error == ETIME) 289789Sahrens return (-1); 290789Sahrens 291789Sahrens if (error == EINTR) 292789Sahrens goto top; 293789Sahrens 294789Sahrens ASSERT(error == 0); 295789Sahrens 296789Sahrens return (1); 297789Sahrens } 298789Sahrens 299789Sahrens void 300789Sahrens cv_signal(kcondvar_t *cv) 301789Sahrens { 3022856Snd150628 VERIFY(cond_signal(cv) == 0); 303789Sahrens } 304789Sahrens 305789Sahrens void 306789Sahrens cv_broadcast(kcondvar_t *cv) 307789Sahrens { 3082856Snd150628 VERIFY(cond_broadcast(cv) == 0); 309789Sahrens } 310789Sahrens 311789Sahrens /* 312789Sahrens * ========================================================================= 313789Sahrens * vnode operations 314789Sahrens * ========================================================================= 315789Sahrens */ 316789Sahrens /* 317789Sahrens * Note: for the xxxat() versions of these functions, we assume that the 318789Sahrens * starting vp is always rootdir (which is true for spa_directory.c, the only 319789Sahrens * ZFS consumer of these interfaces). We assert this is true, and then emulate 320789Sahrens * them by adding '/' in front of the path. 321789Sahrens */ 322789Sahrens 323789Sahrens /*ARGSUSED*/ 324789Sahrens int 325789Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) 326789Sahrens { 327789Sahrens int fd; 328789Sahrens vnode_t *vp; 329789Sahrens int old_umask; 330789Sahrens char realpath[MAXPATHLEN]; 331789Sahrens struct stat64 st; 332789Sahrens 333789Sahrens /* 334789Sahrens * If we're accessing a real disk from userland, we need to use 335789Sahrens * the character interface to avoid caching. This is particularly 336789Sahrens * important if we're trying to look at a real in-kernel storage 337789Sahrens * pool from userland, e.g. via zdb, because otherwise we won't 338789Sahrens * see the changes occurring under the segmap cache. 339789Sahrens * On the other hand, the stupid character device returns zero 340789Sahrens * for its size. So -- gag -- we open the block device to get 341789Sahrens * its size, and remember it for subsequent VOP_GETATTR(). 342789Sahrens */ 343789Sahrens if (strncmp(path, "/dev/", 5) == 0) { 344789Sahrens char *dsk; 345789Sahrens fd = open64(path, O_RDONLY); 346789Sahrens if (fd == -1) 347789Sahrens return (errno); 348789Sahrens if (fstat64(fd, &st) == -1) { 349789Sahrens close(fd); 350789Sahrens return (errno); 351789Sahrens } 352789Sahrens close(fd); 353789Sahrens (void) sprintf(realpath, "%s", path); 354789Sahrens dsk = strstr(path, "/dsk/"); 355789Sahrens if (dsk != NULL) 356789Sahrens (void) sprintf(realpath + (dsk - path) + 1, "r%s", 357789Sahrens dsk + 1); 358789Sahrens } else { 359789Sahrens (void) sprintf(realpath, "%s", path); 360789Sahrens if (!(flags & FCREAT) && stat64(realpath, &st) == -1) 361789Sahrens return (errno); 362789Sahrens } 363789Sahrens 364789Sahrens if (flags & FCREAT) 365789Sahrens old_umask = umask(0); 366789Sahrens 367789Sahrens /* 368789Sahrens * The construct 'flags - FREAD' conveniently maps combinations of 369789Sahrens * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. 370789Sahrens */ 371789Sahrens fd = open64(realpath, flags - FREAD, mode); 372789Sahrens 373789Sahrens if (flags & FCREAT) 374789Sahrens (void) umask(old_umask); 375789Sahrens 376789Sahrens if (fd == -1) 377789Sahrens return (errno); 378789Sahrens 379789Sahrens if (fstat64(fd, &st) == -1) { 380789Sahrens close(fd); 381789Sahrens return (errno); 382789Sahrens } 383789Sahrens 384789Sahrens (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 385789Sahrens 386789Sahrens *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); 387789Sahrens 388789Sahrens vp->v_fd = fd; 389789Sahrens vp->v_size = st.st_size; 390789Sahrens vp->v_path = spa_strdup(path); 391789Sahrens 392789Sahrens return (0); 393789Sahrens } 394789Sahrens 3955331Samw /*ARGSUSED*/ 396789Sahrens int 397789Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, 3985331Samw int x3, vnode_t *startvp, int fd) 399789Sahrens { 400789Sahrens char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); 401789Sahrens int ret; 402789Sahrens 403789Sahrens ASSERT(startvp == rootdir); 404789Sahrens (void) sprintf(realpath, "/%s", path); 405789Sahrens 4065331Samw /* fd ignored for now, need if want to simulate nbmand support */ 407789Sahrens ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); 408789Sahrens 409789Sahrens umem_free(realpath, strlen(path) + 2); 410789Sahrens 411789Sahrens return (ret); 412789Sahrens } 413789Sahrens 414789Sahrens /*ARGSUSED*/ 415789Sahrens int 416789Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, 417789Sahrens int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) 418789Sahrens { 419789Sahrens ssize_t iolen, split; 420789Sahrens 421789Sahrens if (uio == UIO_READ) { 422789Sahrens iolen = pread64(vp->v_fd, addr, len, offset); 423789Sahrens } else { 424789Sahrens /* 425789Sahrens * To simulate partial disk writes, we split writes into two 426789Sahrens * system calls so that the process can be killed in between. 427789Sahrens */ 428789Sahrens split = (len > 0 ? rand() % len : 0); 429789Sahrens iolen = pwrite64(vp->v_fd, addr, split, offset); 430789Sahrens iolen += pwrite64(vp->v_fd, (char *)addr + split, 431789Sahrens len - split, offset + split); 432789Sahrens } 433789Sahrens 434789Sahrens if (iolen == -1) 435789Sahrens return (errno); 436789Sahrens if (residp) 437789Sahrens *residp = len - iolen; 438789Sahrens else if (iolen != len) 439789Sahrens return (EIO); 440789Sahrens return (0); 441789Sahrens } 442789Sahrens 443789Sahrens void 444789Sahrens vn_close(vnode_t *vp) 445789Sahrens { 446789Sahrens close(vp->v_fd); 447789Sahrens spa_strfree(vp->v_path); 448789Sahrens umem_free(vp, sizeof (vnode_t)); 449789Sahrens } 450789Sahrens 45110850SGeorge.Wilson@Sun.COM /* 45210850SGeorge.Wilson@Sun.COM * At a minimum we need to update the size since vdev_reopen() 45310850SGeorge.Wilson@Sun.COM * will no longer call vn_openat(). 45410850SGeorge.Wilson@Sun.COM */ 45510850SGeorge.Wilson@Sun.COM int 45610850SGeorge.Wilson@Sun.COM fop_getattr(vnode_t *vp, vattr_t *vap) 45710850SGeorge.Wilson@Sun.COM { 45810850SGeorge.Wilson@Sun.COM struct stat64 st; 45910850SGeorge.Wilson@Sun.COM 46010850SGeorge.Wilson@Sun.COM if (fstat64(vp->v_fd, &st) == -1) { 46110850SGeorge.Wilson@Sun.COM close(vp->v_fd); 46210850SGeorge.Wilson@Sun.COM return (errno); 46310850SGeorge.Wilson@Sun.COM } 46410850SGeorge.Wilson@Sun.COM 46510850SGeorge.Wilson@Sun.COM vap->va_size = st.st_size; 46610850SGeorge.Wilson@Sun.COM return (0); 46710850SGeorge.Wilson@Sun.COM } 46810850SGeorge.Wilson@Sun.COM 469789Sahrens #ifdef ZFS_DEBUG 470789Sahrens 471789Sahrens /* 472789Sahrens * ========================================================================= 473789Sahrens * Figure out which debugging statements to print 474789Sahrens * ========================================================================= 475789Sahrens */ 476789Sahrens 477789Sahrens static char *dprintf_string; 478789Sahrens static int dprintf_print_all; 479789Sahrens 480789Sahrens int 481789Sahrens dprintf_find_string(const char *string) 482789Sahrens { 483789Sahrens char *tmp_str = dprintf_string; 484789Sahrens int len = strlen(string); 485789Sahrens 486789Sahrens /* 487789Sahrens * Find out if this is a string we want to print. 488789Sahrens * String format: file1.c,function_name1,file2.c,file3.c 489789Sahrens */ 490789Sahrens 491789Sahrens while (tmp_str != NULL) { 492789Sahrens if (strncmp(tmp_str, string, len) == 0 && 493789Sahrens (tmp_str[len] == ',' || tmp_str[len] == '\0')) 494789Sahrens return (1); 495789Sahrens tmp_str = strchr(tmp_str, ','); 496789Sahrens if (tmp_str != NULL) 497789Sahrens tmp_str++; /* Get rid of , */ 498789Sahrens } 499789Sahrens return (0); 500789Sahrens } 501789Sahrens 502789Sahrens void 503789Sahrens dprintf_setup(int *argc, char **argv) 504789Sahrens { 505789Sahrens int i, j; 506789Sahrens 507789Sahrens /* 508789Sahrens * Debugging can be specified two ways: by setting the 509789Sahrens * environment variable ZFS_DEBUG, or by including a 510789Sahrens * "debug=..." argument on the command line. The command 511789Sahrens * line setting overrides the environment variable. 512789Sahrens */ 513789Sahrens 514789Sahrens for (i = 1; i < *argc; i++) { 515789Sahrens int len = strlen("debug="); 516789Sahrens /* First look for a command line argument */ 517789Sahrens if (strncmp("debug=", argv[i], len) == 0) { 518789Sahrens dprintf_string = argv[i] + len; 519789Sahrens /* Remove from args */ 520789Sahrens for (j = i; j < *argc; j++) 521789Sahrens argv[j] = argv[j+1]; 522789Sahrens argv[j] = NULL; 523789Sahrens (*argc)--; 524789Sahrens } 525789Sahrens } 526789Sahrens 527789Sahrens if (dprintf_string == NULL) { 528789Sahrens /* Look for ZFS_DEBUG environment variable */ 529789Sahrens dprintf_string = getenv("ZFS_DEBUG"); 530789Sahrens } 531789Sahrens 532789Sahrens /* 533789Sahrens * Are we just turning on all debugging? 534789Sahrens */ 535789Sahrens if (dprintf_find_string("on")) 536789Sahrens dprintf_print_all = 1; 537789Sahrens } 538789Sahrens 539789Sahrens /* 540789Sahrens * ========================================================================= 541789Sahrens * debug printfs 542789Sahrens * ========================================================================= 543789Sahrens */ 544789Sahrens void 545789Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 546789Sahrens { 547789Sahrens const char *newfile; 548789Sahrens va_list adx; 549789Sahrens 550789Sahrens /* 551789Sahrens * Get rid of annoying "../common/" prefix to filename. 552789Sahrens */ 553789Sahrens newfile = strrchr(file, '/'); 554789Sahrens if (newfile != NULL) { 555789Sahrens newfile = newfile + 1; /* Get rid of leading / */ 556789Sahrens } else { 557789Sahrens newfile = file; 558789Sahrens } 559789Sahrens 560789Sahrens if (dprintf_print_all || 561789Sahrens dprintf_find_string(newfile) || 562789Sahrens dprintf_find_string(func)) { 563789Sahrens /* Print out just the function name if requested */ 564789Sahrens flockfile(stdout); 565789Sahrens if (dprintf_find_string("pid")) 566789Sahrens (void) printf("%d ", getpid()); 567789Sahrens if (dprintf_find_string("tid")) 568789Sahrens (void) printf("%u ", thr_self()); 569789Sahrens if (dprintf_find_string("cpu")) 570789Sahrens (void) printf("%u ", getcpuid()); 571789Sahrens if (dprintf_find_string("time")) 572789Sahrens (void) printf("%llu ", gethrtime()); 573789Sahrens if (dprintf_find_string("long")) 574789Sahrens (void) printf("%s, line %d: ", newfile, line); 575789Sahrens (void) printf("%s: ", func); 576789Sahrens va_start(adx, fmt); 577789Sahrens (void) vprintf(fmt, adx); 578789Sahrens va_end(adx); 579789Sahrens funlockfile(stdout); 580789Sahrens } 581789Sahrens } 582789Sahrens 583789Sahrens #endif /* ZFS_DEBUG */ 584789Sahrens 585789Sahrens /* 586789Sahrens * ========================================================================= 587789Sahrens * cmn_err() and panic() 588789Sahrens * ========================================================================= 589789Sahrens */ 590789Sahrens static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 591789Sahrens static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 592789Sahrens 593789Sahrens void 594789Sahrens vpanic(const char *fmt, va_list adx) 595789Sahrens { 596789Sahrens (void) fprintf(stderr, "error: "); 597789Sahrens (void) vfprintf(stderr, fmt, adx); 598789Sahrens (void) fprintf(stderr, "\n"); 599789Sahrens 600789Sahrens abort(); /* think of it as a "user-level crash dump" */ 601789Sahrens } 602789Sahrens 603789Sahrens void 604789Sahrens panic(const char *fmt, ...) 605789Sahrens { 606789Sahrens va_list adx; 607789Sahrens 608789Sahrens va_start(adx, fmt); 609789Sahrens vpanic(fmt, adx); 610789Sahrens va_end(adx); 611789Sahrens } 612789Sahrens 6133713Sahrens void 6143713Sahrens vcmn_err(int ce, const char *fmt, va_list adx) 6153713Sahrens { 6163713Sahrens if (ce == CE_PANIC) 6173713Sahrens vpanic(fmt, adx); 6183713Sahrens if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ 6193713Sahrens (void) fprintf(stderr, "%s", ce_prefix[ce]); 6203713Sahrens (void) vfprintf(stderr, fmt, adx); 6213713Sahrens (void) fprintf(stderr, "%s", ce_suffix[ce]); 6223713Sahrens } 6233713Sahrens } 6243713Sahrens 625789Sahrens /*PRINTFLIKE2*/ 626789Sahrens void 627789Sahrens cmn_err(int ce, const char *fmt, ...) 628789Sahrens { 629789Sahrens va_list adx; 630789Sahrens 631789Sahrens va_start(adx, fmt); 6323713Sahrens vcmn_err(ce, fmt, adx); 633789Sahrens va_end(adx); 634789Sahrens } 635789Sahrens 636789Sahrens /* 637789Sahrens * ========================================================================= 6381544Seschrock * kobj interfaces 6391544Seschrock * ========================================================================= 6401544Seschrock */ 6411544Seschrock struct _buf * 6421544Seschrock kobj_open_file(char *name) 6431544Seschrock { 6441544Seschrock struct _buf *file; 6451544Seschrock vnode_t *vp; 6461544Seschrock 6471544Seschrock /* set vp as the _fd field of the file */ 6485331Samw if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir, 6495331Samw -1) != 0) 6501544Seschrock return ((void *)-1UL); 6511544Seschrock 6521544Seschrock file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 6531544Seschrock file->_fd = (intptr_t)vp; 6541544Seschrock return (file); 6551544Seschrock } 6561544Seschrock 6571544Seschrock int 6581544Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 6591544Seschrock { 6601544Seschrock ssize_t resid; 6611544Seschrock 6621544Seschrock vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 6631544Seschrock UIO_SYSSPACE, 0, 0, 0, &resid); 6641544Seschrock 6653912Slling return (size - resid); 6661544Seschrock } 6671544Seschrock 6681544Seschrock void 6691544Seschrock kobj_close_file(struct _buf *file) 6701544Seschrock { 6711544Seschrock vn_close((vnode_t *)file->_fd); 6721544Seschrock umem_free(file, sizeof (struct _buf)); 6731544Seschrock } 6741544Seschrock 6751544Seschrock int 6763912Slling kobj_get_filesize(struct _buf *file, uint64_t *size) 6771544Seschrock { 6781544Seschrock struct stat64 st; 6793912Slling vnode_t *vp = (vnode_t *)file->_fd; 6803912Slling 6811544Seschrock if (fstat64(vp->v_fd, &st) == -1) { 6821544Seschrock vn_close(vp); 6831544Seschrock return (errno); 6841544Seschrock } 6853912Slling *size = st.st_size; 6861544Seschrock return (0); 6871544Seschrock } 6881544Seschrock 6891544Seschrock /* 6901544Seschrock * ========================================================================= 691789Sahrens * misc routines 692789Sahrens * ========================================================================= 693789Sahrens */ 694789Sahrens 695789Sahrens void 696789Sahrens delay(clock_t ticks) 697789Sahrens { 698789Sahrens poll(0, 0, ticks * (1000 / hz)); 699789Sahrens } 700789Sahrens 701789Sahrens /* 702789Sahrens * Find highest one bit set. 703789Sahrens * Returns bit number + 1 of highest bit that is set, otherwise returns 0. 704789Sahrens * High order bit is 31 (or 63 in _LP64 kernel). 705789Sahrens */ 706789Sahrens int 707789Sahrens highbit(ulong_t i) 708789Sahrens { 709789Sahrens register int h = 1; 710789Sahrens 711789Sahrens if (i == 0) 712789Sahrens return (0); 713789Sahrens #ifdef _LP64 714789Sahrens if (i & 0xffffffff00000000ul) { 715789Sahrens h += 32; i >>= 32; 716789Sahrens } 717789Sahrens #endif 718789Sahrens if (i & 0xffff0000) { 719789Sahrens h += 16; i >>= 16; 720789Sahrens } 721789Sahrens if (i & 0xff00) { 722789Sahrens h += 8; i >>= 8; 723789Sahrens } 724789Sahrens if (i & 0xf0) { 725789Sahrens h += 4; i >>= 4; 726789Sahrens } 727789Sahrens if (i & 0xc) { 728789Sahrens h += 2; i >>= 2; 729789Sahrens } 730789Sahrens if (i & 0x2) { 731789Sahrens h += 1; 732789Sahrens } 733789Sahrens return (h); 734789Sahrens } 735789Sahrens 7365688Sbonwick static int random_fd = -1, urandom_fd = -1; 7375688Sbonwick 738789Sahrens static int 7395688Sbonwick random_get_bytes_common(uint8_t *ptr, size_t len, int fd) 740789Sahrens { 741789Sahrens size_t resid = len; 742789Sahrens ssize_t bytes; 743789Sahrens 744789Sahrens ASSERT(fd != -1); 745789Sahrens 746789Sahrens while (resid != 0) { 747789Sahrens bytes = read(fd, ptr, resid); 7485688Sbonwick ASSERT3S(bytes, >=, 0); 749789Sahrens ptr += bytes; 750789Sahrens resid -= bytes; 751789Sahrens } 752789Sahrens 753789Sahrens return (0); 754789Sahrens } 755789Sahrens 756789Sahrens int 757789Sahrens random_get_bytes(uint8_t *ptr, size_t len) 758789Sahrens { 7595688Sbonwick return (random_get_bytes_common(ptr, len, random_fd)); 760789Sahrens } 761789Sahrens 762789Sahrens int 763789Sahrens random_get_pseudo_bytes(uint8_t *ptr, size_t len) 764789Sahrens { 7655688Sbonwick return (random_get_bytes_common(ptr, len, urandom_fd)); 766789Sahrens } 767789Sahrens 7683975Sek110237 int 7693975Sek110237 ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result) 7703975Sek110237 { 7713975Sek110237 char *end; 7723975Sek110237 7733975Sek110237 *result = strtoul(hw_serial, &end, base); 7743975Sek110237 if (*result == 0) 7753975Sek110237 return (errno); 7763975Sek110237 return (0); 7773975Sek110237 } 7783975Sek110237 779*11935SMark.Shellenbaum@Sun.COM int 780*11935SMark.Shellenbaum@Sun.COM ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result) 781*11935SMark.Shellenbaum@Sun.COM { 782*11935SMark.Shellenbaum@Sun.COM char *end; 783*11935SMark.Shellenbaum@Sun.COM 784*11935SMark.Shellenbaum@Sun.COM *result = strtoull(str, &end, base); 785*11935SMark.Shellenbaum@Sun.COM if (*result == 0) 786*11935SMark.Shellenbaum@Sun.COM return (errno); 787*11935SMark.Shellenbaum@Sun.COM return (0); 788*11935SMark.Shellenbaum@Sun.COM } 789*11935SMark.Shellenbaum@Sun.COM 790789Sahrens /* 791789Sahrens * ========================================================================= 792789Sahrens * kernel emulation setup & teardown 793789Sahrens * ========================================================================= 794789Sahrens */ 795789Sahrens static int 796789Sahrens umem_out_of_memory(void) 797789Sahrens { 798789Sahrens char errmsg[] = "out of memory -- generating core dump\n"; 799789Sahrens 800789Sahrens write(fileno(stderr), errmsg, sizeof (errmsg)); 801789Sahrens abort(); 802789Sahrens return (0); 803789Sahrens } 804789Sahrens 805789Sahrens void 806789Sahrens kernel_init(int mode) 807789Sahrens { 808789Sahrens umem_nofail_callback(umem_out_of_memory); 809789Sahrens 810789Sahrens physmem = sysconf(_SC_PHYS_PAGES); 811789Sahrens 812789Sahrens dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 813789Sahrens (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 814789Sahrens 81510858SVictor.Latushkin@Sun.COM (void) snprintf(hw_serial, sizeof (hw_serial), "%ld", 81610858SVictor.Latushkin@Sun.COM (mode & FWRITE) ? gethostid() : 0); 8173975Sek110237 8185688Sbonwick VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1); 8195688Sbonwick VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1); 8205688Sbonwick 8217837SMatthew.Ahrens@Sun.COM system_taskq_init(); 8227837SMatthew.Ahrens@Sun.COM 823789Sahrens spa_init(mode); 824789Sahrens } 825789Sahrens 826789Sahrens void 827789Sahrens kernel_fini(void) 828789Sahrens { 829789Sahrens spa_fini(); 8305688Sbonwick 83110612SRicardo.M.Correia@Sun.COM system_taskq_fini(); 83210612SRicardo.M.Correia@Sun.COM 8335688Sbonwick close(random_fd); 8345688Sbonwick close(urandom_fd); 8355688Sbonwick 8365688Sbonwick random_fd = -1; 8375688Sbonwick urandom_fd = -1; 838789Sahrens } 8393886Sahl 8403886Sahl int 8413886Sahl z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 8423886Sahl { 8433886Sahl int ret; 8443886Sahl uLongf len = *dstlen; 8453886Sahl 8463886Sahl if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK) 8473886Sahl *dstlen = (size_t)len; 8483886Sahl 8493886Sahl return (ret); 8503886Sahl } 8513886Sahl 8523886Sahl int 8533886Sahl z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen, 8543886Sahl int level) 8553886Sahl { 8563886Sahl int ret; 8573886Sahl uLongf len = *dstlen; 8583886Sahl 8593886Sahl if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK) 8603886Sahl *dstlen = (size_t)len; 8613886Sahl 8623886Sahl return (ret); 8633886Sahl } 8644543Smarks 8654543Smarks uid_t 8664543Smarks crgetuid(cred_t *cr) 8674543Smarks { 8684543Smarks return (0); 8694543Smarks } 8704543Smarks 8714543Smarks gid_t 8724543Smarks crgetgid(cred_t *cr) 8734543Smarks { 8744543Smarks return (0); 8754543Smarks } 8764543Smarks 8774543Smarks int 8784543Smarks crgetngroups(cred_t *cr) 8794543Smarks { 8804543Smarks return (0); 8814543Smarks } 8824543Smarks 8834543Smarks gid_t * 8844543Smarks crgetgroups(cred_t *cr) 8854543Smarks { 8864543Smarks return (NULL); 8874543Smarks } 8884543Smarks 8894543Smarks int 8904543Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 8914543Smarks { 8924543Smarks return (0); 8934543Smarks } 8944543Smarks 8954543Smarks int 8964543Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 8974543Smarks { 8984543Smarks return (0); 8994543Smarks } 9004543Smarks 9014543Smarks int 9024543Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 9034543Smarks { 9044543Smarks return (0); 9054543Smarks } 9065959Smarks 9075959Smarks ksiddomain_t * 9085959Smarks ksid_lookupdomain(const char *dom) 9095959Smarks { 9105959Smarks ksiddomain_t *kd; 9115959Smarks 9125959Smarks kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL); 9135959Smarks kd->kd_name = spa_strdup(dom); 9145959Smarks return (kd); 9155959Smarks } 9165959Smarks 9175959Smarks void 9185959Smarks ksiddomain_rele(ksiddomain_t *ksid) 9195959Smarks { 9205959Smarks spa_strfree(ksid->kd_name); 9215959Smarks umem_free(ksid, sizeof (ksiddomain_t)); 9225959Smarks } 92310272SMatthew.Ahrens@Sun.COM 92410272SMatthew.Ahrens@Sun.COM /* 92510272SMatthew.Ahrens@Sun.COM * Do not change the length of the returned string; it must be freed 92610272SMatthew.Ahrens@Sun.COM * with strfree(). 92710272SMatthew.Ahrens@Sun.COM */ 92810272SMatthew.Ahrens@Sun.COM char * 92910272SMatthew.Ahrens@Sun.COM kmem_asprintf(const char *fmt, ...) 93010272SMatthew.Ahrens@Sun.COM { 93110272SMatthew.Ahrens@Sun.COM int size; 93210272SMatthew.Ahrens@Sun.COM va_list adx; 93310272SMatthew.Ahrens@Sun.COM char *buf; 93410272SMatthew.Ahrens@Sun.COM 93510272SMatthew.Ahrens@Sun.COM va_start(adx, fmt); 93610272SMatthew.Ahrens@Sun.COM size = vsnprintf(NULL, 0, fmt, adx) + 1; 93710272SMatthew.Ahrens@Sun.COM va_end(adx); 93810272SMatthew.Ahrens@Sun.COM 93910272SMatthew.Ahrens@Sun.COM buf = kmem_alloc(size, KM_SLEEP); 94010272SMatthew.Ahrens@Sun.COM 94110272SMatthew.Ahrens@Sun.COM va_start(adx, fmt); 94210272SMatthew.Ahrens@Sun.COM size = vsnprintf(buf, size, fmt, adx); 94310272SMatthew.Ahrens@Sun.COM va_end(adx); 94410272SMatthew.Ahrens@Sun.COM 94510272SMatthew.Ahrens@Sun.COM return (buf); 94610272SMatthew.Ahrens@Sun.COM } 947