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. 23289562Smav * Copyright (c) 2012, 2015 by Delphix. All rights reserved. 24264669Sdelphij * Copyright (c) 2013, Joyent, Inc. All rights reserved. 25168404Spjd */ 26168404Spjd 27168404Spjd#include <assert.h> 28168404Spjd#include <fcntl.h> 29168404Spjd#include <poll.h> 30168404Spjd#include <stdio.h> 31168404Spjd#include <stdlib.h> 32168404Spjd#include <string.h> 33168404Spjd#include <zlib.h> 34268084Sdelphij#include <libgen.h> 35168404Spjd#include <sys/spa.h> 36168404Spjd#include <sys/stat.h> 37168404Spjd#include <sys/processor.h> 38168404Spjd#include <sys/zfs_context.h> 39248571Smm#include <sys/rrwlock.h> 40168404Spjd#include <sys/zmod.h> 41168498Spjd#include <sys/utsname.h> 42219089Spjd#include <sys/systeminfo.h> 43168404Spjd 44168404Spjd/* 45168404Spjd * Emulation of kernel services in userland. 46168404Spjd */ 47168404Spjd 48288340Savg#ifndef __FreeBSD__ 49219089Spjdint aok; 50288340Savg#endif 51168404Spjduint64_t physmem; 52168404Spjdvnode_t *rootdir = (vnode_t *)0xabcd1234; 53219089Spjdchar hw_serial[HW_HOSTID_LEN]; 54247265Smm#ifdef illumos 55247265Smmkmutex_t cpu_lock; 56247265Smm#endif 57168404Spjd 58268084Sdelphij/* If set, all blocks read will be copied to the specified directory. */ 59268084Sdelphijchar *vn_dumpdir = NULL; 60268084Sdelphij 61168498Spjdstruct utsname utsname = { 62168498Spjd "userland", "libzpool", "1", "1", "na" 63168498Spjd}; 64168498Spjd 65219089Spjd/* this only exists to have its address taken */ 66219089Spjdstruct proc p0; 67219089Spjd 68168404Spjd/* 69168404Spjd * ========================================================================= 70168404Spjd * threads 71168404Spjd * ========================================================================= 72168404Spjd */ 73168404Spjd/*ARGSUSED*/ 74168404Spjdkthread_t * 75168404Spjdzk_thread_create(void (*func)(), void *arg) 76168404Spjd{ 77168404Spjd thread_t tid; 78168404Spjd 79168404Spjd VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED, 80168404Spjd &tid) == 0); 81168404Spjd 82168404Spjd return ((void *)(uintptr_t)tid); 83168404Spjd} 84168404Spjd 85168404Spjd/* 86168404Spjd * ========================================================================= 87168404Spjd * kstats 88168404Spjd * ========================================================================= 89168404Spjd */ 90168404Spjd/*ARGSUSED*/ 91168404Spjdkstat_t * 92168404Spjdkstat_create(char *module, int instance, char *name, char *class, 93168404Spjd uchar_t type, ulong_t ndata, uchar_t ks_flag) 94168404Spjd{ 95168404Spjd return (NULL); 96168404Spjd} 97168404Spjd 98168404Spjd/*ARGSUSED*/ 99168404Spjdvoid 100321529Smavkstat_named_init(kstat_named_t *knp, const char *name, uchar_t type) 101321529Smav{} 102321529Smav 103321529Smav/*ARGSUSED*/ 104321529Smavvoid 105168404Spjdkstat_install(kstat_t *ksp) 106168404Spjd{} 107168404Spjd 108168404Spjd/*ARGSUSED*/ 109168404Spjdvoid 110168404Spjdkstat_delete(kstat_t *ksp) 111168404Spjd{} 112168404Spjd 113168404Spjd/* 114168404Spjd * ========================================================================= 115168404Spjd * mutexes 116168404Spjd * ========================================================================= 117168404Spjd */ 118168404Spjdvoid 119168404Spjdzmutex_init(kmutex_t *mp) 120168404Spjd{ 121168404Spjd mp->m_owner = NULL; 122185029Spjd mp->initialized = B_TRUE; 123168404Spjd (void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL); 124168404Spjd} 125168404Spjd 126168404Spjdvoid 127168404Spjdzmutex_destroy(kmutex_t *mp) 128168404Spjd{ 129185029Spjd ASSERT(mp->initialized == B_TRUE); 130168404Spjd ASSERT(mp->m_owner == NULL); 131168404Spjd (void) _mutex_destroy(&(mp)->m_lock); 132168404Spjd mp->m_owner = (void *)-1UL; 133185029Spjd mp->initialized = B_FALSE; 134168404Spjd} 135168404Spjd 136195515Spjdint 137195515Spjdzmutex_owned(kmutex_t *mp) 138195515Spjd{ 139195515Spjd ASSERT(mp->initialized == B_TRUE); 140195515Spjd 141195515Spjd return (mp->m_owner == curthread); 142195515Spjd} 143195515Spjd 144168404Spjdvoid 145168404Spjdmutex_enter(kmutex_t *mp) 146168404Spjd{ 147185029Spjd ASSERT(mp->initialized == B_TRUE); 148168404Spjd ASSERT(mp->m_owner != (void *)-1UL); 149168404Spjd ASSERT(mp->m_owner != curthread); 150168404Spjd VERIFY(mutex_lock(&mp->m_lock) == 0); 151168404Spjd ASSERT(mp->m_owner == NULL); 152168404Spjd mp->m_owner = curthread; 153168404Spjd} 154168404Spjd 155168404Spjdint 156168404Spjdmutex_tryenter(kmutex_t *mp) 157168404Spjd{ 158185029Spjd ASSERT(mp->initialized == B_TRUE); 159168404Spjd ASSERT(mp->m_owner != (void *)-1UL); 160219089Spjd if (0 == mutex_trylock(&mp->m_lock)) { 161168404Spjd ASSERT(mp->m_owner == NULL); 162168404Spjd mp->m_owner = curthread; 163168404Spjd return (1); 164168404Spjd } else { 165168404Spjd return (0); 166168404Spjd } 167168404Spjd} 168168404Spjd 169168404Spjdvoid 170168404Spjdmutex_exit(kmutex_t *mp) 171168404Spjd{ 172185029Spjd ASSERT(mp->initialized == B_TRUE); 173219089Spjd ASSERT(mutex_owner(mp) == curthread); 174168404Spjd mp->m_owner = NULL; 175168404Spjd VERIFY(mutex_unlock(&mp->m_lock) == 0); 176168404Spjd} 177168404Spjd 178168404Spjdvoid * 179168404Spjdmutex_owner(kmutex_t *mp) 180168404Spjd{ 181185029Spjd ASSERT(mp->initialized == B_TRUE); 182168404Spjd return (mp->m_owner); 183168404Spjd} 184168404Spjd 185168404Spjd/* 186168404Spjd * ========================================================================= 187168404Spjd * rwlocks 188168404Spjd * ========================================================================= 189168404Spjd */ 190168404Spjd/*ARGSUSED*/ 191168404Spjdvoid 192168404Spjdrw_init(krwlock_t *rwlp, char *name, int type, void *arg) 193168404Spjd{ 194168404Spjd rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL); 195168404Spjd rwlp->rw_owner = NULL; 196185029Spjd rwlp->initialized = B_TRUE; 197210044Spjd rwlp->rw_count = 0; 198168404Spjd} 199168404Spjd 200168404Spjdvoid 201168404Spjdrw_destroy(krwlock_t *rwlp) 202168404Spjd{ 203210044Spjd ASSERT(rwlp->rw_count == 0); 204168404Spjd rwlock_destroy(&rwlp->rw_lock); 205168404Spjd rwlp->rw_owner = (void *)-1UL; 206185029Spjd rwlp->initialized = B_FALSE; 207168404Spjd} 208168404Spjd 209168404Spjdvoid 210168404Spjdrw_enter(krwlock_t *rwlp, krw_t rw) 211168404Spjd{ 212168404Spjd //ASSERT(!RW_LOCK_HELD(rwlp)); 213185029Spjd ASSERT(rwlp->initialized == B_TRUE); 214168404Spjd ASSERT(rwlp->rw_owner != (void *)-1UL); 215168404Spjd ASSERT(rwlp->rw_owner != curthread); 216168404Spjd 217168404Spjd if (rw == RW_READER) { 218185029Spjd VERIFY(rw_rdlock(&rwlp->rw_lock) == 0); 219168404Spjd ASSERT(rwlp->rw_count >= 0); 220168404Spjd atomic_add_int(&rwlp->rw_count, 1); 221168404Spjd } else { 222185029Spjd VERIFY(rw_wrlock(&rwlp->rw_lock) == 0); 223168404Spjd ASSERT(rwlp->rw_count == 0); 224168404Spjd rwlp->rw_count = -1; 225168404Spjd rwlp->rw_owner = curthread; 226168404Spjd } 227168404Spjd} 228168404Spjd 229168404Spjdvoid 230168404Spjdrw_exit(krwlock_t *rwlp) 231168404Spjd{ 232185029Spjd ASSERT(rwlp->initialized == B_TRUE); 233168404Spjd ASSERT(rwlp->rw_owner != (void *)-1UL); 234168404Spjd 235168404Spjd if (rwlp->rw_owner == curthread) { 236168404Spjd /* Write locked. */ 237168404Spjd ASSERT(rwlp->rw_count == -1); 238168404Spjd rwlp->rw_count = 0; 239168404Spjd rwlp->rw_owner = NULL; 240168404Spjd } else { 241168404Spjd /* Read locked. */ 242168404Spjd ASSERT(rwlp->rw_count > 0); 243168404Spjd atomic_add_int(&rwlp->rw_count, -1); 244168404Spjd } 245185029Spjd VERIFY(rw_unlock(&rwlp->rw_lock) == 0); 246168404Spjd} 247168404Spjd 248168404Spjdint 249168404Spjdrw_tryenter(krwlock_t *rwlp, krw_t rw) 250168404Spjd{ 251168404Spjd int rv; 252168404Spjd 253185029Spjd ASSERT(rwlp->initialized == B_TRUE); 254168404Spjd ASSERT(rwlp->rw_owner != (void *)-1UL); 255168404Spjd ASSERT(rwlp->rw_owner != curthread); 256168404Spjd 257168404Spjd if (rw == RW_READER) 258168404Spjd rv = rw_tryrdlock(&rwlp->rw_lock); 259168404Spjd else 260168404Spjd rv = rw_trywrlock(&rwlp->rw_lock); 261168404Spjd 262168404Spjd if (rv == 0) { 263168404Spjd ASSERT(rwlp->rw_owner == NULL); 264168404Spjd if (rw == RW_READER) { 265168404Spjd ASSERT(rwlp->rw_count >= 0); 266168404Spjd atomic_add_int(&rwlp->rw_count, 1); 267168404Spjd } else { 268168404Spjd ASSERT(rwlp->rw_count == 0); 269168404Spjd rwlp->rw_count = -1; 270168404Spjd rwlp->rw_owner = curthread; 271168404Spjd } 272168404Spjd return (1); 273168404Spjd } 274168404Spjd 275168404Spjd return (0); 276168404Spjd} 277168404Spjd 278168404Spjd/*ARGSUSED*/ 279168404Spjdint 280168404Spjdrw_tryupgrade(krwlock_t *rwlp) 281168404Spjd{ 282185029Spjd ASSERT(rwlp->initialized == B_TRUE); 283168404Spjd ASSERT(rwlp->rw_owner != (void *)-1UL); 284168404Spjd 285168404Spjd return (0); 286168404Spjd} 287168404Spjd 288168404Spjdint 289168404Spjdrw_lock_held(krwlock_t *rwlp) 290168404Spjd{ 291168404Spjd 292168404Spjd return (rwlp->rw_count != 0); 293168404Spjd} 294168404Spjd 295168404Spjd/* 296168404Spjd * ========================================================================= 297168404Spjd * condition variables 298168404Spjd * ========================================================================= 299168404Spjd */ 300168404Spjd/*ARGSUSED*/ 301168404Spjdvoid 302168404Spjdcv_init(kcondvar_t *cv, char *name, int type, void *arg) 303168404Spjd{ 304168404Spjd VERIFY(cond_init(cv, name, NULL) == 0); 305168404Spjd} 306168404Spjd 307168404Spjdvoid 308168404Spjdcv_destroy(kcondvar_t *cv) 309168404Spjd{ 310168404Spjd VERIFY(cond_destroy(cv) == 0); 311168404Spjd} 312168404Spjd 313168404Spjdvoid 314168404Spjdcv_wait(kcondvar_t *cv, kmutex_t *mp) 315168404Spjd{ 316168404Spjd ASSERT(mutex_owner(mp) == curthread); 317168404Spjd mp->m_owner = NULL; 318168404Spjd int ret = cond_wait(cv, &mp->m_lock); 319168404Spjd VERIFY(ret == 0 || ret == EINTR); 320168404Spjd mp->m_owner = curthread; 321168404Spjd} 322168404Spjd 323168404Spjdclock_t 324168404Spjdcv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) 325168404Spjd{ 326168404Spjd int error; 327168404Spjd struct timespec ts; 328168404Spjd struct timeval tv; 329168404Spjd clock_t delta; 330168404Spjd 331219089Spjd abstime += ddi_get_lbolt(); 332168404Spjdtop: 333219089Spjd delta = abstime - ddi_get_lbolt(); 334168404Spjd if (delta <= 0) 335168404Spjd return (-1); 336168404Spjd 337168404Spjd if (gettimeofday(&tv, NULL) != 0) 338168404Spjd assert(!"gettimeofday() failed"); 339168404Spjd 340168404Spjd ts.tv_sec = tv.tv_sec + delta / hz; 341168404Spjd ts.tv_nsec = tv.tv_usec * 1000 + (delta % hz) * (NANOSEC / hz); 342168404Spjd ASSERT(ts.tv_nsec >= 0); 343168404Spjd 344214622Spjd if (ts.tv_nsec >= NANOSEC) { 345168404Spjd ts.tv_sec++; 346168404Spjd ts.tv_nsec -= NANOSEC; 347168404Spjd } 348168404Spjd 349168404Spjd ASSERT(mutex_owner(mp) == curthread); 350168404Spjd mp->m_owner = NULL; 351168404Spjd error = pthread_cond_timedwait(cv, &mp->m_lock, &ts); 352168404Spjd mp->m_owner = curthread; 353168404Spjd 354168404Spjd if (error == EINTR) 355168404Spjd goto top; 356168404Spjd 357168404Spjd if (error == ETIMEDOUT) 358168404Spjd return (-1); 359168404Spjd 360168404Spjd ASSERT(error == 0); 361168404Spjd 362168404Spjd return (1); 363168404Spjd} 364168404Spjd 365255437Sdelphij/*ARGSUSED*/ 366255437Sdelphijclock_t 367255437Sdelphijcv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res, 368255437Sdelphij int flag) 369255437Sdelphij{ 370255437Sdelphij int error; 371318909Smav timespec_t ts; 372255437Sdelphij hrtime_t delta; 373255437Sdelphij 374297508Smav ASSERT(flag == 0 || flag == CALLOUT_FLAG_ABSOLUTE); 375255437Sdelphij 376255437Sdelphijtop: 377297508Smav delta = tim; 378297508Smav if (flag & CALLOUT_FLAG_ABSOLUTE) 379297508Smav delta -= gethrtime(); 380297508Smav 381255437Sdelphij if (delta <= 0) 382255437Sdelphij return (-1); 383255437Sdelphij 384318909Smav clock_gettime(CLOCK_REALTIME, &ts); 385318909Smav ts.tv_sec += delta / NANOSEC; 386318909Smav ts.tv_nsec += delta % NANOSEC; 387318909Smav if (ts.tv_nsec >= NANOSEC) { 388318909Smav ts.tv_sec++; 389318909Smav ts.tv_nsec -= NANOSEC; 390318909Smav } 391255437Sdelphij 392255437Sdelphij ASSERT(mutex_owner(mp) == curthread); 393255437Sdelphij mp->m_owner = NULL; 394255437Sdelphij error = pthread_cond_timedwait(cv, &mp->m_lock, &ts); 395255437Sdelphij mp->m_owner = curthread; 396255437Sdelphij 397255437Sdelphij if (error == ETIMEDOUT) 398255437Sdelphij return (-1); 399255437Sdelphij 400255437Sdelphij if (error == EINTR) 401255437Sdelphij goto top; 402255437Sdelphij 403255437Sdelphij ASSERT(error == 0); 404255437Sdelphij 405255437Sdelphij return (1); 406255437Sdelphij} 407255437Sdelphij 408168404Spjdvoid 409168404Spjdcv_signal(kcondvar_t *cv) 410168404Spjd{ 411168404Spjd VERIFY(cond_signal(cv) == 0); 412168404Spjd} 413168404Spjd 414168404Spjdvoid 415168404Spjdcv_broadcast(kcondvar_t *cv) 416168404Spjd{ 417168404Spjd VERIFY(cond_broadcast(cv) == 0); 418168404Spjd} 419168404Spjd 420168404Spjd/* 421168404Spjd * ========================================================================= 422168404Spjd * vnode operations 423168404Spjd * ========================================================================= 424168404Spjd */ 425168404Spjd/* 426168404Spjd * Note: for the xxxat() versions of these functions, we assume that the 427168404Spjd * starting vp is always rootdir (which is true for spa_directory.c, the only 428168404Spjd * ZFS consumer of these interfaces). We assert this is true, and then emulate 429168404Spjd * them by adding '/' in front of the path. 430168404Spjd */ 431168404Spjd 432168404Spjd/*ARGSUSED*/ 433168404Spjdint 434168404Spjdvn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) 435168404Spjd{ 436168404Spjd int fd; 437268084Sdelphij int dump_fd; 438168404Spjd vnode_t *vp; 439168404Spjd int old_umask; 440168404Spjd char realpath[MAXPATHLEN]; 441168404Spjd struct stat64 st; 442168404Spjd 443168404Spjd /* 444168404Spjd * If we're accessing a real disk from userland, we need to use 445168404Spjd * the character interface to avoid caching. This is particularly 446168404Spjd * important if we're trying to look at a real in-kernel storage 447168404Spjd * pool from userland, e.g. via zdb, because otherwise we won't 448168404Spjd * see the changes occurring under the segmap cache. 449168404Spjd * On the other hand, the stupid character device returns zero 450168404Spjd * for its size. So -- gag -- we open the block device to get 451168404Spjd * its size, and remember it for subsequent VOP_GETATTR(). 452168404Spjd */ 453168404Spjd if (strncmp(path, "/dev/", 5) == 0) { 454168404Spjd char *dsk; 455168404Spjd fd = open64(path, O_RDONLY); 456168404Spjd if (fd == -1) 457168404Spjd return (errno); 458168404Spjd if (fstat64(fd, &st) == -1) { 459168404Spjd close(fd); 460168404Spjd return (errno); 461168404Spjd } 462168404Spjd close(fd); 463168404Spjd (void) sprintf(realpath, "%s", path); 464168404Spjd dsk = strstr(path, "/dsk/"); 465168404Spjd if (dsk != NULL) 466168404Spjd (void) sprintf(realpath + (dsk - path) + 1, "r%s", 467168404Spjd dsk + 1); 468168404Spjd } else { 469168404Spjd (void) sprintf(realpath, "%s", path); 470168404Spjd if (!(flags & FCREAT) && stat64(realpath, &st) == -1) 471168404Spjd return (errno); 472168404Spjd } 473168404Spjd 474168404Spjd if (flags & FCREAT) 475168404Spjd old_umask = umask(0); 476168404Spjd 477168404Spjd /* 478168404Spjd * The construct 'flags - FREAD' conveniently maps combinations of 479168404Spjd * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. 480168404Spjd */ 481168404Spjd fd = open64(realpath, flags - FREAD, mode); 482168404Spjd 483168404Spjd if (flags & FCREAT) 484168404Spjd (void) umask(old_umask); 485168404Spjd 486268084Sdelphij if (vn_dumpdir != NULL) { 487268084Sdelphij char dumppath[MAXPATHLEN]; 488268084Sdelphij (void) snprintf(dumppath, sizeof (dumppath), 489268084Sdelphij "%s/%s", vn_dumpdir, basename(realpath)); 490268084Sdelphij dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666); 491268084Sdelphij if (dump_fd == -1) 492268084Sdelphij return (errno); 493268084Sdelphij } else { 494268084Sdelphij dump_fd = -1; 495268084Sdelphij } 496268084Sdelphij 497168404Spjd if (fd == -1) 498168404Spjd return (errno); 499168404Spjd 500168404Spjd if (fstat64(fd, &st) == -1) { 501168404Spjd close(fd); 502168404Spjd return (errno); 503168404Spjd } 504168404Spjd 505168404Spjd (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 506168404Spjd 507168404Spjd *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); 508168404Spjd 509168404Spjd vp->v_fd = fd; 510219089Spjd vp->v_size = st.st_size; 511168404Spjd vp->v_path = spa_strdup(path); 512268084Sdelphij vp->v_dump_fd = dump_fd; 513168404Spjd 514168404Spjd return (0); 515168404Spjd} 516168404Spjd 517185029Spjd/*ARGSUSED*/ 518168404Spjdint 519168404Spjdvn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, 520185029Spjd int x3, vnode_t *startvp, int fd) 521168404Spjd{ 522168404Spjd char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); 523168404Spjd int ret; 524168404Spjd 525168404Spjd ASSERT(startvp == rootdir); 526168404Spjd (void) sprintf(realpath, "/%s", path); 527168404Spjd 528185029Spjd /* fd ignored for now, need if want to simulate nbmand support */ 529168404Spjd ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); 530168404Spjd 531168404Spjd umem_free(realpath, strlen(path) + 2); 532168404Spjd 533168404Spjd return (ret); 534168404Spjd} 535168404Spjd 536168404Spjd/*ARGSUSED*/ 537168404Spjdint 538168404Spjdvn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, 539289562Smav int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) 540168404Spjd{ 541168404Spjd ssize_t iolen, split; 542168404Spjd 543168404Spjd if (uio == UIO_READ) { 544168404Spjd iolen = pread64(vp->v_fd, addr, len, offset); 545268084Sdelphij if (vp->v_dump_fd != -1) { 546268084Sdelphij int status = 547268084Sdelphij pwrite64(vp->v_dump_fd, addr, iolen, offset); 548268084Sdelphij ASSERT(status != -1); 549268084Sdelphij } 550168404Spjd } else { 551168404Spjd /* 552168404Spjd * To simulate partial disk writes, we split writes into two 553168404Spjd * system calls so that the process can be killed in between. 554168404Spjd */ 555236884Smm int sectors = len >> SPA_MINBLOCKSHIFT; 556236884Smm split = (sectors > 0 ? rand() % sectors : 0) << 557236884Smm SPA_MINBLOCKSHIFT; 558168404Spjd iolen = pwrite64(vp->v_fd, addr, split, offset); 559168404Spjd iolen += pwrite64(vp->v_fd, (char *)addr + split, 560168404Spjd len - split, offset + split); 561168404Spjd } 562168404Spjd 563168404Spjd if (iolen == -1) 564168404Spjd return (errno); 565168404Spjd if (residp) 566168404Spjd *residp = len - iolen; 567168404Spjd else if (iolen != len) 568168404Spjd return (EIO); 569168404Spjd return (0); 570168404Spjd} 571168404Spjd 572168404Spjdvoid 573185029Spjdvn_close(vnode_t *vp, int openflag, cred_t *cr, kthread_t *td) 574168404Spjd{ 575168404Spjd close(vp->v_fd); 576268084Sdelphij if (vp->v_dump_fd != -1) 577268084Sdelphij close(vp->v_dump_fd); 578168404Spjd spa_strfree(vp->v_path); 579168404Spjd umem_free(vp, sizeof (vnode_t)); 580168404Spjd} 581168404Spjd 582219089Spjd/* 583219089Spjd * At a minimum we need to update the size since vdev_reopen() 584219089Spjd * will no longer call vn_openat(). 585219089Spjd */ 586219089Spjdint 587219089Spjdfop_getattr(vnode_t *vp, vattr_t *vap) 588219089Spjd{ 589219089Spjd struct stat64 st; 590219089Spjd 591219089Spjd if (fstat64(vp->v_fd, &st) == -1) { 592219089Spjd close(vp->v_fd); 593219089Spjd return (errno); 594219089Spjd } 595219089Spjd 596219089Spjd vap->va_size = st.st_size; 597219089Spjd return (0); 598219089Spjd} 599219089Spjd 600168404Spjd#ifdef ZFS_DEBUG 601168404Spjd 602168404Spjd/* 603168404Spjd * ========================================================================= 604168404Spjd * Figure out which debugging statements to print 605168404Spjd * ========================================================================= 606168404Spjd */ 607168404Spjd 608168404Spjdstatic char *dprintf_string; 609168404Spjdstatic int dprintf_print_all; 610168404Spjd 611168404Spjdint 612168404Spjddprintf_find_string(const char *string) 613168404Spjd{ 614168404Spjd char *tmp_str = dprintf_string; 615168404Spjd int len = strlen(string); 616168404Spjd 617168404Spjd /* 618168404Spjd * Find out if this is a string we want to print. 619168404Spjd * String format: file1.c,function_name1,file2.c,file3.c 620168404Spjd */ 621168404Spjd 622168404Spjd while (tmp_str != NULL) { 623168404Spjd if (strncmp(tmp_str, string, len) == 0 && 624168404Spjd (tmp_str[len] == ',' || tmp_str[len] == '\0')) 625168404Spjd return (1); 626168404Spjd tmp_str = strchr(tmp_str, ','); 627168404Spjd if (tmp_str != NULL) 628168404Spjd tmp_str++; /* Get rid of , */ 629168404Spjd } 630168404Spjd return (0); 631168404Spjd} 632168404Spjd 633168404Spjdvoid 634168404Spjddprintf_setup(int *argc, char **argv) 635168404Spjd{ 636168404Spjd int i, j; 637168404Spjd 638168404Spjd /* 639168404Spjd * Debugging can be specified two ways: by setting the 640168404Spjd * environment variable ZFS_DEBUG, or by including a 641168404Spjd * "debug=..." argument on the command line. The command 642168404Spjd * line setting overrides the environment variable. 643168404Spjd */ 644168404Spjd 645168404Spjd for (i = 1; i < *argc; i++) { 646168404Spjd int len = strlen("debug="); 647168404Spjd /* First look for a command line argument */ 648168404Spjd if (strncmp("debug=", argv[i], len) == 0) { 649168404Spjd dprintf_string = argv[i] + len; 650168404Spjd /* Remove from args */ 651168404Spjd for (j = i; j < *argc; j++) 652168404Spjd argv[j] = argv[j+1]; 653168404Spjd argv[j] = NULL; 654168404Spjd (*argc)--; 655168404Spjd } 656168404Spjd } 657168404Spjd 658168404Spjd if (dprintf_string == NULL) { 659168404Spjd /* Look for ZFS_DEBUG environment variable */ 660168404Spjd dprintf_string = getenv("ZFS_DEBUG"); 661168404Spjd } 662168404Spjd 663168404Spjd /* 664168404Spjd * Are we just turning on all debugging? 665168404Spjd */ 666168404Spjd if (dprintf_find_string("on")) 667168404Spjd dprintf_print_all = 1; 668271533Sdelphij 669271533Sdelphij if (dprintf_string != NULL) 670271533Sdelphij zfs_flags |= ZFS_DEBUG_DPRINTF; 671168404Spjd} 672168404Spjd 673254591Sgibbsint 674254591Sgibbssysctl_handle_64(SYSCTL_HANDLER_ARGS) 675254591Sgibbs{ 676254591Sgibbs return (0); 677254591Sgibbs} 678254591Sgibbs 679168404Spjd/* 680168404Spjd * ========================================================================= 681168404Spjd * debug printfs 682168404Spjd * ========================================================================= 683168404Spjd */ 684168404Spjdvoid 685168404Spjd__dprintf(const char *file, const char *func, int line, const char *fmt, ...) 686168404Spjd{ 687168404Spjd const char *newfile; 688168404Spjd va_list adx; 689168404Spjd 690168404Spjd /* 691168404Spjd * Get rid of annoying "../common/" prefix to filename. 692168404Spjd */ 693168404Spjd newfile = strrchr(file, '/'); 694168404Spjd if (newfile != NULL) { 695168404Spjd newfile = newfile + 1; /* Get rid of leading / */ 696168404Spjd } else { 697168404Spjd newfile = file; 698168404Spjd } 699168404Spjd 700168404Spjd if (dprintf_print_all || 701168404Spjd dprintf_find_string(newfile) || 702168404Spjd dprintf_find_string(func)) { 703168404Spjd /* Print out just the function name if requested */ 704168404Spjd flockfile(stdout); 705168404Spjd if (dprintf_find_string("pid")) 706168404Spjd (void) printf("%d ", getpid()); 707168404Spjd if (dprintf_find_string("tid")) 708269730Ssbruno (void) printf("%lu ", thr_self()); 709168404Spjd#if 0 710168404Spjd if (dprintf_find_string("cpu")) 711168404Spjd (void) printf("%u ", getcpuid()); 712168404Spjd#endif 713168404Spjd if (dprintf_find_string("time")) 714168404Spjd (void) printf("%llu ", gethrtime()); 715168404Spjd if (dprintf_find_string("long")) 716168404Spjd (void) printf("%s, line %d: ", newfile, line); 717168404Spjd (void) printf("%s: ", func); 718168404Spjd va_start(adx, fmt); 719168404Spjd (void) vprintf(fmt, adx); 720168404Spjd va_end(adx); 721168404Spjd funlockfile(stdout); 722168404Spjd } 723168404Spjd} 724168404Spjd 725168404Spjd#endif /* ZFS_DEBUG */ 726168404Spjd 727168404Spjd/* 728168404Spjd * ========================================================================= 729168404Spjd * cmn_err() and panic() 730168404Spjd * ========================================================================= 731168404Spjd */ 732168404Spjdstatic char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 733168404Spjdstatic char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 734168404Spjd 735168404Spjdvoid 736168404Spjdvpanic(const char *fmt, va_list adx) 737168404Spjd{ 738324586Savg char buf[512]; 739324586Savg (void) vsnprintf(buf, 512, fmt, adx); 740324586Savg assfail(buf, NULL, 0); 741325534Savg abort(); /* necessary to make vpanic meet noreturn requirements */ 742168404Spjd} 743168404Spjd 744168404Spjdvoid 745168404Spjdpanic(const char *fmt, ...) 746168404Spjd{ 747168404Spjd va_list adx; 748168404Spjd 749168404Spjd va_start(adx, fmt); 750168404Spjd vpanic(fmt, adx); 751168404Spjd va_end(adx); 752168404Spjd} 753168404Spjd 754168404Spjdvoid 755168404Spjdvcmn_err(int ce, const char *fmt, va_list adx) 756168404Spjd{ 757168404Spjd if (ce == CE_PANIC) 758168404Spjd vpanic(fmt, adx); 759168404Spjd if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ 760168404Spjd (void) fprintf(stderr, "%s", ce_prefix[ce]); 761168404Spjd (void) vfprintf(stderr, fmt, adx); 762168404Spjd (void) fprintf(stderr, "%s", ce_suffix[ce]); 763168404Spjd } 764168404Spjd} 765168404Spjd 766168404Spjd/*PRINTFLIKE2*/ 767168404Spjdvoid 768168404Spjdcmn_err(int ce, const char *fmt, ...) 769168404Spjd{ 770168404Spjd va_list adx; 771168404Spjd 772168404Spjd va_start(adx, fmt); 773168404Spjd vcmn_err(ce, fmt, adx); 774168404Spjd va_end(adx); 775168404Spjd} 776168404Spjd 777168404Spjd/* 778168404Spjd * ========================================================================= 779168404Spjd * kobj interfaces 780168404Spjd * ========================================================================= 781168404Spjd */ 782168404Spjdstruct _buf * 783168404Spjdkobj_open_file(char *name) 784168404Spjd{ 785168404Spjd struct _buf *file; 786168404Spjd vnode_t *vp; 787168404Spjd 788168404Spjd /* set vp as the _fd field of the file */ 789185029Spjd if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir, 790185029Spjd -1) != 0) 791168404Spjd return ((void *)-1UL); 792168404Spjd 793168404Spjd file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 794168404Spjd file->_fd = (intptr_t)vp; 795168404Spjd return (file); 796168404Spjd} 797168404Spjd 798168404Spjdint 799168404Spjdkobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 800168404Spjd{ 801168404Spjd ssize_t resid; 802168404Spjd 803168404Spjd vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 804168404Spjd UIO_SYSSPACE, 0, 0, 0, &resid); 805168404Spjd 806168404Spjd return (size - resid); 807168404Spjd} 808168404Spjd 809168404Spjdvoid 810168404Spjdkobj_close_file(struct _buf *file) 811168404Spjd{ 812185029Spjd vn_close((vnode_t *)file->_fd, 0, NULL, NULL); 813168404Spjd umem_free(file, sizeof (struct _buf)); 814168404Spjd} 815168404Spjd 816168404Spjdint 817168404Spjdkobj_get_filesize(struct _buf *file, uint64_t *size) 818168404Spjd{ 819168404Spjd struct stat64 st; 820168404Spjd vnode_t *vp = (vnode_t *)file->_fd; 821168404Spjd 822168404Spjd if (fstat64(vp->v_fd, &st) == -1) { 823185029Spjd vn_close(vp, 0, NULL, NULL); 824168404Spjd return (errno); 825168404Spjd } 826168404Spjd *size = st.st_size; 827168404Spjd return (0); 828168404Spjd} 829168404Spjd 830168404Spjd/* 831168404Spjd * ========================================================================= 832168404Spjd * misc routines 833168404Spjd * ========================================================================= 834168404Spjd */ 835168404Spjd 836168404Spjdvoid 837168404Spjddelay(clock_t ticks) 838168404Spjd{ 839168404Spjd poll(0, 0, ticks * (1000 / hz)); 840168404Spjd} 841168404Spjd 842168404Spjd#if 0 843168404Spjd/* 844168404Spjd * Find highest one bit set. 845168404Spjd * Returns bit number + 1 of highest bit that is set, otherwise returns 0. 846168404Spjd */ 847168404Spjdint 848264669Sdelphijhighbit64(uint64_t i) 849168404Spjd{ 850264669Sdelphij int h = 1; 851168404Spjd 852168404Spjd if (i == 0) 853168404Spjd return (0); 854264669Sdelphij if (i & 0xffffffff00000000ULL) { 855168404Spjd h += 32; i >>= 32; 856168404Spjd } 857168404Spjd if (i & 0xffff0000) { 858168404Spjd h += 16; i >>= 16; 859168404Spjd } 860168404Spjd if (i & 0xff00) { 861168404Spjd h += 8; i >>= 8; 862168404Spjd } 863168404Spjd if (i & 0xf0) { 864168404Spjd h += 4; i >>= 4; 865168404Spjd } 866168404Spjd if (i & 0xc) { 867168404Spjd h += 2; i >>= 2; 868168404Spjd } 869168404Spjd if (i & 0x2) { 870168404Spjd h += 1; 871168404Spjd } 872168404Spjd return (h); 873168404Spjd} 874168404Spjd#endif 875168404Spjd 876185029Spjdstatic int random_fd = -1, urandom_fd = -1; 877185029Spjd 878168404Spjdstatic int 879185029Spjdrandom_get_bytes_common(uint8_t *ptr, size_t len, int fd) 880168404Spjd{ 881168404Spjd size_t resid = len; 882168404Spjd ssize_t bytes; 883168404Spjd 884168404Spjd ASSERT(fd != -1); 885168404Spjd 886168404Spjd while (resid != 0) { 887168404Spjd bytes = read(fd, ptr, resid); 888185029Spjd ASSERT3S(bytes, >=, 0); 889168404Spjd ptr += bytes; 890168404Spjd resid -= bytes; 891168404Spjd } 892168404Spjd 893168404Spjd return (0); 894168404Spjd} 895168404Spjd 896168404Spjdint 897168404Spjdrandom_get_bytes(uint8_t *ptr, size_t len) 898168404Spjd{ 899185029Spjd return (random_get_bytes_common(ptr, len, random_fd)); 900168404Spjd} 901168404Spjd 902168404Spjdint 903168404Spjdrandom_get_pseudo_bytes(uint8_t *ptr, size_t len) 904168404Spjd{ 905185029Spjd return (random_get_bytes_common(ptr, len, urandom_fd)); 906168404Spjd} 907168404Spjd 908168498Spjdint 909168498Spjdddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result) 910168498Spjd{ 911168498Spjd char *end; 912168498Spjd 913168498Spjd *result = strtoul(hw_serial, &end, base); 914168498Spjd if (*result == 0) 915168498Spjd return (errno); 916168498Spjd return (0); 917168498Spjd} 918168498Spjd 919219089Spjdint 920219089Spjdddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result) 921219089Spjd{ 922219089Spjd char *end; 923219089Spjd 924219089Spjd *result = strtoull(str, &end, base); 925219089Spjd if (*result == 0) 926219089Spjd return (errno); 927219089Spjd return (0); 928219089Spjd} 929219089Spjd 930247265Smm#ifdef illumos 931247265Smm/* ARGSUSED */ 932247265Smmcyclic_id_t 933247265Smmcyclic_add(cyc_handler_t *hdlr, cyc_time_t *when) 934247265Smm{ 935247265Smm return (1); 936247265Smm} 937247265Smm 938247265Smm/* ARGSUSED */ 939247265Smmvoid 940247265Smmcyclic_remove(cyclic_id_t id) 941247265Smm{ 942247265Smm} 943247265Smm 944247265Smm/* ARGSUSED */ 945247265Smmint 946247265Smmcyclic_reprogram(cyclic_id_t id, hrtime_t expiration) 947247265Smm{ 948247265Smm return (1); 949247265Smm} 950247265Smm#endif 951247265Smm 952168404Spjd/* 953168404Spjd * ========================================================================= 954168404Spjd * kernel emulation setup & teardown 955168404Spjd * ========================================================================= 956168404Spjd */ 957168404Spjdstatic int 958168404Spjdumem_out_of_memory(void) 959168404Spjd{ 960168404Spjd char errmsg[] = "out of memory -- generating core dump\n"; 961168404Spjd 962168404Spjd write(fileno(stderr), errmsg, sizeof (errmsg)); 963168404Spjd abort(); 964168404Spjd return (0); 965168404Spjd} 966168404Spjd 967168404Spjdvoid 968168404Spjdkernel_init(int mode) 969168404Spjd{ 970248571Smm extern uint_t rrw_tsd_key; 971248571Smm 972168404Spjd umem_nofail_callback(umem_out_of_memory); 973168404Spjd 974168404Spjd physmem = sysconf(_SC_PHYS_PAGES); 975168404Spjd 976168404Spjd dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 977168404Spjd (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 978168404Spjd 979219089Spjd (void) snprintf(hw_serial, sizeof (hw_serial), "%lu", 980219089Spjd (mode & FWRITE) ? (unsigned long)gethostid() : 0); 981168498Spjd 982185029Spjd VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1); 983185029Spjd VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1); 984185029Spjd 985208047Smm system_taskq_init(); 986208047Smm 987247265Smm#ifdef illumos 988247265Smm mutex_init(&cpu_lock, NULL, MUTEX_DEFAULT, NULL); 989247265Smm#endif 990247265Smm 991168404Spjd spa_init(mode); 992248571Smm 993248571Smm tsd_create(&rrw_tsd_key, rrw_tsd_destroy); 994168404Spjd} 995168404Spjd 996168404Spjdvoid 997168404Spjdkernel_fini(void) 998168404Spjd{ 999168404Spjd spa_fini(); 1000185029Spjd 1001219089Spjd system_taskq_fini(); 1002219089Spjd 1003185029Spjd close(random_fd); 1004185029Spjd close(urandom_fd); 1005185029Spjd 1006185029Spjd random_fd = -1; 1007185029Spjd urandom_fd = -1; 1008168404Spjd} 1009168404Spjd 1010332536Smav/* ARGSUSED */ 1011332536Smavuint32_t 1012332536Smavzone_get_hostid(void *zonep) 1013332536Smav{ 1014332536Smav /* 1015332536Smav * We're emulating the system's hostid in userland. 1016332536Smav */ 1017332536Smav return (strtoul(hw_serial, NULL, 10)); 1018332536Smav} 1019332536Smav 1020168404Spjdint 1021168404Spjdz_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 1022168404Spjd{ 1023168404Spjd int ret; 1024168404Spjd uLongf len = *dstlen; 1025168404Spjd 1026168404Spjd if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK) 1027168404Spjd *dstlen = (size_t)len; 1028168404Spjd 1029168404Spjd return (ret); 1030168404Spjd} 1031168404Spjd 1032168404Spjdint 1033168404Spjdz_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen, 1034168404Spjd int level) 1035168404Spjd{ 1036168404Spjd int ret; 1037168404Spjd uLongf len = *dstlen; 1038168404Spjd 1039168404Spjd if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK) 1040168404Spjd *dstlen = (size_t)len; 1041168404Spjd 1042168404Spjd return (ret); 1043168404Spjd} 1044185029Spjd 1045185029Spjduid_t 1046185029Spjdcrgetuid(cred_t *cr) 1047185029Spjd{ 1048185029Spjd return (0); 1049185029Spjd} 1050185029Spjd 1051248571Smmuid_t 1052248571Smmcrgetruid(cred_t *cr) 1053248571Smm{ 1054248571Smm return (0); 1055248571Smm} 1056248571Smm 1057185029Spjdgid_t 1058185029Spjdcrgetgid(cred_t *cr) 1059185029Spjd{ 1060185029Spjd return (0); 1061185029Spjd} 1062185029Spjd 1063185029Spjdint 1064185029Spjdcrgetngroups(cred_t *cr) 1065185029Spjd{ 1066185029Spjd return (0); 1067185029Spjd} 1068185029Spjd 1069185029Spjdgid_t * 1070185029Spjdcrgetgroups(cred_t *cr) 1071185029Spjd{ 1072185029Spjd return (NULL); 1073185029Spjd} 1074185029Spjd 1075185029Spjdint 1076185029Spjdzfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 1077185029Spjd{ 1078185029Spjd return (0); 1079185029Spjd} 1080185029Spjd 1081185029Spjdint 1082185029Spjdzfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 1083185029Spjd{ 1084185029Spjd return (0); 1085185029Spjd} 1086185029Spjd 1087185029Spjdint 1088185029Spjdzfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 1089185029Spjd{ 1090185029Spjd return (0); 1091185029Spjd} 1092185029Spjd 1093185029Spjdksiddomain_t * 1094185029Spjdksid_lookupdomain(const char *dom) 1095185029Spjd{ 1096185029Spjd ksiddomain_t *kd; 1097185029Spjd 1098185029Spjd kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL); 1099185029Spjd kd->kd_name = spa_strdup(dom); 1100185029Spjd return (kd); 1101185029Spjd} 1102185029Spjd 1103185029Spjdvoid 1104185029Spjdksiddomain_rele(ksiddomain_t *ksid) 1105185029Spjd{ 1106185029Spjd spa_strfree(ksid->kd_name); 1107185029Spjd umem_free(ksid, sizeof (ksiddomain_t)); 1108185029Spjd} 1109219089Spjd 1110219089Spjd/* 1111219089Spjd * Do not change the length of the returned string; it must be freed 1112219089Spjd * with strfree(). 1113219089Spjd */ 1114219089Spjdchar * 1115219089Spjdkmem_asprintf(const char *fmt, ...) 1116219089Spjd{ 1117219089Spjd int size; 1118219089Spjd va_list adx; 1119219089Spjd char *buf; 1120219089Spjd 1121219089Spjd va_start(adx, fmt); 1122219089Spjd size = vsnprintf(NULL, 0, fmt, adx) + 1; 1123219089Spjd va_end(adx); 1124219089Spjd 1125219089Spjd buf = kmem_alloc(size, KM_SLEEP); 1126219089Spjd 1127219089Spjd va_start(adx, fmt); 1128219089Spjd size = vsnprintf(buf, size, fmt, adx); 1129219089Spjd va_end(adx); 1130219089Spjd 1131219089Spjd return (buf); 1132219089Spjd} 1133219089Spjd 1134219089Spjd/* ARGSUSED */ 1135219089Spjdint 1136219089Spjdzfs_onexit_fd_hold(int fd, minor_t *minorp) 1137219089Spjd{ 1138219089Spjd *minorp = 0; 1139219089Spjd return (0); 1140219089Spjd} 1141219089Spjd 1142219089Spjd/* ARGSUSED */ 1143219089Spjdvoid 1144219089Spjdzfs_onexit_fd_rele(int fd) 1145219089Spjd{ 1146219089Spjd} 1147219089Spjd 1148219089Spjd/* ARGSUSED */ 1149219089Spjdint 1150219089Spjdzfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data, 1151219089Spjd uint64_t *action_handle) 1152219089Spjd{ 1153219089Spjd return (0); 1154219089Spjd} 1155219089Spjd 1156219089Spjd/* ARGSUSED */ 1157219089Spjdint 1158219089Spjdzfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire) 1159219089Spjd{ 1160219089Spjd return (0); 1161219089Spjd} 1162219089Spjd 1163219089Spjd/* ARGSUSED */ 1164219089Spjdint 1165219089Spjdzfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data) 1166219089Spjd{ 1167219089Spjd return (0); 1168219089Spjd} 1169219089Spjd 1170219089Spjd#ifdef __FreeBSD__ 1171219089Spjd/* ARGSUSED */ 1172219089Spjdint 1173219089Spjdzvol_create_minors(const char *name) 1174219089Spjd{ 1175219089Spjd return (0); 1176219089Spjd} 1177219089Spjd#endif 1178260138Sdelphij 1179260138Sdelphij#ifdef illumos 1180260138Sdelphijvoid 1181260138Sdelphijbioinit(buf_t *bp) 1182260138Sdelphij{ 1183260138Sdelphij bzero(bp, sizeof (buf_t)); 1184260138Sdelphij} 1185260138Sdelphij 1186260138Sdelphijvoid 1187260138Sdelphijbiodone(buf_t *bp) 1188260138Sdelphij{ 1189260138Sdelphij if (bp->b_iodone != NULL) { 1190260138Sdelphij (*(bp->b_iodone))(bp); 1191260138Sdelphij return; 1192260138Sdelphij } 1193260138Sdelphij ASSERT((bp->b_flags & B_DONE) == 0); 1194260138Sdelphij bp->b_flags |= B_DONE; 1195260138Sdelphij} 1196260138Sdelphij 1197260138Sdelphijvoid 1198260138Sdelphijbioerror(buf_t *bp, int error) 1199260138Sdelphij{ 1200260138Sdelphij ASSERT(bp != NULL); 1201260138Sdelphij ASSERT(error >= 0); 1202260138Sdelphij 1203260138Sdelphij if (error != 0) { 1204260138Sdelphij bp->b_flags |= B_ERROR; 1205260138Sdelphij } else { 1206260138Sdelphij bp->b_flags &= ~B_ERROR; 1207260138Sdelphij } 1208260138Sdelphij bp->b_error = error; 1209260138Sdelphij} 1210260138Sdelphij 1211260138Sdelphij 1212260138Sdelphijint 1213260138Sdelphijgeterror(struct buf *bp) 1214260138Sdelphij{ 1215260138Sdelphij int error = 0; 1216260138Sdelphij 1217260138Sdelphij if (bp->b_flags & B_ERROR) { 1218260138Sdelphij error = bp->b_error; 1219260138Sdelphij if (!error) 1220260138Sdelphij error = EIO; 1221260138Sdelphij } 1222260138Sdelphij return (error); 1223260138Sdelphij} 1224260138Sdelphij#endif 1225