Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/lib/libzpool/kernel.c
106840 views
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
/* If set, all blocks read will be copied to the specified directory. */
66
char *vn_dumpdir = NULL;
67
68
uint32_t
69
zone_get_hostid(void *zonep)
70
{
71
/*
72
* We're emulating the system's hostid in userland.
73
*/
74
(void) zonep;
75
return (hostid);
76
}
77
78
/*
79
* =========================================================================
80
* vnode operations
81
* =========================================================================
82
*/
83
84
/*
85
* =========================================================================
86
* Figure out which debugging statements to print
87
* =========================================================================
88
*/
89
90
static char *dprintf_string;
91
static int dprintf_print_all;
92
93
int
94
dprintf_find_string(const char *string)
95
{
96
char *tmp_str = dprintf_string;
97
int len = strlen(string);
98
99
/*
100
* Find out if this is a string we want to print.
101
* String format: file1.c,function_name1,file2.c,file3.c
102
*/
103
104
while (tmp_str != NULL) {
105
if (strncmp(tmp_str, string, len) == 0 &&
106
(tmp_str[len] == ',' || tmp_str[len] == '\0'))
107
return (1);
108
tmp_str = strchr(tmp_str, ',');
109
if (tmp_str != NULL)
110
tmp_str++; /* Get rid of , */
111
}
112
return (0);
113
}
114
115
void
116
dprintf_setup(int *argc, char **argv)
117
{
118
int i, j;
119
120
/*
121
* Debugging can be specified two ways: by setting the
122
* environment variable ZFS_DEBUG, or by including a
123
* "debug=..." argument on the command line. The command
124
* line setting overrides the environment variable.
125
*/
126
127
for (i = 1; i < *argc; i++) {
128
int len = strlen("debug=");
129
/* First look for a command line argument */
130
if (strncmp("debug=", argv[i], len) == 0) {
131
dprintf_string = argv[i] + len;
132
/* Remove from args */
133
for (j = i; j < *argc; j++)
134
argv[j] = argv[j+1];
135
argv[j] = NULL;
136
(*argc)--;
137
}
138
}
139
140
if (dprintf_string == NULL) {
141
/* Look for ZFS_DEBUG environment variable */
142
dprintf_string = getenv("ZFS_DEBUG");
143
}
144
145
/*
146
* Are we just turning on all debugging?
147
*/
148
if (dprintf_find_string("on"))
149
dprintf_print_all = 1;
150
151
if (dprintf_string != NULL)
152
zfs_flags |= ZFS_DEBUG_DPRINTF;
153
}
154
155
/*
156
* =========================================================================
157
* debug printfs
158
* =========================================================================
159
*/
160
void
161
__dprintf(boolean_t dprint, const char *file, const char *func,
162
int line, const char *fmt, ...)
163
{
164
/* Get rid of annoying "../common/" prefix to filename. */
165
const char *newfile = zfs_basename(file);
166
167
va_list adx;
168
if (dprint) {
169
/* dprintf messages are printed immediately */
170
171
if (!dprintf_print_all &&
172
!dprintf_find_string(newfile) &&
173
!dprintf_find_string(func))
174
return;
175
176
/* Print out just the function name if requested */
177
flockfile(stdout);
178
if (dprintf_find_string("pid"))
179
(void) printf("%d ", getpid());
180
if (dprintf_find_string("tid"))
181
(void) printf("%ju ",
182
(uintmax_t)(uintptr_t)pthread_self());
183
if (dprintf_find_string("cpu"))
184
(void) printf("%u ", getcpuid());
185
if (dprintf_find_string("time"))
186
(void) printf("%llu ", gethrtime());
187
if (dprintf_find_string("long"))
188
(void) printf("%s, line %d: ", newfile, line);
189
(void) printf("dprintf: %s: ", func);
190
va_start(adx, fmt);
191
(void) vprintf(fmt, adx);
192
va_end(adx);
193
funlockfile(stdout);
194
} else {
195
/* zfs_dbgmsg is logged for dumping later */
196
size_t size;
197
char *buf;
198
int i;
199
200
size = 1024;
201
buf = umem_alloc(size, UMEM_NOFAIL);
202
i = snprintf(buf, size, "%s:%d:%s(): ", newfile, line, func);
203
204
if (i < size) {
205
va_start(adx, fmt);
206
(void) vsnprintf(buf + i, size - i, fmt, adx);
207
va_end(adx);
208
}
209
210
__zfs_dbgmsg(buf);
211
212
umem_free(buf, size);
213
}
214
}
215
216
/*
217
* =========================================================================
218
* cmn_err() and panic()
219
* =========================================================================
220
*/
221
222
static __attribute__((noreturn)) void
223
panic_stop_or_abort(void)
224
{
225
const char *stopenv = getenv("LIBZPOOL_PANIC_STOP");
226
if (stopenv != NULL && atoi(stopenv)) {
227
fputs("libzpool: LIBZPOOL_PANIC_STOP is set, sending "
228
"SIGSTOP to process group\n", stderr);
229
fflush(stderr);
230
231
kill(0, SIGSTOP);
232
233
fputs("libzpool: continued after panic stop, "
234
"aborting\n", stderr);
235
}
236
237
abort(); /* think of it as a "user-level crash dump" */
238
}
239
240
static void
241
vcmn_msg(int ce, const char *fmt, va_list adx)
242
{
243
switch (ce) {
244
case CE_IGNORE:
245
return;
246
case CE_CONT:
247
break;
248
case CE_NOTE:
249
fputs("libzpool: NOTICE: ", stderr);
250
break;
251
case CE_WARN:
252
fputs("libzpool: WARNING: ", stderr);
253
break;
254
case CE_PANIC:
255
fputs("libzpool: PANIC: ", stderr);
256
break;
257
default:
258
fputs("libzpool: [unknown severity %d]: ", stderr);
259
break;
260
}
261
262
vfprintf(stderr, fmt, adx);
263
if (ce != CE_CONT)
264
fputc('\n', stderr);
265
fflush(stderr);
266
}
267
268
void
269
vcmn_err(int ce, const char *fmt, va_list adx)
270
{
271
vcmn_msg(ce, fmt, adx);
272
273
if (ce == CE_PANIC)
274
panic_stop_or_abort();
275
}
276
277
void
278
cmn_err(int ce, const char *fmt, ...)
279
{
280
va_list adx;
281
282
va_start(adx, fmt);
283
vcmn_err(ce, fmt, adx);
284
va_end(adx);
285
}
286
287
__attribute__((noreturn)) void
288
panic(const char *fmt, ...)
289
{
290
va_list adx;
291
292
va_start(adx, fmt);
293
vcmn_msg(CE_PANIC, fmt, adx);
294
va_end(adx);
295
296
panic_stop_or_abort();
297
}
298
299
__attribute__((noreturn)) void
300
vpanic(const char *fmt, va_list adx)
301
{
302
vcmn_msg(CE_PANIC, fmt, adx);
303
panic_stop_or_abort();
304
}
305
306
/*
307
* =========================================================================
308
* misc routines
309
* =========================================================================
310
*/
311
312
void
313
delay(clock_t ticks)
314
{
315
(void) poll(0, 0, ticks * (1000 / hz));
316
}
317
318
/*
319
* Find highest one bit set.
320
* Returns bit number + 1 of highest bit that is set, otherwise returns 0.
321
* The __builtin_clzll() function is supported by both GCC and Clang.
322
*/
323
int
324
highbit64(uint64_t i)
325
{
326
if (i == 0)
327
return (0);
328
329
return (NBBY * sizeof (uint64_t) - __builtin_clzll(i));
330
}
331
332
/*
333
* Find lowest one bit set.
334
* Returns bit number + 1 of lowest bit that is set, otherwise returns 0.
335
* The __builtin_ffsll() function is supported by both GCC and Clang.
336
*/
337
int
338
lowbit64(uint64_t i)
339
{
340
if (i == 0)
341
return (0);
342
343
return (__builtin_ffsll(i));
344
}
345
346
int
347
ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result)
348
{
349
errno = 0;
350
*result = strtoull(str, nptr, base);
351
if (*result == 0)
352
return (errno);
353
return (0);
354
}
355
356
/*
357
* =========================================================================
358
* kernel emulation setup & teardown
359
* =========================================================================
360
*/
361
static int
362
umem_out_of_memory(void)
363
{
364
char errmsg[] = "out of memory -- generating core dump\n";
365
366
(void) fprintf(stderr, "%s", errmsg);
367
abort();
368
return (0);
369
}
370
371
static void
372
spa_config_load(void)
373
{
374
void *buf = NULL;
375
nvlist_t *nvlist, *child;
376
nvpair_t *nvpair;
377
char *pathname;
378
zfs_file_t *fp;
379
zfs_file_attr_t zfa;
380
uint64_t fsize;
381
int err;
382
383
/*
384
* Open the configuration file.
385
*/
386
pathname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
387
388
(void) snprintf(pathname, MAXPATHLEN, "%s", spa_config_path);
389
390
err = zfs_file_open(pathname, O_RDONLY, 0, &fp);
391
if (err)
392
err = zfs_file_open(ZPOOL_CACHE_BOOT, O_RDONLY, 0, &fp);
393
394
kmem_free(pathname, MAXPATHLEN);
395
396
if (err)
397
return;
398
399
if (zfs_file_getattr(fp, &zfa))
400
goto out;
401
402
fsize = zfa.zfa_size;
403
buf = kmem_alloc(fsize, KM_SLEEP);
404
405
/*
406
* Read the nvlist from the file.
407
*/
408
if (zfs_file_read(fp, buf, fsize, NULL) < 0)
409
goto out;
410
411
/*
412
* Unpack the nvlist.
413
*/
414
if (nvlist_unpack(buf, fsize, &nvlist, KM_SLEEP) != 0)
415
goto out;
416
417
/*
418
* Iterate over all elements in the nvlist, creating a new spa_t for
419
* each one with the specified configuration.
420
*/
421
spa_namespace_enter(FTAG);
422
nvpair = NULL;
423
while ((nvpair = nvlist_next_nvpair(nvlist, nvpair)) != NULL) {
424
if (nvpair_type(nvpair) != DATA_TYPE_NVLIST)
425
continue;
426
427
child = fnvpair_value_nvlist(nvpair);
428
429
if (spa_lookup(nvpair_name(nvpair)) != NULL)
430
continue;
431
(void) spa_add(nvpair_name(nvpair), child, NULL);
432
}
433
spa_namespace_exit(FTAG);
434
435
nvlist_free(nvlist);
436
437
out:
438
if (buf != NULL)
439
kmem_free(buf, fsize);
440
441
zfs_file_close(fp);
442
}
443
444
void
445
kernel_init(int mode)
446
{
447
extern uint_t rrw_tsd_key;
448
449
libspl_init();
450
451
umem_nofail_callback(umem_out_of_memory);
452
453
dprintf("physmem = %llu pages (%.2f GB)\n", (u_longlong_t)physmem,
454
(double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
455
456
hostid = (mode & SPA_MODE_WRITE) ? get_system_hostid() : 0;
457
458
system_taskq_init();
459
icp_init();
460
461
zstd_init();
462
463
spa_init((spa_mode_t)mode);
464
spa_config_load();
465
466
fletcher_4_init();
467
468
tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
469
}
470
471
void
472
kernel_fini(void)
473
{
474
fletcher_4_fini();
475
spa_fini();
476
477
zstd_fini();
478
479
icp_fini();
480
system_taskq_fini();
481
482
libspl_fini();
483
}
484
485
zfs_file_t *
486
zfs_onexit_fd_hold(int fd, minor_t *minorp)
487
{
488
(void) fd;
489
*minorp = 0;
490
return (NULL);
491
}
492
493
void
494
zfs_onexit_fd_rele(zfs_file_t *fp)
495
{
496
(void) fp;
497
}
498
499
int
500
zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
501
uintptr_t *action_handle)
502
{
503
(void) minor, (void) func, (void) data, (void) action_handle;
504
return (0);
505
}
506
507
void
508
zvol_create_minors(const char *name)
509
{
510
(void) name;
511
}
512
513
void
514
zvol_remove_minors(spa_t *spa, const char *name, boolean_t async)
515
{
516
(void) spa, (void) name, (void) async;
517
}
518
519
void
520
zvol_rename_minors(spa_t *spa, const char *oldname, const char *newname,
521
boolean_t async)
522
{
523
(void) spa, (void) oldname, (void) newname, (void) async;
524
}
525
526
/*
527
* Open file
528
*
529
* path - fully qualified path to file
530
* flags - file attributes O_READ / O_WRITE / O_EXCL
531
* fpp - pointer to return file pointer
532
*
533
* Returns 0 on success underlying error on failure.
534
*/
535
int
536
zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fpp)
537
{
538
int fd;
539
int dump_fd;
540
int err;
541
int old_umask = 0;
542
zfs_file_t *fp;
543
struct stat64 st;
544
545
if (!(flags & O_CREAT) && stat64(path, &st) == -1)
546
return (errno);
547
548
if (!(flags & O_CREAT) && S_ISBLK(st.st_mode))
549
flags |= O_DIRECT;
550
551
if (flags & O_CREAT)
552
old_umask = umask(0);
553
554
fd = open64(path, flags, mode);
555
if (fd == -1)
556
return (errno);
557
558
if (flags & O_CREAT)
559
(void) umask(old_umask);
560
561
if (vn_dumpdir != NULL) {
562
char *dumppath = umem_zalloc(MAXPATHLEN, UMEM_NOFAIL);
563
const char *inpath = zfs_basename(path);
564
565
(void) snprintf(dumppath, MAXPATHLEN,
566
"%s/%s", vn_dumpdir, inpath);
567
dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666);
568
umem_free(dumppath, MAXPATHLEN);
569
if (dump_fd == -1) {
570
err = errno;
571
close(fd);
572
return (err);
573
}
574
} else {
575
dump_fd = -1;
576
}
577
578
(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
579
580
fp = umem_zalloc(sizeof (zfs_file_t), UMEM_NOFAIL);
581
fp->f_fd = fd;
582
fp->f_dump_fd = dump_fd;
583
*fpp = fp;
584
585
return (0);
586
}
587
588
void
589
zfs_file_close(zfs_file_t *fp)
590
{
591
close(fp->f_fd);
592
if (fp->f_dump_fd != -1)
593
close(fp->f_dump_fd);
594
595
umem_free(fp, sizeof (zfs_file_t));
596
}
597
598
/*
599
* Stateful write - use os internal file pointer to determine where to
600
* write and update on successful completion.
601
*
602
* fp - pointer to file (pipe, socket, etc) to write to
603
* buf - buffer to write
604
* count - # of bytes to write
605
* resid - pointer to count of unwritten bytes (if short write)
606
*
607
* Returns 0 on success errno on failure.
608
*/
609
int
610
zfs_file_write(zfs_file_t *fp, const void *buf, size_t count, ssize_t *resid)
611
{
612
ssize_t rc;
613
614
rc = write(fp->f_fd, buf, count);
615
if (rc < 0)
616
return (errno);
617
618
if (resid) {
619
*resid = count - rc;
620
} else if (rc != count) {
621
return (EIO);
622
}
623
624
return (0);
625
}
626
627
/*
628
* Stateless write - os internal file pointer is not updated.
629
*
630
* fp - pointer to file (pipe, socket, etc) to write to
631
* buf - buffer to write
632
* count - # of bytes to write
633
* off - file offset to write to (only valid for seekable types)
634
* resid - pointer to count of unwritten bytes
635
*
636
* Returns 0 on success errno on failure.
637
*/
638
int
639
zfs_file_pwrite(zfs_file_t *fp, const void *buf,
640
size_t count, loff_t pos, uint8_t ashift, ssize_t *resid)
641
{
642
ssize_t rc, split, done;
643
int sectors;
644
645
/*
646
* To simulate partial disk writes, we split writes into two
647
* system calls so that the process can be killed in between.
648
* This is used by ztest to simulate realistic failure modes.
649
*/
650
sectors = count >> ashift;
651
split = (sectors > 0 ? rand() % sectors : 0) << ashift;
652
rc = pwrite64(fp->f_fd, buf, split, pos);
653
if (rc != -1) {
654
done = rc;
655
rc = pwrite64(fp->f_fd, (char *)buf + split,
656
count - split, pos + split);
657
}
658
#ifdef __linux__
659
if (rc == -1 && errno == EINVAL) {
660
/*
661
* Under Linux, this most likely means an alignment issue
662
* (memory or disk) due to O_DIRECT, so we abort() in order
663
* to catch the offender.
664
*/
665
abort();
666
}
667
#endif
668
669
if (rc < 0)
670
return (errno);
671
672
done += rc;
673
674
if (resid) {
675
*resid = count - done;
676
} else if (done != count) {
677
return (EIO);
678
}
679
680
return (0);
681
}
682
683
/*
684
* Stateful read - use os internal file pointer to determine where to
685
* read and update on successful completion.
686
*
687
* fp - pointer to file (pipe, socket, etc) to read from
688
* buf - buffer to write
689
* count - # of bytes to read
690
* resid - pointer to count of unread bytes (if short read)
691
*
692
* Returns 0 on success errno on failure.
693
*/
694
int
695
zfs_file_read(zfs_file_t *fp, void *buf, size_t count, ssize_t *resid)
696
{
697
int rc;
698
699
rc = read(fp->f_fd, buf, count);
700
if (rc < 0)
701
return (errno);
702
703
if (resid) {
704
*resid = count - rc;
705
} else if (rc != count) {
706
return (EIO);
707
}
708
709
return (0);
710
}
711
712
/*
713
* Stateless read - os internal file pointer is not updated.
714
*
715
* fp - pointer to file (pipe, socket, etc) to read from
716
* buf - buffer to write
717
* count - # of bytes to write
718
* off - file offset to read from (only valid for seekable types)
719
* resid - pointer to count of unwritten bytes (if short write)
720
*
721
* Returns 0 on success errno on failure.
722
*/
723
int
724
zfs_file_pread(zfs_file_t *fp, void *buf, size_t count, loff_t off,
725
ssize_t *resid)
726
{
727
ssize_t rc;
728
729
rc = pread64(fp->f_fd, buf, count, off);
730
if (rc < 0) {
731
#ifdef __linux__
732
/*
733
* Under Linux, this most likely means an alignment issue
734
* (memory or disk) due to O_DIRECT, so we abort() in order to
735
* catch the offender.
736
*/
737
if (errno == EINVAL)
738
abort();
739
#endif
740
return (errno);
741
}
742
743
if (fp->f_dump_fd != -1) {
744
int status;
745
746
status = pwrite64(fp->f_dump_fd, buf, rc, off);
747
ASSERT(status != -1);
748
}
749
750
if (resid) {
751
*resid = count - rc;
752
} else if (rc != count) {
753
return (EIO);
754
}
755
756
return (0);
757
}
758
759
/*
760
* lseek - set / get file pointer
761
*
762
* fp - pointer to file (pipe, socket, etc) to read from
763
* offp - value to seek to, returns current value plus passed offset
764
* whence - see man pages for standard lseek whence values
765
*
766
* Returns 0 on success errno on failure (ESPIPE for non seekable types)
767
*/
768
int
769
zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence)
770
{
771
loff_t rc;
772
773
rc = lseek(fp->f_fd, *offp, whence);
774
if (rc < 0)
775
return (errno);
776
777
*offp = rc;
778
779
return (0);
780
}
781
782
/*
783
* Get file attributes
784
*
785
* filp - file pointer
786
* zfattr - pointer to file attr structure
787
*
788
* Currently only used for fetching size and file mode
789
*
790
* Returns 0 on success or error code of underlying getattr call on failure.
791
*/
792
int
793
zfs_file_getattr(zfs_file_t *fp, zfs_file_attr_t *zfattr)
794
{
795
struct stat64 st;
796
797
if (fstat64_blk(fp->f_fd, &st) == -1)
798
return (errno);
799
800
zfattr->zfa_size = st.st_size;
801
zfattr->zfa_mode = st.st_mode;
802
803
return (0);
804
}
805
806
/*
807
* Sync file to disk
808
*
809
* filp - file pointer
810
* flags - O_SYNC and or O_DSYNC
811
*
812
* Returns 0 on success or error code of underlying sync call on failure.
813
*/
814
int
815
zfs_file_fsync(zfs_file_t *fp, int flags)
816
{
817
(void) flags;
818
819
if (fsync(fp->f_fd) < 0)
820
return (errno);
821
822
return (0);
823
}
824
825
/*
826
* deallocate - zero and/or deallocate file storage
827
*
828
* fp - file pointer
829
* offset - offset to start zeroing or deallocating
830
* len - length to zero or deallocate
831
*/
832
int
833
zfs_file_deallocate(zfs_file_t *fp, loff_t offset, loff_t len)
834
{
835
int rc;
836
#if defined(__linux__)
837
rc = fallocate(fp->f_fd,
838
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, offset, len);
839
#elif defined(__FreeBSD__) && (__FreeBSD_version >= 1400029)
840
struct spacectl_range rqsr = {
841
.r_offset = offset,
842
.r_len = len,
843
};
844
rc = fspacectl(fp->f_fd, SPACECTL_DEALLOC, &rqsr, 0, &rqsr);
845
#else
846
(void) fp, (void) offset, (void) len;
847
rc = EOPNOTSUPP;
848
#endif
849
if (rc)
850
return (SET_ERROR(rc));
851
return (0);
852
}
853
854
/*
855
* Request current file pointer offset
856
*
857
* fp - pointer to file
858
*
859
* Returns current file offset.
860
*/
861
loff_t
862
zfs_file_off(zfs_file_t *fp)
863
{
864
return (lseek(fp->f_fd, SEEK_CUR, 0));
865
}
866
867
/*
868
* unlink file
869
*
870
* path - fully qualified file path
871
*
872
* Returns 0 on success.
873
*
874
* OPTIONAL
875
*/
876
int
877
zfs_file_unlink(const char *path)
878
{
879
return (remove(path));
880
}
881
882
/*
883
* Get reference to file pointer
884
*
885
* fd - input file descriptor
886
*
887
* Returns pointer to file struct or NULL.
888
* Unsupported in user space.
889
*/
890
zfs_file_t *
891
zfs_file_get(int fd)
892
{
893
(void) fd;
894
abort();
895
return (NULL);
896
}
897
/*
898
* Drop reference to file pointer
899
*
900
* fp - pointer to file struct
901
*
902
* Unsupported in user space.
903
*/
904
void
905
zfs_file_put(zfs_file_t *fp)
906
{
907
abort();
908
(void) fp;
909
}
910
911
void
912
zfsvfs_update_fromname(const char *oldname, const char *newname)
913
{
914
(void) oldname, (void) newname;
915
}
916
917
void
918
spa_import_os(spa_t *spa)
919
{
920
(void) spa;
921
}
922
923
void
924
spa_export_os(spa_t *spa)
925
{
926
(void) spa;
927
}
928
929
void
930
spa_activate_os(spa_t *spa)
931
{
932
(void) spa;
933
}
934
935
void
936
spa_deactivate_os(spa_t *spa)
937
{
938
(void) spa;
939
}
940
941