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