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 split = (len > 0 ? rand() % len : 0); 430 iolen = pwrite64(vp->v_fd, addr, split, offset); 431 iolen += pwrite64(vp->v_fd, (char *)addr + split, 432 len - split, offset + split); 433 } 434 435 if (iolen == -1) 436 return (errno); 437 if (residp) 438 *residp = len - iolen; 439 else if (iolen != len) 440 return (EIO); 441 return (0); 442 } 443 444 void 445 vn_close(vnode_t *vp) 446 { 447 close(vp->v_fd); 448 spa_strfree(vp->v_path); 449 umem_free(vp, sizeof (vnode_t)); 450 } 451 452 /* 453 * At a minimum we need to update the size since vdev_reopen() 454 * will no longer call vn_openat(). 455 */ 456 int 457 fop_getattr(vnode_t *vp, vattr_t *vap) 458 { 459 struct stat64 st; 460 461 if (fstat64(vp->v_fd, &st) == -1) { 462 close(vp->v_fd); 463 return (errno); 464 } 465 466 vap->va_size = st.st_size; 467 return (0); 468 } 469 470 #ifdef ZFS_DEBUG 471 472 /* 473 * ========================================================================= 474 * Figure out which debugging statements to print 475 * ========================================================================= 476 */ 477 478 static char *dprintf_string; 479 static int dprintf_print_all; 480 481 int 482 dprintf_find_string(const char *string) 483 { 484 char *tmp_str = dprintf_string; 485 int len = strlen(string); 486 487 /* 488 * Find out if this is a string we want to print. 489 * String format: file1.c,function_name1,file2.c,file3.c 490 */ 491 492 while (tmp_str != NULL) { 493 if (strncmp(tmp_str, string, len) == 0 && 494 (tmp_str[len] == ',' || tmp_str[len] == '\0')) 495 return (1); 496 tmp_str = strchr(tmp_str, ','); 497 if (tmp_str != NULL) 498 tmp_str++; /* Get rid of , */ 499 } 500 return (0); 501 } 502 503 void 504 dprintf_setup(int *argc, char **argv) 505 { 506 int i, j; 507 508 /* 509 * Debugging can be specified two ways: by setting the 510 * environment variable ZFS_DEBUG, or by including a 511 * "debug=..." argument on the command line. The command 512 * line setting overrides the environment variable. 513 */ 514 515 for (i = 1; i < *argc; i++) { 516 int len = strlen("debug="); 517 /* First look for a command line argument */ 518 if (strncmp("debug=", argv[i], len) == 0) { 519 dprintf_string = argv[i] + len; 520 /* Remove from args */ 521 for (j = i; j < *argc; j++) 522 argv[j] = argv[j+1]; 523 argv[j] = NULL; 524 (*argc)--; 525 } 526 } 527 528 if (dprintf_string == NULL) { 529 /* Look for ZFS_DEBUG environment variable */ 530 dprintf_string = getenv("ZFS_DEBUG"); 531 } 532 533 /* 534 * Are we just turning on all debugging? 535 */ 536 if (dprintf_find_string("on")) 537 dprintf_print_all = 1; 538 } 539 540 /* 541 * ========================================================================= 542 * debug printfs 543 * ========================================================================= 544 */ 545 void 546 __dprintf(const char *file, const char *func, int line, const char *fmt, ...) 547 { 548 const char *newfile; 549 va_list adx; 550 551 /* 552 * Get rid of annoying "../common/" prefix to filename. 553 */ 554 newfile = strrchr(file, '/'); 555 if (newfile != NULL) { 556 newfile = newfile + 1; /* Get rid of leading / */ 557 } else { 558 newfile = file; 559 } 560 561 if (dprintf_print_all || 562 dprintf_find_string(newfile) || 563 dprintf_find_string(func)) { 564 /* Print out just the function name if requested */ 565 flockfile(stdout); 566 if (dprintf_find_string("pid")) 567 (void) printf("%d ", getpid()); 568 if (dprintf_find_string("tid")) 569 (void) printf("%u ", thr_self()); 570 if (dprintf_find_string("cpu")) 571 (void) printf("%u ", getcpuid()); 572 if (dprintf_find_string("time")) 573 (void) printf("%llu ", gethrtime()); 574 if (dprintf_find_string("long")) 575 (void) printf("%s, line %d: ", newfile, line); 576 (void) printf("%s: ", func); 577 va_start(adx, fmt); 578 (void) vprintf(fmt, adx); 579 va_end(adx); 580 funlockfile(stdout); 581 } 582 } 583 584 #endif /* ZFS_DEBUG */ 585 586 /* 587 * ========================================================================= 588 * cmn_err() and panic() 589 * ========================================================================= 590 */ 591 static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 592 static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 593 594 void 595 vpanic(const char *fmt, va_list adx) 596 { 597 (void) fprintf(stderr, "error: "); 598 (void) vfprintf(stderr, fmt, adx); 599 (void) fprintf(stderr, "\n"); 600 601 abort(); /* think of it as a "user-level crash dump" */ 602 } 603 604 void 605 panic(const char *fmt, ...) 606 { 607 va_list adx; 608 609 va_start(adx, fmt); 610 vpanic(fmt, adx); 611 va_end(adx); 612 } 613 614 void 615 vcmn_err(int ce, const char *fmt, va_list adx) 616 { 617 if (ce == CE_PANIC) 618 vpanic(fmt, adx); 619 if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ 620 (void) fprintf(stderr, "%s", ce_prefix[ce]); 621 (void) vfprintf(stderr, fmt, adx); 622 (void) fprintf(stderr, "%s", ce_suffix[ce]); 623 } 624 } 625 626 /*PRINTFLIKE2*/ 627 void 628 cmn_err(int ce, const char *fmt, ...) 629 { 630 va_list adx; 631 632 va_start(adx, fmt); 633 vcmn_err(ce, fmt, adx); 634 va_end(adx); 635 } 636 637 /* 638 * ========================================================================= 639 * kobj interfaces 640 * ========================================================================= 641 */ 642 struct _buf * 643 kobj_open_file(char *name) 644 { 645 struct _buf *file; 646 vnode_t *vp; 647 648 /* set vp as the _fd field of the file */ 649 if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir, 650 -1) != 0) 651 return ((void *)-1UL); 652 653 file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL); 654 file->_fd = (intptr_t)vp; 655 return (file); 656 } 657 658 int 659 kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off) 660 { 661 ssize_t resid; 662 663 vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off, 664 UIO_SYSSPACE, 0, 0, 0, &resid); 665 666 return (size - resid); 667 } 668 669 void 670 kobj_close_file(struct _buf *file) 671 { 672 vn_close((vnode_t *)file->_fd); 673 umem_free(file, sizeof (struct _buf)); 674 } 675 676 int 677 kobj_get_filesize(struct _buf *file, uint64_t *size) 678 { 679 struct stat64 st; 680 vnode_t *vp = (vnode_t *)file->_fd; 681 682 if (fstat64(vp->v_fd, &st) == -1) { 683 vn_close(vp); 684 return (errno); 685 } 686 *size = st.st_size; 687 return (0); 688 } 689 690 /* 691 * ========================================================================= 692 * misc routines 693 * ========================================================================= 694 */ 695 696 void 697 delay(clock_t ticks) 698 { 699 poll(0, 0, ticks * (1000 / hz)); 700 } 701 702 /* 703 * Find highest one bit set. 704 * Returns bit number + 1 of highest bit that is set, otherwise returns 0. 705 * High order bit is 31 (or 63 in _LP64 kernel). 706 */ 707 int 708 highbit(ulong_t i) 709 { 710 register int h = 1; 711 712 if (i == 0) 713 return (0); 714 #ifdef _LP64 715 if (i & 0xffffffff00000000ul) { 716 h += 32; i >>= 32; 717 } 718 #endif 719 if (i & 0xffff0000) { 720 h += 16; i >>= 16; 721 } 722 if (i & 0xff00) { 723 h += 8; i >>= 8; 724 } 725 if (i & 0xf0) { 726 h += 4; i >>= 4; 727 } 728 if (i & 0xc) { 729 h += 2; i >>= 2; 730 } 731 if (i & 0x2) { 732 h += 1; 733 } 734 return (h); 735 } 736 737 static int random_fd = -1, urandom_fd = -1; 738 739 static int 740 random_get_bytes_common(uint8_t *ptr, size_t len, int fd) 741 { 742 size_t resid = len; 743 ssize_t bytes; 744 745 ASSERT(fd != -1); 746 747 while (resid != 0) { 748 bytes = read(fd, ptr, resid); 749 ASSERT3S(bytes, >=, 0); 750 ptr += bytes; 751 resid -= bytes; 752 } 753 754 return (0); 755 } 756 757 int 758 random_get_bytes(uint8_t *ptr, size_t len) 759 { 760 return (random_get_bytes_common(ptr, len, random_fd)); 761 } 762 763 int 764 random_get_pseudo_bytes(uint8_t *ptr, size_t len) 765 { 766 return (random_get_bytes_common(ptr, len, urandom_fd)); 767 } 768 769 int 770 ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result) 771 { 772 char *end; 773 774 *result = strtoul(hw_serial, &end, base); 775 if (*result == 0) 776 return (errno); 777 return (0); 778 } 779 780 int 781 ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result) 782 { 783 char *end; 784 785 *result = strtoull(str, &end, base); 786 if (*result == 0) 787 return (errno); 788 return (0); 789 } 790 791 /* 792 * ========================================================================= 793 * kernel emulation setup & teardown 794 * ========================================================================= 795 */ 796 static int 797 umem_out_of_memory(void) 798 { 799 char errmsg[] = "out of memory -- generating core dump\n"; 800 801 write(fileno(stderr), errmsg, sizeof (errmsg)); 802 abort(); 803 return (0); 804 } 805 806 void 807 kernel_init(int mode) 808 { 809 umem_nofail_callback(umem_out_of_memory); 810 811 physmem = sysconf(_SC_PHYS_PAGES); 812 813 dprintf("physmem = %llu pages (%.2f GB)\n", physmem, 814 (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 815 816 (void) snprintf(hw_serial, sizeof (hw_serial), "%ld", 817 (mode & FWRITE) ? gethostid() : 0); 818 819 VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1); 820 VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1); 821 822 system_taskq_init(); 823 824 spa_init(mode); 825 } 826 827 void 828 kernel_fini(void) 829 { 830 spa_fini(); 831 832 system_taskq_fini(); 833 834 close(random_fd); 835 close(urandom_fd); 836 837 random_fd = -1; 838 urandom_fd = -1; 839 } 840 841 int 842 z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen) 843 { 844 int ret; 845 uLongf len = *dstlen; 846 847 if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK) 848 *dstlen = (size_t)len; 849 850 return (ret); 851 } 852 853 int 854 z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen, 855 int level) 856 { 857 int ret; 858 uLongf len = *dstlen; 859 860 if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK) 861 *dstlen = (size_t)len; 862 863 return (ret); 864 } 865 866 uid_t 867 crgetuid(cred_t *cr) 868 { 869 return (0); 870 } 871 872 gid_t 873 crgetgid(cred_t *cr) 874 { 875 return (0); 876 } 877 878 int 879 crgetngroups(cred_t *cr) 880 { 881 return (0); 882 } 883 884 gid_t * 885 crgetgroups(cred_t *cr) 886 { 887 return (NULL); 888 } 889 890 int 891 zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) 892 { 893 return (0); 894 } 895 896 int 897 zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) 898 { 899 return (0); 900 } 901 902 int 903 zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) 904 { 905 return (0); 906 } 907 908 ksiddomain_t * 909 ksid_lookupdomain(const char *dom) 910 { 911 ksiddomain_t *kd; 912 913 kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL); 914 kd->kd_name = spa_strdup(dom); 915 return (kd); 916 } 917 918 void 919 ksiddomain_rele(ksiddomain_t *ksid) 920 { 921 spa_strfree(ksid->kd_name); 922 umem_free(ksid, sizeof (ksiddomain_t)); 923 } 924 925 /* 926 * Do not change the length of the returned string; it must be freed 927 * with strfree(). 928 */ 929 char * 930 kmem_asprintf(const char *fmt, ...) 931 { 932 int size; 933 va_list adx; 934 char *buf; 935 936 va_start(adx, fmt); 937 size = vsnprintf(NULL, 0, fmt, adx) + 1; 938 va_end(adx); 939 940 buf = kmem_alloc(size, KM_SLEEP); 941 942 va_start(adx, fmt); 943 size = vsnprintf(buf, size, fmt, adx); 944 va_end(adx); 945 946 return (buf); 947 } 948 949 /* ARGSUSED */ 950 int 951 zfs_onexit_fd_hold(int fd, minor_t *minorp) 952 { 953 *minorp = 0; 954 return (0); 955 } 956 957 /* ARGSUSED */ 958 void 959 zfs_onexit_fd_rele(int fd) 960 { 961 } 962 963 /* ARGSUSED */ 964 int 965 zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data, 966 uint64_t *action_handle) 967 { 968 return (0); 969 } 970 971 /* ARGSUSED */ 972 int 973 zfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire) 974 { 975 return (0); 976 } 977 978 /* ARGSUSED */ 979 int 980 zfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data) 981 { 982 return (0); 983 } 984