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. 24d8ab6e12SDon Brady * Copyright 2020 Joyent, Inc. 25f06dce2cSAndrew 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> 44d8ab6e12SDon Brady #include <libzutil.h> 45eb633035STom Caputi #include <sys/crypto/common.h> 46eb633035STom Caputi #include <sys/crypto/impl.h> 47eb633035STom Caputi #include <sys/crypto/api.h> 48eb633035STom Caputi #include <sys/sha2.h> 49eb633035STom Caputi #include <crypto/aes/aes_impl.h> 505ad82045Snd 51f06dce2cSAndrew Stormont extern void system_taskq_init(void); 52f06dce2cSAndrew Stormont extern void system_taskq_fini(void); 53f06dce2cSAndrew Stormont 54fa9e4066Sahrens /* 55fa9e4066Sahrens * Emulation of kernel services in userland. 56fa9e4066Sahrens */ 57fa9e4066Sahrens 58f06dce2cSAndrew Stormont pgcnt_t physmem; 59fa9e4066Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234; 605679c89fSjv char hw_serial[HW_HOSTID_LEN]; 61283b8460SGeorge.Wilson kmutex_t cpu_lock; 6294dd93aeSGeorge Wilson vmem_t *zio_arena = NULL; 6395173954Sek 64df15e419SMatthew Ahrens /* If set, all blocks read will be copied to the specified directory. */ 65df15e419SMatthew Ahrens char *vn_dumpdir = NULL; 66df15e419SMatthew Ahrens 6795173954Sek struct utsname utsname = { 6895173954Sek "userland", "libzpool", "1", "1", "na" 6995173954Sek }; 70fa9e4066Sahrens 71fa9e4066Sahrens /* 72fa9e4066Sahrens * ========================================================================= 73fa9e4066Sahrens * vnode operations 74fa9e4066Sahrens * ========================================================================= 75fa9e4066Sahrens */ 76fa9e4066Sahrens /* 77fa9e4066Sahrens * Note: for the xxxat() versions of these functions, we assume that the 78fa9e4066Sahrens * starting vp is always rootdir (which is true for spa_directory.c, the only 79fa9e4066Sahrens * ZFS consumer of these interfaces). We assert this is true, and then emulate 80fa9e4066Sahrens * them by adding '/' in front of the path. 81fa9e4066Sahrens */ 82fa9e4066Sahrens 83fa9e4066Sahrens /*ARGSUSED*/ 84fa9e4066Sahrens int 85fa9e4066Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) 86fa9e4066Sahrens { 87fa9e4066Sahrens int fd; 88df15e419SMatthew Ahrens int dump_fd; 89fa9e4066Sahrens vnode_t *vp; 90fa9e4066Sahrens int old_umask; 91fa9e4066Sahrens char realpath[MAXPATHLEN]; 92fa9e4066Sahrens struct stat64 st; 93fa9e4066Sahrens 94fa9e4066Sahrens /* 95fa9e4066Sahrens * If we're accessing a real disk from userland, we need to use 96fa9e4066Sahrens * the character interface to avoid caching. This is particularly 97fa9e4066Sahrens * important if we're trying to look at a real in-kernel storage 98fa9e4066Sahrens * pool from userland, e.g. via zdb, because otherwise we won't 99fa9e4066Sahrens * see the changes occurring under the segmap cache. 100fa9e4066Sahrens * On the other hand, the stupid character device returns zero 101fa9e4066Sahrens * for its size. So -- gag -- we open the block device to get 102fa9e4066Sahrens * its size, and remember it for subsequent VOP_GETATTR(). 103fa9e4066Sahrens */ 104fa9e4066Sahrens if (strncmp(path, "/dev/", 5) == 0) { 105fa9e4066Sahrens char *dsk; 106fa9e4066Sahrens fd = open64(path, O_RDONLY); 107fa9e4066Sahrens if (fd == -1) 108fa9e4066Sahrens return (errno); 109fa9e4066Sahrens if (fstat64(fd, &st) == -1) { 110fa9e4066Sahrens close(fd); 111fa9e4066Sahrens return (errno); 112fa9e4066Sahrens } 113fa9e4066Sahrens close(fd); 114fa9e4066Sahrens (void) sprintf(realpath, "%s", path); 115fa9e4066Sahrens dsk = strstr(path, "/dsk/"); 116fa9e4066Sahrens if (dsk != NULL) 117fa9e4066Sahrens (void) sprintf(realpath + (dsk - path) + 1, "r%s", 118fa9e4066Sahrens dsk + 1); 119fa9e4066Sahrens } else { 120fa9e4066Sahrens (void) sprintf(realpath, "%s", path); 121fa9e4066Sahrens if (!(flags & FCREAT) && stat64(realpath, &st) == -1) 122fa9e4066Sahrens return (errno); 123fa9e4066Sahrens } 124fa9e4066Sahrens 125fa9e4066Sahrens if (flags & FCREAT) 126fa9e4066Sahrens old_umask = umask(0); 127fa9e4066Sahrens 128fa9e4066Sahrens /* 129fa9e4066Sahrens * The construct 'flags - FREAD' conveniently maps combinations of 130fa9e4066Sahrens * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. 131fa9e4066Sahrens */ 132fa9e4066Sahrens fd = open64(realpath, flags - FREAD, mode); 133fa9e4066Sahrens 134fa9e4066Sahrens if (flags & FCREAT) 135fa9e4066Sahrens (void) umask(old_umask); 136fa9e4066Sahrens 137df15e419SMatthew Ahrens if (vn_dumpdir != NULL) { 138df15e419SMatthew Ahrens char dumppath[MAXPATHLEN]; 139df15e419SMatthew Ahrens (void) snprintf(dumppath, sizeof (dumppath), 140df15e419SMatthew Ahrens "%s/%s", vn_dumpdir, basename(realpath)); 141df15e419SMatthew Ahrens dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666); 142df15e419SMatthew Ahrens if (dump_fd == -1) 143df15e419SMatthew Ahrens return (errno); 144df15e419SMatthew Ahrens } else { 145df15e419SMatthew Ahrens dump_fd = -1; 146df15e419SMatthew Ahrens } 147df15e419SMatthew Ahrens 148fa9e4066Sahrens if (fd == -1) 149fa9e4066Sahrens return (errno); 150fa9e4066Sahrens 151fa9e4066Sahrens if (fstat64(fd, &st) == -1) { 152fa9e4066Sahrens close(fd); 153fa9e4066Sahrens return (errno); 154fa9e4066Sahrens } 155fa9e4066Sahrens 156fa9e4066Sahrens (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 157fa9e4066Sahrens 158fa9e4066Sahrens *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); 159fa9e4066Sahrens 160fa9e4066Sahrens vp->v_fd = fd; 161fa9e4066Sahrens vp->v_size = st.st_size; 162fa9e4066Sahrens vp->v_path = spa_strdup(path); 163df15e419SMatthew Ahrens vp->v_dump_fd = dump_fd; 164fa9e4066Sahrens 165fa9e4066Sahrens return (0); 166fa9e4066Sahrens } 167fa9e4066Sahrens 168da6c28aaSamw /*ARGSUSED*/ 169fa9e4066Sahrens int 170fa9e4066Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, 171da6c28aaSamw int x3, vnode_t *startvp, int fd) 172fa9e4066Sahrens { 173fa9e4066Sahrens char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); 174fa9e4066Sahrens int ret; 175fa9e4066Sahrens 176fa9e4066Sahrens ASSERT(startvp == rootdir); 177fa9e4066Sahrens (void) sprintf(realpath, "/%s", path); 178fa9e4066Sahrens 179da6c28aaSamw /* fd ignored for now, need if want to simulate nbmand support */ 180fa9e4066Sahrens ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); 181fa9e4066Sahrens 182fa9e4066Sahrens umem_free(realpath, strlen(path) + 2); 183fa9e4066Sahrens 184fa9e4066Sahrens return (ret); 185fa9e4066Sahrens } 186fa9e4066Sahrens 187fa9e4066Sahrens /*ARGSUSED*/ 188fa9e4066Sahrens int 189fa9e4066Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, 1909a686fbcSPaul Dagnelie int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) 191fa9e4066Sahrens { 192fa9e4066Sahrens ssize_t iolen, split; 193fa9e4066Sahrens 194fa9e4066Sahrens if (uio == UIO_READ) { 195fa9e4066Sahrens iolen = pread64(vp->v_fd, addr, len, offset); 196df15e419SMatthew Ahrens if (vp->v_dump_fd != -1) { 197df15e419SMatthew Ahrens int status = 198df15e419SMatthew Ahrens pwrite64(vp->v_dump_fd, addr, iolen, offset); 199df15e419SMatthew Ahrens ASSERT(status != -1); 200df15e419SMatthew Ahrens } 201fa9e4066Sahrens } else { 202fa9e4066Sahrens /* 203fa9e4066Sahrens * To simulate partial disk writes, we split writes into two 204fa9e4066Sahrens * system calls so that the process can be killed in between. 205fa9e4066Sahrens */ 206ad135b5dSChristopher Siden int sectors = len >> SPA_MINBLOCKSHIFT; 207ad135b5dSChristopher Siden split = (sectors > 0 ? rand() % sectors : 0) << 208ad135b5dSChristopher Siden SPA_MINBLOCKSHIFT; 209fa9e4066Sahrens iolen = pwrite64(vp->v_fd, addr, split, offset); 210fa9e4066Sahrens iolen += pwrite64(vp->v_fd, (char *)addr + split, 211fa9e4066Sahrens len - split, offset + split); 212fa9e4066Sahrens } 213fa9e4066Sahrens 214fa9e4066Sahrens if (iolen == -1) 215fa9e4066Sahrens return (errno); 216fa9e4066Sahrens if (residp) 217fa9e4066Sahrens *residp = len - iolen; 218fa9e4066Sahrens else if (iolen != len) 219fa9e4066Sahrens return (EIO); 220fa9e4066Sahrens return (0); 221fa9e4066Sahrens } 222fa9e4066Sahrens 223fa9e4066Sahrens void 224fa9e4066Sahrens vn_close(vnode_t *vp) 225fa9e4066Sahrens { 226fa9e4066Sahrens close(vp->v_fd); 227df15e419SMatthew Ahrens if (vp->v_dump_fd != -1) 228df15e419SMatthew Ahrens close(vp->v_dump_fd); 229fa9e4066Sahrens spa_strfree(vp->v_path); 230fa9e4066Sahrens umem_free(vp, sizeof (vnode_t)); 231fa9e4066Sahrens } 232fa9e4066Sahrens 233095bcd66SGeorge Wilson /* 234095bcd66SGeorge Wilson * At a minimum we need to update the size since vdev_reopen() 235095bcd66SGeorge Wilson * will no longer call vn_openat(). 236095bcd66SGeorge Wilson */ 237095bcd66SGeorge Wilson int 238095bcd66SGeorge Wilson fop_getattr(vnode_t *vp, vattr_t *vap) 239095bcd66SGeorge Wilson { 240095bcd66SGeorge Wilson struct stat64 st; 241095bcd66SGeorge Wilson 242095bcd66SGeorge Wilson if (fstat64(vp->v_fd, &st) == -1) { 243095bcd66SGeorge Wilson close(vp->v_fd); 244095bcd66SGeorge Wilson return (errno); 245095bcd66SGeorge Wilson } 246095bcd66SGeorge Wilson 247095bcd66SGeorge Wilson vap->va_size = st.st_size; 248095bcd66SGeorge Wilson return (0); 249095bcd66SGeorge Wilson } 250095bcd66SGeorge Wilson 251fa9e4066Sahrens #ifdef ZFS_DEBUG 252fa9e4066Sahrens 253fa9e4066Sahrens /* 254fa9e4066Sahrens * ========================================================================= 255fa9e4066Sahrens * Figure out which debugging statements to print 256fa9e4066Sahrens * ========================================================================= 257fa9e4066Sahrens */ 258fa9e4066Sahrens 259fa9e4066Sahrens static char *dprintf_string; 260fa9e4066Sahrens static int dprintf_print_all; 261fa9e4066Sahrens 262fa9e4066Sahrens int 263fa9e4066Sahrens dprintf_find_string(const char *string) 264fa9e4066Sahrens { 265fa9e4066Sahrens char *tmp_str = dprintf_string; 266fa9e4066Sahrens int len = strlen(string); 267fa9e4066Sahrens 268fa9e4066Sahrens /* 269fa9e4066Sahrens * Find out if this is a string we want to print. 270fa9e4066Sahrens * String format: file1.c,function_name1,file2.c,file3.c 271fa9e4066Sahrens */ 272fa9e4066Sahrens 273fa9e4066Sahrens while (tmp_str != NULL) { 274fa9e4066Sahrens if (strncmp(tmp_str, string, len) == 0 && 275fa9e4066Sahrens (tmp_str[len] == ',' || tmp_str[len] == '\0')) 276fa9e4066Sahrens return (1); 277fa9e4066Sahrens tmp_str = strchr(tmp_str, ','); 278fa9e4066Sahrens if (tmp_str != NULL) 279fa9e4066Sahrens tmp_str++; /* Get rid of , */ 280fa9e4066Sahrens } 281fa9e4066Sahrens return (0); 282fa9e4066Sahrens } 283fa9e4066Sahrens 284fa9e4066Sahrens void 285fa9e4066Sahrens dprintf_setup(int *argc, char **argv) 286fa9e4066Sahrens { 287fa9e4066Sahrens int i, j; 288fa9e4066Sahrens 289fa9e4066Sahrens /* 290fa9e4066Sahrens * Debugging can be specified two ways: by setting the 291fa9e4066Sahrens * environment variable ZFS_DEBUG, or by including a 292fa9e4066Sahrens * "debug=..." argument on the command line. The command 293fa9e4066Sahrens * line setting overrides the environment variable. 294fa9e4066Sahrens */ 295fa9e4066Sahrens 296fa9e4066Sahrens for (i = 1; i < *argc; i++) { 297fa9e4066Sahrens int len = strlen("debug="); 298fa9e4066Sahrens /* First look for a command line argument */ 299fa9e4066Sahrens if (strncmp("debug=", argv[i], len) == 0) { 300fa9e4066Sahrens dprintf_string = argv[i] + len; 301fa9e4066Sahrens /* Remove from args */ 302fa9e4066Sahrens for (j = i; j < *argc; j++) 303fa9e4066Sahrens argv[j] = argv[j+1]; 304fa9e4066Sahrens argv[j] = NULL; 305fa9e4066Sahrens (*argc)--; 306fa9e4066Sahrens } 307fa9e4066Sahrens } 308fa9e4066Sahrens 309fa9e4066Sahrens if (dprintf_string == NULL) { 310fa9e4066Sahrens /* Look for ZFS_DEBUG environment variable */ 311fa9e4066Sahrens dprintf_string = getenv("ZFS_DEBUG"); 312fa9e4066Sahrens } 313fa9e4066Sahrens 314fa9e4066Sahrens /* 315fa9e4066Sahrens * Are we just turning on all debugging? 316fa9e4066Sahrens */ 317fa9e4066Sahrens if (dprintf_find_string("on")) 318fa9e4066Sahrens dprintf_print_all = 1; 3197fa49ea5SMatthew Ahrens 3207fa49ea5SMatthew Ahrens if (dprintf_string != NULL) 3217fa49ea5SMatthew Ahrens zfs_flags |= ZFS_DEBUG_DPRINTF; 322fa9e4066Sahrens } 323fa9e4066Sahrens 324fa9e4066Sahrens /* 325fa9e4066Sahrens * ========================================================================= 326fa9e4066Sahrens * debug printfs 327fa9e4066Sahrens * ========================================================================= 328fa9e4066Sahrens */ 329fa9e4066Sahrens void 330fa9e4066Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 331fa9e4066Sahrens { 332fa9e4066Sahrens const char *newfile; 333fa9e4066Sahrens va_list adx; 334fa9e4066Sahrens 335fa9e4066Sahrens /* 336fa9e4066Sahrens * Get rid of annoying "../common/" prefix to filename. 337fa9e4066Sahrens */ 338fa9e4066Sahrens newfile = strrchr(file, '/'); 339fa9e4066Sahrens if (newfile != NULL) { 340fa9e4066Sahrens newfile = newfile + 1; /* Get rid of leading / */ 341fa9e4066Sahrens } else { 342fa9e4066Sahrens newfile = file; 343fa9e4066Sahrens } 344fa9e4066Sahrens 345fa9e4066Sahrens if (dprintf_print_all || 346fa9e4066Sahrens dprintf_find_string(newfile) || 347fa9e4066Sahrens dprintf_find_string(func)) { 348fa9e4066Sahrens /* Print out just the function name if requested */ 349fa9e4066Sahrens flockfile(stdout); 350fa9e4066Sahrens if (dprintf_find_string("pid")) 351fa9e4066Sahrens (void) printf("%d ", getpid()); 352fa9e4066Sahrens if (dprintf_find_string("tid")) 353fa9e4066Sahrens (void) printf("%u ", thr_self()); 354fa9e4066Sahrens if (dprintf_find_string("cpu")) 355fa9e4066Sahrens (void) printf("%u ", getcpuid()); 356fa9e4066Sahrens if (dprintf_find_string("time")) 357fa9e4066Sahrens (void) printf("%llu ", gethrtime()); 358fa9e4066Sahrens if (dprintf_find_string("long")) 359fa9e4066Sahrens (void) printf("%s, line %d: ", newfile, line); 360fa9e4066Sahrens (void) printf("%s: ", func); 361fa9e4066Sahrens va_start(adx, fmt); 362fa9e4066Sahrens (void) vprintf(fmt, adx); 363fa9e4066Sahrens va_end(adx); 364fa9e4066Sahrens funlockfile(stdout); 365fa9e4066Sahrens } 366fa9e4066Sahrens } 367fa9e4066Sahrens 368fa9e4066Sahrens #endif /* ZFS_DEBUG */ 369fa9e4066Sahrens 370ea8dc4b6Seschrock /* 371ea8dc4b6Seschrock * ========================================================================= 372ea8dc4b6Seschrock * kobj interfaces 373ea8dc4b6Seschrock * ========================================================================= 374ea8dc4b6Seschrock */ 375ea8dc4b6Seschrock struct _buf * 376ea8dc4b6Seschrock kobj_open_file(char *name) 377ea8dc4b6Seschrock { 378ea8dc4b6Seschrock struct _buf *file; 379ea8dc4b6Seschrock vnode_t *vp; 380ea8dc4b6Seschrock 381ea8dc4b6Seschrock /* set vp as the _fd field of the file */ 382da6c28aaSamw if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir, 383da6c28aaSamw -1) != 0) 384ea8dc4b6Seschrock return ((void *)-1UL); 385ea8dc4b6Seschrock 386ea8dc4b6Seschrock file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 387ea8dc4b6Seschrock file->_fd = (intptr_t)vp; 388ea8dc4b6Seschrock return (file); 389ea8dc4b6Seschrock } 390ea8dc4b6Seschrock 391ea8dc4b6Seschrock int 392ea8dc4b6Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 393ea8dc4b6Seschrock { 394ea8dc4b6Seschrock ssize_t resid; 395ea8dc4b6Seschrock 396ea8dc4b6Seschrock vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 397ea8dc4b6Seschrock UIO_SYSSPACE, 0, 0, 0, &resid); 398ea8dc4b6Seschrock 399b1b8ab34Slling return (size - resid); 400ea8dc4b6Seschrock } 401ea8dc4b6Seschrock 402ea8dc4b6Seschrock void 403ea8dc4b6Seschrock kobj_close_file(struct _buf *file) 404ea8dc4b6Seschrock { 405ea8dc4b6Seschrock vn_close((vnode_t *)file->_fd); 406ea8dc4b6Seschrock umem_free(file, sizeof (struct _buf)); 407ea8dc4b6Seschrock } 408ea8dc4b6Seschrock 409ea8dc4b6Seschrock int 410b1b8ab34Slling kobj_get_filesize(struct _buf *file, uint64_t *size) 411ea8dc4b6Seschrock { 412ea8dc4b6Seschrock struct stat64 st; 413b1b8ab34Slling vnode_t *vp = (vnode_t *)file->_fd; 414b1b8ab34Slling 415ea8dc4b6Seschrock if (fstat64(vp->v_fd, &st) == -1) { 416ea8dc4b6Seschrock vn_close(vp); 417ea8dc4b6Seschrock return (errno); 418ea8dc4b6Seschrock } 419b1b8ab34Slling *size = st.st_size; 420ea8dc4b6Seschrock return (0); 421ea8dc4b6Seschrock } 422ea8dc4b6Seschrock 423*dd50e0ccSTony Hutter /* 424*dd50e0ccSTony Hutter * ========================================================================= 425*dd50e0ccSTony Hutter * misc routines 426*dd50e0ccSTony Hutter * ========================================================================= 427*dd50e0ccSTony Hutter */ 428*dd50e0ccSTony Hutter 429*dd50e0ccSTony Hutter /* 430*dd50e0ccSTony Hutter * Find lowest one bit set. 431*dd50e0ccSTony Hutter * Returns bit number + 1 of lowest bit that is set, otherwise returns 0. 432*dd50e0ccSTony Hutter * This is basically a reimplementation of ffsll(), which is GNU specific. 433*dd50e0ccSTony Hutter */ 434*dd50e0ccSTony Hutter int 435*dd50e0ccSTony Hutter lowbit64(uint64_t i) 436*dd50e0ccSTony Hutter { 437*dd50e0ccSTony Hutter register int h = 64; 438*dd50e0ccSTony Hutter if (i == 0) 439*dd50e0ccSTony Hutter return (0); 440*dd50e0ccSTony Hutter 441*dd50e0ccSTony Hutter if (i & 0x00000000ffffffffULL) 442*dd50e0ccSTony Hutter h -= 32; 443*dd50e0ccSTony Hutter else 444*dd50e0ccSTony Hutter i >>= 32; 445*dd50e0ccSTony Hutter 446*dd50e0ccSTony Hutter if (i & 0x0000ffff) 447*dd50e0ccSTony Hutter h -= 16; 448*dd50e0ccSTony Hutter else 449*dd50e0ccSTony Hutter i >>= 16; 450*dd50e0ccSTony Hutter 451*dd50e0ccSTony Hutter if (i & 0x00ff) 452*dd50e0ccSTony Hutter h -= 8; 453*dd50e0ccSTony Hutter else 454*dd50e0ccSTony Hutter i >>= 8; 455*dd50e0ccSTony Hutter 456*dd50e0ccSTony Hutter if (i & 0x0f) 457*dd50e0ccSTony Hutter h -= 4; 458*dd50e0ccSTony Hutter else 459*dd50e0ccSTony Hutter i >>= 4; 460*dd50e0ccSTony Hutter 461*dd50e0ccSTony Hutter if (i & 0x3) 462*dd50e0ccSTony Hutter h -= 2; 463*dd50e0ccSTony Hutter else 464*dd50e0ccSTony Hutter i >>= 2; 465*dd50e0ccSTony Hutter 466*dd50e0ccSTony Hutter if (i & 0x1) 467*dd50e0ccSTony Hutter h -= 1; 468*dd50e0ccSTony Hutter 469*dd50e0ccSTony Hutter return (h); 470*dd50e0ccSTony Hutter } 471*dd50e0ccSTony Hutter 472*dd50e0ccSTony Hutter int 473*dd50e0ccSTony Hutter highbit64(uint64_t i) 474*dd50e0ccSTony Hutter { 475*dd50e0ccSTony Hutter int h = 1; 476*dd50e0ccSTony Hutter 477*dd50e0ccSTony Hutter if (i == 0) 478*dd50e0ccSTony Hutter return (0); 479*dd50e0ccSTony Hutter if (i & 0xffffffff00000000ULL) { 480*dd50e0ccSTony Hutter h += 32; i >>= 32; 481*dd50e0ccSTony Hutter } 482*dd50e0ccSTony Hutter if (i & 0xffff0000) { 483*dd50e0ccSTony Hutter h += 16; i >>= 16; 484*dd50e0ccSTony Hutter } 485*dd50e0ccSTony Hutter if (i & 0xff00) { 486*dd50e0ccSTony Hutter h += 8; i >>= 8; 487*dd50e0ccSTony Hutter } 488*dd50e0ccSTony Hutter if (i & 0xf0) { 489*dd50e0ccSTony Hutter h += 4; i >>= 4; 490*dd50e0ccSTony Hutter } 491*dd50e0ccSTony Hutter if (i & 0xc) { 492*dd50e0ccSTony Hutter h += 2; i >>= 2; 493*dd50e0ccSTony Hutter } 494*dd50e0ccSTony Hutter if (i & 0x2) { 495*dd50e0ccSTony Hutter h += 1; 496*dd50e0ccSTony Hutter } 497*dd50e0ccSTony Hutter return (h); 498*dd50e0ccSTony Hutter } 499*dd50e0ccSTony Hutter 500fa9e4066Sahrens /* 501fa9e4066Sahrens * ========================================================================= 502fa9e4066Sahrens * kernel emulation setup & teardown 503fa9e4066Sahrens * ========================================================================= 504fa9e4066Sahrens */ 505fa9e4066Sahrens static int 506fa9e4066Sahrens umem_out_of_memory(void) 507fa9e4066Sahrens { 508fa9e4066Sahrens char errmsg[] = "out of memory -- generating core dump\n"; 509fa9e4066Sahrens 510fa9e4066Sahrens write(fileno(stderr), errmsg, sizeof (errmsg)); 511fa9e4066Sahrens abort(); 512fa9e4066Sahrens return (0); 513fa9e4066Sahrens } 514fa9e4066Sahrens 515fa9e4066Sahrens void 516fa9e4066Sahrens kernel_init(int mode) 517fa9e4066Sahrens { 5183b2aab18SMatthew Ahrens extern uint_t rrw_tsd_key; 5193b2aab18SMatthew Ahrens 520fa9e4066Sahrens umem_nofail_callback(umem_out_of_memory); 521fa9e4066Sahrens 522fa9e4066Sahrens physmem = sysconf(_SC_PHYS_PAGES); 523fa9e4066Sahrens 524fa9e4066Sahrens dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 525fa9e4066Sahrens (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 526fa9e4066Sahrens 5273ad6c7f9SVictor Latushkin (void) snprintf(hw_serial, sizeof (hw_serial), "%ld", 528e0f1c0afSOlaf Faaland (mode & FWRITE) ? get_system_hostid() : 0); 52995173954Sek 53088b7b0f2SMatthew Ahrens system_taskq_init(); 53188b7b0f2SMatthew Ahrens 532283b8460SGeorge.Wilson mutex_init(&cpu_lock, NULL, MUTEX_DEFAULT, NULL); 533283b8460SGeorge.Wilson 534fa9e4066Sahrens spa_init(mode); 5353b2aab18SMatthew Ahrens 5363b2aab18SMatthew Ahrens tsd_create(&rrw_tsd_key, rrw_tsd_destroy); 537fa9e4066Sahrens } 538fa9e4066Sahrens 539fa9e4066Sahrens void 540fa9e4066Sahrens kernel_fini(void) 541fa9e4066Sahrens { 542fa9e4066Sahrens spa_fini(); 54317f17c2dSbonwick 544d20e665cSRicardo M. Correia system_taskq_fini(); 545fa9e4066Sahrens } 546c9431fa1Sahl 5476f793812SPavel Zakharov /* ARGSUSED */ 5486f793812SPavel Zakharov uint32_t 5496f793812SPavel Zakharov zone_get_hostid(void *zonep) 5506f793812SPavel Zakharov { 5516f793812SPavel Zakharov /* 5526f793812SPavel Zakharov * We're emulating the system's hostid in userland. 5536f793812SPavel Zakharov */ 5546f793812SPavel Zakharov return (strtoul(hw_serial, NULL, 10)); 5556f793812SPavel Zakharov } 5566f793812SPavel Zakharov 557c9431fa1Sahl int 558c9431fa1Sahl z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 559c9431fa1Sahl { 560c9431fa1Sahl int ret; 561c9431fa1Sahl uLongf len = *dstlen; 562c9431fa1Sahl 563c9431fa1Sahl if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK) 564c9431fa1Sahl *dstlen = (size_t)len; 565c9431fa1Sahl 566c9431fa1Sahl return (ret); 567c9431fa1Sahl } 568c9431fa1Sahl 569c9431fa1Sahl int 570c9431fa1Sahl z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen, 571c9431fa1Sahl int level) 572c9431fa1Sahl { 573c9431fa1Sahl int ret; 574c9431fa1Sahl uLongf len = *dstlen; 575c9431fa1Sahl 576c9431fa1Sahl if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK) 577c9431fa1Sahl *dstlen = (size_t)len; 578c9431fa1Sahl 579c9431fa1Sahl return (ret); 580c9431fa1Sahl } 581ecd6cf80Smarks 582ecd6cf80Smarks int 583ecd6cf80Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 584ecd6cf80Smarks { 585ecd6cf80Smarks return (0); 586ecd6cf80Smarks } 587ecd6cf80Smarks 588ecd6cf80Smarks int 589ecd6cf80Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 590ecd6cf80Smarks { 591ecd6cf80Smarks return (0); 592ecd6cf80Smarks } 593ecd6cf80Smarks 594ecd6cf80Smarks int 595ecd6cf80Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 596ecd6cf80Smarks { 597ecd6cf80Smarks return (0); 598ecd6cf80Smarks } 599e0d35c44Smarks 600c99e4bdcSChris Kirby /* ARGSUSED */ 601c99e4bdcSChris Kirby int 602a7f53a56SChris Kirby zfs_onexit_fd_hold(int fd, minor_t *minorp) 603a7f53a56SChris Kirby { 604a7f53a56SChris Kirby *minorp = 0; 605a7f53a56SChris Kirby return (0); 606a7f53a56SChris Kirby } 607a7f53a56SChris Kirby 608a7f53a56SChris Kirby /* ARGSUSED */ 609a7f53a56SChris Kirby void 610a7f53a56SChris Kirby zfs_onexit_fd_rele(int fd) 611a7f53a56SChris Kirby { 612a7f53a56SChris Kirby } 613a7f53a56SChris Kirby 614a7f53a56SChris Kirby /* ARGSUSED */ 615a7f53a56SChris Kirby int 616a7f53a56SChris Kirby zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data, 617c99e4bdcSChris Kirby uint64_t *action_handle) 618c99e4bdcSChris Kirby { 619c99e4bdcSChris Kirby return (0); 620c99e4bdcSChris Kirby } 621c99e4bdcSChris Kirby 622c99e4bdcSChris Kirby /* ARGSUSED */ 623c99e4bdcSChris Kirby int 624a7f53a56SChris Kirby zfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire) 625c99e4bdcSChris Kirby { 626c99e4bdcSChris Kirby return (0); 627c99e4bdcSChris Kirby } 628c99e4bdcSChris Kirby 629c99e4bdcSChris Kirby /* ARGSUSED */ 630c99e4bdcSChris Kirby int 631a7f53a56SChris Kirby zfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data) 632c99e4bdcSChris Kirby { 633c99e4bdcSChris Kirby return (0); 634c99e4bdcSChris Kirby } 63531d7e8faSGeorge Wilson 63631d7e8faSGeorge Wilson void 63731d7e8faSGeorge Wilson bioinit(buf_t *bp) 63831d7e8faSGeorge Wilson { 63931d7e8faSGeorge Wilson bzero(bp, sizeof (buf_t)); 64031d7e8faSGeorge Wilson } 64131d7e8faSGeorge Wilson 64231d7e8faSGeorge Wilson void 64331d7e8faSGeorge Wilson biodone(buf_t *bp) 64431d7e8faSGeorge Wilson { 64531d7e8faSGeorge Wilson if (bp->b_iodone != NULL) { 64631d7e8faSGeorge Wilson (*(bp->b_iodone))(bp); 64731d7e8faSGeorge Wilson return; 64831d7e8faSGeorge Wilson } 64931d7e8faSGeorge Wilson ASSERT((bp->b_flags & B_DONE) == 0); 65031d7e8faSGeorge Wilson bp->b_flags |= B_DONE; 65131d7e8faSGeorge Wilson } 65231d7e8faSGeorge Wilson 65331d7e8faSGeorge Wilson void 65431d7e8faSGeorge Wilson bioerror(buf_t *bp, int error) 65531d7e8faSGeorge Wilson { 65631d7e8faSGeorge Wilson ASSERT(bp != NULL); 65731d7e8faSGeorge Wilson ASSERT(error >= 0); 65831d7e8faSGeorge Wilson 65931d7e8faSGeorge Wilson if (error != 0) { 66031d7e8faSGeorge Wilson bp->b_flags |= B_ERROR; 66131d7e8faSGeorge Wilson } else { 66231d7e8faSGeorge Wilson bp->b_flags &= ~B_ERROR; 66331d7e8faSGeorge Wilson } 66431d7e8faSGeorge Wilson bp->b_error = error; 66531d7e8faSGeorge Wilson } 66631d7e8faSGeorge Wilson 66731d7e8faSGeorge Wilson 66831d7e8faSGeorge Wilson int 66931d7e8faSGeorge Wilson geterror(struct buf *bp) 67031d7e8faSGeorge Wilson { 67131d7e8faSGeorge Wilson int error = 0; 67231d7e8faSGeorge Wilson 67331d7e8faSGeorge Wilson if (bp->b_flags & B_ERROR) { 67431d7e8faSGeorge Wilson error = bp->b_error; 67531d7e8faSGeorge Wilson if (!error) 67631d7e8faSGeorge Wilson error = EIO; 67731d7e8faSGeorge Wilson } 67831d7e8faSGeorge Wilson return (error); 67931d7e8faSGeorge Wilson } 680eb633035STom Caputi 681eb633035STom Caputi int 682eb633035STom Caputi crypto_create_ctx_template(crypto_mechanism_t *mech, 683eb633035STom Caputi crypto_key_t *key, crypto_ctx_template_t *tmpl, int kmflag) 684eb633035STom Caputi { 685eb633035STom Caputi return (0); 686eb633035STom Caputi } 687eb633035STom Caputi 688eb633035STom Caputi crypto_mech_type_t 689eb633035STom Caputi crypto_mech2id(crypto_mech_name_t name) 690eb633035STom Caputi { 691eb633035STom Caputi return (CRYPTO_MECH_INVALID); 692eb633035STom Caputi } 693eb633035STom Caputi 694eb633035STom Caputi int 695eb633035STom Caputi crypto_mac(crypto_mechanism_t *mech, crypto_data_t *data, 696eb633035STom Caputi crypto_key_t *key, crypto_ctx_template_t impl, 697eb633035STom Caputi crypto_data_t *mac, crypto_call_req_t *cr) 698eb633035STom Caputi { 699eb633035STom Caputi return (0); 700eb633035STom Caputi } 701eb633035STom Caputi 702eb633035STom Caputi int 703eb633035STom Caputi crypto_encrypt(crypto_mechanism_t *mech, crypto_data_t *plaintext, 704eb633035STom Caputi crypto_key_t *key, crypto_ctx_template_t tmpl, 705eb633035STom Caputi crypto_data_t *ciphertext, crypto_call_req_t *cr) 706eb633035STom Caputi { 707eb633035STom Caputi return (0); 708eb633035STom Caputi } 709eb633035STom Caputi 710eb633035STom Caputi /* This could probably be a weak reference */ 711eb633035STom Caputi int 712eb633035STom Caputi crypto_decrypt(crypto_mechanism_t *mech, crypto_data_t *plaintext, 713eb633035STom Caputi crypto_key_t *key, crypto_ctx_template_t tmpl, 714eb633035STom Caputi crypto_data_t *ciphertext, crypto_call_req_t *cr) 715eb633035STom Caputi { 716eb633035STom Caputi return (0); 717eb633035STom Caputi } 718eb633035STom Caputi 719eb633035STom Caputi 720eb633035STom Caputi int 721eb633035STom Caputi crypto_digest_final(crypto_context_t context, crypto_data_t *digest, 722eb633035STom Caputi crypto_call_req_t *cr) 723eb633035STom Caputi { 724eb633035STom Caputi return (0); 725eb633035STom Caputi } 726eb633035STom Caputi 727eb633035STom Caputi int 728eb633035STom Caputi crypto_digest_update(crypto_context_t context, crypto_data_t *data, 729eb633035STom Caputi crypto_call_req_t *cr) 730eb633035STom Caputi { 731eb633035STom Caputi return (0); 732eb633035STom Caputi } 733eb633035STom Caputi 734eb633035STom Caputi int 735eb633035STom Caputi crypto_digest_init(crypto_mechanism_t *mech, crypto_context_t *ctxp, 736eb633035STom Caputi crypto_call_req_t *crq) 737eb633035STom Caputi { 738eb633035STom Caputi return (0); 739eb633035STom Caputi } 740eb633035STom Caputi 741eb633035STom Caputi void 742eb633035STom Caputi crypto_destroy_ctx_template(crypto_ctx_template_t tmpl) 743eb633035STom Caputi { 744eb633035STom Caputi } 745eb633035STom Caputi 746eb633035STom Caputi extern int crypto_mac_init(crypto_mechanism_t *mech, crypto_key_t *key, 747eb633035STom Caputi crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 748eb633035STom Caputi crypto_call_req_t *cr) 749eb633035STom Caputi { 750eb633035STom Caputi return (0); 751eb633035STom Caputi } 752eb633035STom Caputi 753eb633035STom Caputi extern int crypto_mac_update(crypto_context_t ctx, crypto_data_t *data, 754eb633035STom Caputi crypto_call_req_t *cr) 755eb633035STom Caputi { 756eb633035STom Caputi return (0); 757eb633035STom Caputi } 758eb633035STom Caputi 759eb633035STom Caputi extern int crypto_mac_final(crypto_context_t ctx, crypto_data_t *data, 760eb633035STom Caputi crypto_call_req_t *cr) 761eb633035STom Caputi { 762eb633035STom Caputi return (0); 763eb633035STom Caputi } 764