1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd/* 22219089Spjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23168404Spjd */ 24168404Spjd 25168404Spjd#include <assert.h> 26168404Spjd#include <fcntl.h> 27168404Spjd#include <poll.h> 28168404Spjd#include <stdio.h> 29168404Spjd#include <stdlib.h> 30168404Spjd#include <string.h> 31168404Spjd#include <zlib.h> 32168404Spjd#include <sys/spa.h> 33168404Spjd#include <sys/stat.h> 34168404Spjd#include <sys/processor.h> 35168404Spjd#include <sys/zfs_context.h> 36248571Smm#include <sys/rrwlock.h> 37168404Spjd#include <sys/zmod.h> 38168498Spjd#include <sys/utsname.h> 39219089Spjd#include <sys/systeminfo.h> 40168404Spjd 41168404Spjd/* 42168404Spjd * Emulation of kernel services in userland. 43168404Spjd */ 44168404Spjd 45219089Spjdint aok; 46168404Spjduint64_t physmem; 47168404Spjdvnode_t *rootdir = (vnode_t *)0xabcd1234; 48219089Spjdchar hw_serial[HW_HOSTID_LEN]; 49247265Smm#ifdef illumos 50247265Smmkmutex_t cpu_lock; 51247265Smm#endif 52168404Spjd 53168498Spjdstruct utsname utsname = { 54168498Spjd "userland", "libzpool", "1", "1", "na" 55168498Spjd}; 56168498Spjd 57219089Spjd/* this only exists to have its address taken */ 58219089Spjdstruct proc p0; 59219089Spjd 60168404Spjd/* 61168404Spjd * ========================================================================= 62168404Spjd * threads 63168404Spjd * ========================================================================= 64168404Spjd */ 65168404Spjd/*ARGSUSED*/ 66168404Spjdkthread_t * 67168404Spjdzk_thread_create(void (*func)(), void *arg) 68168404Spjd{ 69168404Spjd thread_t tid; 70168404Spjd 71168404Spjd VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED, 72168404Spjd &tid) == 0); 73168404Spjd 74168404Spjd return ((void *)(uintptr_t)tid); 75168404Spjd} 76168404Spjd 77168404Spjd/* 78168404Spjd * ========================================================================= 79168404Spjd * kstats 80168404Spjd * ========================================================================= 81168404Spjd */ 82168404Spjd/*ARGSUSED*/ 83168404Spjdkstat_t * 84168404Spjdkstat_create(char *module, int instance, char *name, char *class, 85168404Spjd uchar_t type, ulong_t ndata, uchar_t ks_flag) 86168404Spjd{ 87168404Spjd return (NULL); 88168404Spjd} 89168404Spjd 90168404Spjd/*ARGSUSED*/ 91168404Spjdvoid 92168404Spjdkstat_install(kstat_t *ksp) 93168404Spjd{} 94168404Spjd 95168404Spjd/*ARGSUSED*/ 96168404Spjdvoid 97168404Spjdkstat_delete(kstat_t *ksp) 98168404Spjd{} 99168404Spjd 100168404Spjd/* 101168404Spjd * ========================================================================= 102168404Spjd * mutexes 103168404Spjd * ========================================================================= 104168404Spjd */ 105168404Spjdvoid 106168404Spjdzmutex_init(kmutex_t *mp) 107168404Spjd{ 108168404Spjd mp->m_owner = NULL; 109185029Spjd mp->initialized = B_TRUE; 110168404Spjd (void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL); 111168404Spjd} 112168404Spjd 113168404Spjdvoid 114168404Spjdzmutex_destroy(kmutex_t *mp) 115168404Spjd{ 116185029Spjd ASSERT(mp->initialized == B_TRUE); 117168404Spjd ASSERT(mp->m_owner == NULL); 118168404Spjd (void) _mutex_destroy(&(mp)->m_lock); 119168404Spjd mp->m_owner = (void *)-1UL; 120185029Spjd mp->initialized = B_FALSE; 121168404Spjd} 122168404Spjd 123195515Spjdint 124195515Spjdzmutex_owned(kmutex_t *mp) 125195515Spjd{ 126195515Spjd ASSERT(mp->initialized == B_TRUE); 127195515Spjd 128195515Spjd return (mp->m_owner == curthread); 129195515Spjd} 130195515Spjd 131168404Spjdvoid 132168404Spjdmutex_enter(kmutex_t *mp) 133168404Spjd{ 134185029Spjd ASSERT(mp->initialized == B_TRUE); 135168404Spjd ASSERT(mp->m_owner != (void *)-1UL); 136168404Spjd ASSERT(mp->m_owner != curthread); 137168404Spjd VERIFY(mutex_lock(&mp->m_lock) == 0); 138168404Spjd ASSERT(mp->m_owner == NULL); 139168404Spjd mp->m_owner = curthread; 140168404Spjd} 141168404Spjd 142168404Spjdint 143168404Spjdmutex_tryenter(kmutex_t *mp) 144168404Spjd{ 145185029Spjd ASSERT(mp->initialized == B_TRUE); 146168404Spjd ASSERT(mp->m_owner != (void *)-1UL); 147219089Spjd if (0 == mutex_trylock(&mp->m_lock)) { 148168404Spjd ASSERT(mp->m_owner == NULL); 149168404Spjd mp->m_owner = curthread; 150168404Spjd return (1); 151168404Spjd } else { 152168404Spjd return (0); 153168404Spjd } 154168404Spjd} 155168404Spjd 156168404Spjdvoid 157168404Spjdmutex_exit(kmutex_t *mp) 158168404Spjd{ 159185029Spjd ASSERT(mp->initialized == B_TRUE); 160219089Spjd ASSERT(mutex_owner(mp) == curthread); 161168404Spjd mp->m_owner = NULL; 162168404Spjd VERIFY(mutex_unlock(&mp->m_lock) == 0); 163168404Spjd} 164168404Spjd 165168404Spjdvoid * 166168404Spjdmutex_owner(kmutex_t *mp) 167168404Spjd{ 168185029Spjd ASSERT(mp->initialized == B_TRUE); 169168404Spjd return (mp->m_owner); 170168404Spjd} 171168404Spjd 172168404Spjd/* 173168404Spjd * ========================================================================= 174168404Spjd * rwlocks 175168404Spjd * ========================================================================= 176168404Spjd */ 177168404Spjd/*ARGSUSED*/ 178168404Spjdvoid 179168404Spjdrw_init(krwlock_t *rwlp, char *name, int type, void *arg) 180168404Spjd{ 181168404Spjd rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL); 182168404Spjd rwlp->rw_owner = NULL; 183185029Spjd rwlp->initialized = B_TRUE; 184210044Spjd rwlp->rw_count = 0; 185168404Spjd} 186168404Spjd 187168404Spjdvoid 188168404Spjdrw_destroy(krwlock_t *rwlp) 189168404Spjd{ 190210044Spjd ASSERT(rwlp->rw_count == 0); 191168404Spjd rwlock_destroy(&rwlp->rw_lock); 192168404Spjd rwlp->rw_owner = (void *)-1UL; 193185029Spjd rwlp->initialized = B_FALSE; 194168404Spjd} 195168404Spjd 196168404Spjdvoid 197168404Spjdrw_enter(krwlock_t *rwlp, krw_t rw) 198168404Spjd{ 199168404Spjd //ASSERT(!RW_LOCK_HELD(rwlp)); 200185029Spjd ASSERT(rwlp->initialized == B_TRUE); 201168404Spjd ASSERT(rwlp->rw_owner != (void *)-1UL); 202168404Spjd ASSERT(rwlp->rw_owner != curthread); 203168404Spjd 204168404Spjd if (rw == RW_READER) { 205185029Spjd VERIFY(rw_rdlock(&rwlp->rw_lock) == 0); 206168404Spjd ASSERT(rwlp->rw_count >= 0); 207168404Spjd atomic_add_int(&rwlp->rw_count, 1); 208168404Spjd } else { 209185029Spjd VERIFY(rw_wrlock(&rwlp->rw_lock) == 0); 210168404Spjd ASSERT(rwlp->rw_count == 0); 211168404Spjd rwlp->rw_count = -1; 212168404Spjd rwlp->rw_owner = curthread; 213168404Spjd } 214168404Spjd} 215168404Spjd 216168404Spjdvoid 217168404Spjdrw_exit(krwlock_t *rwlp) 218168404Spjd{ 219185029Spjd ASSERT(rwlp->initialized == B_TRUE); 220168404Spjd ASSERT(rwlp->rw_owner != (void *)-1UL); 221168404Spjd 222168404Spjd if (rwlp->rw_owner == curthread) { 223168404Spjd /* Write locked. */ 224168404Spjd ASSERT(rwlp->rw_count == -1); 225168404Spjd rwlp->rw_count = 0; 226168404Spjd rwlp->rw_owner = NULL; 227168404Spjd } else { 228168404Spjd /* Read locked. */ 229168404Spjd ASSERT(rwlp->rw_count > 0); 230168404Spjd atomic_add_int(&rwlp->rw_count, -1); 231168404Spjd } 232185029Spjd VERIFY(rw_unlock(&rwlp->rw_lock) == 0); 233168404Spjd} 234168404Spjd 235168404Spjdint 236168404Spjdrw_tryenter(krwlock_t *rwlp, krw_t rw) 237168404Spjd{ 238168404Spjd int rv; 239168404Spjd 240185029Spjd ASSERT(rwlp->initialized == B_TRUE); 241168404Spjd ASSERT(rwlp->rw_owner != (void *)-1UL); 242168404Spjd ASSERT(rwlp->rw_owner != curthread); 243168404Spjd 244168404Spjd if (rw == RW_READER) 245168404Spjd rv = rw_tryrdlock(&rwlp->rw_lock); 246168404Spjd else 247168404Spjd rv = rw_trywrlock(&rwlp->rw_lock); 248168404Spjd 249168404Spjd if (rv == 0) { 250168404Spjd ASSERT(rwlp->rw_owner == NULL); 251168404Spjd if (rw == RW_READER) { 252168404Spjd ASSERT(rwlp->rw_count >= 0); 253168404Spjd atomic_add_int(&rwlp->rw_count, 1); 254168404Spjd } else { 255168404Spjd ASSERT(rwlp->rw_count == 0); 256168404Spjd rwlp->rw_count = -1; 257168404Spjd rwlp->rw_owner = curthread; 258168404Spjd } 259168404Spjd return (1); 260168404Spjd } 261168404Spjd 262168404Spjd return (0); 263168404Spjd} 264168404Spjd 265168404Spjd/*ARGSUSED*/ 266168404Spjdint 267168404Spjdrw_tryupgrade(krwlock_t *rwlp) 268168404Spjd{ 269185029Spjd ASSERT(rwlp->initialized == B_TRUE); 270168404Spjd ASSERT(rwlp->rw_owner != (void *)-1UL); 271168404Spjd 272168404Spjd return (0); 273168404Spjd} 274168404Spjd 275168404Spjdint 276168404Spjdrw_lock_held(krwlock_t *rwlp) 277168404Spjd{ 278168404Spjd 279168404Spjd return (rwlp->rw_count != 0); 280168404Spjd} 281168404Spjd 282168404Spjd/* 283168404Spjd * ========================================================================= 284168404Spjd * condition variables 285168404Spjd * ========================================================================= 286168404Spjd */ 287168404Spjd/*ARGSUSED*/ 288168404Spjdvoid 289168404Spjdcv_init(kcondvar_t *cv, char *name, int type, void *arg) 290168404Spjd{ 291168404Spjd VERIFY(cond_init(cv, name, NULL) == 0); 292168404Spjd} 293168404Spjd 294168404Spjdvoid 295168404Spjdcv_destroy(kcondvar_t *cv) 296168404Spjd{ 297168404Spjd VERIFY(cond_destroy(cv) == 0); 298168404Spjd} 299168404Spjd 300168404Spjdvoid 301168404Spjdcv_wait(kcondvar_t *cv, kmutex_t *mp) 302168404Spjd{ 303168404Spjd ASSERT(mutex_owner(mp) == curthread); 304168404Spjd mp->m_owner = NULL; 305168404Spjd int ret = cond_wait(cv, &mp->m_lock); 306168404Spjd VERIFY(ret == 0 || ret == EINTR); 307168404Spjd mp->m_owner = curthread; 308168404Spjd} 309168404Spjd 310168404Spjdclock_t 311168404Spjdcv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) 312168404Spjd{ 313168404Spjd int error; 314168404Spjd struct timespec ts; 315168404Spjd struct timeval tv; 316168404Spjd clock_t delta; 317168404Spjd 318219089Spjd abstime += ddi_get_lbolt(); 319168404Spjdtop: 320219089Spjd delta = abstime - ddi_get_lbolt(); 321168404Spjd if (delta <= 0) 322168404Spjd return (-1); 323168404Spjd 324168404Spjd if (gettimeofday(&tv, NULL) != 0) 325168404Spjd assert(!"gettimeofday() failed"); 326168404Spjd 327168404Spjd ts.tv_sec = tv.tv_sec + delta / hz; 328168404Spjd ts.tv_nsec = tv.tv_usec * 1000 + (delta % hz) * (NANOSEC / hz); 329168404Spjd ASSERT(ts.tv_nsec >= 0); 330168404Spjd 331214622Spjd if (ts.tv_nsec >= NANOSEC) { 332168404Spjd ts.tv_sec++; 333168404Spjd ts.tv_nsec -= NANOSEC; 334168404Spjd } 335168404Spjd 336168404Spjd ASSERT(mutex_owner(mp) == curthread); 337168404Spjd mp->m_owner = NULL; 338168404Spjd error = pthread_cond_timedwait(cv, &mp->m_lock, &ts); 339168404Spjd mp->m_owner = curthread; 340168404Spjd 341168404Spjd if (error == EINTR) 342168404Spjd goto top; 343168404Spjd 344168404Spjd if (error == ETIMEDOUT) 345168404Spjd return (-1); 346168404Spjd 347168404Spjd ASSERT(error == 0); 348168404Spjd 349168404Spjd return (1); 350168404Spjd} 351168404Spjd 352255437Sdelphij/*ARGSUSED*/ 353255437Sdelphijclock_t 354255437Sdelphijcv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res, 355255437Sdelphij int flag) 356255437Sdelphij{ 357255437Sdelphij int error; 358255437Sdelphij timestruc_t ts; 359255437Sdelphij hrtime_t delta; 360255437Sdelphij 361255437Sdelphij ASSERT(flag == 0); 362255437Sdelphij 363255437Sdelphijtop: 364255437Sdelphij delta = tim - gethrtime(); 365255437Sdelphij if (delta <= 0) 366255437Sdelphij return (-1); 367255437Sdelphij 368255437Sdelphij ts.tv_sec = delta / NANOSEC; 369255437Sdelphij ts.tv_nsec = delta % NANOSEC; 370255437Sdelphij 371255437Sdelphij ASSERT(mutex_owner(mp) == curthread); 372255437Sdelphij mp->m_owner = NULL; 373255437Sdelphij error = pthread_cond_timedwait(cv, &mp->m_lock, &ts); 374255437Sdelphij mp->m_owner = curthread; 375255437Sdelphij 376255437Sdelphij if (error == ETIMEDOUT) 377255437Sdelphij return (-1); 378255437Sdelphij 379255437Sdelphij if (error == EINTR) 380255437Sdelphij goto top; 381255437Sdelphij 382255437Sdelphij ASSERT(error == 0); 383255437Sdelphij 384255437Sdelphij return (1); 385255437Sdelphij} 386255437Sdelphij 387168404Spjdvoid 388168404Spjdcv_signal(kcondvar_t *cv) 389168404Spjd{ 390168404Spjd VERIFY(cond_signal(cv) == 0); 391168404Spjd} 392168404Spjd 393168404Spjdvoid 394168404Spjdcv_broadcast(kcondvar_t *cv) 395168404Spjd{ 396168404Spjd VERIFY(cond_broadcast(cv) == 0); 397168404Spjd} 398168404Spjd 399168404Spjd/* 400168404Spjd * ========================================================================= 401168404Spjd * vnode operations 402168404Spjd * ========================================================================= 403168404Spjd */ 404168404Spjd/* 405168404Spjd * Note: for the xxxat() versions of these functions, we assume that the 406168404Spjd * starting vp is always rootdir (which is true for spa_directory.c, the only 407168404Spjd * ZFS consumer of these interfaces). We assert this is true, and then emulate 408168404Spjd * them by adding '/' in front of the path. 409168404Spjd */ 410168404Spjd 411168404Spjd/*ARGSUSED*/ 412168404Spjdint 413168404Spjdvn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) 414168404Spjd{ 415168404Spjd int fd; 416168404Spjd vnode_t *vp; 417168404Spjd int old_umask; 418168404Spjd char realpath[MAXPATHLEN]; 419168404Spjd struct stat64 st; 420168404Spjd 421168404Spjd /* 422168404Spjd * If we're accessing a real disk from userland, we need to use 423168404Spjd * the character interface to avoid caching. This is particularly 424168404Spjd * important if we're trying to look at a real in-kernel storage 425168404Spjd * pool from userland, e.g. via zdb, because otherwise we won't 426168404Spjd * see the changes occurring under the segmap cache. 427168404Spjd * On the other hand, the stupid character device returns zero 428168404Spjd * for its size. So -- gag -- we open the block device to get 429168404Spjd * its size, and remember it for subsequent VOP_GETATTR(). 430168404Spjd */ 431168404Spjd if (strncmp(path, "/dev/", 5) == 0) { 432168404Spjd char *dsk; 433168404Spjd fd = open64(path, O_RDONLY); 434168404Spjd if (fd == -1) 435168404Spjd return (errno); 436168404Spjd if (fstat64(fd, &st) == -1) { 437168404Spjd close(fd); 438168404Spjd return (errno); 439168404Spjd } 440168404Spjd close(fd); 441168404Spjd (void) sprintf(realpath, "%s", path); 442168404Spjd dsk = strstr(path, "/dsk/"); 443168404Spjd if (dsk != NULL) 444168404Spjd (void) sprintf(realpath + (dsk - path) + 1, "r%s", 445168404Spjd dsk + 1); 446168404Spjd } else { 447168404Spjd (void) sprintf(realpath, "%s", path); 448168404Spjd if (!(flags & FCREAT) && stat64(realpath, &st) == -1) 449168404Spjd return (errno); 450168404Spjd } 451168404Spjd 452168404Spjd if (flags & FCREAT) 453168404Spjd old_umask = umask(0); 454168404Spjd 455168404Spjd /* 456168404Spjd * The construct 'flags - FREAD' conveniently maps combinations of 457168404Spjd * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. 458168404Spjd */ 459168404Spjd fd = open64(realpath, flags - FREAD, mode); 460168404Spjd 461168404Spjd if (flags & FCREAT) 462168404Spjd (void) umask(old_umask); 463168404Spjd 464168404Spjd if (fd == -1) 465168404Spjd return (errno); 466168404Spjd 467168404Spjd if (fstat64(fd, &st) == -1) { 468168404Spjd close(fd); 469168404Spjd return (errno); 470168404Spjd } 471168404Spjd 472168404Spjd (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 473168404Spjd 474168404Spjd *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); 475168404Spjd 476168404Spjd vp->v_fd = fd; 477219089Spjd vp->v_size = st.st_size; 478168404Spjd vp->v_path = spa_strdup(path); 479168404Spjd 480168404Spjd return (0); 481168404Spjd} 482168404Spjd 483185029Spjd/*ARGSUSED*/ 484168404Spjdint 485168404Spjdvn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, 486185029Spjd int x3, vnode_t *startvp, int fd) 487168404Spjd{ 488168404Spjd char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); 489168404Spjd int ret; 490168404Spjd 491168404Spjd ASSERT(startvp == rootdir); 492168404Spjd (void) sprintf(realpath, "/%s", path); 493168404Spjd 494185029Spjd /* fd ignored for now, need if want to simulate nbmand support */ 495168404Spjd ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); 496168404Spjd 497168404Spjd umem_free(realpath, strlen(path) + 2); 498168404Spjd 499168404Spjd return (ret); 500168404Spjd} 501168404Spjd 502168404Spjd/*ARGSUSED*/ 503168404Spjdint 504168404Spjdvn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, 505168404Spjd int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) 506168404Spjd{ 507168404Spjd ssize_t iolen, split; 508168404Spjd 509168404Spjd if (uio == UIO_READ) { 510168404Spjd iolen = pread64(vp->v_fd, addr, len, offset); 511168404Spjd } else { 512168404Spjd /* 513168404Spjd * To simulate partial disk writes, we split writes into two 514168404Spjd * system calls so that the process can be killed in between. 515168404Spjd */ 516236884Smm int sectors = len >> SPA_MINBLOCKSHIFT; 517236884Smm split = (sectors > 0 ? rand() % sectors : 0) << 518236884Smm SPA_MINBLOCKSHIFT; 519168404Spjd iolen = pwrite64(vp->v_fd, addr, split, offset); 520168404Spjd iolen += pwrite64(vp->v_fd, (char *)addr + split, 521168404Spjd len - split, offset + split); 522168404Spjd } 523168404Spjd 524168404Spjd if (iolen == -1) 525168404Spjd return (errno); 526168404Spjd if (residp) 527168404Spjd *residp = len - iolen; 528168404Spjd else if (iolen != len) 529168404Spjd return (EIO); 530168404Spjd return (0); 531168404Spjd} 532168404Spjd 533168404Spjdvoid 534185029Spjdvn_close(vnode_t *vp, int openflag, cred_t *cr, kthread_t *td) 535168404Spjd{ 536168404Spjd close(vp->v_fd); 537168404Spjd spa_strfree(vp->v_path); 538168404Spjd umem_free(vp, sizeof (vnode_t)); 539168404Spjd} 540168404Spjd 541219089Spjd/* 542219089Spjd * At a minimum we need to update the size since vdev_reopen() 543219089Spjd * will no longer call vn_openat(). 544219089Spjd */ 545219089Spjdint 546219089Spjdfop_getattr(vnode_t *vp, vattr_t *vap) 547219089Spjd{ 548219089Spjd struct stat64 st; 549219089Spjd 550219089Spjd if (fstat64(vp->v_fd, &st) == -1) { 551219089Spjd close(vp->v_fd); 552219089Spjd return (errno); 553219089Spjd } 554219089Spjd 555219089Spjd vap->va_size = st.st_size; 556219089Spjd return (0); 557219089Spjd} 558219089Spjd 559168404Spjd#ifdef ZFS_DEBUG 560168404Spjd 561168404Spjd/* 562168404Spjd * ========================================================================= 563168404Spjd * Figure out which debugging statements to print 564168404Spjd * ========================================================================= 565168404Spjd */ 566168404Spjd 567168404Spjdstatic char *dprintf_string; 568168404Spjdstatic int dprintf_print_all; 569168404Spjd 570168404Spjdint 571168404Spjddprintf_find_string(const char *string) 572168404Spjd{ 573168404Spjd char *tmp_str = dprintf_string; 574168404Spjd int len = strlen(string); 575168404Spjd 576168404Spjd /* 577168404Spjd * Find out if this is a string we want to print. 578168404Spjd * String format: file1.c,function_name1,file2.c,file3.c 579168404Spjd */ 580168404Spjd 581168404Spjd while (tmp_str != NULL) { 582168404Spjd if (strncmp(tmp_str, string, len) == 0 && 583168404Spjd (tmp_str[len] == ',' || tmp_str[len] == '\0')) 584168404Spjd return (1); 585168404Spjd tmp_str = strchr(tmp_str, ','); 586168404Spjd if (tmp_str != NULL) 587168404Spjd tmp_str++; /* Get rid of , */ 588168404Spjd } 589168404Spjd return (0); 590168404Spjd} 591168404Spjd 592168404Spjdvoid 593168404Spjddprintf_setup(int *argc, char **argv) 594168404Spjd{ 595168404Spjd int i, j; 596168404Spjd 597168404Spjd /* 598168404Spjd * Debugging can be specified two ways: by setting the 599168404Spjd * environment variable ZFS_DEBUG, or by including a 600168404Spjd * "debug=..." argument on the command line. The command 601168404Spjd * line setting overrides the environment variable. 602168404Spjd */ 603168404Spjd 604168404Spjd for (i = 1; i < *argc; i++) { 605168404Spjd int len = strlen("debug="); 606168404Spjd /* First look for a command line argument */ 607168404Spjd if (strncmp("debug=", argv[i], len) == 0) { 608168404Spjd dprintf_string = argv[i] + len; 609168404Spjd /* Remove from args */ 610168404Spjd for (j = i; j < *argc; j++) 611168404Spjd argv[j] = argv[j+1]; 612168404Spjd argv[j] = NULL; 613168404Spjd (*argc)--; 614168404Spjd } 615168404Spjd } 616168404Spjd 617168404Spjd if (dprintf_string == NULL) { 618168404Spjd /* Look for ZFS_DEBUG environment variable */ 619168404Spjd dprintf_string = getenv("ZFS_DEBUG"); 620168404Spjd } 621168404Spjd 622168404Spjd /* 623168404Spjd * Are we just turning on all debugging? 624168404Spjd */ 625168404Spjd if (dprintf_find_string("on")) 626168404Spjd dprintf_print_all = 1; 627168404Spjd} 628168404Spjd 629254591Sgibbsint 630254591Sgibbssysctl_handle_64(SYSCTL_HANDLER_ARGS) 631254591Sgibbs{ 632254591Sgibbs return (0); 633254591Sgibbs} 634254591Sgibbs 635168404Spjd/* 636168404Spjd * ========================================================================= 637168404Spjd * debug printfs 638168404Spjd * ========================================================================= 639168404Spjd */ 640168404Spjdvoid 641168404Spjd__dprintf(const char *file, const char *func, int line, const char *fmt, ...) 642168404Spjd{ 643168404Spjd const char *newfile; 644168404Spjd va_list adx; 645168404Spjd 646168404Spjd /* 647168404Spjd * Get rid of annoying "../common/" prefix to filename. 648168404Spjd */ 649168404Spjd newfile = strrchr(file, '/'); 650168404Spjd if (newfile != NULL) { 651168404Spjd newfile = newfile + 1; /* Get rid of leading / */ 652168404Spjd } else { 653168404Spjd newfile = file; 654168404Spjd } 655168404Spjd 656168404Spjd if (dprintf_print_all || 657168404Spjd dprintf_find_string(newfile) || 658168404Spjd dprintf_find_string(func)) { 659168404Spjd /* Print out just the function name if requested */ 660168404Spjd flockfile(stdout); 661168404Spjd if (dprintf_find_string("pid")) 662168404Spjd (void) printf("%d ", getpid()); 663168404Spjd if (dprintf_find_string("tid")) 664168404Spjd (void) printf("%u ", thr_self()); 665168404Spjd#if 0 666168404Spjd if (dprintf_find_string("cpu")) 667168404Spjd (void) printf("%u ", getcpuid()); 668168404Spjd#endif 669168404Spjd if (dprintf_find_string("time")) 670168404Spjd (void) printf("%llu ", gethrtime()); 671168404Spjd if (dprintf_find_string("long")) 672168404Spjd (void) printf("%s, line %d: ", newfile, line); 673168404Spjd (void) printf("%s: ", func); 674168404Spjd va_start(adx, fmt); 675168404Spjd (void) vprintf(fmt, adx); 676168404Spjd va_end(adx); 677168404Spjd funlockfile(stdout); 678168404Spjd } 679168404Spjd} 680168404Spjd 681168404Spjd#endif /* ZFS_DEBUG */ 682168404Spjd 683168404Spjd/* 684168404Spjd * ========================================================================= 685168404Spjd * cmn_err() and panic() 686168404Spjd * ========================================================================= 687168404Spjd */ 688168404Spjdstatic char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 689168404Spjdstatic char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 690168404Spjd 691168404Spjdvoid 692168404Spjdvpanic(const char *fmt, va_list adx) 693168404Spjd{ 694168404Spjd (void) fprintf(stderr, "error: "); 695168404Spjd (void) vfprintf(stderr, fmt, adx); 696168404Spjd (void) fprintf(stderr, "\n"); 697168404Spjd 698168404Spjd abort(); /* think of it as a "user-level crash dump" */ 699168404Spjd} 700168404Spjd 701168404Spjdvoid 702168404Spjdpanic(const char *fmt, ...) 703168404Spjd{ 704168404Spjd va_list adx; 705168404Spjd 706168404Spjd va_start(adx, fmt); 707168404Spjd vpanic(fmt, adx); 708168404Spjd va_end(adx); 709168404Spjd} 710168404Spjd 711168404Spjdvoid 712168404Spjdvcmn_err(int ce, const char *fmt, va_list adx) 713168404Spjd{ 714168404Spjd if (ce == CE_PANIC) 715168404Spjd vpanic(fmt, adx); 716168404Spjd if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ 717168404Spjd (void) fprintf(stderr, "%s", ce_prefix[ce]); 718168404Spjd (void) vfprintf(stderr, fmt, adx); 719168404Spjd (void) fprintf(stderr, "%s", ce_suffix[ce]); 720168404Spjd } 721168404Spjd} 722168404Spjd 723168404Spjd/*PRINTFLIKE2*/ 724168404Spjdvoid 725168404Spjdcmn_err(int ce, const char *fmt, ...) 726168404Spjd{ 727168404Spjd va_list adx; 728168404Spjd 729168404Spjd va_start(adx, fmt); 730168404Spjd vcmn_err(ce, fmt, adx); 731168404Spjd va_end(adx); 732168404Spjd} 733168404Spjd 734168404Spjd/* 735168404Spjd * ========================================================================= 736168404Spjd * kobj interfaces 737168404Spjd * ========================================================================= 738168404Spjd */ 739168404Spjdstruct _buf * 740168404Spjdkobj_open_file(char *name) 741168404Spjd{ 742168404Spjd struct _buf *file; 743168404Spjd vnode_t *vp; 744168404Spjd 745168404Spjd /* set vp as the _fd field of the file */ 746185029Spjd if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir, 747185029Spjd -1) != 0) 748168404Spjd return ((void *)-1UL); 749168404Spjd 750168404Spjd file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 751168404Spjd file->_fd = (intptr_t)vp; 752168404Spjd return (file); 753168404Spjd} 754168404Spjd 755168404Spjdint 756168404Spjdkobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 757168404Spjd{ 758168404Spjd ssize_t resid; 759168404Spjd 760168404Spjd vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 761168404Spjd UIO_SYSSPACE, 0, 0, 0, &resid); 762168404Spjd 763168404Spjd return (size - resid); 764168404Spjd} 765168404Spjd 766168404Spjdvoid 767168404Spjdkobj_close_file(struct _buf *file) 768168404Spjd{ 769185029Spjd vn_close((vnode_t *)file->_fd, 0, NULL, NULL); 770168404Spjd umem_free(file, sizeof (struct _buf)); 771168404Spjd} 772168404Spjd 773168404Spjdint 774168404Spjdkobj_get_filesize(struct _buf *file, uint64_t *size) 775168404Spjd{ 776168404Spjd struct stat64 st; 777168404Spjd vnode_t *vp = (vnode_t *)file->_fd; 778168404Spjd 779168404Spjd if (fstat64(vp->v_fd, &st) == -1) { 780185029Spjd vn_close(vp, 0, NULL, NULL); 781168404Spjd return (errno); 782168404Spjd } 783168404Spjd *size = st.st_size; 784168404Spjd return (0); 785168404Spjd} 786168404Spjd 787168404Spjd/* 788168404Spjd * ========================================================================= 789168404Spjd * misc routines 790168404Spjd * ========================================================================= 791168404Spjd */ 792168404Spjd 793168404Spjdvoid 794168404Spjddelay(clock_t ticks) 795168404Spjd{ 796168404Spjd poll(0, 0, ticks * (1000 / hz)); 797168404Spjd} 798168404Spjd 799168404Spjd#if 0 800168404Spjd/* 801168404Spjd * Find highest one bit set. 802168404Spjd * Returns bit number + 1 of highest bit that is set, otherwise returns 0. 803168404Spjd * High order bit is 31 (or 63 in _LP64 kernel). 804168404Spjd */ 805168404Spjdint 806168404Spjdhighbit(ulong_t i) 807168404Spjd{ 808168404Spjd register int h = 1; 809168404Spjd 810168404Spjd if (i == 0) 811168404Spjd return (0); 812168404Spjd#ifdef _LP64 813168404Spjd if (i & 0xffffffff00000000ul) { 814168404Spjd h += 32; i >>= 32; 815168404Spjd } 816168404Spjd#endif 817168404Spjd if (i & 0xffff0000) { 818168404Spjd h += 16; i >>= 16; 819168404Spjd } 820168404Spjd if (i & 0xff00) { 821168404Spjd h += 8; i >>= 8; 822168404Spjd } 823168404Spjd if (i & 0xf0) { 824168404Spjd h += 4; i >>= 4; 825168404Spjd } 826168404Spjd if (i & 0xc) { 827168404Spjd h += 2; i >>= 2; 828168404Spjd } 829168404Spjd if (i & 0x2) { 830168404Spjd h += 1; 831168404Spjd } 832168404Spjd return (h); 833168404Spjd} 834168404Spjd#endif 835168404Spjd 836185029Spjdstatic int random_fd = -1, urandom_fd = -1; 837185029Spjd 838168404Spjdstatic int 839185029Spjdrandom_get_bytes_common(uint8_t *ptr, size_t len, int fd) 840168404Spjd{ 841168404Spjd size_t resid = len; 842168404Spjd ssize_t bytes; 843168404Spjd 844168404Spjd ASSERT(fd != -1); 845168404Spjd 846168404Spjd while (resid != 0) { 847168404Spjd bytes = read(fd, ptr, resid); 848185029Spjd ASSERT3S(bytes, >=, 0); 849168404Spjd ptr += bytes; 850168404Spjd resid -= bytes; 851168404Spjd } 852168404Spjd 853168404Spjd return (0); 854168404Spjd} 855168404Spjd 856168404Spjdint 857168404Spjdrandom_get_bytes(uint8_t *ptr, size_t len) 858168404Spjd{ 859185029Spjd return (random_get_bytes_common(ptr, len, random_fd)); 860168404Spjd} 861168404Spjd 862168404Spjdint 863168404Spjdrandom_get_pseudo_bytes(uint8_t *ptr, size_t len) 864168404Spjd{ 865185029Spjd return (random_get_bytes_common(ptr, len, urandom_fd)); 866168404Spjd} 867168404Spjd 868168498Spjdint 869168498Spjdddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result) 870168498Spjd{ 871168498Spjd char *end; 872168498Spjd 873168498Spjd *result = strtoul(hw_serial, &end, base); 874168498Spjd if (*result == 0) 875168498Spjd return (errno); 876168498Spjd return (0); 877168498Spjd} 878168498Spjd 879219089Spjdint 880219089Spjdddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result) 881219089Spjd{ 882219089Spjd char *end; 883219089Spjd 884219089Spjd *result = strtoull(str, &end, base); 885219089Spjd if (*result == 0) 886219089Spjd return (errno); 887219089Spjd return (0); 888219089Spjd} 889219089Spjd 890247265Smm#ifdef illumos 891247265Smm/* ARGSUSED */ 892247265Smmcyclic_id_t 893247265Smmcyclic_add(cyc_handler_t *hdlr, cyc_time_t *when) 894247265Smm{ 895247265Smm return (1); 896247265Smm} 897247265Smm 898247265Smm/* ARGSUSED */ 899247265Smmvoid 900247265Smmcyclic_remove(cyclic_id_t id) 901247265Smm{ 902247265Smm} 903247265Smm 904247265Smm/* ARGSUSED */ 905247265Smmint 906247265Smmcyclic_reprogram(cyclic_id_t id, hrtime_t expiration) 907247265Smm{ 908247265Smm return (1); 909247265Smm} 910247265Smm#endif 911247265Smm 912168404Spjd/* 913168404Spjd * ========================================================================= 914168404Spjd * kernel emulation setup & teardown 915168404Spjd * ========================================================================= 916168404Spjd */ 917168404Spjdstatic int 918168404Spjdumem_out_of_memory(void) 919168404Spjd{ 920168404Spjd char errmsg[] = "out of memory -- generating core dump\n"; 921168404Spjd 922168404Spjd write(fileno(stderr), errmsg, sizeof (errmsg)); 923168404Spjd abort(); 924168404Spjd return (0); 925168404Spjd} 926168404Spjd 927168404Spjdvoid 928168404Spjdkernel_init(int mode) 929168404Spjd{ 930248571Smm extern uint_t rrw_tsd_key; 931248571Smm 932168404Spjd umem_nofail_callback(umem_out_of_memory); 933168404Spjd 934168404Spjd physmem = sysconf(_SC_PHYS_PAGES); 935168404Spjd 936168404Spjd dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 937168404Spjd (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 938168404Spjd 939219089Spjd (void) snprintf(hw_serial, sizeof (hw_serial), "%lu", 940219089Spjd (mode & FWRITE) ? (unsigned long)gethostid() : 0); 941168498Spjd 942185029Spjd VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1); 943185029Spjd VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1); 944185029Spjd 945208047Smm system_taskq_init(); 946208047Smm 947247265Smm#ifdef illumos 948247265Smm mutex_init(&cpu_lock, NULL, MUTEX_DEFAULT, NULL); 949247265Smm#endif 950247265Smm 951168404Spjd spa_init(mode); 952248571Smm 953248571Smm tsd_create(&rrw_tsd_key, rrw_tsd_destroy); 954168404Spjd} 955168404Spjd 956168404Spjdvoid 957168404Spjdkernel_fini(void) 958168404Spjd{ 959168404Spjd spa_fini(); 960185029Spjd 961219089Spjd system_taskq_fini(); 962219089Spjd 963185029Spjd close(random_fd); 964185029Spjd close(urandom_fd); 965185029Spjd 966185029Spjd random_fd = -1; 967185029Spjd urandom_fd = -1; 968168404Spjd} 969168404Spjd 970168404Spjdint 971168404Spjdz_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 972168404Spjd{ 973168404Spjd int ret; 974168404Spjd uLongf len = *dstlen; 975168404Spjd 976168404Spjd if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK) 977168404Spjd *dstlen = (size_t)len; 978168404Spjd 979168404Spjd return (ret); 980168404Spjd} 981168404Spjd 982168404Spjdint 983168404Spjdz_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen, 984168404Spjd int level) 985168404Spjd{ 986168404Spjd int ret; 987168404Spjd uLongf len = *dstlen; 988168404Spjd 989168404Spjd if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK) 990168404Spjd *dstlen = (size_t)len; 991168404Spjd 992168404Spjd return (ret); 993168404Spjd} 994185029Spjd 995185029Spjduid_t 996185029Spjdcrgetuid(cred_t *cr) 997185029Spjd{ 998185029Spjd return (0); 999185029Spjd} 1000185029Spjd 1001248571Smmuid_t 1002248571Smmcrgetruid(cred_t *cr) 1003248571Smm{ 1004248571Smm return (0); 1005248571Smm} 1006248571Smm 1007185029Spjdgid_t 1008185029Spjdcrgetgid(cred_t *cr) 1009185029Spjd{ 1010185029Spjd return (0); 1011185029Spjd} 1012185029Spjd 1013185029Spjdint 1014185029Spjdcrgetngroups(cred_t *cr) 1015185029Spjd{ 1016185029Spjd return (0); 1017185029Spjd} 1018185029Spjd 1019185029Spjdgid_t * 1020185029Spjdcrgetgroups(cred_t *cr) 1021185029Spjd{ 1022185029Spjd return (NULL); 1023185029Spjd} 1024185029Spjd 1025185029Spjdint 1026185029Spjdzfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 1027185029Spjd{ 1028185029Spjd return (0); 1029185029Spjd} 1030185029Spjd 1031185029Spjdint 1032185029Spjdzfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 1033185029Spjd{ 1034185029Spjd return (0); 1035185029Spjd} 1036185029Spjd 1037185029Spjdint 1038185029Spjdzfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 1039185029Spjd{ 1040185029Spjd return (0); 1041185029Spjd} 1042185029Spjd 1043185029Spjdksiddomain_t * 1044185029Spjdksid_lookupdomain(const char *dom) 1045185029Spjd{ 1046185029Spjd ksiddomain_t *kd; 1047185029Spjd 1048185029Spjd kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL); 1049185029Spjd kd->kd_name = spa_strdup(dom); 1050185029Spjd return (kd); 1051185029Spjd} 1052185029Spjd 1053185029Spjdvoid 1054185029Spjdksiddomain_rele(ksiddomain_t *ksid) 1055185029Spjd{ 1056185029Spjd spa_strfree(ksid->kd_name); 1057185029Spjd umem_free(ksid, sizeof (ksiddomain_t)); 1058185029Spjd} 1059219089Spjd 1060219089Spjd/* 1061219089Spjd * Do not change the length of the returned string; it must be freed 1062219089Spjd * with strfree(). 1063219089Spjd */ 1064219089Spjdchar * 1065219089Spjdkmem_asprintf(const char *fmt, ...) 1066219089Spjd{ 1067219089Spjd int size; 1068219089Spjd va_list adx; 1069219089Spjd char *buf; 1070219089Spjd 1071219089Spjd va_start(adx, fmt); 1072219089Spjd size = vsnprintf(NULL, 0, fmt, adx) + 1; 1073219089Spjd va_end(adx); 1074219089Spjd 1075219089Spjd buf = kmem_alloc(size, KM_SLEEP); 1076219089Spjd 1077219089Spjd va_start(adx, fmt); 1078219089Spjd size = vsnprintf(buf, size, fmt, adx); 1079219089Spjd va_end(adx); 1080219089Spjd 1081219089Spjd return (buf); 1082219089Spjd} 1083219089Spjd 1084219089Spjd/* ARGSUSED */ 1085219089Spjdint 1086219089Spjdzfs_onexit_fd_hold(int fd, minor_t *minorp) 1087219089Spjd{ 1088219089Spjd *minorp = 0; 1089219089Spjd return (0); 1090219089Spjd} 1091219089Spjd 1092219089Spjd/* ARGSUSED */ 1093219089Spjdvoid 1094219089Spjdzfs_onexit_fd_rele(int fd) 1095219089Spjd{ 1096219089Spjd} 1097219089Spjd 1098219089Spjd/* ARGSUSED */ 1099219089Spjdint 1100219089Spjdzfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data, 1101219089Spjd uint64_t *action_handle) 1102219089Spjd{ 1103219089Spjd return (0); 1104219089Spjd} 1105219089Spjd 1106219089Spjd/* ARGSUSED */ 1107219089Spjdint 1108219089Spjdzfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire) 1109219089Spjd{ 1110219089Spjd return (0); 1111219089Spjd} 1112219089Spjd 1113219089Spjd/* ARGSUSED */ 1114219089Spjdint 1115219089Spjdzfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data) 1116219089Spjd{ 1117219089Spjd return (0); 1118219089Spjd} 1119219089Spjd 1120219089Spjd#ifdef __FreeBSD__ 1121219089Spjd/* ARGSUSED */ 1122219089Spjdint 1123219089Spjdzvol_create_minors(const char *name) 1124219089Spjd{ 1125219089Spjd return (0); 1126219089Spjd} 1127219089Spjd#endif 1128