1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright (c) 2012 by Delphix. All rights reserved. 24 */ 25 26 #include <assert.h> 27 #include <fcntl.h> 28 #include <poll.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <zlib.h> 33 #include <sys/spa.h> 34 #include <sys/stat.h> 35 #include <sys/processor.h> 36 #include <sys/zfs_context.h> 37 #include <sys/zmod.h> 38 #include <sys/utsname.h> 39 #include <sys/systeminfo.h> 40 41 /* 42 * Emulation of kernel services in userland. 43 */ 44 45 int aok; 46 uint64_t physmem; 47 vnode_t *rootdir = (vnode_t *)0xabcd1234; 48 char hw_serial[HW_HOSTID_LEN]; 49 vmem_t *zio_arena = NULL; 50 51 struct utsname utsname = { 52 "userland", "libzpool", "1", "1", "na" 53 }; 54 55 /* this only exists to have its address taken */ 56 struct proc p0; 57 58 /* 59 * ========================================================================= 60 * threads 61 * ========================================================================= 62 */ 63 /*ARGSUSED*/ 64 kthread_t * 65 zk_thread_create(void (*func)(), void *arg) 66 { 67 thread_t tid; 68 69 VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED, 70 &tid) == 0); 71 72 return ((void *)(uintptr_t)tid); 73 } 74 75 /* 76 * ========================================================================= 77 * kstats 78 * ========================================================================= 79 */ 80 /*ARGSUSED*/ 81 kstat_t * 82 kstat_create(char *module, int instance, char *name, char *class, 83 uchar_t type, ulong_t ndata, uchar_t ks_flag) 84 { 85 return (NULL); 86 } 87 88 /*ARGSUSED*/ 89 void 90 kstat_install(kstat_t *ksp) 91 {} 92 93 /*ARGSUSED*/ 94 void 95 kstat_delete(kstat_t *ksp) 96 {} 97 98 /* 99 * ========================================================================= 100 * mutexes 101 * ========================================================================= 102 */ 103 void 104 zmutex_init(kmutex_t *mp) 105 { 106 mp->m_owner = NULL; 107 mp->initialized = B_TRUE; 108 (void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL); 109 } 110 111 void 112 zmutex_destroy(kmutex_t *mp) 113 { 114 ASSERT(mp->initialized == B_TRUE); 115 ASSERT(mp->m_owner == NULL); 116 (void) _mutex_destroy(&(mp)->m_lock); 117 mp->m_owner = (void *)-1UL; 118 mp->initialized = B_FALSE; 119 } 120 121 void 122 mutex_enter(kmutex_t *mp) 123 { 124 ASSERT(mp->initialized == B_TRUE); 125 ASSERT(mp->m_owner != (void *)-1UL); 126 ASSERT(mp->m_owner != curthread); 127 VERIFY(mutex_lock(&mp->m_lock) == 0); 128 ASSERT(mp->m_owner == NULL); 129 mp->m_owner = curthread; 130 } 131 132 int 133 mutex_tryenter(kmutex_t *mp) 134 { 135 ASSERT(mp->initialized == B_TRUE); 136 ASSERT(mp->m_owner != (void *)-1UL); 137 if (0 == mutex_trylock(&mp->m_lock)) { 138 ASSERT(mp->m_owner == NULL); 139 mp->m_owner = curthread; 140 return (1); 141 } else { 142 return (0); 143 } 144 } 145 146 void 147 mutex_exit(kmutex_t *mp) 148 { 149 ASSERT(mp->initialized == B_TRUE); 150 ASSERT(mutex_owner(mp) == curthread); 151 mp->m_owner = NULL; 152 VERIFY(mutex_unlock(&mp->m_lock) == 0); 153 } 154 155 void * 156 mutex_owner(kmutex_t *mp) 157 { 158 ASSERT(mp->initialized == B_TRUE); 159 return (mp->m_owner); 160 } 161 162 /* 163 * ========================================================================= 164 * rwlocks 165 * ========================================================================= 166 */ 167 /*ARGSUSED*/ 168 void 169 rw_init(krwlock_t *rwlp, char *name, int type, void *arg) 170 { 171 rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL); 172 rwlp->rw_owner = NULL; 173 rwlp->initialized = B_TRUE; 174 } 175 176 void 177 rw_destroy(krwlock_t *rwlp) 178 { 179 rwlock_destroy(&rwlp->rw_lock); 180 rwlp->rw_owner = (void *)-1UL; 181 rwlp->initialized = B_FALSE; 182 } 183 184 void 185 rw_enter(krwlock_t *rwlp, krw_t rw) 186 { 187 ASSERT(!RW_LOCK_HELD(rwlp)); 188 ASSERT(rwlp->initialized == B_TRUE); 189 ASSERT(rwlp->rw_owner != (void *)-1UL); 190 ASSERT(rwlp->rw_owner != curthread); 191 192 if (rw == RW_READER) 193 VERIFY(rw_rdlock(&rwlp->rw_lock) == 0); 194 else 195 VERIFY(rw_wrlock(&rwlp->rw_lock) == 0); 196 197 rwlp->rw_owner = curthread; 198 } 199 200 void 201 rw_exit(krwlock_t *rwlp) 202 { 203 ASSERT(rwlp->initialized == B_TRUE); 204 ASSERT(rwlp->rw_owner != (void *)-1UL); 205 206 rwlp->rw_owner = NULL; 207 VERIFY(rw_unlock(&rwlp->rw_lock) == 0); 208 } 209 210 int 211 rw_tryenter(krwlock_t *rwlp, krw_t rw) 212 { 213 int rv; 214 215 ASSERT(rwlp->initialized == B_TRUE); 216 ASSERT(rwlp->rw_owner != (void *)-1UL); 217 218 if (rw == RW_READER) 219 rv = rw_tryrdlock(&rwlp->rw_lock); 220 else 221 rv = rw_trywrlock(&rwlp->rw_lock); 222 223 if (rv == 0) { 224 rwlp->rw_owner = curthread; 225 return (1); 226 } 227 228 return (0); 229 } 230 231 /*ARGSUSED*/ 232 int 233 rw_tryupgrade(krwlock_t *rwlp) 234 { 235 ASSERT(rwlp->initialized == B_TRUE); 236 ASSERT(rwlp->rw_owner != (void *)-1UL); 237 238 return (0); 239 } 240 241 /* 242 * ========================================================================= 243 * condition variables 244 * ========================================================================= 245 */ 246 /*ARGSUSED*/ 247 void 248 cv_init(kcondvar_t *cv, char *name, int type, void *arg) 249 { 250 VERIFY(cond_init(cv, type, NULL) == 0); 251 } 252 253 void 254 cv_destroy(kcondvar_t *cv) 255 { 256 VERIFY(cond_destroy(cv) == 0); 257 } 258 259 void 260 cv_wait(kcondvar_t *cv, kmutex_t *mp) 261 { 262 ASSERT(mutex_owner(mp) == curthread); 263 mp->m_owner = NULL; 264 int ret = cond_wait(cv, &mp->m_lock); 265 VERIFY(ret == 0 || ret == EINTR); 266 mp->m_owner = curthread; 267 } 268 269 clock_t 270 cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) 271 { 272 int error; 273 timestruc_t ts; 274 clock_t delta; 275 276 top: 277 delta = abstime - ddi_get_lbolt(); 278 if (delta <= 0) 279 return (-1); 280 281 ts.tv_sec = delta / hz; 282 ts.tv_nsec = (delta % hz) * (NANOSEC / hz); 283 284 ASSERT(mutex_owner(mp) == curthread); 285 mp->m_owner = NULL; 286 error = cond_reltimedwait(cv, &mp->m_lock, &ts); 287 mp->m_owner = curthread; 288 289 if (error == ETIME) 290 return (-1); 291 292 if (error == EINTR) 293 goto top; 294 295 ASSERT(error == 0); 296 297 return (1); 298 } 299 300 void 301 cv_signal(kcondvar_t *cv) 302 { 303 VERIFY(cond_signal(cv) == 0); 304 } 305 306 void 307 cv_broadcast(kcondvar_t *cv) 308 { 309 VERIFY(cond_broadcast(cv) == 0); 310 } 311 312 /* 313 * ========================================================================= 314 * vnode operations 315 * ========================================================================= 316 */ 317 /* 318 * Note: for the xxxat() versions of these functions, we assume that the 319 * starting vp is always rootdir (which is true for spa_directory.c, the only 320 * ZFS consumer of these interfaces). We assert this is true, and then emulate 321 * them by adding '/' in front of the path. 322 */ 323 324 /*ARGSUSED*/ 325 int 326 vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) 327 { 328 int fd; 329 vnode_t *vp; 330 int old_umask; 331 char realpath[MAXPATHLEN]; 332 struct stat64 st; 333 334 /* 335 * If we're accessing a real disk from userland, we need to use 336 * the character interface to avoid caching. This is particularly 337 * important if we're trying to look at a real in-kernel storage 338 * pool from userland, e.g. via zdb, because otherwise we won't 339 * see the changes occurring under the segmap cache. 340 * On the other hand, the stupid character device returns zero 341 * for its size. So -- gag -- we open the block device to get 342 * its size, and remember it for subsequent VOP_GETATTR(). 343 */ 344 if (strncmp(path, "/dev/", 5) == 0) { 345 char *dsk; 346 fd = open64(path, O_RDONLY); 347 if (fd == -1) 348 return (errno); 349 if (fstat64(fd, &st) == -1) { 350 close(fd); 351 return (errno); 352 } 353 close(fd); 354 (void) sprintf(realpath, "%s", path); 355 dsk = strstr(path, "/dsk/"); 356 if (dsk != NULL) 357 (void) sprintf(realpath + (dsk - path) + 1, "r%s", 358 dsk + 1); 359 } else { 360 (void) sprintf(realpath, "%s", path); 361 if (!(flags & FCREAT) && stat64(realpath, &st) == -1) 362 return (errno); 363 } 364 365 if (flags & FCREAT) 366 old_umask = umask(0); 367 368 /* 369 * The construct 'flags - FREAD' conveniently maps combinations of 370 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. 371 */ 372 fd = open64(realpath, flags - FREAD, mode); 373 374 if (flags & FCREAT) 375 (void) umask(old_umask); 376 377 if (fd == -1) 378 return (errno); 379 380 if (fstat64(fd, &st) == -1) { 381 close(fd); 382 return (errno); 383 } 384 385 (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 386 387 *vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL); 388 389 vp->v_fd = fd; 390 vp->v_size = st.st_size; 391 vp->v_path = spa_strdup(path); 392 393 return (0); 394 } 395 396 /*ARGSUSED*/ 397 int 398 vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, 399 int x3, vnode_t *startvp, int fd) 400 { 401 char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL); 402 int ret; 403 404 ASSERT(startvp == rootdir); 405 (void) sprintf(realpath, "/%s", path); 406 407 /* fd ignored for now, need if want to simulate nbmand support */ 408 ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3); 409 410 umem_free(realpath, strlen(path) + 2); 411 412 return (ret); 413 } 414 415 /*ARGSUSED*/ 416 int 417 vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, 418 int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) 419 { 420 ssize_t iolen, split; 421 422 if (uio == UIO_READ) { 423 iolen = pread64(vp->v_fd, addr, len, offset); 424 } else { 425 /* 426 * To simulate partial disk writes, we split writes into two 427 * system calls so that the process can be killed in between. 428 */ 429 int sectors = len >> SPA_MINBLOCKSHIFT; 430 split = (sectors > 0 ? rand() % sectors : 0) << 431 SPA_MINBLOCKSHIFT; 432 iolen = pwrite64(vp->v_fd, addr, split, offset); 433 iolen += pwrite64(vp->v_fd, (char *)addr + split, 434 len - split, offset + split); 435 } 436 437 if (iolen == -1) 438 return (errno); 439 if (residp) 440 *residp = len - iolen; 441 else if (iolen != len) 442 return (EIO); 443 return (0); 444 } 445 446 void 447 vn_close(vnode_t *vp) 448 { 449 close(vp->v_fd); 450 spa_strfree(vp->v_path); 451 umem_free(vp, sizeof (vnode_t)); 452 } 453 454 /* 455 * At a minimum we need to update the size since vdev_reopen() 456 * will no longer call vn_openat(). 457 */ 458 int 459 fop_getattr(vnode_t *vp, vattr_t *vap) 460 { 461 struct stat64 st; 462 463 if (fstat64(vp->v_fd, &st) == -1) { 464 close(vp->v_fd); 465 return (errno); 466 } 467 468 vap->va_size = st.st_size; 469 return (0); 470 } 471 472 #ifdef ZFS_DEBUG 473 474 /* 475 * ========================================================================= 476 * Figure out which debugging statements to print 477 * ========================================================================= 478 */ 479 480 static char *dprintf_string; 481 static int dprintf_print_all; 482 483 int 484 dprintf_find_string(const char *string) 485 { 486 char *tmp_str = dprintf_string; 487 int len = strlen(string); 488 489 /* 490 * Find out if this is a string we want to print. 491 * String format: file1.c,function_name1,file2.c,file3.c 492 */ 493 494 while (tmp_str != NULL) { 495 if (strncmp(tmp_str, string, len) == 0 && 496 (tmp_str[len] == ',' || tmp_str[len] == '\0')) 497 return (1); 498 tmp_str = strchr(tmp_str, ','); 499 if (tmp_str != NULL) 500 tmp_str++; /* Get rid of , */ 501 } 502 return (0); 503 } 504 505 void 506 dprintf_setup(int *argc, char **argv) 507 { 508 int i, j; 509 510 /* 511 * Debugging can be specified two ways: by setting the 512 * environment variable ZFS_DEBUG, or by including a 513 * "debug=..." argument on the command line. The command 514 * line setting overrides the environment variable. 515 */ 516 517 for (i = 1; i < *argc; i++) { 518 int len = strlen("debug="); 519 /* First look for a command line argument */ 520 if (strncmp("debug=", argv[i], len) == 0) { 521 dprintf_string = argv[i] + len; 522 /* Remove from args */ 523 for (j = i; j < *argc; j++) 524 argv[j] = argv[j+1]; 525 argv[j] = NULL; 526 (*argc)--; 527 } 528 } 529 530 if (dprintf_string == NULL) { 531 /* Look for ZFS_DEBUG environment variable */ 532 dprintf_string = getenv("ZFS_DEBUG"); 533 } 534 535 /* 536 * Are we just turning on all debugging? 537 */ 538 if (dprintf_find_string("on")) 539 dprintf_print_all = 1; 540 } 541 542 /* 543 * ========================================================================= 544 * debug printfs 545 * ========================================================================= 546 */ 547 void 548 __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 549 { 550 const char *newfile; 551 va_list adx; 552 553 /* 554 * Get rid of annoying "../common/" prefix to filename. 555 */ 556 newfile = strrchr(file, '/'); 557 if (newfile != NULL) { 558 newfile = newfile + 1; /* Get rid of leading / */ 559 } else { 560 newfile = file; 561 } 562 563 if (dprintf_print_all || 564 dprintf_find_string(newfile) || 565 dprintf_find_string(func)) { 566 /* Print out just the function name if requested */ 567 flockfile(stdout); 568 if (dprintf_find_string("pid")) 569 (void) printf("%d ", getpid()); 570 if (dprintf_find_string("tid")) 571 (void) printf("%u ", thr_self()); 572 if (dprintf_find_string("cpu")) 573 (void) printf("%u ", getcpuid()); 574 if (dprintf_find_string("time")) 575 (void) printf("%llu ", gethrtime()); 576 if (dprintf_find_string("long")) 577 (void) printf("%s, line %d: ", newfile, line); 578 (void) printf("%s: ", func); 579 va_start(adx, fmt); 580 (void) vprintf(fmt, adx); 581 va_end(adx); 582 funlockfile(stdout); 583 } 584 } 585 586 #endif /* ZFS_DEBUG */ 587 588 /* 589 * ========================================================================= 590 * cmn_err() and panic() 591 * ========================================================================= 592 */ 593 static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 594 static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 595 596 void 597 vpanic(const char *fmt, va_list adx) 598 { 599 (void) fprintf(stderr, "error: "); 600 (void) vfprintf(stderr, fmt, adx); 601 (void) fprintf(stderr, "\n"); 602 603 abort(); /* think of it as a "user-level crash dump" */ 604 } 605 606 void 607 panic(const char *fmt, ...) 608 { 609 va_list adx; 610 611 va_start(adx, fmt); 612 vpanic(fmt, adx); 613 va_end(adx); 614 } 615 616 void 617 vcmn_err(int ce, const char *fmt, va_list adx) 618 { 619 if (ce == CE_PANIC) 620 vpanic(fmt, adx); 621 if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ 622 (void) fprintf(stderr, "%s", ce_prefix[ce]); 623 (void) vfprintf(stderr, fmt, adx); 624 (void) fprintf(stderr, "%s", ce_suffix[ce]); 625 } 626 } 627 628 /*PRINTFLIKE2*/ 629 void 630 cmn_err(int ce, const char *fmt, ...) 631 { 632 va_list adx; 633 634 va_start(adx, fmt); 635 vcmn_err(ce, fmt, adx); 636 va_end(adx); 637 } 638 639 /* 640 * ========================================================================= 641 * kobj interfaces 642 * ========================================================================= 643 */ 644 struct _buf * 645 kobj_open_file(char *name) 646 { 647 struct _buf *file; 648 vnode_t *vp; 649 650 /* set vp as the _fd field of the file */ 651 if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir, 652 -1) != 0) 653 return ((void *)-1UL); 654 655 file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 656 file->_fd = (intptr_t)vp; 657 return (file); 658 } 659 660 int 661 kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 662 { 663 ssize_t resid; 664 665 vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 666 UIO_SYSSPACE, 0, 0, 0, &resid); 667 668 return (size - resid); 669 } 670 671 void 672 kobj_close_file(struct _buf *file) 673 { 674 vn_close((vnode_t *)file->_fd); 675 umem_free(file, sizeof (struct _buf)); 676 } 677 678 int 679 kobj_get_filesize(struct _buf *file, uint64_t *size) 680 { 681 struct stat64 st; 682 vnode_t *vp = (vnode_t *)file->_fd; 683 684 if (fstat64(vp->v_fd, &st) == -1) { 685 vn_close(vp); 686 return (errno); 687 } 688 *size = st.st_size; 689 return (0); 690 } 691 692 /* 693 * ========================================================================= 694 * misc routines 695 * ========================================================================= 696 */ 697 698 void 699 delay(clock_t ticks) 700 { 701 poll(0, 0, ticks * (1000 / hz)); 702 } 703 704 /* 705 * Find highest one bit set. 706 * Returns bit number + 1 of highest bit that is set, otherwise returns 0. 707 * High order bit is 31 (or 63 in _LP64 kernel). 708 */ 709 int 710 highbit(ulong_t i) 711 { 712 register int h = 1; 713 714 if (i == 0) 715 return (0); 716 #ifdef _LP64 717 if (i & 0xffffffff00000000ul) { 718 h += 32; i >>= 32; 719 } 720 #endif 721 if (i & 0xffff0000) { 722 h += 16; i >>= 16; 723 } 724 if (i & 0xff00) { 725 h += 8; i >>= 8; 726 } 727 if (i & 0xf0) { 728 h += 4; i >>= 4; 729 } 730 if (i & 0xc) { 731 h += 2; i >>= 2; 732 } 733 if (i & 0x2) { 734 h += 1; 735 } 736 return (h); 737 } 738 739 static int random_fd = -1, urandom_fd = -1; 740 741 static int 742 random_get_bytes_common(uint8_t *ptr, size_t len, int fd) 743 { 744 size_t resid = len; 745 ssize_t bytes; 746 747 ASSERT(fd != -1); 748 749 while (resid != 0) { 750 bytes = read(fd, ptr, resid); 751 ASSERT3S(bytes, >=, 0); 752 ptr += bytes; 753 resid -= bytes; 754 } 755 756 return (0); 757 } 758 759 int 760 random_get_bytes(uint8_t *ptr, size_t len) 761 { 762 return (random_get_bytes_common(ptr, len, random_fd)); 763 } 764 765 int 766 random_get_pseudo_bytes(uint8_t *ptr, size_t len) 767 { 768 return (random_get_bytes_common(ptr, len, urandom_fd)); 769 } 770 771 int 772 ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result) 773 { 774 char *end; 775 776 *result = strtoul(hw_serial, &end, base); 777 if (*result == 0) 778 return (errno); 779 return (0); 780 } 781 782 int 783 ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result) 784 { 785 char *end; 786 787 *result = strtoull(str, &end, base); 788 if (*result == 0) 789 return (errno); 790 return (0); 791 } 792 793 /* 794 * ========================================================================= 795 * kernel emulation setup & teardown 796 * ========================================================================= 797 */ 798 static int 799 umem_out_of_memory(void) 800 { 801 char errmsg[] = "out of memory -- generating core dump\n"; 802 803 write(fileno(stderr), errmsg, sizeof (errmsg)); 804 abort(); 805 return (0); 806 } 807 808 void 809 kernel_init(int mode) 810 { 811 umem_nofail_callback(umem_out_of_memory); 812 813 physmem = sysconf(_SC_PHYS_PAGES); 814 815 dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 816 (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 817 818 (void) snprintf(hw_serial, sizeof (hw_serial), "%ld", 819 (mode & FWRITE) ? gethostid() : 0); 820 821 VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1); 822 VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1); 823 824 system_taskq_init(); 825 826 spa_init(mode); 827 } 828 829 void 830 kernel_fini(void) 831 { 832 spa_fini(); 833 834 system_taskq_fini(); 835 836 close(random_fd); 837 close(urandom_fd); 838 839 random_fd = -1; 840 urandom_fd = -1; 841 } 842 843 int 844 z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 845 { 846 int ret; 847 uLongf len = *dstlen; 848 849 if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK) 850 *dstlen = (size_t)len; 851 852 return (ret); 853 } 854 855 int 856 z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen, 857 int level) 858 { 859 int ret; 860 uLongf len = *dstlen; 861 862 if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK) 863 *dstlen = (size_t)len; 864 865 return (ret); 866 } 867 868 uid_t 869 crgetuid(cred_t *cr) 870 { 871 return (0); 872 } 873 874 gid_t 875 crgetgid(cred_t *cr) 876 { 877 return (0); 878 } 879 880 int 881 crgetngroups(cred_t *cr) 882 { 883 return (0); 884 } 885 886 gid_t * 887 crgetgroups(cred_t *cr) 888 { 889 return (NULL); 890 } 891 892 int 893 zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 894 { 895 return (0); 896 } 897 898 int 899 zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 900 { 901 return (0); 902 } 903 904 int 905 zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 906 { 907 return (0); 908 } 909 910 ksiddomain_t * 911 ksid_lookupdomain(const char *dom) 912 { 913 ksiddomain_t *kd; 914 915 kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL); 916 kd->kd_name = spa_strdup(dom); 917 return (kd); 918 } 919 920 void 921 ksiddomain_rele(ksiddomain_t *ksid) 922 { 923 spa_strfree(ksid->kd_name); 924 umem_free(ksid, sizeof (ksiddomain_t)); 925 } 926 927 /* 928 * Do not change the length of the returned string; it must be freed 929 * with strfree(). 930 */ 931 char * 932 kmem_asprintf(const char *fmt, ...) 933 { 934 int size; 935 va_list adx; 936 char *buf; 937 938 va_start(adx, fmt); 939 size = vsnprintf(NULL, 0, fmt, adx) + 1; 940 va_end(adx); 941 942 buf = kmem_alloc(size, KM_SLEEP); 943 944 va_start(adx, fmt); 945 size = vsnprintf(buf, size, fmt, adx); 946 va_end(adx); 947 948 return (buf); 949 } 950 951 /* ARGSUSED */ 952 int 953 zfs_onexit_fd_hold(int fd, minor_t *minorp) 954 { 955 *minorp = 0; 956 return (0); 957 } 958 959 /* ARGSUSED */ 960 void 961 zfs_onexit_fd_rele(int fd) 962 { 963 } 964 965 /* ARGSUSED */ 966 int 967 zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data, 968 uint64_t *action_handle) 969 { 970 return (0); 971 } 972 973 /* ARGSUSED */ 974 int 975 zfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire) 976 { 977 return (0); 978 } 979 980 /* ARGSUSED */ 981 int 982 zfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data) 983 { 984 return (0); 985 }