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