1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5ea8dc4b6Seschrock * Common Development and Distribution License (the "License"). 6ea8dc4b6Seschrock * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 21fa9e4066Sahrens /* 22c99e4bdcSChris Kirby * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 239a686fbcSPaul Dagnelie * Copyright (c) 2012, 2015 by Delphix. All rights reserved. 24b3d32f0cSBryan Cantrill * Copyright (c) 2013, Joyent, Inc. All rights reserved. 25*f06dce2cSAndrew Stormont * Copyright 2017 RackTop Systems. 26fa9e4066Sahrens */ 27fa9e4066Sahrens 28fa9e4066Sahrens #include <assert.h> 29c9431fa1Sahl #include <fcntl.h> 30fa9e4066Sahrens #include <poll.h> 31fa9e4066Sahrens #include <stdio.h> 32fa9e4066Sahrens #include <stdlib.h> 33c9431fa1Sahl #include <string.h> 34c9431fa1Sahl #include <zlib.h> 35df15e419SMatthew Ahrens #include <libgen.h> 36fa9e4066Sahrens #include <sys/spa.h> 37c9431fa1Sahl #include <sys/stat.h> 38fa9e4066Sahrens #include <sys/processor.h> 39c9431fa1Sahl #include <sys/zfs_context.h> 403b2aab18SMatthew Ahrens #include <sys/rrwlock.h> 41c9431fa1Sahl #include <sys/zmod.h> 4295173954Sek #include <sys/utsname.h> 435679c89fSjv #include <sys/systeminfo.h> 445ad82045Snd 45*f06dce2cSAndrew Stormont extern void system_taskq_init(void); 46*f06dce2cSAndrew Stormont extern void system_taskq_fini(void); 47*f06dce2cSAndrew Stormont 48fa9e4066Sahrens /* 49fa9e4066Sahrens * Emulation of kernel services in userland. 50fa9e4066Sahrens */ 51fa9e4066Sahrens 52*f06dce2cSAndrew Stormont pgcnt_t physmem; 53fa9e4066Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234; 545679c89fSjv char hw_serial[HW_HOSTID_LEN]; 55283b8460SGeorge.Wilson kmutex_t cpu_lock; 5694dd93aeSGeorge Wilson vmem_t *zio_arena = NULL; 5795173954Sek 58df15e419SMatthew Ahrens /* If set, all blocks read will be copied to the specified directory. */ 59df15e419SMatthew Ahrens char *vn_dumpdir = NULL; 60df15e419SMatthew Ahrens 6195173954Sek struct utsname utsname = { 6295173954Sek "userland", "libzpool", "1", "1", "na" 6395173954Sek }; 64fa9e4066Sahrens 65fa9e4066Sahrens /* 66fa9e4066Sahrens * ========================================================================= 67fa9e4066Sahrens * vnode operations 68fa9e4066Sahrens * ========================================================================= 69fa9e4066Sahrens */ 70fa9e4066Sahrens /* 71fa9e4066Sahrens * Note: for the xxxat() versions of these functions, we assume that the 72fa9e4066Sahrens * starting vp is always rootdir (which is true for spa_directory.c, the only 73fa9e4066Sahrens * ZFS consumer of these interfaces). We assert this is true, and then emulate 74fa9e4066Sahrens * them by adding '/' in front of the path. 75fa9e4066Sahrens */ 76fa9e4066Sahrens 77fa9e4066Sahrens /*ARGSUSED*/ 78fa9e4066Sahrens int 79fa9e4066Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) 80fa9e4066Sahrens { 81fa9e4066Sahrens int fd; 82df15e419SMatthew Ahrens int dump_fd; 83fa9e4066Sahrens vnode_t *vp; 84fa9e4066Sahrens int old_umask; 85fa9e4066Sahrens char realpath[MAXPATHLEN]; 86fa9e4066Sahrens struct stat64 st; 87fa9e4066Sahrens 88fa9e4066Sahrens /* 89fa9e4066Sahrens * If we're accessing a real disk from userland, we need to use 90fa9e4066Sahrens * the character interface to avoid caching. This is particularly 91fa9e4066Sahrens * important if we're trying to look at a real in-kernel storage 92fa9e4066Sahrens * pool from userland, e.g. via zdb, because otherwise we won't 93fa9e4066Sahrens * see the changes occurring under the segmap cache. 94fa9e4066Sahrens * On the other hand, the stupid character device returns zero 95fa9e4066Sahrens * for its size. So -- gag -- we open the block device to get 96fa9e4066Sahrens * its size, and remember it for subsequent VOP_GETATTR(). 97fa9e4066Sahrens */ 98fa9e4066Sahrens if (strncmp(path, "/dev/", 5) == 0) { 99fa9e4066Sahrens char *dsk; 100fa9e4066Sahrens fd = open64(path, O_RDONLY); 101fa9e4066Sahrens if (fd == -1) 102fa9e4066Sahrens return (errno); 103fa9e4066Sahrens if (fstat64(fd, &st) == -1) { 104fa9e4066Sahrens close(fd); 105fa9e4066Sahrens return (errno); 106fa9e4066Sahrens } 107fa9e4066Sahrens close(fd); 108fa9e4066Sahrens (void) sprintf(realpath, "%s", path); 109fa9e4066Sahrens dsk = strstr(path, "/dsk/"); 110fa9e4066Sahrens if (dsk != NULL) 111fa9e4066Sahrens (void) sprintf(realpath + (dsk - path) + 1, "r%s", 112fa9e4066Sahrens dsk + 1); 113fa9e4066Sahrens } else { 114fa9e4066Sahrens (void) sprintf(realpath, "%s", path); 115fa9e4066Sahrens if (!(flags & FCREAT) && stat64(realpath, &st) == -1) 116fa9e4066Sahrens return (errno); 117fa9e4066Sahrens } 118fa9e4066Sahrens 119fa9e4066Sahrens if (flags & FCREAT) 120fa9e4066Sahrens old_umask = umask(0); 121fa9e4066Sahrens 122fa9e4066Sahrens /* 123fa9e4066Sahrens * The construct 'flags - FREAD' conveniently maps combinations of 124fa9e4066Sahrens * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. 125fa9e4066Sahrens */ 126fa9e4066Sahrens fd = open64(realpath, flags - FREAD, mode); 127fa9e4066Sahrens 128fa9e4066Sahrens if (flags & FCREAT) 129fa9e4066Sahrens (void) umask(old_umask); 130fa9e4066Sahrens 131df15e419SMatthew Ahrens if (vn_dumpdir != NULL) { 132df15e419SMatthew Ahrens char dumppath[MAXPATHLEN]; 133df15e419SMatthew Ahrens (void) snprintf(dumppath, sizeof (dumppath), 134df15e419SMatthew Ahrens "%s/%s", vn_dumpdir, basename(realpath)); 135df15e419SMatthew Ahrens dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666); 136df15e419SMatthew Ahrens if (dump_fd == -1) 137df15e419SMatthew Ahrens return (errno); 138df15e419SMatthew Ahrens } else { 139df15e419SMatthew Ahrens dump_fd = -1; 140df15e419SMatthew Ahrens } 141df15e419SMatthew Ahrens 142fa9e4066Sahrens if (fd == -1) 143fa9e4066Sahrens return (errno); 144fa9e4066Sahrens 145fa9e4066Sahrens if (fstat64(fd, &st) == -1) { 146fa9e4066Sahrens close(fd); 147fa9e4066Sahrens return (errno); 148fa9e4066Sahrens } 149fa9e4066Sahrens 150fa9e4066Sahrens (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 151fa9e4066Sahrens 152fa9e4066Sahrens *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); 153fa9e4066Sahrens 154fa9e4066Sahrens vp->v_fd = fd; 155fa9e4066Sahrens vp->v_size = st.st_size; 156fa9e4066Sahrens vp->v_path = spa_strdup(path); 157df15e419SMatthew Ahrens vp->v_dump_fd = dump_fd; 158fa9e4066Sahrens 159fa9e4066Sahrens return (0); 160fa9e4066Sahrens } 161fa9e4066Sahrens 162da6c28aaSamw /*ARGSUSED*/ 163fa9e4066Sahrens int 164fa9e4066Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, 165da6c28aaSamw int x3, vnode_t *startvp, int fd) 166fa9e4066Sahrens { 167fa9e4066Sahrens char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); 168fa9e4066Sahrens int ret; 169fa9e4066Sahrens 170fa9e4066Sahrens ASSERT(startvp == rootdir); 171fa9e4066Sahrens (void) sprintf(realpath, "/%s", path); 172fa9e4066Sahrens 173da6c28aaSamw /* fd ignored for now, need if want to simulate nbmand support */ 174fa9e4066Sahrens ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); 175fa9e4066Sahrens 176fa9e4066Sahrens umem_free(realpath, strlen(path) + 2); 177fa9e4066Sahrens 178fa9e4066Sahrens return (ret); 179fa9e4066Sahrens } 180fa9e4066Sahrens 181fa9e4066Sahrens /*ARGSUSED*/ 182fa9e4066Sahrens int 183fa9e4066Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, 1849a686fbcSPaul Dagnelie int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) 185fa9e4066Sahrens { 186fa9e4066Sahrens ssize_t iolen, split; 187fa9e4066Sahrens 188fa9e4066Sahrens if (uio == UIO_READ) { 189fa9e4066Sahrens iolen = pread64(vp->v_fd, addr, len, offset); 190df15e419SMatthew Ahrens if (vp->v_dump_fd != -1) { 191df15e419SMatthew Ahrens int status = 192df15e419SMatthew Ahrens pwrite64(vp->v_dump_fd, addr, iolen, offset); 193df15e419SMatthew Ahrens ASSERT(status != -1); 194df15e419SMatthew Ahrens } 195fa9e4066Sahrens } else { 196fa9e4066Sahrens /* 197fa9e4066Sahrens * To simulate partial disk writes, we split writes into two 198fa9e4066Sahrens * system calls so that the process can be killed in between. 199fa9e4066Sahrens */ 200ad135b5dSChristopher Siden int sectors = len >> SPA_MINBLOCKSHIFT; 201ad135b5dSChristopher Siden split = (sectors > 0 ? rand() % sectors : 0) << 202ad135b5dSChristopher Siden SPA_MINBLOCKSHIFT; 203fa9e4066Sahrens iolen = pwrite64(vp->v_fd, addr, split, offset); 204fa9e4066Sahrens iolen += pwrite64(vp->v_fd, (char *)addr + split, 205fa9e4066Sahrens len - split, offset + split); 206fa9e4066Sahrens } 207fa9e4066Sahrens 208fa9e4066Sahrens if (iolen == -1) 209fa9e4066Sahrens return (errno); 210fa9e4066Sahrens if (residp) 211fa9e4066Sahrens *residp = len - iolen; 212fa9e4066Sahrens else if (iolen != len) 213fa9e4066Sahrens return (EIO); 214fa9e4066Sahrens return (0); 215fa9e4066Sahrens } 216fa9e4066Sahrens 217fa9e4066Sahrens void 218fa9e4066Sahrens vn_close(vnode_t *vp) 219fa9e4066Sahrens { 220fa9e4066Sahrens close(vp->v_fd); 221df15e419SMatthew Ahrens if (vp->v_dump_fd != -1) 222df15e419SMatthew Ahrens close(vp->v_dump_fd); 223fa9e4066Sahrens spa_strfree(vp->v_path); 224fa9e4066Sahrens umem_free(vp, sizeof (vnode_t)); 225fa9e4066Sahrens } 226fa9e4066Sahrens 227095bcd66SGeorge Wilson /* 228095bcd66SGeorge Wilson * At a minimum we need to update the size since vdev_reopen() 229095bcd66SGeorge Wilson * will no longer call vn_openat(). 230095bcd66SGeorge Wilson */ 231095bcd66SGeorge Wilson int 232095bcd66SGeorge Wilson fop_getattr(vnode_t *vp, vattr_t *vap) 233095bcd66SGeorge Wilson { 234095bcd66SGeorge Wilson struct stat64 st; 235095bcd66SGeorge Wilson 236095bcd66SGeorge Wilson if (fstat64(vp->v_fd, &st) == -1) { 237095bcd66SGeorge Wilson close(vp->v_fd); 238095bcd66SGeorge Wilson return (errno); 239095bcd66SGeorge Wilson } 240095bcd66SGeorge Wilson 241095bcd66SGeorge Wilson vap->va_size = st.st_size; 242095bcd66SGeorge Wilson return (0); 243095bcd66SGeorge Wilson } 244095bcd66SGeorge Wilson 245fa9e4066Sahrens #ifdef ZFS_DEBUG 246fa9e4066Sahrens 247fa9e4066Sahrens /* 248fa9e4066Sahrens * ========================================================================= 249fa9e4066Sahrens * Figure out which debugging statements to print 250fa9e4066Sahrens * ========================================================================= 251fa9e4066Sahrens */ 252fa9e4066Sahrens 253fa9e4066Sahrens static char *dprintf_string; 254fa9e4066Sahrens static int dprintf_print_all; 255fa9e4066Sahrens 256fa9e4066Sahrens int 257fa9e4066Sahrens dprintf_find_string(const char *string) 258fa9e4066Sahrens { 259fa9e4066Sahrens char *tmp_str = dprintf_string; 260fa9e4066Sahrens int len = strlen(string); 261fa9e4066Sahrens 262fa9e4066Sahrens /* 263fa9e4066Sahrens * Find out if this is a string we want to print. 264fa9e4066Sahrens * String format: file1.c,function_name1,file2.c,file3.c 265fa9e4066Sahrens */ 266fa9e4066Sahrens 267fa9e4066Sahrens while (tmp_str != NULL) { 268fa9e4066Sahrens if (strncmp(tmp_str, string, len) == 0 && 269fa9e4066Sahrens (tmp_str[len] == ',' || tmp_str[len] == '\0')) 270fa9e4066Sahrens return (1); 271fa9e4066Sahrens tmp_str = strchr(tmp_str, ','); 272fa9e4066Sahrens if (tmp_str != NULL) 273fa9e4066Sahrens tmp_str++; /* Get rid of , */ 274fa9e4066Sahrens } 275fa9e4066Sahrens return (0); 276fa9e4066Sahrens } 277fa9e4066Sahrens 278fa9e4066Sahrens void 279fa9e4066Sahrens dprintf_setup(int *argc, char **argv) 280fa9e4066Sahrens { 281fa9e4066Sahrens int i, j; 282fa9e4066Sahrens 283fa9e4066Sahrens /* 284fa9e4066Sahrens * Debugging can be specified two ways: by setting the 285fa9e4066Sahrens * environment variable ZFS_DEBUG, or by including a 286fa9e4066Sahrens * "debug=..." argument on the command line. The command 287fa9e4066Sahrens * line setting overrides the environment variable. 288fa9e4066Sahrens */ 289fa9e4066Sahrens 290fa9e4066Sahrens for (i = 1; i < *argc; i++) { 291fa9e4066Sahrens int len = strlen("debug="); 292fa9e4066Sahrens /* First look for a command line argument */ 293fa9e4066Sahrens if (strncmp("debug=", argv[i], len) == 0) { 294fa9e4066Sahrens dprintf_string = argv[i] + len; 295fa9e4066Sahrens /* Remove from args */ 296fa9e4066Sahrens for (j = i; j < *argc; j++) 297fa9e4066Sahrens argv[j] = argv[j+1]; 298fa9e4066Sahrens argv[j] = NULL; 299fa9e4066Sahrens (*argc)--; 300fa9e4066Sahrens } 301fa9e4066Sahrens } 302fa9e4066Sahrens 303fa9e4066Sahrens if (dprintf_string == NULL) { 304fa9e4066Sahrens /* Look for ZFS_DEBUG environment variable */ 305fa9e4066Sahrens dprintf_string = getenv("ZFS_DEBUG"); 306fa9e4066Sahrens } 307fa9e4066Sahrens 308fa9e4066Sahrens /* 309fa9e4066Sahrens * Are we just turning on all debugging? 310fa9e4066Sahrens */ 311fa9e4066Sahrens if (dprintf_find_string("on")) 312fa9e4066Sahrens dprintf_print_all = 1; 3137fa49ea5SMatthew Ahrens 3147fa49ea5SMatthew Ahrens if (dprintf_string != NULL) 3157fa49ea5SMatthew Ahrens zfs_flags |= ZFS_DEBUG_DPRINTF; 316fa9e4066Sahrens } 317fa9e4066Sahrens 318fa9e4066Sahrens /* 319fa9e4066Sahrens * ========================================================================= 320fa9e4066Sahrens * debug printfs 321fa9e4066Sahrens * ========================================================================= 322fa9e4066Sahrens */ 323fa9e4066Sahrens void 324fa9e4066Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 325fa9e4066Sahrens { 326fa9e4066Sahrens const char *newfile; 327fa9e4066Sahrens va_list adx; 328fa9e4066Sahrens 329fa9e4066Sahrens /* 330fa9e4066Sahrens * Get rid of annoying "../common/" prefix to filename. 331fa9e4066Sahrens */ 332fa9e4066Sahrens newfile = strrchr(file, '/'); 333fa9e4066Sahrens if (newfile != NULL) { 334fa9e4066Sahrens newfile = newfile + 1; /* Get rid of leading / */ 335fa9e4066Sahrens } else { 336fa9e4066Sahrens newfile = file; 337fa9e4066Sahrens } 338fa9e4066Sahrens 339fa9e4066Sahrens if (dprintf_print_all || 340fa9e4066Sahrens dprintf_find_string(newfile) || 341fa9e4066Sahrens dprintf_find_string(func)) { 342fa9e4066Sahrens /* Print out just the function name if requested */ 343fa9e4066Sahrens flockfile(stdout); 344fa9e4066Sahrens if (dprintf_find_string("pid")) 345fa9e4066Sahrens (void) printf("%d ", getpid()); 346fa9e4066Sahrens if (dprintf_find_string("tid")) 347fa9e4066Sahrens (void) printf("%u ", thr_self()); 348fa9e4066Sahrens if (dprintf_find_string("cpu")) 349fa9e4066Sahrens (void) printf("%u ", getcpuid()); 350fa9e4066Sahrens if (dprintf_find_string("time")) 351fa9e4066Sahrens (void) printf("%llu ", gethrtime()); 352fa9e4066Sahrens if (dprintf_find_string("long")) 353fa9e4066Sahrens (void) printf("%s, line %d: ", newfile, line); 354fa9e4066Sahrens (void) printf("%s: ", func); 355fa9e4066Sahrens va_start(adx, fmt); 356fa9e4066Sahrens (void) vprintf(fmt, adx); 357fa9e4066Sahrens va_end(adx); 358fa9e4066Sahrens funlockfile(stdout); 359fa9e4066Sahrens } 360fa9e4066Sahrens } 361fa9e4066Sahrens 362fa9e4066Sahrens #endif /* ZFS_DEBUG */ 363fa9e4066Sahrens 364ea8dc4b6Seschrock /* 365ea8dc4b6Seschrock * ========================================================================= 366ea8dc4b6Seschrock * kobj interfaces 367ea8dc4b6Seschrock * ========================================================================= 368ea8dc4b6Seschrock */ 369ea8dc4b6Seschrock struct _buf * 370ea8dc4b6Seschrock kobj_open_file(char *name) 371ea8dc4b6Seschrock { 372ea8dc4b6Seschrock struct _buf *file; 373ea8dc4b6Seschrock vnode_t *vp; 374ea8dc4b6Seschrock 375ea8dc4b6Seschrock /* set vp as the _fd field of the file */ 376da6c28aaSamw if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir, 377da6c28aaSamw -1) != 0) 378ea8dc4b6Seschrock return ((void *)-1UL); 379ea8dc4b6Seschrock 380ea8dc4b6Seschrock file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 381ea8dc4b6Seschrock file->_fd = (intptr_t)vp; 382ea8dc4b6Seschrock return (file); 383ea8dc4b6Seschrock } 384ea8dc4b6Seschrock 385ea8dc4b6Seschrock int 386ea8dc4b6Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 387ea8dc4b6Seschrock { 388ea8dc4b6Seschrock ssize_t resid; 389ea8dc4b6Seschrock 390ea8dc4b6Seschrock vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 391ea8dc4b6Seschrock UIO_SYSSPACE, 0, 0, 0, &resid); 392ea8dc4b6Seschrock 393b1b8ab34Slling return (size - resid); 394ea8dc4b6Seschrock } 395ea8dc4b6Seschrock 396ea8dc4b6Seschrock void 397ea8dc4b6Seschrock kobj_close_file(struct _buf *file) 398ea8dc4b6Seschrock { 399ea8dc4b6Seschrock vn_close((vnode_t *)file->_fd); 400ea8dc4b6Seschrock umem_free(file, sizeof (struct _buf)); 401ea8dc4b6Seschrock } 402ea8dc4b6Seschrock 403ea8dc4b6Seschrock int 404b1b8ab34Slling kobj_get_filesize(struct _buf *file, uint64_t *size) 405ea8dc4b6Seschrock { 406ea8dc4b6Seschrock struct stat64 st; 407b1b8ab34Slling vnode_t *vp = (vnode_t *)file->_fd; 408b1b8ab34Slling 409ea8dc4b6Seschrock if (fstat64(vp->v_fd, &st) == -1) { 410ea8dc4b6Seschrock vn_close(vp); 411ea8dc4b6Seschrock return (errno); 412ea8dc4b6Seschrock } 413b1b8ab34Slling *size = st.st_size; 414ea8dc4b6Seschrock return (0); 415ea8dc4b6Seschrock } 416ea8dc4b6Seschrock 417fa9e4066Sahrens /* 418fa9e4066Sahrens * ========================================================================= 419fa9e4066Sahrens * kernel emulation setup & teardown 420fa9e4066Sahrens * ========================================================================= 421fa9e4066Sahrens */ 422fa9e4066Sahrens static int 423fa9e4066Sahrens umem_out_of_memory(void) 424fa9e4066Sahrens { 425fa9e4066Sahrens char errmsg[] = "out of memory -- generating core dump\n"; 426fa9e4066Sahrens 427fa9e4066Sahrens write(fileno(stderr), errmsg, sizeof (errmsg)); 428fa9e4066Sahrens abort(); 429fa9e4066Sahrens return (0); 430fa9e4066Sahrens } 431fa9e4066Sahrens 432fa9e4066Sahrens void 433fa9e4066Sahrens kernel_init(int mode) 434fa9e4066Sahrens { 4353b2aab18SMatthew Ahrens extern uint_t rrw_tsd_key; 4363b2aab18SMatthew Ahrens 437fa9e4066Sahrens umem_nofail_callback(umem_out_of_memory); 438fa9e4066Sahrens 439fa9e4066Sahrens physmem = sysconf(_SC_PHYS_PAGES); 440fa9e4066Sahrens 441fa9e4066Sahrens dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 442fa9e4066Sahrens (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 443fa9e4066Sahrens 4443ad6c7f9SVictor Latushkin (void) snprintf(hw_serial, sizeof (hw_serial), "%ld", 4453ad6c7f9SVictor Latushkin (mode & FWRITE) ? gethostid() : 0); 44695173954Sek 44788b7b0f2SMatthew Ahrens system_taskq_init(); 44888b7b0f2SMatthew Ahrens 449283b8460SGeorge.Wilson mutex_init(&cpu_lock, NULL, MUTEX_DEFAULT, NULL); 450283b8460SGeorge.Wilson 451fa9e4066Sahrens spa_init(mode); 4523b2aab18SMatthew Ahrens 4533b2aab18SMatthew Ahrens tsd_create(&rrw_tsd_key, rrw_tsd_destroy); 454fa9e4066Sahrens } 455fa9e4066Sahrens 456fa9e4066Sahrens void 457fa9e4066Sahrens kernel_fini(void) 458fa9e4066Sahrens { 459fa9e4066Sahrens spa_fini(); 46017f17c2dSbonwick 461d20e665cSRicardo M. Correia system_taskq_fini(); 462fa9e4066Sahrens } 463c9431fa1Sahl 464c9431fa1Sahl int 465c9431fa1Sahl z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 466c9431fa1Sahl { 467c9431fa1Sahl int ret; 468c9431fa1Sahl uLongf len = *dstlen; 469c9431fa1Sahl 470c9431fa1Sahl if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK) 471c9431fa1Sahl *dstlen = (size_t)len; 472c9431fa1Sahl 473c9431fa1Sahl return (ret); 474c9431fa1Sahl } 475c9431fa1Sahl 476c9431fa1Sahl int 477c9431fa1Sahl z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen, 478c9431fa1Sahl int level) 479c9431fa1Sahl { 480c9431fa1Sahl int ret; 481c9431fa1Sahl uLongf len = *dstlen; 482c9431fa1Sahl 483c9431fa1Sahl if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK) 484c9431fa1Sahl *dstlen = (size_t)len; 485c9431fa1Sahl 486c9431fa1Sahl return (ret); 487c9431fa1Sahl } 488ecd6cf80Smarks 489ecd6cf80Smarks int 490ecd6cf80Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 491ecd6cf80Smarks { 492ecd6cf80Smarks return (0); 493ecd6cf80Smarks } 494ecd6cf80Smarks 495ecd6cf80Smarks int 496ecd6cf80Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 497ecd6cf80Smarks { 498ecd6cf80Smarks return (0); 499ecd6cf80Smarks } 500ecd6cf80Smarks 501ecd6cf80Smarks int 502ecd6cf80Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 503ecd6cf80Smarks { 504ecd6cf80Smarks return (0); 505ecd6cf80Smarks } 506e0d35c44Smarks 507c99e4bdcSChris Kirby /* ARGSUSED */ 508c99e4bdcSChris Kirby int 509a7f53a56SChris Kirby zfs_onexit_fd_hold(int fd, minor_t *minorp) 510a7f53a56SChris Kirby { 511a7f53a56SChris Kirby *minorp = 0; 512a7f53a56SChris Kirby return (0); 513a7f53a56SChris Kirby } 514a7f53a56SChris Kirby 515a7f53a56SChris Kirby /* ARGSUSED */ 516a7f53a56SChris Kirby void 517a7f53a56SChris Kirby zfs_onexit_fd_rele(int fd) 518a7f53a56SChris Kirby { 519a7f53a56SChris Kirby } 520a7f53a56SChris Kirby 521a7f53a56SChris Kirby /* ARGSUSED */ 522a7f53a56SChris Kirby int 523a7f53a56SChris Kirby zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data, 524c99e4bdcSChris Kirby uint64_t *action_handle) 525c99e4bdcSChris Kirby { 526c99e4bdcSChris Kirby return (0); 527c99e4bdcSChris Kirby } 528c99e4bdcSChris Kirby 529c99e4bdcSChris Kirby /* ARGSUSED */ 530c99e4bdcSChris Kirby int 531a7f53a56SChris Kirby zfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire) 532c99e4bdcSChris Kirby { 533c99e4bdcSChris Kirby return (0); 534c99e4bdcSChris Kirby } 535c99e4bdcSChris Kirby 536c99e4bdcSChris Kirby /* ARGSUSED */ 537c99e4bdcSChris Kirby int 538a7f53a56SChris Kirby zfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data) 539c99e4bdcSChris Kirby { 540c99e4bdcSChris Kirby return (0); 541c99e4bdcSChris Kirby } 54231d7e8faSGeorge Wilson 54331d7e8faSGeorge Wilson void 54431d7e8faSGeorge Wilson bioinit(buf_t *bp) 54531d7e8faSGeorge Wilson { 54631d7e8faSGeorge Wilson bzero(bp, sizeof (buf_t)); 54731d7e8faSGeorge Wilson } 54831d7e8faSGeorge Wilson 54931d7e8faSGeorge Wilson void 55031d7e8faSGeorge Wilson biodone(buf_t *bp) 55131d7e8faSGeorge Wilson { 55231d7e8faSGeorge Wilson if (bp->b_iodone != NULL) { 55331d7e8faSGeorge Wilson (*(bp->b_iodone))(bp); 55431d7e8faSGeorge Wilson return; 55531d7e8faSGeorge Wilson } 55631d7e8faSGeorge Wilson ASSERT((bp->b_flags & B_DONE) == 0); 55731d7e8faSGeorge Wilson bp->b_flags |= B_DONE; 55831d7e8faSGeorge Wilson } 55931d7e8faSGeorge Wilson 56031d7e8faSGeorge Wilson void 56131d7e8faSGeorge Wilson bioerror(buf_t *bp, int error) 56231d7e8faSGeorge Wilson { 56331d7e8faSGeorge Wilson ASSERT(bp != NULL); 56431d7e8faSGeorge Wilson ASSERT(error >= 0); 56531d7e8faSGeorge Wilson 56631d7e8faSGeorge Wilson if (error != 0) { 56731d7e8faSGeorge Wilson bp->b_flags |= B_ERROR; 56831d7e8faSGeorge Wilson } else { 56931d7e8faSGeorge Wilson bp->b_flags &= ~B_ERROR; 57031d7e8faSGeorge Wilson } 57131d7e8faSGeorge Wilson bp->b_error = error; 57231d7e8faSGeorge Wilson } 57331d7e8faSGeorge Wilson 57431d7e8faSGeorge Wilson 57531d7e8faSGeorge Wilson int 57631d7e8faSGeorge Wilson geterror(struct buf *bp) 57731d7e8faSGeorge Wilson { 57831d7e8faSGeorge Wilson int error = 0; 57931d7e8faSGeorge Wilson 58031d7e8faSGeorge Wilson if (bp->b_flags & B_ERROR) { 58131d7e8faSGeorge Wilson error = bp->b_error; 58231d7e8faSGeorge Wilson if (!error) 58331d7e8faSGeorge Wilson error = EIO; 58431d7e8faSGeorge Wilson } 58531d7e8faSGeorge Wilson return (error); 58631d7e8faSGeorge Wilson } 587