1 // SPDX-License-Identifier: CDDL-1.0 2 /* 3 * CDDL HEADER START 4 * 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License (the "License"). 7 * You may not use this file except in compliance with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or https://opensource.org/licenses/CDDL-1.0. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright (c) 2012, 2018 by Delphix. All rights reserved. 25 * Copyright (c) 2016 Actifio, Inc. All rights reserved. 26 * Copyright (c) 2025, Klara, Inc. 27 */ 28 29 #include <assert.h> 30 #include <fcntl.h> 31 #include <libgen.h> 32 #include <poll.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <limits.h> 37 #include <libzutil.h> 38 #include <sys/crypto/icp.h> 39 #include <sys/processor.h> 40 #include <sys/rrwlock.h> 41 #include <sys/spa.h> 42 #include <sys/spa_impl.h> 43 #include <sys/sid.h> 44 #include <sys/stat.h> 45 #include <sys/systeminfo.h> 46 #include <sys/time.h> 47 #include <sys/tsd.h> 48 49 #include <libspl.h> 50 #include <libzpool.h> 51 #include <sys/zfs_context.h> 52 #include <sys/zfs_onexit.h> 53 #include <sys/zfs_vfsops.h> 54 #include <sys/zstd/zstd.h> 55 #include <sys/zvol.h> 56 #include <zfs_fletcher.h> 57 #include <zlib.h> 58 59 /* 60 * Emulation of kernel services in userland. 61 */ 62 63 uint32_t hostid; 64 65 uint32_t 66 zone_get_hostid(void *zonep) 67 { 68 /* 69 * We're emulating the system's hostid in userland. 70 */ 71 (void) zonep; 72 return (hostid); 73 } 74 75 /* 76 * ========================================================================= 77 * vnode operations 78 * ========================================================================= 79 */ 80 81 /* 82 * ========================================================================= 83 * Figure out which debugging statements to print 84 * ========================================================================= 85 */ 86 87 static char *dprintf_string; 88 static int dprintf_print_all; 89 90 int 91 dprintf_find_string(const char *string) 92 { 93 char *tmp_str = dprintf_string; 94 int len = strlen(string); 95 96 /* 97 * Find out if this is a string we want to print. 98 * String format: file1.c,function_name1,file2.c,file3.c 99 */ 100 101 while (tmp_str != NULL) { 102 if (strncmp(tmp_str, string, len) == 0 && 103 (tmp_str[len] == ',' || tmp_str[len] == '\0')) 104 return (1); 105 tmp_str = strchr(tmp_str, ','); 106 if (tmp_str != NULL) 107 tmp_str++; /* Get rid of , */ 108 } 109 return (0); 110 } 111 112 void 113 dprintf_setup(int *argc, char **argv) 114 { 115 int i, j; 116 117 /* 118 * Debugging can be specified two ways: by setting the 119 * environment variable ZFS_DEBUG, or by including a 120 * "debug=..." argument on the command line. The command 121 * line setting overrides the environment variable. 122 */ 123 124 for (i = 1; i < *argc; i++) { 125 int len = strlen("debug="); 126 /* First look for a command line argument */ 127 if (strncmp("debug=", argv[i], len) == 0) { 128 dprintf_string = argv[i] + len; 129 /* Remove from args */ 130 for (j = i; j < *argc; j++) 131 argv[j] = argv[j+1]; 132 argv[j] = NULL; 133 (*argc)--; 134 } 135 } 136 137 if (dprintf_string == NULL) { 138 /* Look for ZFS_DEBUG environment variable */ 139 dprintf_string = getenv("ZFS_DEBUG"); 140 } 141 142 /* 143 * Are we just turning on all debugging? 144 */ 145 if (dprintf_find_string("on")) 146 dprintf_print_all = 1; 147 148 if (dprintf_string != NULL) 149 zfs_flags |= ZFS_DEBUG_DPRINTF; 150 } 151 152 /* 153 * ========================================================================= 154 * debug printfs 155 * ========================================================================= 156 */ 157 void 158 __dprintf(boolean_t dprint, const char *file, const char *func, 159 int line, const char *fmt, ...) 160 { 161 /* Get rid of annoying "../common/" prefix to filename. */ 162 const char *newfile = zfs_basename(file); 163 164 va_list adx; 165 if (dprint) { 166 /* dprintf messages are printed immediately */ 167 168 if (!dprintf_print_all && 169 !dprintf_find_string(newfile) && 170 !dprintf_find_string(func)) 171 return; 172 173 /* Print out just the function name if requested */ 174 flockfile(stdout); 175 if (dprintf_find_string("pid")) 176 (void) printf("%d ", getpid()); 177 if (dprintf_find_string("tid")) 178 (void) printf("%ju ", 179 (uintmax_t)(uintptr_t)pthread_self()); 180 if (dprintf_find_string("cpu")) 181 (void) printf("%u ", getcpuid()); 182 if (dprintf_find_string("time")) 183 (void) printf("%llu ", gethrtime()); 184 if (dprintf_find_string("long")) 185 (void) printf("%s, line %d: ", newfile, line); 186 (void) printf("dprintf: %s: ", func); 187 va_start(adx, fmt); 188 (void) vprintf(fmt, adx); 189 va_end(adx); 190 funlockfile(stdout); 191 } else { 192 /* zfs_dbgmsg is logged for dumping later */ 193 size_t size; 194 char *buf; 195 int i; 196 197 size = 1024; 198 buf = umem_alloc(size, UMEM_NOFAIL); 199 i = snprintf(buf, size, "%s:%d:%s(): ", newfile, line, func); 200 201 if (i < size) { 202 va_start(adx, fmt); 203 (void) vsnprintf(buf + i, size - i, fmt, adx); 204 va_end(adx); 205 } 206 207 __zfs_dbgmsg(buf); 208 209 umem_free(buf, size); 210 } 211 } 212 213 /* 214 * ========================================================================= 215 * cmn_err() and panic() 216 * ========================================================================= 217 */ 218 219 static __attribute__((noreturn)) void 220 panic_stop_or_abort(void) 221 { 222 const char *stopenv = getenv("LIBZPOOL_PANIC_STOP"); 223 if (stopenv != NULL && atoi(stopenv)) { 224 fputs("libzpool: LIBZPOOL_PANIC_STOP is set, sending " 225 "SIGSTOP to process group\n", stderr); 226 fflush(stderr); 227 228 kill(0, SIGSTOP); 229 230 fputs("libzpool: continued after panic stop, " 231 "aborting\n", stderr); 232 } 233 234 abort(); /* think of it as a "user-level crash dump" */ 235 } 236 237 static void 238 vcmn_msg(int ce, const char *fmt, va_list adx) 239 { 240 switch (ce) { 241 case CE_IGNORE: 242 return; 243 case CE_CONT: 244 break; 245 case CE_NOTE: 246 fputs("libzpool: NOTICE: ", stderr); 247 break; 248 case CE_WARN: 249 fputs("libzpool: WARNING: ", stderr); 250 break; 251 case CE_PANIC: 252 fputs("libzpool: PANIC: ", stderr); 253 break; 254 default: 255 fputs("libzpool: [unknown severity %d]: ", stderr); 256 break; 257 } 258 259 vfprintf(stderr, fmt, adx); 260 if (ce != CE_CONT) 261 fputc('\n', stderr); 262 fflush(stderr); 263 } 264 265 void 266 vcmn_err(int ce, const char *fmt, va_list adx) 267 { 268 vcmn_msg(ce, fmt, adx); 269 270 if (ce == CE_PANIC) 271 panic_stop_or_abort(); 272 } 273 274 void 275 cmn_err(int ce, const char *fmt, ...) 276 { 277 va_list adx; 278 279 va_start(adx, fmt); 280 vcmn_err(ce, fmt, adx); 281 va_end(adx); 282 } 283 284 __attribute__((noreturn)) void 285 panic(const char *fmt, ...) 286 { 287 va_list adx; 288 289 va_start(adx, fmt); 290 vcmn_msg(CE_PANIC, fmt, adx); 291 va_end(adx); 292 293 panic_stop_or_abort(); 294 } 295 296 __attribute__((noreturn)) void 297 vpanic(const char *fmt, va_list adx) 298 { 299 vcmn_msg(CE_PANIC, fmt, adx); 300 panic_stop_or_abort(); 301 } 302 303 /* 304 * ========================================================================= 305 * misc routines 306 * ========================================================================= 307 */ 308 309 void 310 delay(clock_t ticks) 311 { 312 (void) poll(0, 0, ticks * (1000 / hz)); 313 } 314 315 int 316 ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result) 317 { 318 errno = 0; 319 *result = strtoull(str, nptr, base); 320 if (*result == 0) 321 return (errno); 322 return (0); 323 } 324 325 /* 326 * ========================================================================= 327 * kernel emulation setup & teardown 328 * ========================================================================= 329 */ 330 static int 331 umem_out_of_memory(void) 332 { 333 char errmsg[] = "out of memory -- generating core dump\n"; 334 335 (void) fprintf(stderr, "%s", errmsg); 336 abort(); 337 return (0); 338 } 339 340 static void 341 spa_config_load(void) 342 { 343 void *buf = NULL; 344 nvlist_t *nvlist, *child; 345 nvpair_t *nvpair; 346 char *pathname; 347 zfs_file_t *fp; 348 zfs_file_attr_t zfa; 349 uint64_t fsize; 350 int err; 351 352 /* 353 * Open the configuration file. 354 */ 355 pathname = kmem_alloc(MAXPATHLEN, KM_SLEEP); 356 357 (void) snprintf(pathname, MAXPATHLEN, "%s", spa_config_path); 358 359 err = zfs_file_open(pathname, O_RDONLY, 0, &fp); 360 if (err) 361 err = zfs_file_open(ZPOOL_CACHE_BOOT, O_RDONLY, 0, &fp); 362 363 kmem_free(pathname, MAXPATHLEN); 364 365 if (err) 366 return; 367 368 if (zfs_file_getattr(fp, &zfa)) 369 goto out; 370 371 fsize = zfa.zfa_size; 372 buf = kmem_alloc(fsize, KM_SLEEP); 373 374 /* 375 * Read the nvlist from the file. 376 */ 377 if (zfs_file_read(fp, buf, fsize, NULL) < 0) 378 goto out; 379 380 /* 381 * Unpack the nvlist. 382 */ 383 if (nvlist_unpack(buf, fsize, &nvlist, KM_SLEEP) != 0) 384 goto out; 385 386 /* 387 * Iterate over all elements in the nvlist, creating a new spa_t for 388 * each one with the specified configuration. 389 */ 390 spa_namespace_enter(FTAG); 391 nvpair = NULL; 392 while ((nvpair = nvlist_next_nvpair(nvlist, nvpair)) != NULL) { 393 if (nvpair_type(nvpair) != DATA_TYPE_NVLIST) 394 continue; 395 396 child = fnvpair_value_nvlist(nvpair); 397 398 if (spa_lookup(nvpair_name(nvpair)) != NULL) 399 continue; 400 (void) spa_add(nvpair_name(nvpair), child, NULL); 401 } 402 spa_namespace_exit(FTAG); 403 404 nvlist_free(nvlist); 405 406 out: 407 if (buf != NULL) 408 kmem_free(buf, fsize); 409 410 zfs_file_close(fp); 411 } 412 413 void 414 kernel_init(int mode) 415 { 416 extern uint_t rrw_tsd_key; 417 418 libspl_init(); 419 420 umem_nofail_callback(umem_out_of_memory); 421 422 dprintf("physmem = %llu pages (%.2f GB)\n", (u_longlong_t)physmem, 423 (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); 424 425 hostid = (mode & SPA_MODE_WRITE) ? get_system_hostid() : 0; 426 427 system_taskq_init(); 428 icp_init(); 429 430 zstd_init(); 431 432 spa_init((spa_mode_t)mode); 433 spa_config_load(); 434 435 fletcher_4_init(); 436 437 tsd_create(&rrw_tsd_key, rrw_tsd_destroy); 438 } 439 440 void 441 kernel_fini(void) 442 { 443 fletcher_4_fini(); 444 spa_fini(); 445 446 zstd_fini(); 447 448 icp_fini(); 449 system_taskq_fini(); 450 451 libspl_fini(); 452 } 453 454 zfs_file_t * 455 zfs_onexit_fd_hold(int fd, minor_t *minorp) 456 { 457 (void) fd; 458 *minorp = 0; 459 return (NULL); 460 } 461 462 void 463 zfs_onexit_fd_rele(zfs_file_t *fp) 464 { 465 (void) fp; 466 } 467 468 int 469 zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data, 470 uintptr_t *action_handle) 471 { 472 (void) minor, (void) func, (void) data, (void) action_handle; 473 return (0); 474 } 475 476 void 477 zvol_create_minors(const char *name) 478 { 479 (void) name; 480 } 481 482 void 483 zvol_remove_minors(spa_t *spa, const char *name, boolean_t async) 484 { 485 (void) spa, (void) name, (void) async; 486 } 487 488 void 489 zvol_rename_minors(spa_t *spa, const char *oldname, const char *newname, 490 boolean_t async) 491 { 492 (void) spa, (void) oldname, (void) newname, (void) async; 493 } 494 495 void 496 zfsvfs_update_fromname(const char *oldname, const char *newname) 497 { 498 (void) oldname, (void) newname; 499 } 500 501 void 502 spa_import_os(spa_t *spa) 503 { 504 (void) spa; 505 } 506 507 void 508 spa_export_os(spa_t *spa) 509 { 510 (void) spa; 511 } 512 513 void 514 spa_activate_os(spa_t *spa) 515 { 516 (void) spa; 517 } 518 519 void 520 spa_deactivate_os(spa_t *spa) 521 { 522 (void) spa; 523 } 524