1 diff --git a/Makefile.am b/Makefile.am
2 index 34fe16ce4..7e2b10b39 100644
5 @@ -103,7 +103,7 @@ endif
9 -codecheck: cstyle shellcheck checkbashisms flake8 mancheck testscheck vcscheck
10 +codecheck: cstyle shellcheck checkbashisms flake8 mancheck testscheck vcscheck zstdcheck
13 checkstyle: codecheck commitcheck
14 @@ -120,6 +120,7 @@ cstyle:
15 -o -type f -name '*.[hc]' \
16 ! -name 'zfs_config.*' ! -name '*.mod.c' \
17 ! -name 'opt_global.h' ! -name '*_if*.h' \
18 + ! -name 'zstd_compat_wrapper.h' \
19 ! -path './module/zstd/lib/*' \
20 -exec ${top_srcdir}/scripts/cstyle.pl -cpP {} \+
22 @@ -173,6 +174,10 @@ vcscheck:
23 awk '{c++; print} END {if(c>0) exit 1}' ; \
28 + @$(MAKE) -C module/zstd checksymbols
31 lint: cppcheck paxcheck
33 diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
34 index 9de41cef2..75688205f 100644
37 @@ -110,6 +110,7 @@ extern int zfs_recover;
38 extern unsigned long zfs_arc_meta_min, zfs_arc_meta_limit;
39 extern int zfs_vdev_async_read_max_active;
40 extern boolean_t spa_load_verify_dryrun;
41 +extern boolean_t spa_mode_readable_spacemaps;
42 extern int zfs_reconstruct_indirect_combinations_max;
43 extern int zfs_btree_verify_intensity;
45 @@ -8469,6 +8470,11 @@ main(int argc, char **argv)
47 spa_load_verify_dryrun = B_TRUE;
50 + * ZDB should have ability to read spacemaps.
52 + spa_mode_readable_spacemaps = B_TRUE;
54 kernel_init(SPA_MODE_READ);
57 diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c
58 index d0bb73a72..6f0c846fd 100644
59 --- a/cmd/zfs/zfs_main.c
60 +++ b/cmd/zfs/zfs_main.c
61 @@ -6593,7 +6593,7 @@ zfs_do_holds(int argc, char **argv)
63 * 1. collect holds data, set format options
65 - ret = zfs_for_each(argc, argv, flags, types, NULL, NULL, limit,
66 + ret = zfs_for_each(1, argv + i, flags, types, NULL, NULL, limit,
70 @@ -7672,7 +7672,7 @@ zfs_do_diff(int argc, char **argv)
74 - while ((c = getopt(argc, argv, "FHt")) != -1) {
75 + while ((c = getopt(argc, argv, "FHth")) != -1) {
78 flags |= ZFS_DIFF_CLASSIFY;
79 @@ -7683,6 +7683,9 @@ zfs_do_diff(int argc, char **argv)
81 flags |= ZFS_DIFF_TIMESTAMP;
84 + flags |= ZFS_DIFF_NO_MANGLE;
87 (void) fprintf(stderr,
88 gettext("invalid option '%c'\n"), optopt);
89 diff --git a/cmd/zvol_wait/zvol_wait b/cmd/zvol_wait/zvol_wait
90 index 2aa929b0c..f1fa42e27 100755
91 --- a/cmd/zvol_wait/zvol_wait
92 +++ b/cmd/zvol_wait/zvol_wait
93 @@ -28,15 +28,17 @@ filter_out_deleted_zvols() {
95 read -r default_volmode < /sys/module/zfs/parameters/zvol_volmode
96 zfs list -t volume -H -o \
97 - name,volmode,receive_resume_token,redact_snaps |
98 - while IFS=" " read -r name volmode token redacted; do # IFS=\t here!
99 + name,volmode,receive_resume_token,redact_snaps,keystatus |
100 + while IFS=" " read -r name volmode token redacted keystatus; do # IFS=\t here!
102 - # /dev links are not created for zvols with volmode = "none"
103 - # or for redacted zvols.
104 + # /dev links are not created for zvols with volmode = "none",
105 + # redacted zvols, or encrypted zvols for which the key has not
107 [ "$volmode" = "none" ] && continue
108 [ "$volmode" = "default" ] && [ "$default_volmode" = "3" ] &&
110 [ "$redacted" = "-" ] || continue
111 + [ "$keystatus" = "unavailable" ] && continue
113 # We also ignore partially received zvols if it is
114 # not an incremental receive, as those won't even have a block
115 diff --git a/config/ax_python_devel.m4 b/config/ax_python_devel.m4
116 index fcf73dc20..7adcf01a0 100644
117 --- a/config/ax_python_devel.m4
118 +++ b/config/ax_python_devel.m4
119 @@ -224,7 +224,7 @@ EOD`
120 ac_python_version=$PYTHON_VERSION
122 ac_python_version=`$PYTHON -c "import sys; \
123 - print (sys.version[[:3]])"`
124 + print ('.'.join(sys.version.split('.')[[:2]]))"`
128 diff --git a/config/kernel-add-disk.m4 b/config/kernel-add-disk.m4
129 index 5d1779eb4..44a8a5fd2 100644
130 --- a/config/kernel-add-disk.m4
131 +++ b/config/kernel-add-disk.m4
132 @@ -3,16 +3,15 @@ dnl # 5.16 API change
133 dnl # add_disk grew a must-check return code
135 AC_DEFUN([ZFS_AC_KERNEL_SRC_ADD_DISK], [
137 ZFS_LINUX_TEST_SRC([add_disk_ret], [
138 - #include <linux/genhd.h>
139 + #include <linux/blkdev.h>
141 struct gendisk *disk = NULL;
142 int err = add_disk(disk);
148 AC_DEFUN([ZFS_AC_KERNEL_ADD_DISK], [
149 AC_MSG_CHECKING([whether add_disk() returns int])
150 ZFS_LINUX_TEST_RESULT([add_disk_ret],
151 diff --git a/config/kernel-bio.m4 b/config/kernel-bio.m4
152 index d088d7023..b5d254481 100644
153 --- a/config/kernel-bio.m4
154 +++ b/config/kernel-bio.m4
155 @@ -474,6 +474,41 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_CGROUP_HEADER], [
160 +dnl # Linux 5.18 API
162 +dnl # In 07888c665b405b1cd3577ddebfeb74f4717a84c4 ("block: pass a block_device and opf to bio_alloc")
163 +dnl # bio_alloc(gfp_t gfp_mask, unsigned short nr_iovecs)
165 +dnl # bio_alloc(struct block_device *bdev, unsigned short nr_vecs, unsigned int opf, gfp_t gfp_mask)
167 +dnl # > NULL/0 can be passed, both for the
168 +dnl # > passthrough case on a raw request_queue and to temporarily avoid
169 +dnl # > refactoring some nasty code.
171 +AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_ALLOC_4ARG], [
172 + ZFS_LINUX_TEST_SRC([bio_alloc_4arg], [
173 + #include <linux/bio.h>
175 + gfp_t gfp_mask = 0;
176 + unsigned short nr_iovecs = 0;
177 + struct block_device *bdev = NULL;
178 + unsigned int opf = 0;
180 + struct bio *__attribute__((unused)) allocated = bio_alloc(bdev, nr_iovecs, opf, gfp_mask);
184 +AC_DEFUN([ZFS_AC_KERNEL_BIO_ALLOC_4ARG], [
185 + AC_MSG_CHECKING([for 4-argument bio_alloc()])
186 + ZFS_LINUX_TEST_RESULT([bio_alloc_4arg],[
188 + AC_DEFINE([HAVE_BIO_ALLOC_4ARG], 1, [bio_alloc() takes 4 arguments])
194 AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO], [
195 ZFS_AC_KERNEL_SRC_REQ
196 ZFS_AC_KERNEL_SRC_BIO_OPS
197 @@ -488,6 +523,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO], [
198 ZFS_AC_KERNEL_SRC_BDEV_SUBMIT_BIO_RETURNS_VOID
199 ZFS_AC_KERNEL_SRC_BIO_SET_DEV_MACRO
200 ZFS_AC_KERNEL_SRC_BLK_CGROUP_HEADER
201 + ZFS_AC_KERNEL_SRC_BIO_ALLOC_4ARG
204 AC_DEFUN([ZFS_AC_KERNEL_BIO], [
205 @@ -512,4 +548,5 @@ AC_DEFUN([ZFS_AC_KERNEL_BIO], [
206 ZFS_AC_KERNEL_BIO_BDEV_DISK
207 ZFS_AC_KERNEL_BDEV_SUBMIT_BIO_RETURNS_VOID
208 ZFS_AC_KERNEL_BLK_CGROUP_HEADER
209 + ZFS_AC_KERNEL_BIO_ALLOC_4ARG
211 diff --git a/config/kernel-blk-queue.m4 b/config/kernel-blk-queue.m4
212 index ff5d2d370..091952f57 100644
213 --- a/config/kernel-blk-queue.m4
214 +++ b/config/kernel-blk-queue.m4
215 @@ -93,8 +93,10 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_DISCARD], [
216 ZFS_LINUX_TEST_SRC([blk_queue_discard], [
217 #include <linux/blkdev.h>
219 - struct request_queue *q __attribute__ ((unused)) = NULL;
220 + struct request_queue r;
221 + struct request_queue *q = &r;
222 int value __attribute__ ((unused));
223 + memset(q, 0, sizeof(r));
224 value = blk_queue_discard(q);
227 @@ -119,16 +121,20 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_SECURE_ERASE], [
228 ZFS_LINUX_TEST_SRC([blk_queue_secure_erase], [
229 #include <linux/blkdev.h>
231 - struct request_queue *q __attribute__ ((unused)) = NULL;
232 + struct request_queue r;
233 + struct request_queue *q = &r;
234 int value __attribute__ ((unused));
235 + memset(q, 0, sizeof(r));
236 value = blk_queue_secure_erase(q);
239 ZFS_LINUX_TEST_SRC([blk_queue_secdiscard], [
240 #include <linux/blkdev.h>
242 - struct request_queue *q __attribute__ ((unused)) = NULL;
243 + struct request_queue r;
244 + struct request_queue *q = &r;
245 int value __attribute__ ((unused));
246 + memset(q, 0, sizeof(r));
247 value = blk_queue_secdiscard(q);
250 diff --git a/config/kernel-config-defined.m4 b/config/kernel-config-defined.m4
251 index c7d18b49b..54837d728 100644
252 --- a/config/kernel-config-defined.m4
253 +++ b/config/kernel-config-defined.m4
254 @@ -19,19 +19,48 @@ AC_DEFUN([ZFS_AC_KERNEL_CONFIG_DEFINED], [
258 + ZFS_AC_KERNEL_SRC_CONFIG_MODULES
259 + ZFS_AC_KERNEL_SRC_CONFIG_BLOCK
260 ZFS_AC_KERNEL_SRC_CONFIG_DEBUG_LOCK_ALLOC
261 ZFS_AC_KERNEL_SRC_CONFIG_TRIM_UNUSED_KSYMS
262 - ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_INFLATE
263 ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_DEFLATE
264 + ZFS_AC_KERNEL_SRC_CONFIG_ZLIB_INFLATE
266 AC_MSG_CHECKING([for kernel config option compatibility])
267 ZFS_LINUX_TEST_COMPILE_ALL([config])
268 AC_MSG_RESULT([done])
270 + ZFS_AC_KERNEL_CONFIG_MODULES
271 + ZFS_AC_KERNEL_CONFIG_BLOCK
272 ZFS_AC_KERNEL_CONFIG_DEBUG_LOCK_ALLOC
273 ZFS_AC_KERNEL_CONFIG_TRIM_UNUSED_KSYMS
274 - ZFS_AC_KERNEL_CONFIG_ZLIB_INFLATE
275 ZFS_AC_KERNEL_CONFIG_ZLIB_DEFLATE
276 + ZFS_AC_KERNEL_CONFIG_ZLIB_INFLATE
280 +dnl # Check CONFIG_BLOCK
282 +dnl # Verify the kernel has CONFIG_BLOCK support enabled.
284 +AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_BLOCK], [
285 + ZFS_LINUX_TEST_SRC([config_block], [
286 + #if !defined(CONFIG_BLOCK)
287 + #error CONFIG_BLOCK not defined
292 +AC_DEFUN([ZFS_AC_KERNEL_CONFIG_BLOCK], [
293 + AC_MSG_CHECKING([whether CONFIG_BLOCK is defined])
294 + ZFS_LINUX_TEST_RESULT([config_block], [
295 + AC_MSG_RESULT([yes])
297 + AC_MSG_RESULT([no])
299 + *** This kernel does not include the required block device support.
300 + *** Rebuild the kernel with CONFIG_BLOCK=y set.])
305 @@ -72,6 +101,61 @@ AC_DEFUN([ZFS_AC_KERNEL_CONFIG_DEBUG_LOCK_ALLOC], [
310 +dnl # Check CONFIG_MODULES
312 +dnl # Verify the kernel has CONFIG_MODULES support enabled.
314 +AC_DEFUN([ZFS_AC_KERNEL_SRC_CONFIG_MODULES], [
315 + ZFS_LINUX_TEST_SRC([config_modules], [
316 + #if !defined(CONFIG_MODULES)
317 + #error CONFIG_MODULES not defined
322 +AC_DEFUN([ZFS_AC_KERNEL_CONFIG_MODULES], [
323 + AC_MSG_CHECKING([whether CONFIG_MODULES is defined])
324 + AS_IF([test "x$enable_linux_builtin" != xyes], [
325 + ZFS_LINUX_TEST_RESULT([config_modules], [
326 + AC_MSG_RESULT([yes])
328 + AC_MSG_RESULT([no])
330 + *** This kernel does not include the required loadable module
333 + *** To build OpenZFS as a loadable Linux kernel module
334 + *** enable loadable module support by setting
335 + *** `CONFIG_MODULES=y` in the kernel configuration and run
336 + *** `make modules_prepare` in the Linux source tree.
338 + *** If you don't intend to enable loadable kernel module
339 + *** support, please compile OpenZFS as a Linux kernel built-in.
341 + *** Prepare the Linux source tree by running `make prepare`,
342 + *** use the OpenZFS `--enable-linux-builtin` configure option,
343 + *** copy the OpenZFS sources into the Linux source tree using
344 + *** `./copy-builtin <linux source directory>`,
345 + *** set `CONFIG_ZFS=y` in the kernel configuration and compile
346 + *** kernel as usual.
350 + ZFS_LINUX_TRY_COMPILE([], [], [
351 + AC_MSG_RESULT([not needed])
353 + AC_MSG_RESULT([error])
355 + *** This kernel is unable to compile object files.
357 + *** Please make sure you prepared the Linux source tree
358 + *** by running `make prepare` there.
365 dnl # Check CONFIG_TRIM_UNUSED_KSYMS
367 diff --git a/config/kernel-copy-from-user-inatomic.m4 b/config/kernel-copy-from-user-inatomic.m4
369 index 000000000..fec354b2f
371 +++ b/config/kernel-copy-from-user-inatomic.m4
374 +dnl # On certain architectures `__copy_from_user_inatomic`
375 +dnl # is a GPL exported variable and cannot be used by OpenZFS.
379 +dnl # Checking if `__copy_from_user_inatomic` is available.
381 +AC_DEFUN([ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC], [
382 + ZFS_LINUX_TEST_SRC([__copy_from_user_inatomic], [
383 + #include <linux/uaccess.h>
385 + int result __attribute__ ((unused)) = __copy_from_user_inatomic(NULL, NULL, 0);
386 + ], [], [ZFS_META_LICENSE])
389 +AC_DEFUN([ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC], [
390 + AC_MSG_CHECKING([whether __copy_from_user_inatomic is available])
391 + ZFS_LINUX_TEST_RESULT([__copy_from_user_inatomic_license], [
396 + *** The `__copy_from_user_inatomic()` Linux kernel function is
397 + *** incompatible with the CDDL license and will prevent the module
398 + *** linking stage from succeeding. OpenZFS cannot be compiled.
402 diff --git a/config/kernel-genhd-flags.m4 b/config/kernel-genhd-flags.m4
404 index 000000000..af6a8a086
406 +++ b/config/kernel-genhd-flags.m4
409 +dnl # 5.17 API change,
411 +dnl # GENHD_FL_EXT_DEVT flag removed
412 +dnl # GENHD_FL_NO_PART_SCAN renamed GENHD_FL_NO_PART
414 +AC_DEFUN([ZFS_AC_KERNEL_SRC_GENHD_FLAGS], [
416 + ZFS_LINUX_TEST_SRC([genhd_fl_ext_devt], [
417 + #include <linux/blkdev.h>
419 + int flags __attribute__ ((unused)) = GENHD_FL_EXT_DEVT;
422 + ZFS_LINUX_TEST_SRC([genhd_fl_no_part], [
423 + #include <linux/blkdev.h>
425 + int flags __attribute__ ((unused)) = GENHD_FL_NO_PART;
428 + ZFS_LINUX_TEST_SRC([genhd_fl_no_part_scan], [
429 + #include <linux/blkdev.h>
431 + int flags __attribute__ ((unused)) = GENHD_FL_NO_PART_SCAN;
435 +AC_DEFUN([ZFS_AC_KERNEL_GENHD_FLAGS], [
437 + AC_MSG_CHECKING([whether GENHD_FL_EXT_DEVT flag is available])
438 + ZFS_LINUX_TEST_RESULT([genhd_fl_ext_devt], [
440 + AC_DEFINE(ZFS_GENHD_FL_EXT_DEVT, GENHD_FL_EXT_DEVT,
441 + [GENHD_FL_EXT_DEVT flag is available])
444 + AC_DEFINE(ZFS_GENHD_FL_EXT_DEVT, 0,
445 + [GENHD_FL_EXT_DEVT flag is not available])
448 + AC_MSG_CHECKING([whether GENHD_FL_NO_PART flag is available])
449 + ZFS_LINUX_TEST_RESULT([genhd_fl_no_part], [
451 + AC_DEFINE(ZFS_GENHD_FL_NO_PART, GENHD_FL_NO_PART,
452 + [GENHD_FL_NO_PART flag is available])
456 + AC_MSG_CHECKING([whether GENHD_FL_NO_PART_SCAN flag is available])
457 + ZFS_LINUX_TEST_RESULT([genhd_fl_no_part_scan], [
459 + AC_DEFINE(ZFS_GENHD_FL_NO_PART, GENHD_FL_NO_PART_SCAN,
460 + [GENHD_FL_NO_PART_SCAN flag is available])
462 + ZFS_LINUX_TEST_ERROR([GENHD_FL_NO_PART|GENHD_FL_NO_PART_SCAN])
466 diff --git a/config/kernel-group-info.m4 b/config/kernel-group-info.m4
467 index 0fee1d36d..6941d62da 100644
468 --- a/config/kernel-group-info.m4
469 +++ b/config/kernel-group-info.m4
470 @@ -6,8 +6,8 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_GROUP_INFO_GID], [
471 ZFS_LINUX_TEST_SRC([group_info_gid], [
472 #include <linux/cred.h>
474 - struct group_info *gi = groups_alloc(1);
475 - gi->gid[0] = KGIDT_INIT(0);
476 + struct group_info gi __attribute__ ((unused)) = {};
477 + gi.gid[0] = KGIDT_INIT(0);
481 diff --git a/config/kernel-mkdir.m4 b/config/kernel-mkdir.m4
482 index a162bcd88..6667ed04f 100644
483 --- a/config/kernel-mkdir.m4
484 +++ b/config/kernel-mkdir.m4
485 @@ -53,6 +53,8 @@ AC_DEFUN([ZFS_AC_KERNEL_MKDIR], [
486 AC_DEFINE(HAVE_IOPS_MKDIR_USERNS, 1,
487 [iops->mkdir() takes struct user_namespace*])
491 AC_MSG_CHECKING([whether iops->mkdir() takes umode_t])
492 ZFS_LINUX_TEST_RESULT([inode_operations_mkdir], [
494 diff --git a/config/kernel-readpages.m4 b/config/kernel-readpages.m4
496 index 000000000..0bf67ffd9
498 +++ b/config/kernel-readpages.m4
501 +dnl # Linux 5.18 removes address_space_operations ->readpages in favour of
504 +AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_READPAGES], [
505 + ZFS_LINUX_TEST_SRC([vfs_has_readpages], [
506 + #include <linux/fs.h>
508 + static const struct address_space_operations
509 + aops __attribute__ ((unused)) = {
515 +AC_DEFUN([ZFS_AC_KERNEL_VFS_READPAGES], [
516 + AC_MSG_CHECKING([address_space_operations->readpages exists])
517 + ZFS_LINUX_TEST_RESULT([vfs_has_readpages], [
518 + AC_MSG_RESULT([yes])
519 + AC_DEFINE(HAVE_VFS_READPAGES, 1,
520 + [address_space_operations->readpages exists])
522 + AC_MSG_RESULT([no])
525 diff --git a/config/kernel-revalidate-disk-size.m4 b/config/kernel-revalidate-disk-size.m4
526 index a7d0cb3cd..13cb92a17 100644
527 --- a/config/kernel-revalidate-disk-size.m4
528 +++ b/config/kernel-revalidate-disk-size.m4
529 @@ -8,14 +8,14 @@ dnl #
530 AC_DEFUN([ZFS_AC_KERNEL_SRC_REVALIDATE_DISK], [
532 ZFS_LINUX_TEST_SRC([revalidate_disk_size], [
533 - #include <linux/genhd.h>
534 + #include <linux/blkdev.h>
536 struct gendisk *disk = NULL;
537 (void) revalidate_disk_size(disk, false);
540 ZFS_LINUX_TEST_SRC([revalidate_disk], [
541 - #include <linux/genhd.h>
542 + #include <linux/blkdev.h>
544 struct gendisk *disk = NULL;
545 (void) revalidate_disk(disk);
546 diff --git a/config/kernel-sysfs.m4 b/config/kernel-sysfs.m4
548 index 000000000..668def5fe
550 +++ b/config/kernel-sysfs.m4
553 +dnl # Linux 5.2/5.18 API
555 +dnl # In cdb4f26a63c391317e335e6e683a614358e70aeb ("kobject: kobj_type: remove default_attrs")
556 +dnl # struct kobj_type.default_attrs
557 +dnl # was finally removed in favour of
558 +dnl # struct kobj_type.default_groups
560 +dnl # This was added in aa30f47cf666111f6bbfd15f290a27e8a7b9d854 ("kobject: Add support for default attribute groups to kobj_type"),
561 +dnl # if both are present (5.2-5.17), we prefer default_groups; they're otherwise equivalent
563 +AC_DEFUN([ZFS_AC_KERNEL_SRC_SYSFS_DEFAULT_GROUPS], [
564 + ZFS_LINUX_TEST_SRC([sysfs_default_groups], [
565 + #include <linux/kobject.h>
567 + struct kobj_type __attribute__ ((unused)) kt = {
568 + .default_groups = (const struct attribute_group **)NULL };
572 +AC_DEFUN([ZFS_AC_KERNEL_SYSFS_DEFAULT_GROUPS], [
573 + AC_MSG_CHECKING([for struct kobj_type.default_groups])
574 + ZFS_LINUX_TEST_RESULT([sysfs_default_groups],[
576 + AC_DEFINE([HAVE_SYSFS_DEFAULT_GROUPS], 1, [struct kobj_type has default_groups])
582 +AC_DEFUN([ZFS_AC_KERNEL_SRC_SYSFS], [
583 + ZFS_AC_KERNEL_SRC_SYSFS_DEFAULT_GROUPS
586 +AC_DEFUN([ZFS_AC_KERNEL_SYSFS], [
587 + ZFS_AC_KERNEL_SYSFS_DEFAULT_GROUPS
589 diff --git a/config/kernel-vfs-filemap_dirty_folio.m4 b/config/kernel-vfs-filemap_dirty_folio.m4
591 index 000000000..872879002
593 +++ b/config/kernel-vfs-filemap_dirty_folio.m4
596 +dnl # Linux 5.18 uses filemap_dirty_folio in lieu of
597 +dnl # ___set_page_dirty_nobuffers
599 +AC_DEFUN([ZFS_AC_KERNEL_SRC_VFS_FILEMAP_DIRTY_FOLIO], [
600 + ZFS_LINUX_TEST_SRC([vfs_has_filemap_dirty_folio], [
601 + #include <linux/pagemap.h>
602 + #include <linux/writeback.h>
604 + static const struct address_space_operations
605 + aops __attribute__ ((unused)) = {
606 + .dirty_folio = filemap_dirty_folio,
611 +AC_DEFUN([ZFS_AC_KERNEL_VFS_FILEMAP_DIRTY_FOLIO], [
613 + dnl # Linux 5.18 uses filemap_dirty_folio in lieu of
614 + dnl # ___set_page_dirty_nobuffers
616 + AC_MSG_CHECKING([filemap_dirty_folio exists])
617 + ZFS_LINUX_TEST_RESULT([vfs_has_filemap_dirty_folio], [
618 + AC_MSG_RESULT([yes])
619 + AC_DEFINE(HAVE_VFS_FILEMAP_DIRTY_FOLIO, 1,
620 + [filemap_dirty_folio exists])
622 + AC_MSG_RESULT([no])
625 diff --git a/config/kernel-zero_page.m4 b/config/kernel-zero_page.m4
627 index 000000000..1461781ac
629 +++ b/config/kernel-zero_page.m4
632 +dnl # ZERO_PAGE() is an alias for emtpy_zero_page. On certain architectures
633 +dnl # this is a GPL exported variable.
637 +dnl # Checking if ZERO_PAGE is exported GPL-only
639 +AC_DEFUN([ZFS_AC_KERNEL_SRC_ZERO_PAGE], [
640 + ZFS_LINUX_TEST_SRC([zero_page], [
641 + #include <asm/pgtable.h>
643 + struct page *p __attribute__ ((unused));
645 + ], [], [ZFS_META_LICENSE])
648 +AC_DEFUN([ZFS_AC_KERNEL_ZERO_PAGE], [
649 + AC_MSG_CHECKING([whether ZERO_PAGE() is GPL-only])
650 + ZFS_LINUX_TEST_RESULT([zero_page_license], [
654 + AC_DEFINE(HAVE_ZERO_PAGE_GPL_ONLY, 1,
655 + [ZERO_PAGE() is GPL-only])
658 diff --git a/config/kernel.m4 b/config/kernel.m4
659 index 3122e9dba..25df16a90 100644
660 --- a/config/kernel.m4
661 +++ b/config/kernel.m4
662 @@ -8,8 +8,8 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
665 dnl # Sanity checks for module building and CONFIG_* defines
666 - ZFS_AC_KERNEL_TEST_MODULE
667 ZFS_AC_KERNEL_CONFIG_DEFINED
668 + ZFS_AC_MODULE_SYMVERS
670 dnl # Sequential ZFS_LINUX_TRY_COMPILE tests
671 ZFS_AC_KERNEL_FPU_HEADER
672 @@ -61,6 +61,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
673 ZFS_AC_KERNEL_SRC_BIO
674 ZFS_AC_KERNEL_SRC_BLKDEV
675 ZFS_AC_KERNEL_SRC_BLK_QUEUE
676 + ZFS_AC_KERNEL_SRC_GENHD_FLAGS
677 ZFS_AC_KERNEL_SRC_REVALIDATE_DISK
678 ZFS_AC_KERNEL_SRC_GET_DISK_RO
679 ZFS_AC_KERNEL_SRC_GENERIC_READLINK_GLOBAL
680 @@ -99,6 +100,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
681 ZFS_AC_KERNEL_SRC_SET_NLINK
682 ZFS_AC_KERNEL_SRC_SGET
683 ZFS_AC_KERNEL_SRC_LSEEK_EXECUTE
684 + ZFS_AC_KERNEL_SRC_VFS_FILEMAP_DIRTY_FOLIO
685 ZFS_AC_KERNEL_SRC_VFS_GETATTR
686 ZFS_AC_KERNEL_SRC_VFS_FSYNC_2ARGS
687 ZFS_AC_KERNEL_SRC_VFS_ITERATE
688 @@ -131,12 +133,16 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
689 ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS
690 ZFS_AC_KERNEL_SRC_SIGNAL_STOP
691 ZFS_AC_KERNEL_SRC_SIGINFO
692 + ZFS_AC_KERNEL_SRC_SYSFS
693 ZFS_AC_KERNEL_SRC_SET_SPECIAL_STATE
694 + ZFS_AC_KERNEL_SRC_VFS_READPAGES
695 ZFS_AC_KERNEL_SRC_VFS_SET_PAGE_DIRTY_NOBUFFERS
696 ZFS_AC_KERNEL_SRC_STANDALONE_LINUX_STDARG
697 ZFS_AC_KERNEL_SRC_PAGEMAP_FOLIO_WAIT_BIT
698 ZFS_AC_KERNEL_SRC_ADD_DISK
699 ZFS_AC_KERNEL_SRC_KTHREAD
700 + ZFS_AC_KERNEL_SRC_ZERO_PAGE
701 + ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC
703 AC_MSG_CHECKING([for available kernel interfaces])
704 ZFS_LINUX_TEST_COMPILE_ALL([kabi])
705 @@ -171,6 +177,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
708 ZFS_AC_KERNEL_BLK_QUEUE
709 + ZFS_AC_KERNEL_GENHD_FLAGS
710 ZFS_AC_KERNEL_REVALIDATE_DISK
711 ZFS_AC_KERNEL_GET_DISK_RO
712 ZFS_AC_KERNEL_GENERIC_READLINK_GLOBAL
713 @@ -209,6 +216,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
714 ZFS_AC_KERNEL_SET_NLINK
716 ZFS_AC_KERNEL_LSEEK_EXECUTE
717 + ZFS_AC_KERNEL_VFS_FILEMAP_DIRTY_FOLIO
718 ZFS_AC_KERNEL_VFS_GETATTR
719 ZFS_AC_KERNEL_VFS_FSYNC_2ARGS
720 ZFS_AC_KERNEL_VFS_ITERATE
721 @@ -241,12 +249,16 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
722 ZFS_AC_KERNEL_BIO_MAX_SEGS
723 ZFS_AC_KERNEL_SIGNAL_STOP
724 ZFS_AC_KERNEL_SIGINFO
725 + ZFS_AC_KERNEL_SYSFS
726 ZFS_AC_KERNEL_SET_SPECIAL_STATE
727 + ZFS_AC_KERNEL_VFS_READPAGES
728 ZFS_AC_KERNEL_VFS_SET_PAGE_DIRTY_NOBUFFERS
729 ZFS_AC_KERNEL_STANDALONE_LINUX_STDARG
730 ZFS_AC_KERNEL_PAGEMAP_FOLIO_WAIT_BIT
731 ZFS_AC_KERNEL_ADD_DISK
732 ZFS_AC_KERNEL_KTHREAD
733 + ZFS_AC_KERNEL_ZERO_PAGE
734 + ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC
738 @@ -435,8 +447,6 @@ AC_DEFUN([ZFS_AC_KERNEL], [
741 AC_SUBST(LINUX_VERSION)
743 - ZFS_AC_MODULE_SYMVERS
747 @@ -531,27 +541,6 @@ AC_DEFUN([ZFS_AC_QAT], [
752 -dnl # Basic toolchain sanity check.
754 -AC_DEFUN([ZFS_AC_KERNEL_TEST_MODULE], [
755 - AC_MSG_CHECKING([whether modules can be built])
756 - ZFS_LINUX_TRY_COMPILE([], [], [
757 - AC_MSG_RESULT([yes])
759 - AC_MSG_RESULT([no])
760 - if test "x$enable_linux_builtin" != xyes; then
762 - *** Unable to build an empty module.
766 - *** Unable to build an empty module.
767 - *** Please run 'make scripts' inside the kernel source tree.])
773 dnl # ZFS_LINUX_CONFTEST_H
775 @@ -654,8 +643,10 @@ AC_DEFUN([ZFS_LINUX_COMPILE], [
776 build kernel modules with LLVM/CLANG toolchain])
778 KBUILD_MODPOST_NOFINAL="$5" KBUILD_MODPOST_WARN="$6"
779 - make modules -k -j$TEST_JOBS ${KERNEL_CC:+CC=$KERNEL_CC} ${KERNEL_LD:+LD=$KERNEL_LD} ${KERNEL_LLVM:+LLVM=$KERNEL_LLVM} -C $LINUX_OBJ $ARCH_UM
780 - M=$PWD/$1 >$1/build.log 2>&1])
781 + make modules -k -j$TEST_JOBS ${KERNEL_CC:+CC=$KERNEL_CC}
782 + ${KERNEL_LD:+LD=$KERNEL_LD} ${KERNEL_LLVM:+LLVM=$KERNEL_LLVM}
783 + CONFIG_MODULES=y CFLAGS_MODULE=-DCONFIG_MODULES
784 + -C $LINUX_OBJ $ARCH_UM M=$PWD/$1 >$1/build.log 2>&1])
785 AS_IF([AC_TRY_COMMAND([$2])], [$3], [$4])
788 diff --git a/contrib/dracut/90zfs/export-zfs.sh.in b/contrib/dracut/90zfs/export-zfs.sh.in
789 index 892650383..9e05ee03a 100755
790 --- a/contrib/dracut/90zfs/export-zfs.sh.in
791 +++ b/contrib/dracut/90zfs/export-zfs.sh.in
795 -. /lib/dracut-zfs-lib.sh
802 info "ZFS: Exporting ZFS storage pools..."
803 - errs=$(export_all -F 2>&1)
804 + errs=$(zpool export -aF 2>&1)
806 [ -z "${errs}" ] || echo "${errs}" | vwarn
807 if [ "x${ret}" != "x0" ]; then
808 diff --git a/contrib/dracut/90zfs/module-setup.sh.in b/contrib/dracut/90zfs/module-setup.sh.in
809 index fbf32b658..7c01f125e 100755
810 --- a/contrib/dracut/90zfs/module-setup.sh.in
811 +++ b/contrib/dracut/90zfs/module-setup.sh.in
812 @@ -6,8 +6,8 @@ check() {
813 [ "${1}" = "-d" ] && return 0
815 # Verify the zfs tool chain
816 - for tool in "@sbindir@/zgenhostid" "@sbindir@/zpool" "@sbindir@/zfs" "@mounthelperdir@/mount.zfs" ; do
817 - test -x "$tool" || return 1
818 + for tool in "zgenhostid" "zpool" "zfs" "mount.zfs"; do
819 + command -v "${tool}" >/dev/null || return 1
823 @@ -19,125 +19,86 @@ depends() {
835 - instmods zlib_deflate
836 - instmods zlib_inflate
841 - inst_rules @udevruledir@/90-zfs.rules
842 - inst_rules @udevruledir@/69-vdev.rules
843 - inst_rules @udevruledir@/60-zvol.rules
844 - dracut_install hostid
845 - dracut_install grep
846 - dracut_install @sbindir@/zgenhostid
847 - dracut_install @sbindir@/zfs
848 - dracut_install @sbindir@/zpool
849 - # Workaround for https://github.com/openzfs/zfs/issues/4749 by
850 - # ensuring libgcc_s.so(.1) is included
851 - if ldd @sbindir@/zpool | grep -qF 'libgcc_s.so'; then
852 - # Dracut will have already tracked and included it
854 - elif command -v gcc-config >/dev/null 2>&1; then
855 - # On systems with gcc-config (Gentoo, Funtoo, etc.):
856 - # Use the current profile to resolve the appropriate path
857 - s="$(gcc-config -c)"
858 - dracut_install "/usr/lib/gcc/${s%-*}/${s##*-}/libgcc_s.so"*
859 - elif [ "$(echo /usr/lib/libgcc_s.so*)" != "/usr/lib/libgcc_s.so*" ]; then
860 - # Try a simple path first
861 - dracut_install /usr/lib/libgcc_s.so*
862 - elif [ "$(echo /lib*/libgcc_s.so*)" != "/lib*/libgcc_s.so*" ]; then
864 - dracut_install /lib*/libgcc_s.so*
866 - # Fallback: Guess the path and include all matches
867 - dracut_install /usr/lib*/gcc/**/libgcc_s.so*
869 - # shellcheck disable=SC2050
870 - if [ @LIBFETCH_DYNAMIC@ -gt 0 ]; then
871 - for d in $libdirs; do
872 - [ -e "$d/@LIBFETCH_SONAME@" ] && dracut_install "$d/@LIBFETCH_SONAME@"
874 + inst_rules 90-zfs.rules 69-vdev.rules 60-zvol.rules
887 + { dfatal "Failed to install essential binaries"; exit 1; }
889 + # Adapted from https://github.com/zbm-dev/zfsbootmenu
890 + if ! ldd "$(command -v zpool)" | grep -qF 'libgcc_s.so'; then
891 + # On systems with gcc-config (Gentoo, Funtoo, etc.), use it to find libgcc_s
892 + if command -v gcc-config >/dev/null; then
893 + inst_simple "/usr/lib/gcc/$(s=$(gcc-config -c); echo "${s%-*}/${s##*-}")/libgcc_s.so.1" ||
894 + { dfatal "Unable to install libgcc_s.so"; exit 1; }
895 + # Otherwise, use dracut's library installation function to find the right one
896 + elif ! inst_libdir_file "libgcc_s.so*"; then
897 + # If all else fails, just try looking for some gcc arch directory
898 + inst_simple /usr/lib/gcc/*/*/libgcc_s.so* ||
899 + { dfatal "Unable to install libgcc_s.so"; exit 1; }
902 - dracut_install @mounthelperdir@/mount.zfs
903 - dracut_install @udevdir@/vdev_id
907 - dracut_install head
908 - dracut_install @udevdir@/zvol_id
910 inst_hook cmdline 95 "${moddir}/parse-zfs.sh"
911 - if [ -n "$systemdutildir" ] ; then
912 - inst_script "${moddir}/zfs-generator.sh" "$systemdutildir"/system-generators/dracut-zfs-generator
913 + if [ -n "${systemdutildir}" ]; then
914 + inst_script "${moddir}/zfs-generator.sh" "${systemdutildir}/system-generators/dracut-zfs-generator"
916 inst_hook pre-mount 90 "${moddir}/zfs-load-key.sh"
917 inst_hook mount 98 "${moddir}/mount-zfs.sh"
918 inst_hook cleanup 99 "${moddir}/zfs-needshutdown.sh"
919 inst_hook shutdown 20 "${moddir}/export-zfs.sh"
921 - inst_simple "${moddir}/zfs-lib.sh" "/lib/dracut-zfs-lib.sh"
922 - if [ -e @sysconfdir@/zfs/zpool.cache ]; then
923 - inst @sysconfdir@/zfs/zpool.cache
924 - type mark_hostonly >/dev/null 2>&1 && mark_hostonly @sysconfdir@/zfs/zpool.cache
926 + inst_script "${moddir}/zfs-lib.sh" "/lib/dracut-zfs-lib.sh"
928 - if [ -e @sysconfdir@/zfs/vdev_id.conf ]; then
929 - inst @sysconfdir@/zfs/vdev_id.conf
930 - type mark_hostonly >/dev/null 2>&1 && mark_hostonly @sysconfdir@/zfs/vdev_id.conf
932 + # -H ensures they are marked host-only
933 + # -o ensures there is no error upon absence of these files
934 + inst_multiple -o -H \
935 + "@sysconfdir@/zfs/zpool.cache" \
936 + "@sysconfdir@/zfs/vdev_id.conf"
938 # Synchronize initramfs and system hostid
939 - if [ -f @sysconfdir@/hostid ]; then
940 - inst @sysconfdir@/hostid
941 - type mark_hostonly >/dev/null 2>&1 && mark_hostonly @sysconfdir@/hostid
942 - elif HOSTID="$(hostid 2>/dev/null)" && [ "${HOSTID}" != "00000000" ]; then
943 - zgenhostid -o "${initdir}@sysconfdir@/hostid" "${HOSTID}"
944 - type mark_hostonly >/dev/null 2>&1 && mark_hostonly @sysconfdir@/hostid
945 + if ! inst_simple -H @sysconfdir@/hostid; then
946 + if HOSTID="$(hostid 2>/dev/null)" && [ "${HOSTID}" != "00000000" ]; then
947 + zgenhostid -o "${initdir}@sysconfdir@/hostid" "${HOSTID}"
948 + mark_hostonly @sysconfdir@/hostid
952 if dracut_module_included "systemd"; then
953 - mkdir -p "${initdir}/$systemdsystemunitdir/zfs-import.target.wants"
954 - for _service in "zfs-import-scan.service" "zfs-import-cache.service" ; do
955 - dracut_install "@systemdunitdir@/$_service"
956 - if ! [ -L "${initdir}/$systemdsystemunitdir/zfs-import.target.wants/$_service" ]; then
957 - ln -sf ../$_service "${initdir}/$systemdsystemunitdir/zfs-import.target.wants/$_service"
958 - type mark_hostonly >/dev/null 2>&1 && mark_hostonly "@systemdunitdir@/$_service"
961 + inst_simple "${systemdsystemunitdir}/zfs-import.target"
962 + systemctl -q --root "${initdir}" add-wants initrd.target zfs-import.target
964 - inst "${moddir}"/zfs-env-bootfs.service "${systemdsystemunitdir}"/zfs-env-bootfs.service
965 - ln -s ../zfs-env-bootfs.service "${initdir}/${systemdsystemunitdir}/zfs-import.target.wants"/zfs-env-bootfs.service
966 - type mark_hostonly >/dev/null 2>&1 && mark_hostonly @systemdunitdir@/zfs-env-bootfs.service
967 + inst_simple "${moddir}/zfs-env-bootfs.service" "${systemdsystemunitdir}/zfs-env-bootfs.service"
968 + systemctl -q --root "${initdir}" add-wants zfs-import.target zfs-env-bootfs.service
970 - dracut_install systemd-ask-password
971 - dracut_install systemd-tty-ask-password-agent
973 - mkdir -p "${initdir}/$systemdsystemunitdir/initrd.target.wants"
974 - dracut_install @systemdunitdir@/zfs-import.target
975 - if ! [ -L "${initdir}/$systemdsystemunitdir/initrd.target.wants"/zfs-import.target ]; then
976 - ln -s ../zfs-import.target "${initdir}/$systemdsystemunitdir/initrd.target.wants"/zfs-import.target
977 - type mark_hostonly >/dev/null 2>&1 && mark_hostonly @systemdunitdir@/zfs-import.target
980 + "zfs-import-scan.service" \
981 + "zfs-import-cache.service" \
982 + "zfs-load-module.service"; do
983 + inst_simple "${systemdsystemunitdir}/${_service}"
984 + systemctl -q --root "${initdir}" add-wants zfs-import.target "${_service}"
987 - for _service in zfs-snapshot-bootfs.service zfs-rollback-bootfs.service ; do
988 - inst "${moddir}/$_service" "${systemdsystemunitdir}/$_service"
989 - if ! [ -L "${initdir}/$systemdsystemunitdir/initrd.target.wants/$_service" ]; then
990 - ln -s "../$_service" "${initdir}/$systemdsystemunitdir/initrd.target.wants/$_service"
993 + "zfs-snapshot-bootfs.service" \
994 + "zfs-rollback-bootfs.service"; do
995 + inst_simple "${moddir}/${_service}" "${systemdsystemunitdir}/${_service}"
996 + systemctl -q --root "${initdir}" add-wants initrd.target "${_service}"
999 - # There isn't a pkg-config variable for this,
1000 - # and dracut doesn't automatically resolve anything this'd be next to
1001 - local systemdsystemenvironmentgeneratordir
1002 - systemdsystemenvironmentgeneratordir="$(pkg-config --variable=prefix systemd || echo "/usr")/lib/systemd/system-environment-generators"
1003 - mkdir -p "${initdir}/${systemdsystemenvironmentgeneratordir}"
1004 - inst "${moddir}"/import-opts-generator.sh "${systemdsystemenvironmentgeneratordir}"/zfs-import-opts.sh
1005 + inst_simple "${moddir}/import-opts-generator.sh" "${systemdutildir}/system-environment-generators/zfs-import-opts.sh"
1008 diff --git a/contrib/dracut/90zfs/mount-zfs.sh.in b/contrib/dracut/90zfs/mount-zfs.sh.in
1009 index 68e3f0e0d..fa9f1bb76 100755
1010 --- a/contrib/dracut/90zfs/mount-zfs.sh.in
1011 +++ b/contrib/dracut/90zfs/mount-zfs.sh.in
1014 . /lib/dracut-zfs-lib.sh
1023 +decode_root_args || return 0
1025 GENERATOR_FILE=/run/systemd/generator/sysroot.mount
1026 GENERATOR_EXTENSION=/run/systemd/generator/sysroot.mount.d/zfs-enhancement.conf
1028 -if [ -e "$GENERATOR_FILE" ] && [ -e "$GENERATOR_EXTENSION" ] ; then
1029 - # If the ZFS sysroot.mount flag exists, the initial RAM disk configured
1030 - # it to mount ZFS on root. In that case, we bail early. This flag
1031 - # file gets created by the zfs-generator program upon successful run.
1032 - info "ZFS: There is a sysroot.mount and zfs-generator has extended it."
1033 - info "ZFS: Delegating root mount to sysroot.mount."
1034 - # Let us tell the initrd to run on shutdown.
1035 - # We have a shutdown hook to run
1036 - # because we imported the pool.
1037 +if [ -e "$GENERATOR_FILE" ] && [ -e "$GENERATOR_EXTENSION" ]; then
1038 + # We're under systemd and dracut-zfs-generator ran to completion.
1039 + info "ZFS: Delegating root mount to sysroot.mount at al."
1041 # We now prevent Dracut from running this thing again.
1042 - for zfsmounthook in "$hookdir"/mount/*zfs* ; do
1043 - if [ -f "$zfsmounthook" ] ; then
1044 - rm -f "$zfsmounthook"
1047 + rm -f "$hookdir"/mount/*zfs*
1051 info "ZFS: No sysroot.mount exists or zfs-generator did not extend it."
1052 info "ZFS: Mounting root with the traditional mount-zfs.sh instead."
1054 +# ask_for_password tries prompt cmd
1056 +# Wraps around plymouth ask-for-password and adds fallback to tty password ask
1057 +# if plymouth is not present.
1058 +ask_for_password() {
1066 + # Prompt for password with plymouth, if installed and running.
1067 + if plymouth --ping 2>/dev/null; then
1068 + plymouth ask-for-password \
1069 + --prompt "$prompt" --number-of-tries="$tries" | \
1074 + while [ "$i" -le "$tries" ]; do
1075 + printf "%s [%i/%i]:" "$prompt" "$i" "$tries" >&2
1076 + eval "$cmd" && ret=0 && break
1083 + } 9>/.console_lock
1085 + [ "$ret" -ne 0 ] && echo "Wrong password" >&2
1090 # Delay until all required block devices are present.
1091 modprobe zfs 2>/dev/null
1097 if [ "${root}" = "zfs:AUTO" ] ; then
1098 - if ! ZFS_DATASET="$(find_bootfs)" ; then
1099 + if ! ZFS_DATASET="$(zpool get -Ho value bootfs | grep -m1 -vFx -)"; then
1100 # shellcheck disable=SC2086
1101 zpool import -N -a ${ZPOOL_IMPORT_OPTS}
1102 - if ! ZFS_DATASET="$(find_bootfs)" ; then
1103 + if ! ZFS_DATASET="$(zpool get -Ho value bootfs | grep -m1 -vFx -)"; then
1104 warn "ZFS: No bootfs attribute found in importable pools."
1110 @@ -53,34 +78,43 @@ if [ "${root}" = "zfs:AUTO" ] ; then
1111 info "ZFS: Using ${ZFS_DATASET} as root."
1114 -ZFS_DATASET="${ZFS_DATASET:-${root#zfs:}}"
1115 +ZFS_DATASET="${ZFS_DATASET:-${root}}"
1116 ZFS_POOL="${ZFS_DATASET%%/*}"
1118 -if import_pool "${ZFS_POOL}" ; then
1119 - # Load keys if we can or if we need to
1120 - if [ "$(zpool list -H -o feature@encryption "${ZFS_POOL}")" = 'active' ]; then
1121 - # if the root dataset has encryption enabled
1122 - ENCRYPTIONROOT="$(zfs get -H -o value encryptionroot "${ZFS_DATASET}")"
1123 - if ! [ "${ENCRYPTIONROOT}" = "-" ]; then
1124 - KEYSTATUS="$(zfs get -H -o value keystatus "${ENCRYPTIONROOT}")"
1125 - # if the key needs to be loaded
1126 - if [ "$KEYSTATUS" = "unavailable" ]; then
1128 - ask_for_password \
1130 - --prompt "Encrypted ZFS password for ${ENCRYPTIONROOT}: " \
1131 - --cmd "zfs load-key '${ENCRYPTIONROOT}'"
1134 +if ! zpool get -Ho name "${ZFS_POOL}" > /dev/null 2>&1; then
1135 + info "ZFS: Importing pool ${ZFS_POOL}..."
1136 + # shellcheck disable=SC2086
1137 + if ! zpool import -N ${ZPOOL_IMPORT_OPTS} "${ZFS_POOL}"; then
1138 + warn "ZFS: Unable to import pool ${ZFS_POOL}"
1144 +# Load keys if we can or if we need to
1145 +# TODO: for_relevant_root_children like in zfs-load-key.sh.in
1146 +if [ "$(zpool get -Ho value feature@encryption "${ZFS_POOL}")" = 'active' ]; then
1147 + # if the root dataset has encryption enabled
1148 + ENCRYPTIONROOT="$(zfs get -Ho value encryptionroot "${ZFS_DATASET}")"
1149 + if ! [ "${ENCRYPTIONROOT}" = "-" ]; then
1150 + KEYSTATUS="$(zfs get -Ho value keystatus "${ENCRYPTIONROOT}")"
1151 + # if the key needs to be loaded
1152 + if [ "$KEYSTATUS" = "unavailable" ]; then
1154 + ask_for_password \
1156 + "Encrypted ZFS password for ${ENCRYPTIONROOT}: " \
1157 + "zfs load-key '${ENCRYPTIONROOT}'"
1160 - # Let us tell the initrd to run on shutdown.
1161 - # We have a shutdown hook to run
1162 - # because we imported the pool.
1163 - info "ZFS: Mounting dataset ${ZFS_DATASET}..."
1164 - if mount_dataset "${ZFS_DATASET}" ; then
1165 - ROOTFS_MOUNTED=yes
1171 +# Let us tell the initrd to run on shutdown.
1172 +# We have a shutdown hook to run
1173 +# because we imported the pool.
1174 +info "ZFS: Mounting dataset ${ZFS_DATASET}..."
1175 +if ! mount_dataset "${ZFS_DATASET}"; then
1179 diff --git a/contrib/dracut/90zfs/parse-zfs.sh.in b/contrib/dracut/90zfs/parse-zfs.sh.in
1180 index 0f92f5c80..f7d1f1c5d 100755
1181 --- a/contrib/dracut/90zfs/parse-zfs.sh.in
1182 +++ b/contrib/dracut/90zfs/parse-zfs.sh.in
1185 # shellcheck disable=SC2034,SC2154
1187 -. /lib/dracut-lib.sh
1188 +# shellcheck source=zfs-lib.sh.in
1189 +. /lib/dracut-zfs-lib.sh
1191 # Let the command line override our host id.
1192 spl_hostid=$(getarg spl_hostid=)
1193 @@ -15,49 +16,20 @@ else
1194 warn "ZFS: Pools may not import correctly."
1200 - # We'll take root unset, root=zfs, or root=zfs:
1201 - # No root set, so we want to read the bootfs attribute. We
1202 - # can't do that until udev settles so we'll set dummy values
1203 - # and hope for the best later on.
1208 - info "ZFS: Enabling autodetection of bootfs after udev settles."
1211 - ZFS=*|zfs:*|FILESYSTEM=*)
1212 - # root is explicit ZFS root. Parse it now. We can handle
1213 - # a root=... param in any of the following formats:
1214 - # root=ZFS=rpool/ROOT
1215 - # root=zfs:rpool/ROOT
1216 - # root=zfs:FILESYSTEM=rpool/ROOT
1217 - # root=FILESYSTEM=rpool/ROOT
1218 - # root=ZFS=pool+with+space/ROOT+WITH+SPACE (translates to root=ZFS=pool with space/ROOT WITH SPACE)
1220 - # Strip down to just the pool/fs
1221 - root="${root#zfs:}"
1222 - root="${root#FILESYSTEM=}"
1223 - root="zfs:${root#ZFS=}"
1224 - # switch + with spaces because kernel cmdline does not allow us to quote parameters
1225 - root=$(echo "$root" | tr '+' ' ')
1229 - info "ZFS: Set ${root} as bootfs."
1233 -# Make sure Dracut is happy that we have a root and will wait for ZFS
1234 -# modules to settle before mounting.
1235 -if [ ${wait_for_zfs} -eq 1 ]; then
1236 - ln -s /dev/null /dev/root 2>/dev/null
1237 - initqueuedir="${hookdir}/initqueue/finished"
1238 - test -d "${initqueuedir}" || {
1239 - initqueuedir="${hookdir}/initqueue-finished"
1241 - echo '[ -e /dev/zfs ]' > "${initqueuedir}/zfs.sh"
1242 +if decode_root_args; then
1243 + if [ "$root" = "zfs:AUTO" ]; then
1244 + info "ZFS: Boot dataset autodetected from bootfs=."
1246 + info "ZFS: Boot dataset is ${root}."
1250 + # Make sure Dracut is happy that we have a root and will wait for ZFS
1251 + # modules to settle before mounting.
1252 + if [ -n "${wait_for_zfs}" ]; then
1253 + ln -s null /dev/root
1254 + echo '[ -e /dev/zfs ]' > "${hookdir}/initqueue/finished/zfs.sh"
1257 + info "ZFS: no ZFS-on-root."
1259 diff --git a/contrib/dracut/90zfs/zfs-env-bootfs.service.in b/contrib/dracut/90zfs/zfs-env-bootfs.service.in
1260 index e143cb5ec..34c88037c 100644
1261 --- a/contrib/dracut/90zfs/zfs-env-bootfs.service.in
1262 +++ b/contrib/dracut/90zfs/zfs-env-bootfs.service.in
1263 @@ -8,7 +8,7 @@ Before=zfs-import.target
1267 -ExecStart=/bin/sh -c "exec systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | grep -m1 -v '^-$')"
1268 +ExecStart=/bin/sh -c "exec systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | grep -m1 -vFx -)"
1271 WantedBy=zfs-import.target
1272 diff --git a/contrib/dracut/90zfs/zfs-generator.sh.in b/contrib/dracut/90zfs/zfs-generator.sh.in
1273 index e50b9530c..56f7ca978 100755
1274 --- a/contrib/dracut/90zfs/zfs-generator.sh.in
1275 +++ b/contrib/dracut/90zfs/zfs-generator.sh.in
1278 -# shellcheck disable=SC2016,SC1004
1279 +# shellcheck disable=SC2016,SC1004,SC2154
1281 grep -wq debug /proc/cmdline && debug=1
1282 [ -n "$debug" ] && echo "zfs-generator: starting" >> /dev/kmsg
1283 @@ -10,37 +10,17 @@ GENERATOR_DIR="$1"
1287 -[ -f /lib/dracut-lib.sh ] && dracutlib=/lib/dracut-lib.sh
1288 -[ -f /usr/lib/dracut/modules.d/99base/dracut-lib.sh ] && dracutlib=/usr/lib/dracut/modules.d/99base/dracut-lib.sh
1289 -command -v getarg >/dev/null 2>&1 || {
1290 - [ -n "$debug" ] && echo "zfs-generator: loading Dracut library from $dracutlib" >> /dev/kmsg
1294 +# shellcheck source=zfs-lib.sh.in
1295 . /lib/dracut-zfs-lib.sh
1296 +decode_root_args || exit 0
1298 -[ -z "$root" ] && root=$(getarg root=)
1299 -[ -z "$rootfstype" ] && rootfstype=$(getarg rootfstype=)
1300 -[ -z "$rootflags" ] && rootflags=$(getarg rootflags=)
1302 -# If root is not ZFS= or zfs: or rootfstype is not zfs
1303 -# then we are not supposed to handle it.
1304 -[ "${root##zfs:}" = "${root}" ] &&
1305 - [ "${root##ZFS=}" = "${root}" ] &&
1306 - [ "$rootfstype" != "zfs" ] &&
1309 +[ -z "${rootflags}" ] && rootflags=$(getarg rootflags=)
1310 case ",${rootflags}," in
1312 ,,) rootflags=zfsutil ;;
1313 *) rootflags="zfsutil,${rootflags}" ;;
1316 -if [ "${root}" != "zfs:AUTO" ]; then
1317 - root="${root##zfs:}"
1318 - root="${root##ZFS=}"
1321 [ -n "$debug" ] && echo "zfs-generator: writing extension for sysroot.mount to $GENERATOR_DIR/sysroot.mount.d/zfs-enhancement.conf" >> /dev/kmsg
1324 @@ -89,7 +69,7 @@ else
1325 _zfs_generator_cb() {
1328 - unit="sysroot$(echo "$mpnt" | tr '/' '-').mount"
1329 + unit="$(systemd-escape --suffix=mount -p "/sysroot${mpnt}")"
1333 diff --git a/contrib/dracut/90zfs/zfs-lib.sh.in b/contrib/dracut/90zfs/zfs-lib.sh.in
1334 index defc0bfc8..a91b56ba7 100755
1335 --- a/contrib/dracut/90zfs/zfs-lib.sh.in
1336 +++ b/contrib/dracut/90zfs/zfs-lib.sh.in
1339 +# shellcheck disable=SC2034
1341 -command -v getarg >/dev/null || . /lib/dracut-lib.sh
1342 -command -v getargbool >/dev/null || {
1343 - # Compatibility with older Dracut versions.
1344 - # With apologies to the Dracut developers.
1346 - _default="$1"; shift
1347 - ! _b=$(getarg "$@") && [ -z "$_b" ] && _b="$_default"
1348 - if [ -n "$_b" ]; then
1349 - [ "$_b" = "0" ] && return 1
1350 - [ "$_b" = "no" ] && return 1
1351 - [ "$_b" = "off" ] && return 1
1356 +command -v getarg >/dev/null || . /lib/dracut-lib.sh || . /usr/lib/dracut/modules.d/99base/dracut-lib.sh
1363 -ZPOOL_IMPORT_OPTS=""
1364 -if getargbool 0 zfs_force -y zfs.force -y zfsforce ; then
1366 +if getargbool 0 zfs_force -y zfs.force -y zfsforce; then
1367 warn "ZFS: Will force-import pools if necessary."
1368 - ZPOOL_IMPORT_OPTS="${ZPOOL_IMPORT_OPTS} -f"
1369 + ZPOOL_IMPORT_OPTS=-f
1373 -# returns the first dataset with the bootfs attribute.
1376 - for dataset in $(zpool list -H -o bootfs); do
1377 - case "${dataset}" in
1381 - "no pools available")
1398 -# imports the given zfs pool if it isn't imported already.
1402 - if ! zpool list -H "${pool}" > /dev/null 2>&1; then
1403 - info "ZFS: Importing pool ${pool}..."
1404 - # shellcheck disable=SC2086
1405 - if ! zpool import -N ${ZPOOL_IMPORT_OPTS} "${pool}" ; then
1406 - warn "ZFS: Unable to import pool ${pool}"
1414 _mount_dataset_cb() {
1415 mount -o zfsutil -t zfs "${1}" "${NEWROOT}${2}"
1417 @@ -121,87 +63,57 @@ for_relevant_root_children() {
1422 -# exports all imported zfs pools.
1427 - for pool in $(zpool list -H -o name) ; do
1428 - if zpool list -H "${pool}" > /dev/null 2>&1; then
1429 - zpool export "${pool}" "$@" || ret=$?
1438 +# Parse root=, rootfstype=, return them decoded and normalised to zfs:AUTO for auto, plain dset for explicit
1440 +# True if ZFS-on-root, false if we shouldn't
1442 +# Supported values:
1448 +# root=ZFS=data/set
1449 +# root=zfs:data/set
1450 +# root=zfs:ZFS=data/set (as a side-effect; allowed but undocumented)
1452 -# Wraps around plymouth ask-for-password and adds fallback to tty password ask
1453 -# if plymouth is not present.
1454 +# rootfstype=zfs AND root=data/set <=> root=data/set
1455 +# rootfstype=zfs AND root= <=> root=zfs:AUTO
1458 -# Command to execute. Required.
1460 -# Password prompt. Note that function already adds ':' at the end.
1463 -# How many times repeat command on its failure. Default is 3.
1464 -# --ply-[cmd|prompt|tries]
1465 -# Command/prompt/tries specific for plymouth password ask only.
1466 -# --tty-[cmd|prompt|tries]
1467 -# Command/prompt/tries specific for tty password ask only.
1469 -# Turn off input echo before tty command is executed and turn on after.
1470 -# It's useful when password is read from stdin.
1471 -ask_for_password() {
1474 - while [ "$#" -gt 0 ]; do
1476 - --cmd) ply_cmd="$2"; tty_cmd="$2"; shift;;
1477 - --ply-cmd) ply_cmd="$2"; shift;;
1478 - --tty-cmd) tty_cmd="$2"; shift;;
1479 - --prompt) ply_prompt="$2"; tty_prompt="$2"; shift;;
1480 - --ply-prompt) ply_prompt="$2"; shift;;
1481 - --tty-prompt) tty_prompt="$2"; shift;;
1482 - --tries) ply_tries="$2"; tty_tries="$2"; shift;;
1483 - --ply-tries) ply_tries="$2"; shift;;
1484 - --tty-tries) tty_tries="$2"; shift;;
1485 - --tty-echo-off) tty_echo_off=yes;;
1486 +# '+'es in explicit dataset decoded to ' 's.
1487 +decode_root_args() {
1488 + if [ -n "$rootfstype" ]; then
1489 + [ "$rootfstype" = zfs ]
1493 + root=$(getarg root=)
1494 + rootfstype=$(getarg rootfstype=)
1496 + # shellcheck disable=SC2249
1498 + ""|zfs|zfs:|zfs:AUTO)
1505 + root="${root#zfs:}"
1506 + root="${root#ZFS=}"
1507 + root=$(echo "$root" | tr '+' ' ')
1513 + if [ "$rootfstype" = "zfs" ]; then
1515 + "") root=zfs:AUTO ;;
1516 + *) root=$(echo "$root" | tr '+' ' ') ;;
1522 - # Prompt for password with plymouth, if installed and running.
1523 - if plymouth --ping 2>/dev/null; then
1524 - plymouth ask-for-password \
1525 - --prompt "$ply_prompt" --number-of-tries="$ply_tries" | \
1529 - if [ "$tty_echo_off" = yes ]; then
1530 - stty_orig="$(stty -g)"
1535 - while [ "$i" -le "$tty_tries" ]; do
1536 - [ -n "$tty_prompt" ] && \
1537 - printf "%s [%i/%i]:" "$tty_prompt" "$i" "$tty_tries" >&2
1538 - eval "$tty_cmd" && ret=0 && break
1541 - [ -n "$tty_prompt" ] && printf '\n' >&2
1544 - [ "$tty_echo_off" = yes ] && stty "$stty_orig"
1546 - } 9>/.console_lock
1550 - [ $ret -ne 0 ] && echo "Wrong password" >&2
1554 diff --git a/contrib/dracut/90zfs/zfs-load-key.sh.in b/contrib/dracut/90zfs/zfs-load-key.sh.in
1555 index c974b3d9e..d916f43b4 100755
1556 --- a/contrib/dracut/90zfs/zfs-load-key.sh.in
1557 +++ b/contrib/dracut/90zfs/zfs-load-key.sh.in
1559 # only run this on systemd systems, we handle the decrypt in mount-zfs.sh in the mount hook otherwise
1560 [ -e /bin/systemctl ] || [ -e /usr/bin/systemctl ] || return 0
1562 -# This script only gets executed on systemd systems, see mount-zfs.sh for non-systemd systems
1563 +# shellcheck source=zfs-lib.sh.in
1564 +. /lib/dracut-zfs-lib.sh
1566 -# import the libs now that we know the pool imported
1567 -[ -f /lib/dracut-lib.sh ] && dracutlib=/lib/dracut-lib.sh
1568 -[ -f /usr/lib/dracut/modules.d/99base/dracut-lib.sh ] && dracutlib=/usr/lib/dracut/modules.d/99base/dracut-lib.sh
1569 -# shellcheck source=./lib-zfs.sh.in
1572 -# load the kernel command line vars
1573 -[ -z "$root" ] && root="$(getarg root=)"
1574 -# If root is not ZFS= or zfs: or rootfstype is not zfs then we are not supposed to handle it.
1575 -[ "${root##zfs:}" = "${root}" ] && [ "${root##ZFS=}" = "${root}" ] && [ "$rootfstype" != "zfs" ] && exit 0
1576 +decode_root_args || return 0
1578 # There is a race between the zpool import and the pre-mount hooks, so we wait for a pool to be imported
1579 -while [ "$(zpool list -H)" = "" ]; do
1580 - systemctl is-failed --quiet zfs-import-cache.service zfs-import-scan.service && exit 1
1581 +while ! systemctl is-active --quiet zfs-import.target; do
1582 + systemctl is-failed --quiet zfs-import-cache.service zfs-import-scan.service && return 1
1586 -# run this after import as zfs-import-cache/scan service is confirmed good
1587 -# we do not overwrite the ${root} variable, but create a new one, BOOTFS, to hold the dataset
1588 -if [ "${root}" = "zfs:AUTO" ] ; then
1589 - BOOTFS="$(zpool list -H -o bootfs | awk '$1 != "-" {print; exit}')"
1591 - BOOTFS="${root##zfs:}"
1592 - BOOTFS="${BOOTFS##ZFS=}"
1594 +if [ "$BOOTFS" = "zfs:AUTO" ]; then
1595 + BOOTFS="$(zpool get -Ho value bootfs | grep -m1 -vFx -)"
1598 -# if pool encryption is active and the zfs command understands '-o encryption'
1599 -if [ "$(zpool list -H -o feature@encryption "${BOOTFS%%/*}")" = 'active' ]; then
1600 - # if the root dataset has encryption enabled
1601 - ENCRYPTIONROOT="$(zfs get -H -o value encryptionroot "${BOOTFS}")"
1602 - if ! [ "${ENCRYPTIONROOT}" = "-" ]; then
1603 - KEYSTATUS="$(zfs get -H -o value keystatus "${ENCRYPTIONROOT}")"
1604 - # continue only if the key needs to be loaded
1605 - [ "$KEYSTATUS" = "unavailable" ] || exit 0
1606 +[ "$(zpool get -Ho value feature@encryption "${BOOTFS%%/*}")" = 'active' ] || return 0
1611 + ENCRYPTIONROOT="$(zfs get -Ho value encryptionroot "${dataset}")"
1612 + [ "${ENCRYPTIONROOT}" = "-" ] && return 0
1614 - KEYLOCATION="$(zfs get -H -o value keylocation "${ENCRYPTIONROOT}")"
1615 - case "${KEYLOCATION%%://*}" in
1617 - for _ in 1 2 3; do
1618 - systemd-ask-password --no-tty "Encrypted ZFS password for ${BOOTFS}" | zfs load-key "${ENCRYPTIONROOT}" && break
1619 + [ "$(zfs get -Ho value keystatus "${ENCRYPTIONROOT}")" = "unavailable" ] || return 0
1621 + KEYLOCATION="$(zfs get -Ho value keylocation "${ENCRYPTIONROOT}")"
1622 + case "${KEYLOCATION%%://*}" in
1624 + for _ in 1 2 3; do
1625 + systemd-ask-password --no-tty "Encrypted ZFS password for ${dataset}" | zfs load-key "${ENCRYPTIONROOT}" && break
1629 + systemctl start network-online.target
1630 + zfs load-key "${ENCRYPTIONROOT}"
1633 + KEYFILE="${KEYLOCATION#file://}"
1634 + [ -r "${KEYFILE}" ] || udevadm settle
1635 + [ -r "${KEYFILE}" ] || {
1636 + info "ZFS: Waiting for key ${KEYFILE} for ${ENCRYPTIONROOT}..."
1637 + for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
1639 + [ -r "${KEYFILE}" ] && break
1643 - systemctl start network-online.target
1644 - zfs load-key "${ENCRYPTIONROOT}"
1647 - KEYFILE="${KEYLOCATION#file://}"
1648 - [ -r "${KEYFILE}" ] || udevadm settle
1649 - [ -r "${KEYFILE}" ] || {
1650 - info "Waiting for key ${KEYFILE} for ${ENCRYPTIONROOT}..."
1651 - for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
1653 - [ -r "${KEYFILE}" ] && break
1656 - [ -r "${KEYFILE}" ] || warn "Key ${KEYFILE} for ${ENCRYPTIONROOT} hasn't appeared. Trying anyway."
1657 - zfs load-key "${ENCRYPTIONROOT}"
1660 - zfs load-key "${ENCRYPTIONROOT}"
1666 + [ -r "${KEYFILE}" ] || warn "ZFS: Key ${KEYFILE} for ${ENCRYPTIONROOT} hasn't appeared. Trying anyway."
1667 + zfs load-key "${ENCRYPTIONROOT}"
1670 + zfs load-key "${ENCRYPTIONROOT}"
1675 +_load_key_cb "$BOOTFS"
1676 +for_relevant_root_children "$BOOTFS" _load_key_cb
1677 diff --git a/contrib/dracut/90zfs/zfs-needshutdown.sh.in b/contrib/dracut/90zfs/zfs-needshutdown.sh.in
1678 index dd6de30c2..7fb825bc9 100755
1679 --- a/contrib/dracut/90zfs/zfs-needshutdown.sh.in
1680 +++ b/contrib/dracut/90zfs/zfs-needshutdown.sh.in
1683 command -v getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh
1685 -if zpool list 2>&1 | grep -q 'no pools available' ; then
1686 +if [ -z "$(zpool get -Ho value name)" ]; then
1687 info "ZFS: No active pools, no need to export anything."
1689 info "ZFS: There is an active pool, will export it."
1690 diff --git a/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in b/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in
1691 index bdc246943..b4f570751 100644
1692 --- a/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in
1693 +++ b/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in
1696 Description=Rollback bootfs just before it is mounted
1697 Requisite=zfs-import.target
1698 -After=zfs-import.target zfs-snapshot-bootfs.service
1699 +After=zfs-import.target dracut-pre-mount.service zfs-snapshot-bootfs.service
1700 Before=dracut-mount.service
1701 DefaultDependencies=no
1702 ConditionKernelCommandLine=bootfs.rollback
1705 -# ${BOOTFS} should have been set by zfs-env-bootfs.service
1707 -ExecStartPre=/bin/sh -c 'test -n "${BOOTFS}"'
1708 -ExecStart=/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "${BOOTFS}@${SNAPNAME:-%v}"'
1709 +ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS" SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "$root@${SNAPNAME:-%v}"'
1711 diff --git a/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in b/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in
1712 index 6ea13850c..afdba2c9d 100644
1713 --- a/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in
1714 +++ b/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in
1717 Description=Snapshot bootfs just before it is mounted
1718 Requisite=zfs-import.target
1719 -After=zfs-import.target
1720 +After=zfs-import.target dracut-pre-mount.service
1721 Before=dracut-mount.service
1722 DefaultDependencies=no
1723 ConditionKernelCommandLine=bootfs.snapshot
1726 -# ${BOOTFS} should have been set by zfs-env-bootfs.service
1728 -ExecStartPre=/bin/sh -c 'test -n "${BOOTFS}"'
1729 -ExecStart=-/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "${BOOTFS}@${SNAPNAME:-%v}"'
1730 +ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS" SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$root@${SNAPNAME:-%v}"'
1732 diff --git a/contrib/dracut/README.dracut.markdown b/contrib/dracut/README.dracut.markdown
1733 index f31543c3c..b7cd8c812 100644
1734 --- a/contrib/dracut/README.dracut.markdown
1735 +++ b/contrib/dracut/README.dracut.markdown
1737 -How to setup a zfs root filesystem using dracut
1738 ------------------------------------------------
1740 +1. Install `zfs-dracut`
1741 +2. Set `mountpoint=/` for your root dataset (for compatibility, `legacy` also works, but is not recommended for new installations):
1743 + zfs set mountpoint=/ pool/dataset
1745 +3. Either (a) set `bootfs=` on the pool to the dataset:
1747 + zpool set bootfs=pool/dataset pool
1749 +4. Or (b) append `root=zfs:pool/dataset` to your kernel cmdline.
1750 +5. Re-generate your initrd and update it in your boot bundle
1752 -1) Install the zfs-dracut package. This package adds a zfs dracut module
1753 -to the /usr/share/dracut/modules.d/ directory which allows dracut to
1754 -create an initramfs which is zfs aware.
1755 +Encrypted datasets have keys loaded automatically or prompted for.
1757 -2) Set the bootfs property for the bootable dataset in the pool. Then set
1758 -the dataset mountpoint property to '/'.
1759 +If the root dataset contains children with `mountpoint=`s of `/etc`, `/bin`, `/lib*`, or `/usr`, they're mounted too.
1761 - $ zpool set bootfs=pool/dataset pool
1762 - $ zfs set mountpoint=/ pool/dataset
1763 +For complete documentation, see `dracut.zfs(7)`.
1765 -Alternately, legacy mountpoints can be used by setting the 'root=' option
1766 -on the kernel line of your grub.conf/menu.lst configuration file. Then
1767 -set the dataset mountpoint property to 'legacy'.
1769 +1. `root=` | Root dataset is… |
1770 + ---------------------------|----------------------------------------------------------|
1771 + *(empty)* | the first `bootfs=` after `zpool import -aN` |
1772 + `zfs:AUTO`, `zfs:`, `zfs` | *(as above, but overriding other autoselection methods)* |
1773 + `ZFS=pool/dataset` | `pool/dataset` |
1774 + `zfs:pool/dataset` | *(as above)* |
1776 - $ grub.conf/menu.lst: kernel ... root=ZFS=pool/dataset
1777 - $ zfs set mountpoint=legacy pool/dataset
1778 + All `+`es are replaced with spaces (i.e. to boot from `root pool/data set`, pass `root=zfs:root+pool/data+set`).
1780 -3) To set zfs module options put them in /etc/modprobe.d/zfs.conf file.
1781 -The complete list of zfs module options is available by running the
1782 -_modinfo zfs_ command. Commonly set options include: zfs_arc_min,
1783 -zfs_arc_max, zfs_prefetch_disable, and zfs_vdev_max_pending.
1784 + The dataset can be at any depth, including being the pool's root dataset (i.e. `root=zfs:pool`).
1786 -4) Finally, create your new initramfs by running dracut.
1787 + `rootfstype=zfs` is equivalent to `root=zfs:AUTO`, `rootfstype=zfs root=pool/dataset` is equivalent to `root=zfs:pool/dataset`.
1789 - $ dracut --force /path/to/initramfs kernel_version
1790 +2. `spl_hostid`: passed to `zgenhostid -f`, useful to override the `/etc/hostid` file baked into the initrd.
1792 -Kernel Command Line
1793 --------------------
1794 +3. `bootfs.snapshot`, `bootfs.snapshot=snapshot-name`: enables `zfs-snapshot-bootfs.service`,
1795 + which creates a snapshot `$root_dataset@$(uname -r)` (or, in the second form, `$root_dataset@snapshot-name`)
1796 + after pool import but before the rootfs is mounted.
1797 + Failure to create the snapshot is noted, but booting continues.
1799 -The initramfs' behavior is influenced by the following kernel command line
1800 -parameters passed in from the boot loader:
1801 +4. `bootfs.rollback`, `bootfs.rollback=snapshot-name`: enables `zfs-snapshot-bootfs.service`,
1802 + which `-Rf` rolls back to `$root_dataset@$(uname -r)` (or, in the second form, `$root_dataset@snapshot-name`)
1803 + after pool import but before the rootfs is mounted.
1804 + Failure to roll back will fall down to the rescue shell.
1805 + This has obvious potential for data loss: make sure your persistent data is not below the rootfs and you don't care about any intermediate snapshots.
1807 -* `root=...`: If not set, importable pools are searched for a bootfs
1808 -attribute. If an explicitly set root is desired, you may use
1809 -`root=ZFS:pool/dataset`
1810 +5. If both `bootfs.snapshot` and `bootfs.rollback` are set, `bootfs.rollback` is ordered *after* `bootfs.snapshot`.
1812 -* `zfs_force=0`: If set to 1, the initramfs will run `zpool import -f` when
1813 -attempting to import pools if the required pool isn't automatically imported
1814 -by the zfs module. This can save you a trip to a bootcd if hostid has
1815 -changed, but is dangerous and can lead to zpool corruption, particularly in
1816 -cases where storage is on a shared fabric such as iSCSI where multiple hosts
1817 -can access storage devices concurrently. _Please understand the implications
1818 -of force-importing a pool before enabling this option!_
1820 -* `spl_hostid`: By default, the hostid used by the SPL module is read from
1821 -/etc/hostid inside the initramfs. This file is placed there from the host
1822 -system when the initramfs is built which effectively ties the ramdisk to the
1823 -host which builds it. If a different hostid is desired, one may be set in
1824 -this attribute and will override any file present in the ramdisk. The
1825 -format should be hex exactly as found in the `/etc/hostid` file, IE
1826 -`spl_hostid=0x00bab10c`.
1828 -Note that changing the hostid between boots will most likely lead to an
1829 -un-importable pool since the last importing hostid won't match. In order
1830 -to recover from this, you may use the `zfs_force` option or boot from a
1831 -different filesystem and `zpool import -f` then `zpool export` the pool
1832 -before rebooting with the new hostid.
1834 -* `bootfs.snapshot`: If listed, enables the zfs-snapshot-bootfs service on a Dracut system. The zfs-snapshot-bootfs service simply runs `zfs snapshot $BOOTFS@%v` after the pool has been imported but before the bootfs is mounted. `$BOOTFS` is substituted with the value of the bootfs setting on the pool. `%v` is substituted with the version string of the kernel currently being booted (e.g. 5.6.6-200.fc31.x86\_64). Failure to create the snapshot (e.g. because one with the same name already exists) will be logged, but will not otherwise interrupt the boot process.
1836 - It is safe to leave the bootfs.snapshot flag set persistently on your kernel command line so that a new snapshot of your bootfs will be created on every kernel update. If you leave bootfs.snapshot set persistently on your kernel command line, you may find the below script helpful for automatically removing old snapshots of the bootfs along with their associated kernel.
1840 - if [[ "$1" == "remove" ]] && grep -q "\bbootfs.snapshot\b" /proc/cmdline; then
1841 - zfs destroy $(findmnt -n -o source /)@$2 &> /dev/null
1846 - To use the above script place it in a plain text file named /etc/kernel/install.d/99-zfs-cleanup.install and mark it executable with the following command:
1848 - $ chmod +x /etc/kernel/install.d/99-zfs-cleanup.install
1850 - On Red Hat based systems, you can change the value of `installonly_limit` in /etc/dnf/dnf.conf to adjust the number of kernels and their associated snapshots that are kept.
1852 -* `bootfs.snapshot=<snapname>`: Is identical to the bootfs.snapshot parameter explained above except that the value substituted for \<snapname\> will be used when creating the snapshot instead of the version string of the kernel currently being booted.
1854 -* `bootfs.rollback`: If listed, enables the zfs-rollback-bootfs service on a Dracut system. The zfs-rollback-bootfs service simply runs `zfs rollback -Rf $BOOTFS@%v` after the pool has been imported but before the bootfs is mounted. If the rollback operation fails, the boot process will be interrupted with a Dracut rescue shell. __Use this parameter with caution. Intermediate snapshots of the bootfs will be destroyed!__ TIP: Keep your user data (e.g. /home) on separate file systems (it can be in the same pool though).
1856 -* `bootfs.rollback=<snapname>`: Is identical to the bootfs.rollback parameter explained above except that the value substituted for \<snapname\> will be used when rolling back the bootfs instead of the version string of the kernel currently being booted. If you use this form, choose a snapshot that is new enough to contain the needed kernel modules under /lib/modules or use a kernel that has all the needed modules built-in.
1861 -The Dracut module consists of the following files (less Makefile's):
1863 -* `module-setup.sh`: Script run by the initramfs builder to create the
1864 -ramdisk. Contains instructions on which files are required by the modules
1865 -and z* programs. Also triggers inclusion of `/etc/hostid` and the zpool
1866 -cache. This file is not included in the initramfs.
1868 -* `90-zfs.rules`: udev rules which trigger loading of the ZFS modules at boot.
1870 -* `zfs-lib.sh`: Utility functions used by the other files.
1872 -* `parse-zfs.sh`: Run early in the initramfs boot process to parse kernel
1873 -command line and determine if ZFS is the active root filesystem.
1875 -* `mount-zfs.sh`: Run later in initramfs boot process after udev has settled
1876 -to mount the root dataset.
1878 -* `export-zfs.sh`: Run on shutdown after dracut has restored the initramfs
1879 -and pivoted to it, allowing for a clean unmount and export of the ZFS root.
1884 -This file provides a few handy functions for working with ZFS. Those
1885 -functions are used by the `mount-zfs.sh` and `export-zfs.sh` files.
1886 -However, they could be used by any other file as well, as long as the file
1887 -sources `/lib/dracut-zfs-lib.sh`.
1892 -This file is run by the Dracut script within the live system, not at boot
1893 -time. It's not included in the final initramfs. Functions in this script
1894 -describe which files are needed by ZFS at boot time.
1896 -Currently all the various z* and spl modules are included, a dependency is
1897 -asserted on udev-rules, and the various zfs, zpool, etc. helpers are included.
1898 -Dracut provides library functions which automatically gather the shared libs
1899 -necessary to run each of these binaries, so statically built binaries are
1902 -The zpool and zvol udev rules files are copied from where they are
1903 -installed by the ZFS build. __PACKAGERS TAKE NOTE__: If you move
1904 -`/etc/udev/rules/60-z*.rules`, you'll need to update this file to match.
1906 -Currently this file also includes `/etc/hostid` and `/etc/zfs/zpool.cache`
1907 -which means the generated ramdisk is specific to the host system which built
1908 -it. If a generic initramfs is required, it may be preferable to omit these
1909 -files and specify the `spl_hostid` from the boot loader instead.
1914 -Run during the cmdline phase of the initramfs boot process, this script
1915 -performs some basic sanity checks on kernel command line parameters to
1916 -determine if booting from ZFS is likely to be what is desired. Dracut
1917 -requires this script to adjust the `root` variable if required and to set
1918 -`rootok=1` if a mountable root filesystem is available. Unfortunately this
1919 -script must run before udev is settled and kernel modules are known to be
1920 -loaded, so accessing the zpool and zfs commands is unsafe.
1922 -If the root=ZFS... parameter is set on the command line, then it's at least
1923 -certain that ZFS is what is desired, though this script is unable to
1924 -determine if ZFS is in fact available. This script will alter the `root`
1925 -parameter to replace several historical forms of specifying the pool and
1926 -dataset name with the canonical form of `zfs:pool/dataset`.
1928 -If no root= parameter is set, the best this script can do is guess that
1929 -ZFS is desired. At present, no other known filesystems will work with no
1930 -root= parameter, though this might possibly interfere with using the
1931 -compiled-in default root in the kernel image. It's considered unlikely
1932 -that would ever be the case when an initramfs is in use, so this script
1933 -sets `root=zfs:AUTO` and hopes for the best.
1935 -Once the root=... (or lack thereof) parameter is parsed, a dummy symlink
1936 -is created from `/dev/root` -> `/dev/null` to satisfy parts of the Dracut
1937 -process which check for presence of a single root device node.
1939 -Finally, an initqueue/finished hook is registered which causes the initqueue
1940 -phase of Dracut to wait for `/dev/zfs` to become available before attempting
1946 -This script is run after udev has settled and all tasks in the initqueue
1947 -have succeeded. This ensures that `/dev/zfs` is available and that the
1948 -various ZFS modules are successfully loaded. As it is now safe to call
1949 -zpool and friends, we can proceed to find the bootfs attribute if necessary.
1951 -If the root parameter was explicitly set on the command line, no parsing is
1952 -necessary. The list of imported pools is checked to see if the desired pool
1953 -is already imported. If it's not, and attempt is made to import the pool
1954 -explicitly, though no force is attempted. Finally the specified dataset
1955 -is mounted on `$NEWROOT`, first using the `-o zfsutil` option to handle
1956 -non-legacy mounts, then if that fails, without zfsutil to handle legacy
1959 -If no root parameter was specified, this script attempts to find a pool with
1960 -its bootfs attribute set. First, already-imported pools are scanned and if
1961 -an appropriate pool is found, no additional pools are imported. If no pool
1962 -with bootfs is found, any additional pools in the system are imported with
1963 -`zpool import -N -a`, and the scan for bootfs is tried again. If no bootfs
1964 -is found with all pools imported, all pools are re-exported, and boot fails.
1965 -Assuming a bootfs is found, an attempt is made to mount it to `$NEWROOT`,
1966 -first with, then without the zfsutil option as above.
1968 -Ordinarily pools are imported _without_ the force option which may cause
1969 -boot to fail if the hostid has changed or a pool has been physically moved
1970 -between servers. The `zfs_force` kernel parameter is provided which when
1971 -set to `1` causes `zpool import` to be run with the `-f` flag. Forcing pool
1972 -import can lead to serious data corruption and loss of pools, so this option
1973 -should be used with extreme caution. Note that even with this flag set, if
1974 -the required zpool was auto-imported by the kernel module, no additional
1975 -`zpool import` commands are run, so nothing is forced.
1980 -Normally the zpool containing the root dataset cannot be exported on
1981 -shutdown as it is still in use by the init process. To work around this,
1982 -Dracut is able to restore the initramfs on shutdown and pivot to it.
1983 -All remaining process are then running from a ramdisk, allowing for a
1984 -clean unmount and export of the ZFS root. The theory of operation is
1985 -described in detail in the [Dracut manual](https://www.kernel.org/pub/linux/utils/boot/dracut/dracut.html#_dracut_on_shutdown).
1987 -This script will try to export all remaining zpools after Dracut has
1988 -pivoted to the initramfs. If an initial regular export is not successful,
1989 -Dracut will call this script once more with the `final` option,
1990 -in which case a forceful export is attempted.
1992 -Other Dracut modules include similar shutdown scripts and Dracut
1993 -invokes these scripts round-robin until they succeed. In particular,
1994 -the `90dm` module installs a script which tries to close and remove
1995 -all device mapper targets. Thus, if there are ZVOLs containing
1996 -dm-crypt volumes or if the zpool itself is backed by a dm-crypt
1997 -volume, the shutdown scripts will try to untangle this.
1998 +6. `zfs_force`, `zfs.force`, `zfsforce`: add `-f` to all `zpool import` invocations.
1999 + May be useful. Use with caution.
2000 diff --git a/etc/default/Makefile.am b/etc/default/Makefile.am
2001 index b88eb5494..f061692c3 100644
2002 --- a/etc/default/Makefile.am
2003 +++ b/etc/default/Makefile.am
2005 include $(top_srcdir)/config/Substfiles.am
2006 include $(top_srcdir)/config/Shellcheck.am
2008 -initconf_SCRIPTS = zfs
2009 +initconf_DATA = zfs
2011 -SUBSTFILES += $(initconf_SCRIPTS)
2012 +SUBSTFILES += $(initconf_DATA)
2014 +SHELLCHECKSCRIPTS = $(initconf_DATA)
2015 SHELLCHECK_SHELL = sh
2016 SHELLCHECK_IGNORE = ,SC2034
2017 diff --git a/etc/systemd/system-generators/zfs-mount-generator.c b/etc/systemd/system-generators/zfs-mount-generator.c
2018 index b806339de..f4c6c26a0 100644
2019 --- a/etc/systemd/system-generators/zfs-mount-generator.c
2020 +++ b/etc/systemd/system-generators/zfs-mount-generator.c
2022 #include <sys/types.h>
2023 #include <sys/time.h>
2024 #include <sys/stat.h>
2025 -#include <sys/wait.h>
2026 -#include <sys/mman.h>
2027 -#include <semaphore.h>
2028 #include <stdbool.h>
2035 -#define STRCMP ((int(*)(const void *, const void *))&strcmp)
2036 -#define PID_T_CMP ((int(*)(const void *, const void *))&pid_t_cmp)
2039 -pid_t_cmp(const pid_t *lhs, const pid_t *rhs)
2042 - * This is always valid, quoth sys_types.h(7posix):
2043 - * > blksize_t, pid_t, and ssize_t shall be signed integer types.
2045 - return (*lhs - *rhs);
2048 + * For debugging only.
2050 + * Free statics with trivial life-times,
2051 + * but saved line filenames are replaced with a static string.
2053 +#define FREE_STATICS false
2055 -#define EXIT_ENOMEM() \
2057 - fprintf(stderr, PROGNAME "[%d]: " \
2058 - "not enough memory (L%d)!\n", getpid(), __LINE__); \
2061 +#define nitems(arr) (sizeof (arr) / sizeof (*arr))
2062 +#define STRCMP ((int(*)(const void *, const void *))&strcmp)
2065 #define PROGNAME "zfs-mount-generator"
2066 @@ -80,20 +68,11 @@ pid_t_cmp(const pid_t *lhs, const pid_t *rhs)
2067 #define URI_REGEX_S "^\\([A-Za-z][A-Za-z0-9+.\\-]*\\):\\/\\/\\(.*\\)$"
2068 static regex_t uri_regex;
2070 -static char *argv0;
2072 static const char *destdir = "/tmp";
2073 static int destdir_fd = -1;
2075 static void *known_pools = NULL; /* tsearch() of C strings */
2077 - sem_t noauto_not_on_sem;
2079 - sem_t noauto_names_sem;
2080 - size_t noauto_names_len;
2081 - size_t noauto_names_max;
2082 - char noauto_names[][NAME_MAX];
2084 +static void *noauto_files = NULL; /* tsearch() of C strings */
2088 @@ -103,8 +82,12 @@ systemd_escape(const char *input, const char *prepend, const char *append)
2089 size_t applen = strlen(append);
2090 size_t prelen = strlen(prepend);
2091 char *ret = malloc(4 * len + prelen + applen + 1);
2095 + fprintf(stderr, PROGNAME "[%d]: "
2096 + "out of memory to escape \"%s%s%s\"!\n",
2097 + getpid(), prepend, input, append);
2101 memcpy(ret, prepend, prelen);
2102 char *out = ret + prelen;
2103 @@ -166,8 +149,12 @@ systemd_escape_path(char *input, const char *prepend, const char *append)
2105 if (strcmp(input, "/") == 0) {
2107 - if (asprintf(&ret, "%s-%s", prepend, append) == -1)
2109 + if (asprintf(&ret, "%s-%s", prepend, append) == -1) {
2110 + fprintf(stderr, PROGNAME "[%d]: "
2111 + "out of memory to escape \"%s%s%s\"!\n",
2112 + getpid(), prepend, input, append);
2118 @@ -209,6 +196,10 @@ fopenat(int dirfd, const char *pathname, int flags,
2120 line_worker(char *line, const char *cachefile)
2123 + void *tofree_all[8];
2124 + void **tofree = tofree_all;
2128 const char *dataset = strtok_r(line, "\t", &toktmp);
2129 @@ -240,11 +231,9 @@ line_worker(char *line, const char *cachefile)
2130 if (p_nbmand == NULL) {
2131 fprintf(stderr, PROGNAME "[%d]: %s: not enough tokens!\n",
2137 - strncpy(argv0, dataset, strlen(argv0));
2139 /* Minimal pre-requisites to mount a ZFS dataset */
2140 const char *after = "zfs-import.target";
2141 const char *wants = "zfs-import.target";
2142 @@ -280,28 +269,31 @@ line_worker(char *line, const char *cachefile)
2145 if (strcmp(p_encroot, "-") != 0) {
2146 - char *keyloadunit =
2147 + char *keyloadunit = *(tofree++) =
2148 systemd_escape(p_encroot, "zfs-load-key@", ".service");
2149 + if (keyloadunit == NULL)
2152 if (strcmp(dataset, p_encroot) == 0) {
2153 const char *keymountdep = NULL;
2154 bool is_prompt = false;
2155 + bool need_network = false;
2157 regmatch_t uri_matches[3];
2158 if (regexec(&uri_regex, p_keyloc,
2159 - sizeof (uri_matches) / sizeof (*uri_matches),
2160 - uri_matches, 0) == 0) {
2161 + nitems(uri_matches), uri_matches, 0) == 0) {
2162 + p_keyloc[uri_matches[1].rm_eo] = '\0';
2163 p_keyloc[uri_matches[2].rm_eo] = '\0';
2164 + const char *scheme =
2165 + &p_keyloc[uri_matches[1].rm_so];
2167 &p_keyloc[uri_matches[2].rm_so];
2170 - * Assumes all URI keylocations need
2171 - * the mount for their path;
2172 - * http://, for example, wouldn't
2173 - * (but it'd need network-online.target et al.)
2175 - keymountdep = path;
2176 + if (strcmp(scheme, "https") == 0 ||
2177 + strcmp(scheme, "http") == 0)
2178 + need_network = true;
2180 + keymountdep = path;
2182 if (strcmp(p_keyloc, "prompt") != 0)
2183 fprintf(stderr, PROGNAME "[%d]: %s: "
2184 @@ -321,7 +313,7 @@ line_worker(char *line, const char *cachefile)
2185 "couldn't open %s under %s: %s\n",
2186 getpid(), dataset, keyloadunit, destdir,
2192 fprintf(keyloadunit_f,
2193 @@ -335,20 +327,22 @@ line_worker(char *line, const char *cachefile)
2195 dataset, cachefile, wants, after);
2198 + fprintf(keyloadunit_f,
2199 + "Wants=network-online.target\n"
2200 + "After=network-online.target\n");
2202 if (p_systemd_requires)
2203 fprintf(keyloadunit_f,
2204 "Requires=%s\n", p_systemd_requires);
2206 - if (p_systemd_requiresmountsfor || keymountdep) {
2207 - fprintf(keyloadunit_f, "RequiresMountsFor=");
2208 - if (p_systemd_requiresmountsfor)
2209 - fprintf(keyloadunit_f,
2210 - "%s ", p_systemd_requiresmountsfor);
2212 - fprintf(keyloadunit_f,
2213 - "'%s'", keymountdep);
2214 - fprintf(keyloadunit_f, "\n");
2216 + if (p_systemd_requiresmountsfor)
2217 + fprintf(keyloadunit_f,
2218 + "RequiresMountsFor=%s\n",
2219 + p_systemd_requiresmountsfor);
2221 + fprintf(keyloadunit_f,
2222 + "RequiresMountsFor='%s'\n", keymountdep);
2225 fprintf(keyloadunit_f,
2226 @@ -393,9 +387,13 @@ line_worker(char *line, const char *cachefile)
2227 if (after[0] == '\0')
2228 after = keyloadunit;
2229 else if (asprintf(&toktmp, "%s %s", after, keyloadunit) != -1)
2233 + after = *(tofree++) = toktmp;
2235 + fprintf(stderr, PROGNAME "[%d]: %s: "
2236 + "out of memory to generate after=\"%s %s\"!\n",
2237 + getpid(), dataset, after, keyloadunit);
2243 @@ -404,12 +402,12 @@ line_worker(char *line, const char *cachefile)
2244 strcmp(p_systemd_ignore, "off") == 0) {
2246 } else if (strcmp(p_systemd_ignore, "on") == 0)
2250 fprintf(stderr, PROGNAME "[%d]: %s: "
2251 "invalid org.openzfs.systemd:ignore=%s\n",
2252 getpid(), dataset, p_systemd_ignore);
2257 /* Check for canmount */
2258 @@ -418,21 +416,21 @@ line_worker(char *line, const char *cachefile)
2259 } else if (strcmp(p_canmount, "noauto") == 0)
2261 else if (strcmp(p_canmount, "off") == 0)
2265 fprintf(stderr, PROGNAME "[%d]: %s: invalid canmount=%s\n",
2266 getpid(), dataset, p_canmount);
2271 /* Check for legacy and blank mountpoints */
2272 if (strcmp(p_mountpoint, "legacy") == 0 ||
2273 strcmp(p_mountpoint, "none") == 0)
2276 else if (p_mountpoint[0] != '/') {
2277 fprintf(stderr, PROGNAME "[%d]: %s: invalid mountpoint=%s\n",
2278 getpid(), dataset, p_mountpoint);
2283 /* Escape the mountpoint per systemd policy */
2284 @@ -442,7 +440,7 @@ line_worker(char *line, const char *cachefile)
2286 PROGNAME "[%d]: %s: abnormal simplified mountpoint: %s\n",
2287 getpid(), dataset, p_mountpoint);
2293 @@ -552,8 +550,7 @@ line_worker(char *line, const char *cachefile)
2294 * files if we're sure they were created by us. (see 5.)
2295 * 2. We handle files differently based on canmount.
2296 * Units with canmount=on always have precedence over noauto.
2297 - * This is enforced by the noauto_not_on_sem semaphore,
2298 - * which is only unlocked when the last canmount=on process exits.
2299 + * This is enforced by processing these units before all others.
2300 * It is important to use p_canmount and not noauto here,
2301 * since we categorise by canmount while other properties,
2302 * e.g. org.openzfs.systemd:wanted-by, also modify noauto.
2303 @@ -561,7 +558,7 @@ line_worker(char *line, const char *cachefile)
2304 * Additionally, we use noauto_files to track the unit file names
2305 * (which are the systemd-escaped mountpoints) of all (exclusively)
2306 * noauto datasets that had a file created.
2307 - * 4. If the file to be created is found in the tracking array,
2308 + * 4. If the file to be created is found in the tracking tree,
2309 * we do NOT create it.
2310 * 5. If a file exists for a noauto dataset,
2311 * we check whether the file name is in the array.
2312 @@ -571,29 +568,14 @@ line_worker(char *line, const char *cachefile)
2313 * further noauto datasets creating a file for this path again.
2317 - sem_t *our_sem = (strcmp(p_canmount, "on") == 0) ?
2318 - &noauto_files->noauto_names_sem :
2319 - &noauto_files->noauto_not_on_sem;
2320 - while (sem_wait(our_sem) == -1 && errno == EINTR)
2325 bool already_exists = fstatat(destdir_fd, mountfile, &stbuf, 0) == 0;
2326 + bool is_known = tfind(mountfile, &noauto_files, STRCMP) != NULL;
2328 - bool is_known = false;
2329 - for (size_t i = 0; i < noauto_files->noauto_names_len; ++i) {
2331 - noauto_files->noauto_names[i], mountfile, NAME_MAX) == 0) {
2337 + *(tofree++) = (void *)mountfile;
2338 if (already_exists) {
2340 - /* If it's in $noauto_files, we must be noauto too */
2341 + /* If it's in noauto_files, we must be noauto too */
2345 @@ -614,43 +596,31 @@ line_worker(char *line, const char *cachefile)
2348 /* File exists: skip current dataset */
2349 - if (strcmp(p_canmount, "on") == 0)
2350 - sem_post(&noauto_files->noauto_names_sem);
2356 - if (strcmp(p_canmount, "on") == 0)
2357 - sem_post(&noauto_files->noauto_names_sem);
2360 } else if (strcmp(p_canmount, "noauto") == 0) {
2361 - if (noauto_files->noauto_names_len ==
2362 - noauto_files->noauto_names_max)
2363 + if (tsearch(mountfile, &noauto_files, STRCMP) == NULL)
2364 fprintf(stderr, PROGNAME "[%d]: %s: "
2365 - "noauto dataset limit (%zu) reached! "
2366 - "Not tracking %s. Please report this to "
2367 - "https://github.com/openzfs/zfs\n",
2368 - getpid(), dataset,
2369 - noauto_files->noauto_names_max, mountfile);
2371 - strncpy(noauto_files->noauto_names[
2372 - noauto_files->noauto_names_len],
2373 - mountfile, NAME_MAX);
2374 - ++noauto_files->noauto_names_len;
2376 + "out of memory for noauto datasets! "
2377 + "Not tracking %s.\n",
2378 + getpid(), dataset, mountfile);
2380 + /* mountfile escaped to noauto_files */
2381 + *(--tofree) = NULL;
2386 FILE *mountfile_f = fopenat(destdir_fd, mountfile,
2387 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, "w", 0644);
2388 - if (strcmp(p_canmount, "on") == 0)
2389 - sem_post(&noauto_files->noauto_names_sem);
2392 PROGNAME "[%d]: %s: couldn't open %s under %s: %s\n",
2393 getpid(), dataset, mountfile, destdir, strerror(errno));
2398 fprintf(mountfile_f,
2399 @@ -699,12 +669,17 @@ line_worker(char *line, const char *cachefile)
2400 (void) fclose(mountfile_f);
2402 if (!requiredby && !wantedby)
2406 /* Finally, create the appropriate dependencies */
2408 - if (asprintf(&linktgt, "../%s", mountfile) == -1)
2410 + if (asprintf(&linktgt, "../%s", mountfile) == -1) {
2411 + fprintf(stderr, PROGNAME "[%d]: %s: "
2412 + "out of memory for dependents of %s!\n",
2413 + getpid(), dataset, mountfile);
2416 + *(tofree++) = linktgt;
2418 char *dependencies[][2] = {
2419 {"wants", wantedby},
2420 @@ -719,8 +694,14 @@ line_worker(char *line, const char *cachefile)
2422 reqby = strtok_r(NULL, " ", &toktmp)) {
2424 - if (asprintf(&depdir, "%s.%s", reqby, (*dep)[0]) == -1)
2427 + &depdir, "%s.%s", reqby, (*dep)[0]) == -1) {
2428 + fprintf(stderr, PROGNAME "[%d]: %s: "
2429 + "out of memory for dependent dir name "
2431 + getpid(), dataset, reqby, (*dep)[0]);
2435 (void) mkdirat(destdir_fd, depdir, 0755);
2436 int depdir_fd = openat(destdir_fd, depdir,
2437 @@ -746,7 +727,24 @@ line_worker(char *line, const char *cachefile)
2443 + if (tofree >= tofree_all + nitems(tofree_all)) {
2445 + * This won't happen as-is:
2446 + * we've got 8 slots and allocate 4 things at most.
2449 + PROGNAME "[%d]: %s: need to free %zu > %zu!\n",
2450 + getpid(), dataset, tofree - tofree_all, nitems(tofree_all));
2451 + ret = tofree - tofree_all;
2454 + while (tofree-- != tofree_all)
2463 @@ -780,12 +778,11 @@ main(int argc, char **argv)
2465 (void) dup2(kmfd, STDERR_FILENO);
2468 + setlinebuf(stderr);
2472 - uint8_t debug = 0;
2478 @@ -844,33 +841,9 @@ main(int argc, char **argv)
2484 - * We could just get a gigabyte here and Not Care,
2485 - * but if vm.overcommit_memory=2, then MAP_NORESERVE is ignored
2486 - * and we'd try (and likely fail) to rip it out of swap
2488 - noauto_files = mmap(NULL, 4 * 1024 * 1024,
2489 - PROT_READ | PROT_WRITE,
2490 - MAP_SHARED | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
2491 - if (noauto_files == MAP_FAILED) {
2493 - PROGNAME "[%d]: couldn't allocate IPC region: %s\n",
2494 - getpid(), strerror(errno));
2498 - sem_init(&noauto_files->noauto_not_on_sem, true, 0);
2499 - sem_init(&noauto_files->noauto_names_sem, true, 1);
2500 - noauto_files->noauto_names_len = 0;
2501 - /* Works out to 16447ish, *well* enough */
2502 - noauto_files->noauto_names_max =
2503 - (4 * 1024 * 1024 - sizeof (*noauto_files)) / NAME_MAX;
2506 + bool debug = false;
2509 - struct timespec time_start = {};
2511 const char *dbgenv = getenv("ZFS_DEBUG");
2513 @@ -879,7 +852,7 @@ main(int argc, char **argv)
2514 FILE *cmdline = fopen("/proc/cmdline", "re");
2515 if (cmdline != NULL) {
2516 if (getline(&line, &linelen, cmdline) >= 0)
2517 - debug = strstr(line, "debug") ? 2 : 0;
2518 + debug = strstr(line, "debug");
2519 (void) fclose(cmdline);
2522 @@ -888,19 +861,17 @@ main(int argc, char **argv)
2523 dup2(STDERR_FILENO, STDOUT_FILENO);
2526 - size_t forked_canmount_on = 0;
2527 - size_t forked_canmount_not_on = 0;
2528 - size_t canmount_on_pids_len = 128;
2529 - pid_t *canmount_on_pids =
2530 - malloc(canmount_on_pids_len * sizeof (*canmount_on_pids));
2531 - if (canmount_on_pids == NULL)
2532 - canmount_on_pids_len = 0;
2534 + struct timespec time_start = {};
2536 clock_gettime(CLOCK_MONOTONIC_RAW, &time_start);
2542 + const char *fname;
2543 + struct line *next;
2544 + } *lines_canmount_not_on = NULL;
2547 struct dirent *cachent;
2548 while ((cachent = readdir(fslist_dir)) != NULL) {
2549 if (strcmp(cachent->d_name, ".") == 0 ||
2550 @@ -916,129 +887,67 @@ main(int argc, char **argv)
2554 + const char *filename = FREE_STATICS ? "(elided)" : NULL;
2557 while ((read = getline(&line, &linelen, cachefile)) >= 0) {
2558 line[read - 1] = '\0'; /* newline */
2560 - switch (pid = fork()) {
2563 - PROGNAME "[%d]: couldn't fork for %s: %s\n",
2564 - getpid(), line, strerror(errno));
2566 - case 0: /* child */
2567 - _exit(line_worker(line, cachent->d_name));
2568 - default: { /* parent */
2570 - char *dset = strtok_r(line, "\t", &tmp);
2571 - strtok_r(NULL, "\t", &tmp);
2572 - char *canmount = strtok_r(NULL, "\t", &tmp);
2573 - bool canmount_on =
2574 - canmount && strncmp(canmount, "on", 2) == 0;
2577 - printf(PROGNAME ": forked %d, "
2578 - "canmount_on=%d, dataset=%s\n",
2579 - (int)pid, canmount_on, dset);
2581 - if (canmount_on &&
2582 - forked_canmount_on ==
2583 - canmount_on_pids_len) {
2585 - (canmount_on_pids_len ?: 16) * 2;
2586 - void *new_pidlist =
2587 - realloc(canmount_on_pids,
2589 - sizeof (*canmount_on_pids));
2590 - if (!new_pidlist) {
2594 - "Mount ordering may be "
2595 - "affected.\n", getpid());
2599 - canmount_on_pids = new_pidlist;
2600 - canmount_on_pids_len = new_len;
2602 + char *canmount = line;
2603 + canmount += strcspn(canmount, "\t");
2604 + canmount += strspn(canmount, "\t");
2605 + canmount += strcspn(canmount, "\t");
2606 + canmount += strspn(canmount, "\t");
2607 + bool canmount_on = strncmp(canmount, "on", 2) == 0;
2609 - if (canmount_on) {
2610 - canmount_on_pids[forked_canmount_on] =
2612 - ++forked_canmount_on;
2614 - ++forked_canmount_not_on;
2618 + ret |= line_worker(line, cachent->d_name);
2620 + if (filename == NULL)
2622 + strdup(cachent->d_name) ?: "(?)";
2624 + struct line *l = calloc(1, sizeof (*l));
2625 + char *nl = strdup(line);
2626 + if (l == NULL || nl == NULL) {
2627 + fprintf(stderr, PROGNAME "[%d]: "
2628 + "out of memory for \"%s\" in %s\n",
2629 + getpid(), line, cachent->d_name);
2635 + l->fname = filename;
2636 + l->next = lines_canmount_not_on;
2637 + lines_canmount_not_on = l;
2641 - (void) fclose(cachefile);
2642 + fclose(cachefile);
2646 - if (forked_canmount_on == 0) {
2647 - /* No canmount=on processes to finish, so don't deadlock here */
2648 - for (size_t i = 0; i < forked_canmount_not_on; ++i)
2649 - sem_post(&noauto_files->noauto_not_on_sem);
2651 - /* Likely a no-op, since we got these from a narrow fork loop */
2652 - qsort(canmount_on_pids, forked_canmount_on,
2653 - sizeof (*canmount_on_pids), PID_T_CMP);
2655 + while (lines_canmount_not_on) {
2656 + struct line *l = lines_canmount_not_on;
2657 + lines_canmount_not_on = l->next;
2659 - int status, ret = 0;
2660 - struct rusage usage;
2661 - size_t forked_canmount_on_max = forked_canmount_on;
2662 - while ((pid = wait4(-1, &status, 0, &usage)) != -1) {
2663 - ret |= WEXITSTATUS(status) | WTERMSIG(status);
2665 - if (forked_canmount_on != 0) {
2666 - if (bsearch(&pid, canmount_on_pids,
2667 - forked_canmount_on_max, sizeof (*canmount_on_pids),
2669 - --forked_canmount_on;
2671 - if (forked_canmount_on == 0) {
2673 - * All canmount=on processes have finished,
2674 - * let all the lower-priority ones finish now
2676 - for (size_t i = 0;
2677 - i < forked_canmount_not_on; ++i)
2679 - &noauto_files->noauto_not_on_sem);
2681 + ret |= line_worker(l->line, l->fname);
2682 + if (FREE_STATICS) {
2688 - printf(PROGNAME ": %d done, user=%llu.%06us, "
2689 - "system=%llu.%06us, maxrss=%ldB, ex=0x%x\n",
2691 - (unsigned long long) usage.ru_utime.tv_sec,
2692 - (unsigned int) usage.ru_utime.tv_usec,
2693 - (unsigned long long) usage.ru_stime.tv_sec,
2694 - (unsigned int) usage.ru_stime.tv_usec,
2695 - usage.ru_maxrss * 1024, status);
2699 struct timespec time_end = {};
2700 clock_gettime(CLOCK_MONOTONIC_RAW, &time_end);
2702 + struct rusage usage;
2703 getrusage(RUSAGE_SELF, &usage);
2706 - PROGNAME ": self : "
2707 - "user=%llu.%06us, system=%llu.%06us, maxrss=%ldB\n",
2708 - (unsigned long long) usage.ru_utime.tv_sec,
2709 - (unsigned int) usage.ru_utime.tv_usec,
2710 - (unsigned long long) usage.ru_stime.tv_sec,
2711 - (unsigned int) usage.ru_stime.tv_usec,
2712 - usage.ru_maxrss * 1024);
2714 - getrusage(RUSAGE_CHILDREN, &usage);
2715 - printf(PROGNAME ": children: "
2717 "user=%llu.%06us, system=%llu.%06us, maxrss=%ldB\n",
2718 (unsigned long long) usage.ru_utime.tv_sec,
2719 (unsigned int) usage.ru_utime.tv_usec,
2720 @@ -1068,7 +977,7 @@ main(int argc, char **argv)
2721 time_init.tv_nsec / 1000000000;
2722 time_init.tv_nsec %= 1000000000;
2724 - printf(PROGNAME ": wall : "
2725 + printf(PROGNAME ": "
2726 "total=%llu.%09llus = "
2727 "init=%llu.%09llus + real=%llu.%09llus\n",
2728 (unsigned long long) time_init.tv_sec,
2729 @@ -1077,7 +986,15 @@ main(int argc, char **argv)
2730 (unsigned long long) time_start.tv_nsec,
2731 (unsigned long long) time_end.tv_sec,
2732 (unsigned long long) time_end.tv_nsec);
2737 + if (FREE_STATICS) {
2738 + closedir(fslist_dir);
2739 + tdestroy(noauto_files, free);
2740 + tdestroy(known_pools, free);
2741 + regfree(&uri_regex);
2745 diff --git a/etc/zfs/Makefile.am b/etc/zfs/Makefile.am
2746 index 3dee81c75..1fc57e158 100644
2747 --- a/etc/zfs/Makefile.am
2748 +++ b/etc/zfs/Makefile.am
2749 @@ -10,9 +10,10 @@ dist_pkgsysconf_DATA = \
2750 vdev_id.conf.multipath.example \
2751 vdev_id.conf.scsi.example
2753 -pkgsysconf_SCRIPTS = \
2754 +pkgsysconf_DATA = \
2757 -SUBSTFILES += $(pkgsysconf_SCRIPTS)
2758 +SUBSTFILES += $(pkgsysconf_DATA)
2760 +SHELLCHECKSCRIPTS = $(pkgsysconf_DATA)
2761 SHELLCHECK_SHELL = dash # local variables
2762 diff --git a/include/libzfs.h b/include/libzfs.h
2763 index eeb4daae7..d55e3f2e7 100644
2764 --- a/include/libzfs.h
2765 +++ b/include/libzfs.h
2766 @@ -795,9 +795,10 @@ extern int zfs_receive(libzfs_handle_t *, const char *, nvlist_t *,
2767 recvflags_t *, int, avl_tree_t *);
2769 typedef enum diff_flags {
2770 - ZFS_DIFF_PARSEABLE = 0x1,
2771 - ZFS_DIFF_TIMESTAMP = 0x2,
2772 - ZFS_DIFF_CLASSIFY = 0x4
2773 + ZFS_DIFF_PARSEABLE = 1 << 0,
2774 + ZFS_DIFF_TIMESTAMP = 1 << 1,
2775 + ZFS_DIFF_CLASSIFY = 1 << 2,
2776 + ZFS_DIFF_NO_MANGLE = 1 << 3
2779 extern int zfs_show_diffs(zfs_handle_t *, int, const char *, const char *,
2780 diff --git a/include/libzfs_impl.h b/include/libzfs_impl.h
2781 index 96b11dad1..043ff9cd7 100644
2782 --- a/include/libzfs_impl.h
2783 +++ b/include/libzfs_impl.h
2784 @@ -234,6 +234,7 @@ typedef struct differ_info {
2787 boolean_t timestamped;
2788 + boolean_t no_mangle;
2792 diff --git a/include/os/freebsd/zfs/sys/zfs_znode_impl.h b/include/os/freebsd/zfs/sys/zfs_znode_impl.h
2793 index edb28d041..3d93525b4 100644
2794 --- a/include/os/freebsd/zfs/sys/zfs_znode_impl.h
2795 +++ b/include/os/freebsd/zfs/sys/zfs_znode_impl.h
2796 @@ -123,25 +123,29 @@ extern minor_t zfsdev_minor_alloc(void);
2797 #define zn_rlimit_fsize(zp, uio) \
2798 vn_rlimit_fsize(ZTOV(zp), GET_UIO_STRUCT(uio), zfs_uio_td(uio))
2800 +#define ZFS_ENTER_ERROR(zfsvfs, error) do { \
2801 + ZFS_TEARDOWN_ENTER_READ((zfsvfs), FTAG); \
2802 + if (__predict_false((zfsvfs)->z_unmounted)) { \
2803 + ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
2808 /* Called on entry to each ZFS vnode and vfs operation */
2809 -#define ZFS_ENTER(zfsvfs) \
2811 - ZFS_TEARDOWN_ENTER_READ((zfsvfs), FTAG); \
2812 - if (__predict_false((zfsvfs)->z_unmounted)) { \
2813 - ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
2817 +#define ZFS_ENTER(zfsvfs) ZFS_ENTER_ERROR(zfsvfs, EIO)
2819 /* Must be called before exiting the vop */
2820 -#define ZFS_EXIT(zfsvfs) ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG)
2821 +#define ZFS_EXIT(zfsvfs) ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG)
2823 +#define ZFS_VERIFY_ZP_ERROR(zp, error) do { \
2824 + if (__predict_false((zp)->z_sa_hdl == NULL)) { \
2825 + ZFS_EXIT((zp)->z_zfsvfs); \
2830 /* Verifies the znode is valid */
2831 -#define ZFS_VERIFY_ZP(zp) \
2832 - if (__predict_false((zp)->z_sa_hdl == NULL)) { \
2833 - ZFS_EXIT((zp)->z_zfsvfs); \
2836 +#define ZFS_VERIFY_ZP(zp) ZFS_VERIFY_ZP_ERROR(zp, EIO)
2839 * Macros for dealing with dmu_buf_hold
2840 diff --git a/include/sys/dbuf.h b/include/sys/dbuf.h
2841 index d2c175af6..e7289c0fe 100644
2842 --- a/include/sys/dbuf.h
2843 +++ b/include/sys/dbuf.h
2844 @@ -321,13 +321,12 @@ typedef struct dmu_buf_impl {
2845 uint8_t db_dirtycnt;
2848 -/* Note: the dbuf hash table is exposed only for the mdb module */
2849 -#define DBUF_MUTEXES 2048
2850 -#define DBUF_HASH_MUTEX(h, idx) (&(h)->hash_mutexes[(idx) & (DBUF_MUTEXES-1)])
2851 +#define DBUF_RWLOCKS 8192
2852 +#define DBUF_HASH_RWLOCK(h, idx) (&(h)->hash_rwlocks[(idx) & (DBUF_RWLOCKS-1)])
2853 typedef struct dbuf_hash_table {
2854 uint64_t hash_table_mask;
2855 dmu_buf_impl_t **hash_table;
2856 - kmutex_t hash_mutexes[DBUF_MUTEXES] ____cacheline_aligned;
2857 + krwlock_t hash_rwlocks[DBUF_RWLOCKS] ____cacheline_aligned;
2858 } dbuf_hash_table_t;
2860 typedef void (*dbuf_prefetch_fn)(void *, boolean_t);
2861 diff --git a/include/sys/spa_impl.h b/include/sys/spa_impl.h
2862 index cb2c49e58..c8987e2e6 100644
2863 --- a/include/sys/spa_impl.h
2864 +++ b/include/sys/spa_impl.h
2865 @@ -370,6 +370,7 @@ struct spa {
2866 boolean_t spa_is_root; /* pool is root */
2867 int spa_minref; /* num refs when first opened */
2868 spa_mode_t spa_mode; /* SPA_MODE_{READ|WRITE} */
2869 + boolean_t spa_read_spacemaps; /* spacemaps available if ro */
2870 spa_log_state_t spa_log_state; /* log state */
2871 uint64_t spa_autoexpand; /* lun expansion on/off */
2872 ddt_t *spa_ddt[ZIO_CHECKSUM_FUNCTIONS]; /* in-core DDTs */
2873 diff --git a/lib/libzfs/libzfs_diff.c b/lib/libzfs/libzfs_diff.c
2874 index d46e23a2f..57a7c1556 100644
2875 --- a/lib/libzfs/libzfs_diff.c
2876 +++ b/lib/libzfs/libzfs_diff.c
2877 @@ -122,9 +122,9 @@ stream_bytes(FILE *fp, const char *string)
2879 while ((c = *string++) != '\0') {
2880 if (c > ' ' && c != '\\' && c < '\177') {
2881 - (void) fprintf(fp, "%c", c);
2882 + (void) fputc(c, fp);
2884 - (void) fprintf(fp, "\\%04o", (uint8_t)c);
2885 + (void) fprintf(fp, "\\%04hho", (uint8_t)c);
2889 @@ -176,8 +176,13 @@ print_what(FILE *fp, mode_t what)
2891 print_cmn(FILE *fp, differ_info_t *di, const char *file)
2893 - stream_bytes(fp, di->dsmnt);
2894 - stream_bytes(fp, file);
2895 + if (!di->no_mangle) {
2896 + stream_bytes(fp, di->dsmnt);
2897 + stream_bytes(fp, file);
2899 + (void) fputs(di->dsmnt, fp);
2900 + (void) fputs(file, fp);
2905 @@ -752,6 +757,7 @@ zfs_show_diffs(zfs_handle_t *zhp, int outfd, const char *fromsnap,
2906 di.scripted = (flags & ZFS_DIFF_PARSEABLE);
2907 di.classify = (flags & ZFS_DIFF_CLASSIFY);
2908 di.timestamped = (flags & ZFS_DIFF_TIMESTAMP);
2909 + di.no_mangle = (flags & ZFS_DIFF_NO_MANGLE);
2911 di.outputfd = outfd;
2912 di.datafd = pipefd[0];
2913 diff --git a/lib/libzfs/libzfs_import.c b/lib/libzfs/libzfs_import.c
2914 index 64fa31c67..ddaa5de5d 100644
2915 --- a/lib/libzfs/libzfs_import.c
2916 +++ b/lib/libzfs/libzfs_import.c
2917 @@ -146,10 +146,10 @@ zpool_clear_label(int fd)
2918 struct stat64 statbuf;
2920 vdev_label_t *label;
2921 - l2arc_dev_hdr_phys_t *l2dhdr;
2922 + l2arc_dev_hdr_phys_t *l2dhdr = NULL;
2924 - int labels_cleared = 0, header_cleared = 0;
2925 - boolean_t clear_l2arc_header = B_FALSE;
2926 + int labels_cleared = 0;
2927 + boolean_t clear_l2arc_header = B_FALSE, header_cleared = B_FALSE;
2929 if (fstat64_blk(fd, &statbuf) == -1)
2931 @@ -219,13 +219,10 @@ zpool_clear_label(int fd)
2934 /* Clear the L2ARC header. */
2935 - if (clear_l2arc_header) {
2936 - memset(l2dhdr, 0, sizeof (l2arc_dev_hdr_phys_t));
2937 - if (pwrite64(fd, l2dhdr, sizeof (l2arc_dev_hdr_phys_t),
2938 - VDEV_LABEL_START_SIZE) == sizeof (l2arc_dev_hdr_phys_t)) {
2942 + if (clear_l2arc_header &&
2943 + pwrite64(fd, l2dhdr, sizeof (l2arc_dev_hdr_phys_t),
2944 + VDEV_LABEL_START_SIZE) == sizeof (l2arc_dev_hdr_phys_t))
2945 + header_cleared = B_TRUE;
2949 @@ -233,6 +230,9 @@ zpool_clear_label(int fd)
2950 if (labels_cleared == 0)
2953 + if (clear_l2arc_header && !header_cleared)
2959 diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c
2960 index b67c9b30c..a944cc164 100644
2961 --- a/lib/libzfs/libzfs_sendrecv.c
2962 +++ b/lib/libzfs/libzfs_sendrecv.c
2963 @@ -2133,7 +2133,6 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
2964 avl_tree_t *fsavl = NULL;
2965 static uint64_t holdseq;
2967 - int featureflags = 0;
2970 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2971 @@ -2145,17 +2144,6 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
2972 return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
2975 - if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM) {
2977 - version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
2978 - if (version >= ZPL_VERSION_SA) {
2979 - featureflags |= DMU_BACKUP_FEATURE_SA_SPILL;
2984 - featureflags |= DMU_BACKUP_FEATURE_HOLDS;
2986 if (flags->replicate || flags->doall || flags->props ||
2987 flags->holds || flags->backup) {
2988 char full_tosnap_name[ZFS_MAX_DATASET_NAME_LEN];
2989 @@ -2522,8 +2510,7 @@ zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
2991 if (flags->progress) {
2992 void *status = NULL;
2994 - (void) pthread_cancel(ptid);
2995 + (void) pthread_cancel(ptid);
2996 (void) pthread_join(ptid, &status);
2997 int error = (int)(uintptr_t)status;
2998 if (error != 0 && status != PTHREAD_CANCELED)
2999 diff --git a/lib/libzutil/zutil_import.c b/lib/libzutil/zutil_import.c
3000 index d91953813..f6f125e7a 100644
3001 --- a/lib/libzutil/zutil_import.c
3002 +++ b/lib/libzutil/zutil_import.c
3003 @@ -1791,16 +1791,13 @@ zpool_find_config(void *hdl, const char *target, nvlist_t **configp,
3004 nvlist_t *match = NULL;
3005 nvlist_t *config = NULL;
3009 char *targetdup = strdup(target);
3013 - if ((sepp = strpbrk(targetdup, "/@")) != NULL) {
3015 + if ((sepp = strpbrk(targetdup, "/@")) != NULL)
3019 pools = zpool_search_import(hdl, args, pco);
3021 diff --git a/man/Makefile.am b/man/Makefile.am
3022 index 8ab1b7572..64650c2b9 100644
3023 --- a/man/Makefile.am
3024 +++ b/man/Makefile.am
3025 @@ -15,6 +15,7 @@ dist_man_MANS = \
3029 + man7/dracut.zfs.7 \
3030 man7/zpool-features.7 \
3031 man7/zfsconcepts.7 \
3033 diff --git a/man/man4/zfs.4 b/man/man4/zfs.4
3034 index 657afc616..3eeed8f43 100644
3035 --- a/man/man4/zfs.4
3036 +++ b/man/man4/zfs.4
3037 @@ -1581,12 +1581,12 @@ Allow no-operation writes.
3038 The occurrence of nopwrites will further depend on other pool properties
3039 .Pq i.a. the checksumming and compression algorithms .
3041 -.It Sy zfs_dmu_offset_next_sync Ns = Ns Sy 0 Ns | Ns 1 Pq int
3042 +.It Sy zfs_dmu_offset_next_sync Ns = Ns Sy 1 Ns | Ns 0 Pq int
3043 Enable forcing TXG sync to find holes.
3044 -When enabled forces ZFS to act like prior versions when
3045 +When enabled forces ZFS to sync data when
3046 .Sy SEEK_HOLE No or Sy SEEK_DATA
3047 -flags are used, which, when a dnode is dirty,
3048 -causes TXGs to be synced so that this data can be found.
3049 +flags are used allowing holes in a file to be accurately reported.
3050 +When disabled holes will not be reported in recently dirtied files.
3052 .It Sy zfs_pd_bytes_max Ns = Ns Sy 52428800 Ns B Po 50MB Pc Pq int
3053 The number of bytes which should be prefetched during a pool traversal, like
3054 diff --git a/man/man7/dracut.zfs.7 b/man/man7/dracut.zfs.7
3055 new file mode 100644
3056 index 000000000..0f446fe2f
3058 +++ b/man/man7/dracut.zfs.7
3060 +.\" SPDX-License-Identifier: 0BSD
3068 +.Nd overview of ZFS dracut hooks
3071 +.Bd -literal -compact
3072 + parse-zfs.sh \(-> dracut-cmdline.service
3076 + \e\(em\(em\(em\(em\(em\(em\(em\(em\(-> dracut-initqueue.service
3077 + | zfs-import-opts.sh
3078 + zfs-load-module.service \(da | |
3079 + | | sysinit.target \(da |
3080 + \(da | | zfs-import-scan.service \(da
3081 +zfs-import-scan.service \(da \(da | zfs-import-cache.service
3082 + | zfs-import-cache.service basic.target | |
3083 + \e__________________| | \(da \(da
3084 + \(da | zfs-load-key.sh
3085 + zfs-env-bootfs.service | |
3087 + zfs-import.target \(-> dracut-pre-mount.service
3089 + | dracut-zfs-generator |
3090 + | ____________________/|
3092 + | sysroot.mount \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em dracut-zfs-generator
3094 + | \(da sysroot-{usr,etc,lib,&c.}.mount |
3095 + | initrd-root-fs.target \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em or \(da
3096 + | | zfs-nonroot-necessities.service
3098 + \(da dracut-mount.service |
3099 + zfs-snapshot-bootfs.service | |
3102 + zfs-rollback-bootfs.service | |
3104 + | sysroot-usr.mount \(<-\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em\(em/
3107 + | initrd-fs.target
3108 + \e______________________ |
3111 + export-zfs.sh initrd.target
3114 + dracut-shutdown.service …
3117 + zfs-needshutdown.sh \(-> initrd-cleanup.service
3121 +.Xr dracut.bootup 7
3122 +for the full flowchart.
3125 +Under dracut, booting with
3126 +.No ZFS-on- Ns Pa /
3127 +is facilitated by a number of hooks in the
3131 +Booting into a ZFS dataset requires
3132 +.Sy mountpoint Ns = Ns Pa /
3133 +to be set on the dataset containing the root filesystem (henceforth "the boot dataset") and at the very least either the
3135 +property to be set to that dataset, or the
3137 +kernel cmdline (or dracut drop-in) argument to specify it.
3139 +All children of the boot dataset with
3140 +.Sy canmount Ns = Ns Sy on
3142 +.Sy mountpoint Ns s
3144 +.Pa /etc , /bin , /lib , /lib?? , /libx32 , No and Pa /usr
3145 +globs are deemed essential and will be mounted as well.
3147 +.Xr zfs-mount-generator 8
3148 +is recommended for proper functioning of the system afterward (correct mount properties, remounting, &c.).
3152 +.Bl -tag -compact -width ".Sy root=zfs:AUTO , root=zfs: , root=zfs , Op Sy root="
3153 +.It Sy root=zfs:\& Ns Ar dataset , Sy root=ZFS= Ns Ar dataset
3156 +as the boot dataset.
3159 +are replaced with spaces
3162 +.It Sy root=zfs:AUTO , root=zfs:\& , root=zfs , Op Sy root=
3163 +After import, search for the first pool with the
3165 +property set, use its value as-if specified as the
3169 +.It Sy rootfstype=zfs root= Ns Ar dataset
3171 +.Sy root=zfs:\& Ns Ar dataset .
3173 +.It Sy rootfstype=zfs Op Sy root=
3175 +.Sy root=zfs:AUTO .
3177 +.It Sy rootflags= Ns Ar flags
3178 +Mount the boot dataset with
3181 +.Sx Temporary Mount Point Properties
3184 +These properties will not last, since all filesystems will be re-mounted from the real root.
3188 +.Nm dracut-zfs-generator
3189 +logs to the journal.
3192 +Be careful about setting neither
3195 +.Sy root=zfs:\& Ns Ar dataset
3196 +\(em other automatic boot selection methods, like
3197 +.Nm systemd-gpt-auto-generator
3199 +.Nm systemd-fstab-generator
3200 +might take precedent.
3203 +.Bl -tag -compact -width ".Sy bootfs.snapshot Ns Op Sy = Ns Ar snapshot-name"
3204 +.It Sy bootfs.snapshot Ns Op Sy = Ns Ar snapshot-name
3206 +.Nm zfs Cm snapshot Ar boot-dataset Ns Sy @ Ns Ar snapshot-name
3207 +before pivoting to the real root.
3209 +defaults to the current kernel release.
3211 +.It Sy bootfs.rollback Ns Op Sy = Ns Ar snapshot-name
3213 +.Nm zfs Cm snapshot Fl Rf Ar boot-dataset Ns Sy @ Ns Ar snapshot-name
3214 +before pivoting to the real root.
3216 +defaults to the current kernel release.
3218 +.It Sy spl_hostid= Ns Ar host-id
3221 +to set the host ID to
3225 +inherited from the real root is used.
3227 +.It Sy zfs_force , zfs.force , zfsforce
3231 +.Nm zpool Cm import
3232 +invocations; primarily useful in conjunction with
3234 +or if no host ID was inherited.
3239 +.It Pa parse-zfs.sh Pq Sy cmdline
3244 +matches a known pattern, above, provides
3246 +and delays the initqueue until
3250 +.It Pa zfs-import-opts.sh Pq Nm systemd No environment generator
3252 +.Sy zfs_force , zfs.force , No or Sy zfsforce
3254 +.Ev ZPOOL_IMPORT_OPTS Ns = Ns Fl f
3256 +.Pa zfs-import-scan.service
3258 +.Pa zfs-import-cache.service .
3260 +.It Pa zfs-load-key.sh Pq Sy pre-mount
3261 +Loads encryption keys for the boot dataset and its essential descendants.
3262 +.Bl -tag -compact -offset 4n -width ".Sy keylocation Ns = Ns Sy https:// Ns Ar URL , Sy keylocation Ns = Ns Sy http:// Ns Ar URL"
3263 +.It Sy keylocation Ns = Ns Sy prompt
3264 +Is prompted for via
3265 +.Nm systemd-ask-password
3268 +.It Sy keylocation Ns = Ns Sy https:// Ns Ar URL , Sy keylocation Ns = Ns Sy http:// Ns Ar URL
3269 +.Pa network-online.target
3270 +is started before loading.
3272 +.It Sy keylocation Ns = Ns Sy file:// Ns Ar path
3276 +.Nm udevadm No is Cm settle Ns d .
3277 +If it still doesn't, it's waited for for up to
3281 +.It Pa zfs-env-bootfs.service Pq Nm systemd No service
3282 +After pool import, sets
3284 +in the systemd environment to the first non-null
3286 +value in iteration order.
3288 +.It Pa dracut-zfs-generator Pq Nm systemd No generator
3290 +.Pa sysroot.mount Pq using Sy rootflags= , No if any .
3291 +If an explicit boot dataset was specified, also generates essential mountpoints
3292 +.Pq Pa sysroot-etc.mount , sysroot-bin.mount , No &c.\& ,
3293 +otherwise generates
3294 +.Pa zfs-nonroot-necessities.service
3295 +which mounts them explicitly after
3300 +.It Pa zfs-snapshot-bootfs.service , zfs-rollback-bootfs.service Pq Nm systemd No services
3302 +.Sy bootfs.snapshot
3304 +.Sy bootfs.rollback
3309 +if no explicit boot dataset was specified.
3311 +.It Pa zfs-needshutdown.sh Pq Sy cleanup
3312 +If any pools were imported, signals that shutdown hooks are required.
3314 +.It Pa export-zfs.sh Pq Sy shutdown
3315 +Forcibly exports all pools.
3317 +.It Pa /etc/hostid , /etc/zfs/zpool.cache , /etc/zfs/vdev_id.conf Pq regular files
3318 +Included verbatim, hostonly.
3320 +.It Pa mount-zfs.sh Pq Sy mount
3324 +.Pq if Pa dracut-zfs-generator No succeeded .
3325 +Otherwise, loads encryption key for the boot dataset from the console or via plymouth.
3326 +It may not work at all!
3330 +.Xr dracut.bootup 7 ,
3333 +.Xr dracut-shutdown.service 8 ,
3334 +.Xr systemd-fstab-generator 8 ,
3335 +.Xr systemd-gpt-auto-generator 8 ,
3336 +.Xr zfs-mount-generator 8 ,
3338 diff --git a/man/man8/zfs-diff.8 b/man/man8/zfs-diff.8
3339 index 49443bf47..a347f3252 100644
3340 --- a/man/man8/zfs-diff.8
3341 +++ b/man/man8/zfs-diff.8
3348 .Ar snapshot Ar snapshot Ns | Ns Ar filesystem
3351 @@ -92,6 +92,10 @@ Give more parsable tab-separated output, without header lines and without
3354 Display the path's inode change time as the first column of output.
3357 +.Sy \e0 Ns Ar ooo Ns -escape
3362 diff --git a/man/man8/zfs-mount-generator.8.in b/man/man8/zfs-mount-generator.8.in
3363 index 7aa332ba8..ae8937038 100644
3364 --- a/man/man8/zfs-mount-generator.8.in
3365 +++ b/man/man8/zfs-mount-generator.8.in
3366 @@ -142,22 +142,11 @@ ZEDLET, if enabled
3373 -environment variable can either be
3377 -(print summary accounting information at the end), or at least
3379 -(print accounting information for each subprocess as it finishes).
3383 -is additionally checked for
3385 -in which case the debug level is set to
3387 +environment variable is nonzero
3388 +.Pq or unset and Pa /proc/cmdline No contains Qq Sy debug ,
3389 +print summary accounting information at the end.
3392 To begin, enable tracking for the pool:
3393 diff --git a/man/man8/zfs-set.8 b/man/man8/zfs-set.8
3394 index a3588cc26..ccd90f091 100644
3395 --- a/man/man8/zfs-set.8
3396 +++ b/man/man8/zfs-set.8
3397 @@ -170,8 +170,9 @@ inherited.
3399 Recursively inherit the given property for all children.
3401 -Revert the property to the received value if one exists; otherwise operate as
3403 +Revert the property to the received value, if one exists;
3404 +otherwise, for non-inheritable properties, to the default;
3405 +otherwise, operate as if the
3407 option was not specified.
3409 diff --git a/man/man8/zpool-import.8 b/man/man8/zpool-import.8
3410 index 39b0e17ef..5462e4ebd 100644
3411 --- a/man/man8/zpool-import.8
3412 +++ b/man/man8/zpool-import.8
3415 Lists pools available to import.
3421 options are not specified, this command searches for devices using libblkid
3422 on Linux and geom on
3423 diff --git a/module/icp/algs/modes/gcm.c b/module/icp/algs/modes/gcm.c
3424 index 7332834cb..dc8dd929f 100644
3425 --- a/module/icp/algs/modes/gcm.c
3426 +++ b/module/icp/algs/modes/gcm.c
3427 @@ -798,7 +798,7 @@ static gcm_impl_ops_t *gcm_supp_impl[ARRAY_SIZE(gcm_all_impl)];
3428 * fallback to the fastest generic implementation.
3430 const gcm_impl_ops_t *
3432 +gcm_impl_get_ops(void)
3434 if (!kfpu_allowed())
3435 return (&gcm_generic_impl);
3436 diff --git a/module/os/freebsd/zfs/abd_os.c b/module/os/freebsd/zfs/abd_os.c
3437 index 41ceed1dc..ddd6d68b3 100644
3438 --- a/module/os/freebsd/zfs/abd_os.c
3439 +++ b/module/os/freebsd/zfs/abd_os.c
3440 @@ -113,7 +113,6 @@ static kstat_t *abd_ksp;
3441 * memory by only using a single zero buffer for the scatter chunks.
3443 abd_t *abd_zero_scatter = NULL;
3444 -static char *abd_zero_buf = NULL;
3447 abd_chunkcnt_for_bytes(size_t size)
3448 @@ -241,18 +240,16 @@ abd_free_struct_impl(abd_t *abd)
3451 * Allocate scatter ABD of size SPA_MAXBLOCKSIZE, where
3452 - * each chunk in the scatterlist will be set to abd_zero_buf.
3453 + * each chunk in the scatterlist will be set to the same area.
3455 +_Static_assert(ZERO_REGION_SIZE >= PAGE_SIZE, "zero_region too small");
3457 abd_alloc_zero_scatter(void)
3461 n = abd_chunkcnt_for_bytes(SPA_MAXBLOCKSIZE);
3462 - abd_zero_buf = kmem_cache_alloc(abd_chunk_cache, KM_PUSHPAGE);
3463 - bzero(abd_zero_buf, PAGE_SIZE);
3464 abd_zero_scatter = abd_alloc_struct(SPA_MAXBLOCKSIZE);
3466 abd_zero_scatter->abd_flags |= ABD_FLAG_OWNER | ABD_FLAG_ZEROS;
3467 abd_zero_scatter->abd_size = SPA_MAXBLOCKSIZE;
3469 @@ -260,7 +257,7 @@ abd_alloc_zero_scatter(void)
3471 for (i = 0; i < n; i++) {
3472 ABD_SCATTER(abd_zero_scatter).abd_chunks[i] =
3474 + __DECONST(void *, zero_region);
3477 ABDSTAT_BUMP(abdstat_scatter_cnt);
3478 @@ -275,7 +272,6 @@ abd_free_zero_scatter(void)
3480 abd_free_struct(abd_zero_scatter);
3481 abd_zero_scatter = NULL;
3482 - kmem_cache_free(abd_chunk_cache, abd_zero_buf);
3486 diff --git a/module/os/freebsd/zfs/spa_os.c b/module/os/freebsd/zfs/spa_os.c
3487 index 070e7a5b9..d5f851a30 100644
3488 --- a/module/os/freebsd/zfs/spa_os.c
3489 +++ b/module/os/freebsd/zfs/spa_os.c
3490 @@ -183,7 +183,6 @@ spa_import_rootpool(const char *name, bool checkpointrewind)
3493 nvlist_t *config, *nvtop;
3498 @@ -196,7 +195,6 @@ spa_import_rootpool(const char *name, bool checkpointrewind)
3499 if (config != NULL) {
3500 pname = fnvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME);
3501 VERIFY0(strcmp(name, pname));
3502 - txg = fnvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG);
3504 if ((spa = spa_lookup(pname)) != NULL) {
3506 diff --git a/module/os/freebsd/zfs/vdev_geom.c b/module/os/freebsd/zfs/vdev_geom.c
3507 index 2ef4811a8..5447eb922 100644
3508 --- a/module/os/freebsd/zfs/vdev_geom.c
3509 +++ b/module/os/freebsd/zfs/vdev_geom.c
3510 @@ -1132,8 +1132,12 @@ vdev_geom_fill_unmap_cb(void *buf, size_t len, void *priv)
3511 vm_offset_t addr = (vm_offset_t)buf;
3512 vm_offset_t end = addr + len;
3514 - if (bp->bio_ma_n == 0)
3515 + if (bp->bio_ma_n == 0) {
3516 bp->bio_ma_offset = addr & PAGE_MASK;
3517 + addr &= ~PAGE_MASK;
3519 + ASSERT0(P2PHASE(addr, PAGE_SIZE));
3522 bp->bio_ma[bp->bio_ma_n++] =
3523 PHYS_TO_VM_PAGE(pmap_kextract(addr));
3524 diff --git a/module/os/freebsd/zfs/zfs_vnops_os.c b/module/os/freebsd/zfs/zfs_vnops_os.c
3525 index b2cc3d063..f6bc9c0c6 100644
3526 --- a/module/os/freebsd/zfs/zfs_vnops_os.c
3527 +++ b/module/os/freebsd/zfs/zfs_vnops_os.c
3532 +#if __FreeBSD_version < 1300103
3533 +#define NDFREE_PNBUF(ndp) NDFREE((ndp), NDF_ONLY_PNBUF)
3536 #if __FreeBSD_version >= 1300047
3537 #define vm_page_wire_lock(pp)
3538 #define vm_page_wire_unlock(pp)
3539 @@ -4058,8 +4062,8 @@ zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind,
3540 int pgsin_b, pgsin_a;
3543 - ZFS_ENTER(zfsvfs);
3544 - ZFS_VERIFY_ZP(zp);
3545 + ZFS_ENTER_ERROR(zfsvfs, zfs_vm_pagerret_error);
3546 + ZFS_VERIFY_ZP_ERROR(zp, zfs_vm_pagerret_error);
3548 start = IDX_TO_OFF(ma[0]->pindex);
3549 end = IDX_TO_OFF(ma[count - 1]->pindex + 1);
3550 @@ -4183,19 +4187,18 @@ zfs_putpages(struct vnode *vp, vm_page_t *ma, size_t len, int flags,
3554 - ZFS_ENTER(zfsvfs);
3555 - ZFS_VERIFY_ZP(zp);
3557 object = vp->v_object;
3558 - pcount = btoc(len);
3561 KASSERT(ma[0]->object == object, ("mismatching object"));
3562 KASSERT(len > 0 && (len & PAGE_MASK) == 0, ("unexpected length"));
3564 + pcount = btoc(len);
3566 for (i = 0; i < pcount; i++)
3567 rtvals[i] = zfs_vm_pagerret_error;
3569 + ZFS_ENTER_ERROR(zfsvfs, zfs_vm_pagerret_error);
3570 + ZFS_VERIFY_ZP_ERROR(zp, zfs_vm_pagerret_error);
3572 off = IDX_TO_OFF(ma[0]->pindex);
3573 blksz = zp->z_blksz;
3574 lo_off = rounddown(off, blksz);
3575 @@ -5234,6 +5237,11 @@ zfs_freebsd_pathconf(struct vop_pathconf_args *ap)
3577 *ap->a_retval = NAME_MAX;
3579 +#if __FreeBSD_version >= 1400032
3580 + case _PC_DEALLOC_PRESENT:
3581 + *ap->a_retval = 1;
3585 if (ap->a_vp->v_type == VDIR || ap->a_vp->v_type == VFIFO) {
3586 *ap->a_retval = PIPE_BUF;
3587 @@ -5357,7 +5365,7 @@ zfs_getextattr_dir(struct vop_getextattr_args *ap, const char *attrname)
3589 error = vn_open_cred(&nd, &flags, 0, VN_OPEN_INVFS, ap->a_cred, NULL);
3591 - NDFREE(&nd, NDF_ONLY_PNBUF);
3592 + NDFREE_PNBUF(&nd);
3596 @@ -5430,7 +5438,7 @@ zfs_getextattr(struct vop_getextattr_args *ap)
3601 + ZFS_VERIFY_ZP(zp);
3602 rw_enter(&zp->z_xattr_lock, RW_READER);
3603 if (zfsvfs->z_use_sa && zp->z_is_sa)
3604 error = zfs_getextattr_sa(ap, attrname);
3605 @@ -5475,12 +5483,12 @@ zfs_deleteextattr_dir(struct vop_deleteextattr_args *ap, const char *attrname)
3609 - NDFREE(&nd, NDF_ONLY_PNBUF);
3610 + NDFREE_PNBUF(&nd);
3614 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
3615 - NDFREE(&nd, NDF_ONLY_PNBUF);
3616 + NDFREE_PNBUF(&nd);
3619 if (vp == nd.ni_dvp)
3620 @@ -5605,7 +5613,7 @@ zfs_setextattr_dir(struct vop_setextattr_args *ap, const char *attrname)
3621 error = vn_open_cred(&nd, &flags, 0600, VN_OPEN_INVFS, ap->a_cred,
3624 - NDFREE(&nd, NDF_ONLY_PNBUF);
3625 + NDFREE_PNBUF(&nd);
3629 @@ -5760,7 +5768,7 @@ zfs_listextattr_dir(struct vop_listextattr_args *ap, const char *attrprefix)
3633 - NDFREE(&nd, NDF_ONLY_PNBUF);
3634 + NDFREE_PNBUF(&nd);
3638 @@ -6073,6 +6081,55 @@ zfs_vptocnp(struct vop_vptocnp_args *ap)
3642 +#if __FreeBSD_version >= 1400032
3644 +zfs_deallocate(struct vop_deallocate_args *ap)
3646 + znode_t *zp = VTOZ(ap->a_vp);
3647 + zfsvfs_t *zfsvfs = zp->z_zfsvfs;
3649 + off_t off, len, file_sz;
3652 + ZFS_ENTER(zfsvfs);
3653 + ZFS_VERIFY_ZP(zp);
3656 + * Callers might not be able to detect properly that we are read-only,
3657 + * so check it explicitly here.
3659 + if (zfs_is_readonly(zfsvfs)) {
3661 + return (SET_ERROR(EROFS));
3664 + zilog = zfsvfs->z_log;
3665 + off = *ap->a_offset;
3667 + file_sz = zp->z_size;
3668 + if (off + len > file_sz)
3669 + len = file_sz - off;
3670 + /* Fast path for out-of-range request. */
3677 + error = zfs_freesp(zp, off, len, O_RDWR, TRUE);
3679 + if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS ||
3680 + (ap->a_ioflag & IO_SYNC) != 0)
3681 + zil_commit(zilog, zp->z_id);
3682 + *ap->a_offset = off + len;
3691 struct vop_vector zfs_vnodeops;
3692 struct vop_vector zfs_fifoops;
3693 struct vop_vector zfs_shareops;
3694 @@ -6092,6 +6149,9 @@ struct vop_vector zfs_vnodeops = {
3696 .vop_access = zfs_freebsd_access,
3697 .vop_allocate = VOP_EINVAL,
3698 +#if __FreeBSD_version >= 1400032
3699 + .vop_deallocate = zfs_deallocate,
3701 .vop_lookup = zfs_cache_lookup,
3702 .vop_cachedlookup = zfs_freebsd_cachedlookup,
3703 .vop_getattr = zfs_freebsd_getattr,
3704 diff --git a/module/os/freebsd/zfs/zfs_znode.c b/module/os/freebsd/zfs/zfs_znode.c
3705 index e4a1d2db7..bbc45fda8 100644
3706 --- a/module/os/freebsd/zfs/zfs_znode.c
3707 +++ b/module/os/freebsd/zfs/zfs_znode.c
3708 @@ -575,7 +575,6 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
3715 sa_handle_t *sa_hdl;
3716 @@ -815,12 +814,11 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
3717 VERIFY0(zfs_aclset_common(*zpp, acl_ids->z_aclp, cr, tx));
3719 if (!(flag & IS_ROOT_NODE)) {
3723 + vnode_t *vp = ZTOV(*zpp);
3724 vp->v_vflag |= VV_FORCEINSMQ;
3725 - err = insmntque(vp, zfsvfs->z_vfs);
3726 + int err = insmntque(vp, zfsvfs->z_vfs);
3727 vp->v_vflag &= ~VV_FORCEINSMQ;
3729 KASSERT(err == 0, ("insmntque() failed: error %d", err));
3731 kmem_free(sa_attrs, sizeof (sa_bulk_attr_t) * ZPL_END);
3732 @@ -934,11 +932,9 @@ zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_num, znode_t **zpp)
3736 - struct thread *td;
3741 getnewvnode_reserve_();
3744 @@ -964,7 +960,7 @@ again:
3746 hdl = dmu_buf_get_user(db);
3748 - zp = sa_get_userdata(hdl);
3749 + zp = sa_get_userdata(hdl);
3752 * Since "SA" does immediate eviction we
3753 @@ -1491,12 +1487,16 @@ zfs_free_range(znode_t *zp, uint64_t off, uint64_t len)
3754 error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, off, len);
3757 +#if __FreeBSD_version >= 1400032
3758 + vnode_pager_purge_range(ZTOV(zp), off, off + len);
3761 - * In FreeBSD we cannot free block in the middle of a file,
3762 - * but only at the end of a file, so this code path should
3764 + * Before __FreeBSD_version 1400032 we cannot free block in the
3765 + * middle of a file, but only at the end of a file, so this code
3766 + * path should never happen.
3768 vnode_pager_setsize(ZTOV(zp), off);
3772 zfs_rangelock_exit(lr);
3773 diff --git a/module/os/freebsd/zfs/zvol_os.c b/module/os/freebsd/zfs/zvol_os.c
3774 index 0b347e7f9..09c35b371 100644
3775 --- a/module/os/freebsd/zfs/zvol_os.c
3776 +++ b/module/os/freebsd/zfs/zvol_os.c
3777 @@ -1063,7 +1063,7 @@ zvol_cdev_ioctl(struct cdev *dev, ulong_t cmd, caddr_t data,
3779 zfs_locked_range_t *lr;
3780 off_t offset, length;
3786 @@ -1072,7 +1072,6 @@ zvol_cdev_ioctl(struct cdev *dev, ulong_t cmd, caddr_t data,
3787 KASSERT(zv->zv_open_count > 0,
3788 ("Device with zero access count in %s", __func__));
3790 - i = IOCPARM_LEN(cmd);
3792 case DIOCGSECTORSIZE:
3793 *(uint32_t *)data = DEV_BSIZE;
3794 diff --git a/module/os/linux/spl/spl-kmem-cache.c b/module/os/linux/spl/spl-kmem-cache.c
3795 index 2151ef008..5a318e0a5 100644
3796 --- a/module/os/linux/spl/spl-kmem-cache.c
3797 +++ b/module/os/linux/spl/spl-kmem-cache.c
3798 @@ -1421,7 +1421,7 @@ EXPORT_SYMBOL(spl_kmem_cache_reap_now);
3799 * it should do no harm.
3802 -spl_kmem_cache_reap_active()
3803 +spl_kmem_cache_reap_active(void)
3807 diff --git a/module/os/linux/zfs/abd_os.c b/module/os/linux/zfs/abd_os.c
3808 index d1d238a4e..8afa222de 100644
3809 --- a/module/os/linux/zfs/abd_os.c
3810 +++ b/module/os/linux/zfs/abd_os.c
3811 @@ -184,8 +184,11 @@ abd_t *abd_zero_scatter = NULL;
3815 - * abd_zero_page we will be an allocated zero'd PAGESIZE buffer, which is
3816 - * assigned to set each of the pages of abd_zero_scatter.
3817 + * _KERNEL - Will point to ZERO_PAGE if it is available or it will be
3818 + * an allocated zero'd PAGESIZE buffer.
3819 + * Userspace - Will be an allocated zero'ed PAGESIZE buffer.
3821 + * abd_zero_page is assigned to each of the pages of abd_zero_scatter.
3823 static struct page *abd_zero_page = NULL;
3825 @@ -465,15 +468,19 @@ abd_alloc_zero_scatter(void)
3826 struct scatterlist *sg = NULL;
3827 struct sg_table table;
3828 gfp_t gfp = __GFP_NOWARN | GFP_NOIO;
3829 - gfp_t gfp_zero_page = gfp | __GFP_ZERO;
3830 int nr_pages = abd_chunkcnt_for_bytes(SPA_MAXBLOCKSIZE);
3833 +#if defined(HAVE_ZERO_PAGE_GPL_ONLY)
3834 + gfp_t gfp_zero_page = gfp | __GFP_ZERO;
3835 while ((abd_zero_page = __page_cache_alloc(gfp_zero_page)) == NULL) {
3836 ABDSTAT_BUMP(abdstat_scatter_page_alloc_retry);
3837 schedule_timeout_interruptible(1);
3839 abd_mark_zfs_page(abd_zero_page);
3841 + abd_zero_page = ZERO_PAGE(0);
3842 +#endif /* HAVE_ZERO_PAGE_GPL_ONLY */
3844 while (sg_alloc_table(&table, nr_pages, gfp)) {
3845 ABDSTAT_BUMP(abdstat_scatter_sg_table_retry);
3846 @@ -612,7 +619,6 @@ abd_alloc_zero_scatter(void)
3847 ABD_SCATTER(abd_zero_scatter).abd_offset = 0;
3848 ABD_SCATTER(abd_zero_scatter).abd_nents = nr_pages;
3849 abd_zero_scatter->abd_size = SPA_MAXBLOCKSIZE;
3850 - zfs_refcount_create(&abd_zero_scatter->abd_children);
3851 ABD_SCATTER(abd_zero_scatter).abd_sgl = vmem_alloc(nr_pages *
3852 sizeof (struct scatterlist), KM_SLEEP);
3854 @@ -694,8 +700,10 @@ abd_free_zero_scatter(void)
3855 abd_zero_scatter = NULL;
3856 ASSERT3P(abd_zero_page, !=, NULL);
3857 #if defined(_KERNEL)
3858 +#if defined(HAVE_ZERO_PAGE_GPL_ONLY)
3859 abd_unmark_zfs_page(abd_zero_page);
3860 __free_page(abd_zero_page);
3861 +#endif /* HAVE_ZERO_PAGE_GPL_ONLY */
3863 umem_free(abd_zero_page, PAGESIZE);
3864 #endif /* _KERNEL */
3865 diff --git a/module/os/linux/zfs/vdev_disk.c b/module/os/linux/zfs/vdev_disk.c
3866 index 581a79086..2708535b3 100644
3867 --- a/module/os/linux/zfs/vdev_disk.c
3868 +++ b/module/os/linux/zfs/vdev_disk.c
3869 @@ -467,8 +467,11 @@ vdev_submit_bio_impl(struct bio *bio)
3870 * blkg_tryget() to use rcu_read_lock() instead of rcu_read_lock_sched().
3871 * As a side effect the function was converted to GPL-only. Define our
3872 * own version when needed which uses rcu_read_lock_sched().
3874 + * The Linux 5.17 kernel split linux/blk-cgroup.h into a private and a public
3875 + * part, moving blkg_tryget into the private one. Define our own version.
3877 -#if defined(HAVE_BLKG_TRYGET_GPL_ONLY)
3878 +#if defined(HAVE_BLKG_TRYGET_GPL_ONLY) || !defined(HAVE_BLKG_TRYGET)
3880 vdev_blkg_tryget(struct blkcg_gq *blkg)
3882 @@ -493,7 +496,7 @@ vdev_blkg_tryget(struct blkcg_gq *blkg)
3886 -#elif defined(HAVE_BLKG_TRYGET)
3888 #define vdev_blkg_tryget(bg) blkg_tryget(bg)
3890 #ifdef HAVE_BIO_SET_DEV_MACRO
3891 @@ -563,6 +566,10 @@ vdev_submit_bio(struct bio *bio)
3892 current->bio_list = bio_list;
3895 +#ifdef HAVE_BIO_ALLOC_4ARG
3896 +#define bio_alloc(gfp_mask, nr_iovecs) bio_alloc(NULL, nr_iovecs, 0, gfp_mask)
3900 __vdev_disk_physio(struct block_device *bdev, zio_t *zio,
3901 size_t io_size, uint64_t io_offset, int rw, int flags)
3902 diff --git a/module/os/linux/zfs/zfs_sysfs.c b/module/os/linux/zfs/zfs_sysfs.c
3903 index fb7c68987..e73b34a2f 100644
3904 --- a/module/os/linux/zfs/zfs_sysfs.c
3905 +++ b/module/os/linux/zfs/zfs_sysfs.c
3908 * A zfs_mod_kobj_t represents a zfs kobject under '/sys/module/zfs'
3910 -struct zfs_mod_kobj;
3911 typedef struct zfs_mod_kobj zfs_mod_kobj_t;
3913 struct zfs_mod_kobj {
3914 struct kobject zko_kobj;
3915 struct kobj_type zko_kobj_type;
3916 struct sysfs_ops zko_sysfs_ops;
3917 size_t zko_attr_count;
3918 struct attribute *zko_attr_list; /* allocated */
3919 - struct attribute **zko_default_attrs; /* allocated */
3920 + struct attribute_group zko_default_group; /* .attrs allocated */
3921 + const struct attribute_group *zko_default_groups[2];
3922 size_t zko_child_count;
3923 zfs_mod_kobj_t *zko_children; /* allocated */
3925 @@ -126,10 +125,10 @@ zfs_kobj_release(struct kobject *kobj)
3926 zkobj->zko_attr_list = NULL;
3929 - if (zkobj->zko_default_attrs != NULL) {
3930 - kmem_free(zkobj->zko_default_attrs,
3931 + if (zkobj->zko_default_group.attrs != NULL) {
3932 + kmem_free(zkobj->zko_default_group.attrs,
3933 DEFAULT_ATTR_SIZE(zkobj->zko_attr_count));
3934 - zkobj->zko_default_attrs = NULL;
3935 + zkobj->zko_default_group.attrs = NULL;
3938 if (zkobj->zko_child_count != 0) {
3939 @@ -153,11 +152,12 @@ zfs_kobj_add_attr(zfs_mod_kobj_t *zkobj, int attr_num, const char *attr_name)
3941 VERIFY3U(attr_num, <, zkobj->zko_attr_count);
3942 ASSERT(zkobj->zko_attr_list);
3943 - ASSERT(zkobj->zko_default_attrs);
3944 + ASSERT(zkobj->zko_default_group.attrs);
3946 zkobj->zko_attr_list[attr_num].name = attr_name;
3947 zkobj->zko_attr_list[attr_num].mode = 0444;
3948 - zkobj->zko_default_attrs[attr_num] = &zkobj->zko_attr_list[attr_num];
3949 + zkobj->zko_default_group.attrs[attr_num] =
3950 + &zkobj->zko_attr_list[attr_num];
3951 sysfs_attr_init(&zkobj->zko_attr_list[attr_num]);
3954 @@ -175,9 +175,9 @@ zfs_kobj_init(zfs_mod_kobj_t *zkobj, int attr_cnt, int child_cnt,
3957 /* this will always have at least one slot for NULL termination */
3958 - zkobj->zko_default_attrs = kmem_zalloc(DEFAULT_ATTR_SIZE(attr_cnt),
3960 - if (zkobj->zko_default_attrs == NULL) {
3961 + zkobj->zko_default_group.attrs =
3962 + kmem_zalloc(DEFAULT_ATTR_SIZE(attr_cnt), KM_SLEEP);
3963 + if (zkobj->zko_default_group.attrs == NULL) {
3964 if (zkobj->zko_attr_list != NULL) {
3965 kmem_free(zkobj->zko_attr_list,
3966 ATTR_TABLE_SIZE(attr_cnt));
3967 @@ -185,14 +185,19 @@ zfs_kobj_init(zfs_mod_kobj_t *zkobj, int attr_cnt, int child_cnt,
3970 zkobj->zko_attr_count = attr_cnt;
3971 - zkobj->zko_kobj_type.default_attrs = zkobj->zko_default_attrs;
3972 + zkobj->zko_default_groups[0] = &zkobj->zko_default_group;
3973 +#ifdef HAVE_SYSFS_DEFAULT_GROUPS
3974 + zkobj->zko_kobj_type.default_groups = zkobj->zko_default_groups;
3976 + zkobj->zko_kobj_type.default_attrs = zkobj->zko_default_group.attrs;
3979 if (child_cnt > 0) {
3980 zkobj->zko_children = kmem_zalloc(CHILD_TABLE_SIZE(child_cnt),
3982 if (zkobj->zko_children == NULL) {
3983 - if (zkobj->zko_default_attrs != NULL) {
3984 - kmem_free(zkobj->zko_default_attrs,
3985 + if (zkobj->zko_default_group.attrs != NULL) {
3986 + kmem_free(zkobj->zko_default_group.attrs,
3987 DEFAULT_ATTR_SIZE(attr_cnt));
3989 if (zkobj->zko_attr_list != NULL) {
3990 @@ -214,9 +219,9 @@ zfs_kobj_init(zfs_mod_kobj_t *zkobj, int attr_cnt, int child_cnt,
3992 zfs_kobj_add(zfs_mod_kobj_t *zkobj, struct kobject *parent, const char *name)
3994 - /* zko_default_attrs must be NULL terminated */
3995 - ASSERT(zkobj->zko_default_attrs != NULL);
3996 - ASSERT(zkobj->zko_default_attrs[zkobj->zko_attr_count] == NULL);
3997 + /* zko_default_group.attrs must be NULL terminated */
3998 + ASSERT(zkobj->zko_default_group.attrs != NULL);
3999 + ASSERT(zkobj->zko_default_group.attrs[zkobj->zko_attr_count] == NULL);
4001 kobject_init(&zkobj->zko_kobj, &zkobj->zko_kobj_type);
4002 return (kobject_add(&zkobj->zko_kobj, parent, name));
4003 diff --git a/module/os/linux/zfs/zfs_uio.c b/module/os/linux/zfs/zfs_uio.c
4004 index a3d5d5f83..11cd62f5f 100644
4005 --- a/module/os/linux/zfs/zfs_uio.c
4006 +++ b/module/os/linux/zfs/zfs_uio.c
4007 @@ -248,7 +248,7 @@ zfs_uio_prefaultpages(ssize_t n, zfs_uio_t *uio)
4008 /* touch each page in this segment. */
4009 p = iov->iov_base + skip;
4011 - if (get_user(tmp, (uint8_t *)p))
4012 + if (copy_from_user(&tmp, p, 1))
4014 ulong_t incr = MIN(cnt, PAGESIZE);
4016 @@ -256,7 +256,7 @@ zfs_uio_prefaultpages(ssize_t n, zfs_uio_t *uio)
4018 /* touch the last byte in case it straddles a page. */
4020 - if (get_user(tmp, (uint8_t *)p))
4021 + if (copy_from_user(&tmp, p, 1))
4025 diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c
4026 index 2958439ac..796a86c25 100644
4027 --- a/module/os/linux/zfs/zfs_vnops_os.c
4028 +++ b/module/os/linux/zfs/zfs_vnops_os.c
4029 @@ -3594,7 +3594,11 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc)
4033 +#ifdef HAVE_VFS_FILEMAP_DIRTY_FOLIO
4034 + filemap_dirty_folio(page_mapping(pp), page_folio(pp));
4036 __set_page_dirty_nobuffers(pp);
4039 end_page_writeback(pp);
4040 zfs_rangelock_exit(lr);
4041 diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c
4042 index f1241c443..626e7f79d 100644
4043 --- a/module/os/linux/zfs/zpl_file.c
4044 +++ b/module/os/linux/zfs/zpl_file.c
4046 #include <sys/zfs_vfsops.h>
4047 #include <sys/zfs_vnops.h>
4048 #include <sys/zfs_project.h>
4049 -#ifdef HAVE_VFS_SET_PAGE_DIRTY_NOBUFFERS
4050 +#if defined(HAVE_VFS_SET_PAGE_DIRTY_NOBUFFERS) || \
4051 + defined(HAVE_VFS_FILEMAP_DIRTY_FOLIO)
4052 #include <linux/pagemap.h>
4054 +#ifdef HAVE_VFS_FILEMAP_DIRTY_FOLIO
4055 +#include <linux/writeback.h>
4059 * When using fallocate(2) to preallocate space, inflate the requested
4060 @@ -413,6 +417,8 @@ zpl_aio_write(struct kiocb *kiocb, const struct iovec *iov,
4064 + kiocb->ki_pos = pos;
4067 zfs_uio_iovec_init(&uio, iov, nr_segs, kiocb->ki_pos, UIO_USERSPACE,
4069 @@ -647,12 +653,29 @@ zpl_readpage_filler(void *data, struct page *pp)
4070 * paging. For simplicity, the code relies on read_cache_pages() to
4071 * correctly lock each page for IO and call zpl_readpage().
4073 +#ifdef HAVE_VFS_READPAGES
4075 zpl_readpages(struct file *filp, struct address_space *mapping,
4076 struct list_head *pages, unsigned nr_pages)
4078 return (read_cache_pages(mapping, pages, zpl_readpage_filler, NULL));
4082 +zpl_readahead(struct readahead_control *ractl)
4084 + struct page *page;
4086 + while ((page = readahead_page(ractl)) != NULL) {
4089 + ret = zpl_readpage_filler(NULL, page);
4098 zpl_putpage(struct page *pp, struct writeback_control *wbc, void *data)
4099 @@ -764,11 +787,13 @@ zpl_fallocate_common(struct inode *ip, int mode, loff_t offset, loff_t len)
4100 if (mode & (test_mode)) {
4103 - if (offset > olen)
4105 + if (mode & FALLOC_FL_KEEP_SIZE) {
4106 + if (offset > olen)
4109 - if (offset + len > olen)
4110 - len = olen - offset;
4111 + if (offset + len > olen)
4112 + len = olen - offset;
4114 bf.l_type = F_WRLCK;
4115 bf.l_whence = SEEK_SET;
4116 bf.l_start = offset;
4117 @@ -1027,7 +1052,11 @@ zpl_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
4120 const struct address_space_operations zpl_address_space_operations = {
4121 +#ifdef HAVE_VFS_READPAGES
4122 .readpages = zpl_readpages,
4124 + .readahead = zpl_readahead,
4126 .readpage = zpl_readpage,
4127 .writepage = zpl_writepage,
4128 .writepages = zpl_writepages,
4129 @@ -1035,6 +1064,9 @@ const struct address_space_operations zpl_address_space_operations = {
4130 #ifdef HAVE_VFS_SET_PAGE_DIRTY_NOBUFFERS
4131 .set_page_dirty = __set_page_dirty_nobuffers,
4133 +#ifdef HAVE_VFS_FILEMAP_DIRTY_FOLIO
4134 + .dirty_folio = filemap_dirty_folio,
4138 const struct file_operations zpl_file_operations = {
4139 diff --git a/module/os/linux/zfs/zvol_os.c b/module/os/linux/zfs/zvol_os.c
4140 index 7a979eb91..5c509a06a 100644
4141 --- a/module/os/linux/zfs/zvol_os.c
4142 +++ b/module/os/linux/zfs/zvol_os.c
4143 @@ -903,22 +903,17 @@ zvol_alloc(dev_t dev, const char *name)
4144 zso->zvo_disk->major = zvol_major;
4145 zso->zvo_disk->events = DISK_EVENT_MEDIA_CHANGE;
4148 + * Setting ZFS_VOLMODE_DEV disables partitioning on ZVOL devices.
4149 + * This is accomplished by limiting the number of minors for the
4150 + * device to one and explicitly disabling partition scanning.
4152 if (volmode == ZFS_VOLMODE_DEV) {
4154 - * ZFS_VOLMODE_DEV disable partitioning on ZVOL devices: set
4155 - * gendisk->minors = 1 as noted in include/linux/genhd.h.
4156 - * Also disable extended partition numbers (GENHD_FL_EXT_DEVT)
4157 - * and suppresses partition scanning (GENHD_FL_NO_PART_SCAN)
4158 - * setting gendisk->flags accordingly.
4160 zso->zvo_disk->minors = 1;
4161 -#if defined(GENHD_FL_EXT_DEVT)
4162 - zso->zvo_disk->flags &= ~GENHD_FL_EXT_DEVT;
4164 -#if defined(GENHD_FL_NO_PART_SCAN)
4165 - zso->zvo_disk->flags |= GENHD_FL_NO_PART_SCAN;
4167 + zso->zvo_disk->flags &= ~ZFS_GENHD_FL_EXT_DEVT;
4168 + zso->zvo_disk->flags |= ZFS_GENHD_FL_NO_PART;
4171 zso->zvo_disk->first_minor = (dev & MINORMASK);
4172 zso->zvo_disk->fops = &zvol_ops;
4173 zso->zvo_disk->private_data = zv;
4174 diff --git a/module/zfs/arc.c b/module/zfs/arc.c
4175 index 47b58b6c2..8acb5d5ef 100644
4176 --- a/module/zfs/arc.c
4177 +++ b/module/zfs/arc.c
4178 @@ -3430,7 +3430,6 @@ arc_hdr_realloc_crypt(arc_buf_hdr_t *hdr, boolean_t need_crypt)
4179 arc_buf_hdr_t *nhdr;
4181 kmem_cache_t *ncache, *ocache;
4182 - unsigned nsize, osize;
4185 * This function requires that hdr is in the arc_anon state.
4186 @@ -3447,14 +3446,10 @@ arc_hdr_realloc_crypt(arc_buf_hdr_t *hdr, boolean_t need_crypt)
4189 ncache = hdr_full_crypt_cache;
4190 - nsize = sizeof (hdr->b_crypt_hdr);
4191 ocache = hdr_full_cache;
4192 - osize = HDR_FULL_SIZE;
4194 ncache = hdr_full_cache;
4195 - nsize = HDR_FULL_SIZE;
4196 ocache = hdr_full_crypt_cache;
4197 - osize = sizeof (hdr->b_crypt_hdr);
4200 nhdr = kmem_cache_alloc(ncache, KM_PUSHPAGE);
4201 diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c
4202 index d61724be8..247eeddb6 100644
4203 --- a/module/zfs/dbuf.c
4204 +++ b/module/zfs/dbuf.c
4205 @@ -338,18 +338,18 @@ dbuf_find(objset_t *os, uint64_t obj, uint8_t level, uint64_t blkid)
4206 hv = dbuf_hash(os, obj, level, blkid);
4207 idx = hv & h->hash_table_mask;
4209 - mutex_enter(DBUF_HASH_MUTEX(h, idx));
4210 + rw_enter(DBUF_HASH_RWLOCK(h, idx), RW_READER);
4211 for (db = h->hash_table[idx]; db != NULL; db = db->db_hash_next) {
4212 if (DBUF_EQUAL(db, os, obj, level, blkid)) {
4213 mutex_enter(&db->db_mtx);
4214 if (db->db_state != DB_EVICTING) {
4215 - mutex_exit(DBUF_HASH_MUTEX(h, idx));
4216 + rw_exit(DBUF_HASH_RWLOCK(h, idx));
4219 mutex_exit(&db->db_mtx);
4222 - mutex_exit(DBUF_HASH_MUTEX(h, idx));
4223 + rw_exit(DBUF_HASH_RWLOCK(h, idx));
4227 @@ -392,13 +392,13 @@ dbuf_hash_insert(dmu_buf_impl_t *db)
4228 hv = dbuf_hash(os, obj, level, blkid);
4229 idx = hv & h->hash_table_mask;
4231 - mutex_enter(DBUF_HASH_MUTEX(h, idx));
4232 + rw_enter(DBUF_HASH_RWLOCK(h, idx), RW_WRITER);
4233 for (dbf = h->hash_table[idx], i = 0; dbf != NULL;
4234 dbf = dbf->db_hash_next, i++) {
4235 if (DBUF_EQUAL(dbf, os, obj, level, blkid)) {
4236 mutex_enter(&dbf->db_mtx);
4237 if (dbf->db_state != DB_EVICTING) {
4238 - mutex_exit(DBUF_HASH_MUTEX(h, idx));
4239 + rw_exit(DBUF_HASH_RWLOCK(h, idx));
4242 mutex_exit(&dbf->db_mtx);
4243 @@ -416,7 +416,7 @@ dbuf_hash_insert(dmu_buf_impl_t *db)
4244 mutex_enter(&db->db_mtx);
4245 db->db_hash_next = h->hash_table[idx];
4246 h->hash_table[idx] = db;
4247 - mutex_exit(DBUF_HASH_MUTEX(h, idx));
4248 + rw_exit(DBUF_HASH_RWLOCK(h, idx));
4249 uint64_t he = atomic_inc_64_nv(&dbuf_stats.hash_elements.value.ui64);
4250 DBUF_STAT_MAX(hash_elements_max, he);
4252 @@ -473,13 +473,13 @@ dbuf_hash_remove(dmu_buf_impl_t *db)
4255 * We mustn't hold db_mtx to maintain lock ordering:
4256 - * DBUF_HASH_MUTEX > db_mtx.
4257 + * DBUF_HASH_RWLOCK > db_mtx.
4259 ASSERT(zfs_refcount_is_zero(&db->db_holds));
4260 ASSERT(db->db_state == DB_EVICTING);
4261 ASSERT(!MUTEX_HELD(&db->db_mtx));
4263 - mutex_enter(DBUF_HASH_MUTEX(h, idx));
4264 + rw_enter(DBUF_HASH_RWLOCK(h, idx), RW_WRITER);
4265 dbp = &h->hash_table[idx];
4266 while ((dbf = *dbp) != db) {
4267 dbp = &dbf->db_hash_next;
4268 @@ -490,7 +490,7 @@ dbuf_hash_remove(dmu_buf_impl_t *db)
4269 if (h->hash_table[idx] &&
4270 h->hash_table[idx]->db_hash_next == NULL)
4271 DBUF_STAT_BUMPDOWN(hash_chains);
4272 - mutex_exit(DBUF_HASH_MUTEX(h, idx));
4273 + rw_exit(DBUF_HASH_RWLOCK(h, idx));
4274 atomic_dec_64(&dbuf_stats.hash_elements.value.ui64);
4277 @@ -851,8 +851,8 @@ retry:
4278 sizeof (dmu_buf_impl_t),
4279 0, dbuf_cons, dbuf_dest, NULL, NULL, NULL, 0);
4281 - for (i = 0; i < DBUF_MUTEXES; i++)
4282 - mutex_init(&h->hash_mutexes[i], NULL, MUTEX_DEFAULT, NULL);
4283 + for (i = 0; i < DBUF_RWLOCKS; i++)
4284 + rw_init(&h->hash_rwlocks[i], NULL, RW_DEFAULT, NULL);
4288 @@ -918,8 +918,8 @@ dbuf_fini(void)
4290 dbuf_stats_destroy();
4292 - for (i = 0; i < DBUF_MUTEXES; i++)
4293 - mutex_destroy(&h->hash_mutexes[i]);
4294 + for (i = 0; i < DBUF_RWLOCKS; i++)
4295 + rw_destroy(&h->hash_rwlocks[i]);
4296 #if defined(_KERNEL)
4298 * Large allocations which do not require contiguous pages
4299 @@ -1465,10 +1465,8 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags,
4300 zbookmark_phys_t zb;
4301 uint32_t aflags = ARC_FLAG_NOWAIT;
4303 - boolean_t bonus_read;
4305 err = zio_flags = 0;
4306 - bonus_read = B_FALSE;
4309 ASSERT(!zfs_refcount_is_zero(&db->db_holds));
4310 @@ -3886,7 +3884,7 @@ dmu_buf_get_user(dmu_buf_t *db_fake)
4314 -dmu_buf_user_evict_wait()
4315 +dmu_buf_user_evict_wait(void)
4317 taskq_wait(dbu_evict_taskq);
4319 diff --git a/module/zfs/dbuf_stats.c b/module/zfs/dbuf_stats.c
4320 index 12bb568a0..037190a81 100644
4321 --- a/module/zfs/dbuf_stats.c
4322 +++ b/module/zfs/dbuf_stats.c
4323 @@ -137,7 +137,7 @@ dbuf_stats_hash_table_data(char *buf, size_t size, void *data)
4327 - mutex_enter(DBUF_HASH_MUTEX(h, dsh->idx));
4328 + rw_enter(DBUF_HASH_RWLOCK(h, dsh->idx), RW_READER);
4329 for (db = h->hash_table[dsh->idx]; db != NULL; db = db->db_hash_next) {
4331 * Returning ENOMEM will cause the data and header functions
4332 @@ -158,7 +158,7 @@ dbuf_stats_hash_table_data(char *buf, size_t size, void *data)
4334 mutex_exit(&db->db_mtx);
4336 - mutex_exit(DBUF_HASH_MUTEX(h, dsh->idx));
4337 + rw_exit(DBUF_HASH_RWLOCK(h, dsh->idx));
4341 diff --git a/module/zfs/dmu.c b/module/zfs/dmu.c
4342 index 0c528f68c..4e7127bd1 100644
4343 --- a/module/zfs/dmu.c
4344 +++ b/module/zfs/dmu.c
4345 @@ -73,9 +73,13 @@ int zfs_nopwrite_enabled = 1;
4346 unsigned long zfs_per_txg_dirty_frees_percent = 5;
4349 - * Enable/disable forcing txg sync when dirty in dmu_offset_next.
4350 + * Enable/disable forcing txg sync when dirty checking for holes with lseek().
4351 + * By default this is enabled to ensure accurate hole reporting, it can result
4352 + * in a significant performance penalty for lseek(SEEK_HOLE) heavy workloads.
4353 + * Disabling this option will result in holes never being reported in dirty
4354 + * files which is always safe.
4356 -int zfs_dmu_offset_next_sync = 0;
4357 +int zfs_dmu_offset_next_sync = 1;
4360 * Limit the amount we can prefetch with one call to this amount. This
4361 @@ -2110,8 +2114,8 @@ restart:
4362 * If the zfs_dmu_offset_next_sync module option is enabled
4363 * then strict hole reporting has been requested. Dirty
4364 * dnodes must be synced to disk to accurately report all
4365 - * holes. When disabled (the default) dirty dnodes are
4366 - * reported to not have any holes which is always safe.
4367 + * holes. When disabled dirty dnodes are reported to not
4368 + * have any holes which is always safe.
4370 * When called by zfs_holey_common() the zp->z_rangelock
4371 * is held to prevent zfs_write() and mmap writeback from
4372 diff --git a/module/zfs/metaslab.c b/module/zfs/metaslab.c
4373 index f367bea98..9e216c38d 100644
4374 --- a/module/zfs/metaslab.c
4375 +++ b/module/zfs/metaslab.c
4376 @@ -2659,7 +2659,8 @@ metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object,
4379 * We only open space map objects that already exist. All others
4380 - * will be opened when we finally allocate an object for it.
4381 + * will be opened when we finally allocate an object for it. For
4382 + * readonly pools there is no need to open the space map object.
4385 * When called from vdev_expand(), we can't call into the DMU as
4386 @@ -2668,7 +2669,8 @@ metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object,
4387 * that case, the object parameter is zero though, so we won't
4388 * call into the DMU.
4390 - if (object != 0) {
4391 + if (object != 0 && !(spa->spa_mode == SPA_MODE_READ &&
4392 + !spa->spa_read_spacemaps)) {
4393 error = space_map_open(&ms->ms_sm, mos, object, ms->ms_start,
4394 ms->ms_size, vd->vdev_ashift);
4396 diff --git a/module/zfs/refcount.c b/module/zfs/refcount.c
4397 index 354e021d9..35a379dde 100644
4398 --- a/module/zfs/refcount.c
4399 +++ b/module/zfs/refcount.c
4400 @@ -318,6 +318,14 @@ zfs_refcount_not_held(zfs_refcount_t *rc, const void *holder)
4404 +EXPORT_SYMBOL(zfs_refcount_create);
4405 +EXPORT_SYMBOL(zfs_refcount_destroy);
4406 +EXPORT_SYMBOL(zfs_refcount_is_zero);
4407 +EXPORT_SYMBOL(zfs_refcount_count);
4408 +EXPORT_SYMBOL(zfs_refcount_add);
4409 +EXPORT_SYMBOL(zfs_refcount_remove);
4410 +EXPORT_SYMBOL(zfs_refcount_held);
4413 ZFS_MODULE_PARAM(zfs, ,reference_tracking_enable, INT, ZMOD_RW,
4414 "Track reference holders to refcount_t objects");
4415 diff --git a/module/zfs/spa.c b/module/zfs/spa.c
4416 index 7c49ced99..dfa73483a 100644
4417 --- a/module/zfs/spa.c
4418 +++ b/module/zfs/spa.c
4419 @@ -180,6 +180,12 @@ boolean_t spa_create_process = B_TRUE; /* no process ==> no sysdc */
4421 boolean_t spa_load_verify_dryrun = B_FALSE;
4424 + * Allow read spacemaps in case of readonly import (spa_mode == SPA_MODE_READ).
4425 + * This is used by zdb for spacemaps verification.
4427 +boolean_t spa_mode_readable_spacemaps = B_FALSE;
4430 * This (illegal) pool name is used when temporarily importing a spa_t in order
4431 * to get the vdev stats associated with the imported devices.
4432 @@ -1241,6 +1247,7 @@ spa_activate(spa_t *spa, spa_mode_t mode)
4434 spa->spa_state = POOL_STATE_ACTIVE;
4435 spa->spa_mode = mode;
4436 + spa->spa_read_spacemaps = spa_mode_readable_spacemaps;
4438 spa->spa_normal_class = metaslab_class_create(spa, zfs_metaslab_ops);
4439 spa->spa_log_class = metaslab_class_create(spa, zfs_metaslab_ops);
4440 diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c
4441 index 57dcfe723..a323b90a2 100644
4442 --- a/module/zfs/vdev.c
4443 +++ b/module/zfs/vdev.c
4444 @@ -3147,6 +3147,12 @@ vdev_dtl_load(vdev_t *vd)
4445 if (vd->vdev_ops->vdev_op_leaf && vd->vdev_dtl_object != 0) {
4446 ASSERT(vdev_is_concrete(vd));
4449 + * If the dtl cannot be sync'd there is no need to open it.
4451 + if (spa->spa_mode == SPA_MODE_READ && !spa->spa_read_spacemaps)
4454 error = space_map_open(&vd->vdev_dtl_sm, mos,
4455 vd->vdev_dtl_object, 0, -1ULL, 0);
4457 diff --git a/module/zfs/vdev_indirect.c b/module/zfs/vdev_indirect.c
4458 index b541058d9..8762855d4 100644
4459 --- a/module/zfs/vdev_indirect.c
4460 +++ b/module/zfs/vdev_indirect.c
4461 @@ -1423,11 +1423,6 @@ vdev_indirect_repair(zio_t *zio)
4463 indirect_vsd_t *iv = zio->io_vsd;
4465 - enum zio_flag flags = ZIO_FLAG_IO_REPAIR;
4467 - if (!(zio->io_flags & (ZIO_FLAG_SCRUB | ZIO_FLAG_RESILVER)))
4468 - flags |= ZIO_FLAG_SELF_HEAL;
4470 if (!spa_writeable(zio->io_spa))
4473 diff --git a/module/zfs/vdev_removal.c b/module/zfs/vdev_removal.c
4474 index b51d862f6..d7385cdf2 100644
4475 --- a/module/zfs/vdev_removal.c
4476 +++ b/module/zfs/vdev_removal.c
4477 @@ -1517,10 +1517,6 @@ spa_vdev_remove_thread(void *arg)
4478 * specified by zfs_removal_suspend_progress. We do this
4479 * solely from the test suite or during debugging.
4481 - uint64_t bytes_copied =
4482 - spa->spa_removing_phys.sr_copied;
4483 - for (int i = 0; i < TXG_SIZE; i++)
4484 - bytes_copied += svr->svr_bytes_done[i];
4485 while (zfs_removal_suspend_progress &&
4486 !svr->svr_thread_exit)
4488 diff --git a/module/zfs/zfs_fm.c b/module/zfs/zfs_fm.c
4489 index 87f793cb4..a05ff7330 100644
4490 --- a/module/zfs/zfs_fm.c
4491 +++ b/module/zfs/zfs_fm.c
4492 @@ -825,9 +825,6 @@ annotate_ecksum(nvlist_t *ereport, zio_bad_cksum_t *info,
4493 const uint64_t *good;
4494 const uint64_t *bad;
4496 - uint64_t allset = 0;
4497 - uint64_t allcleared = 0;
4499 size_t nui64s = size / sizeof (uint64_t);
4502 @@ -929,9 +926,6 @@ annotate_ecksum(nvlist_t *ereport, zio_bad_cksum_t *info,
4503 // bits set in good, but not in bad
4504 cleared = (good[idx] & (~bad[idx]));
4507 - allcleared |= cleared;
4510 ASSERT3U(offset, <, inline_size);
4511 eip->zei_bits_set[offset] = set;
4512 diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
4513 index 721a7b4b8..59b05b4b0 100644
4514 --- a/module/zfs/zvol.c
4515 +++ b/module/zfs/zvol.c
4516 @@ -1353,13 +1353,12 @@ static void
4517 zvol_rename_minors_impl(const char *oldname, const char *newname)
4519 zvol_state_t *zv, *zv_next;
4520 - int oldnamelen, newnamelen;
4523 if (zvol_inhibit_dev)
4526 oldnamelen = strlen(oldname);
4527 - newnamelen = strlen(newname);
4529 rw_enter(&zvol_state_lock, RW_READER);
4531 diff --git a/module/zstd/Makefile.in b/module/zstd/Makefile.in
4532 index 091f7cea3..598409ca1 100644
4533 --- a/module/zstd/Makefile.in
4534 +++ b/module/zstd/Makefile.in
4535 @@ -37,3 +37,9 @@ $(MODULE)-objs += zstd_sparc.o
4541 + @OBJDUMP@ -t lib/zstd.o | awk '$$2 == "g" && !/ zfs_/ {print "#define\t" $$6 " zfs_" $$6}' | sort >> include/zstd_compat_wrapper.h
4544 + @OBJDUMP@ -t lib/zstd.o | awk '/file format/ {print} $$2 == "g" && !/ zfs_/ {++ret; print} END {exit ret}'
4545 diff --git a/module/zstd/include/zstd_compat_wrapper.h b/module/zstd/include/zstd_compat_wrapper.h
4546 index 339713590..5d20623a7 100644
4547 --- a/module/zstd/include/zstd_compat_wrapper.h
4548 +++ b/module/zstd/include/zstd_compat_wrapper.h
4549 @@ -36,333 +36,273 @@
4550 * This wrapper fixes a problem, in case the ZFS filesystem driver, is compiled
4551 * statically into the kernel.
4552 * This will cause a symbol collision with the older in-kernel zstd library.
4553 - * The following macros will simply rename all local zstd symbols and references
4555 - * Note: if the zstd library for zfs is updated to a newer version, this macro
4556 - * list usually needs to be updated.
4557 - * this can be done with some hand crafting of the output of the following
4559 - * nm zstd.o | awk '{print "#define "$3 " zfs_" $3}' > macrotable
4560 + * On update, truncate this file at the scissor line, rebuild the module,
4561 + * and make gensymbols.
4564 #define BIT_initDStream zfs_BIT_initDStream
4565 #define BIT_mask zfs_BIT_mask
4566 #define BIT_reloadDStream zfs_BIT_reloadDStream
4570 #define ERR_getErrorString zfs_ERR_getErrorString
4571 -#define FSE_NCountWriteBound zfs_FSE_NCountWriteBound
4572 -#define FSE_buildCTable zfs_FSE_buildCTable
4573 #define FSE_buildCTable_raw zfs_FSE_buildCTable_raw
4574 #define FSE_buildCTable_rle zfs_FSE_buildCTable_rle
4575 #define FSE_buildCTable_wksp zfs_FSE_buildCTable_wksp
4576 -#define FSE_buildDTable zfs_FSE_buildDTable
4577 +#define FSE_buildCTable zfs_FSE_buildCTable
4578 #define FSE_buildDTable_raw zfs_FSE_buildDTable_raw
4579 #define FSE_buildDTable_rle zfs_FSE_buildDTable_rle
4580 -#define FSE_compress zfs_FSE_compress
4581 +#define FSE_buildDTable zfs_FSE_buildDTable
4582 #define FSE_compress2 zfs_FSE_compress2
4583 #define FSE_compressBound zfs_FSE_compressBound
4584 #define FSE_compress_usingCTable zfs_FSE_compress_usingCTable
4585 -#define FSE_compress_usingCTable_generic zfs_FSE_compress_usingCTable_generic
4586 #define FSE_compress_wksp zfs_FSE_compress_wksp
4587 +#define FSE_compress zfs_FSE_compress
4588 #define FSE_createCTable zfs_FSE_createCTable
4589 #define FSE_createDTable zfs_FSE_createDTable
4590 -#define FSE_decompress zfs_FSE_decompress
4591 #define FSE_decompress_usingDTable zfs_FSE_decompress_usingDTable
4592 #define FSE_decompress_wksp zfs_FSE_decompress_wksp
4593 +#define FSE_decompress zfs_FSE_decompress
4594 #define FSE_freeCTable zfs_FSE_freeCTable
4595 #define FSE_freeDTable zfs_FSE_freeDTable
4596 #define FSE_getErrorName zfs_FSE_getErrorName
4597 +#define FSE_isError zfs_FSE_isError
4598 +#define FSE_NCountWriteBound zfs_FSE_NCountWriteBound
4599 #define FSE_normalizeCount zfs_FSE_normalizeCount
4600 -#define FSE_optimalTableLog zfs_FSE_optimalTableLog
4601 #define FSE_optimalTableLog_internal zfs_FSE_optimalTableLog_internal
4602 +#define FSE_optimalTableLog zfs_FSE_optimalTableLog
4603 #define FSE_readNCount zfs_FSE_readNCount
4604 #define FSE_versionNumber zfs_FSE_versionNumber
4605 #define FSE_writeNCount zfs_FSE_writeNCount
4606 -#define HIST_count zfs_HIST_count
4607 -#define HIST_countFast zfs_HIST_countFast
4608 +#define g_debuglevel zfs_g_debuglevel
4609 #define HIST_countFast_wksp zfs_HIST_countFast_wksp
4610 -#define HIST_count_parallel_wksp zfs_HIST_count_parallel_wksp
4611 +#define HIST_countFast zfs_HIST_countFast
4612 #define HIST_count_simple zfs_HIST_count_simple
4613 #define HIST_count_wksp zfs_HIST_count_wksp
4614 -#define HUF_buildCTable zfs_HUF_buildCTable
4615 +#define HIST_count zfs_HIST_count
4616 +#define HIST_isError zfs_HIST_isError
4617 #define HUF_buildCTable_wksp zfs_HUF_buildCTable_wksp
4618 -#define HUF_compress zfs_HUF_compress
4619 -#define HUF_compress1X zfs_HUF_compress1X
4620 +#define HUF_buildCTable zfs_HUF_buildCTable
4621 #define HUF_compress1X_repeat zfs_HUF_compress1X_repeat
4622 #define HUF_compress1X_usingCTable zfs_HUF_compress1X_usingCTable
4623 #define HUF_compress1X_wksp zfs_HUF_compress1X_wksp
4624 +#define HUF_compress1X zfs_HUF_compress1X
4625 #define HUF_compress2 zfs_HUF_compress2
4626 #define HUF_compress4X_repeat zfs_HUF_compress4X_repeat
4627 #define HUF_compress4X_usingCTable zfs_HUF_compress4X_usingCTable
4628 #define HUF_compress4X_wksp zfs_HUF_compress4X_wksp
4629 #define HUF_compressBound zfs_HUF_compressBound
4630 -#define HUF_compressWeights zfs_HUF_compressWeights
4631 -#define HUF_decompress zfs_HUF_decompress
4632 -#define HUF_decompress1X1 zfs_HUF_decompress1X1
4633 -#define HUF_decompress1X1_DCtx zfs_HUF_decompress1X1_DCtx
4634 -#define HUF_decompress1X1_DCtx_wksp zfs_HUF_decompress1X1_DCtx_wksp
4635 +#define HUF_compress zfs_HUF_compress
4636 #define HUF_decompress1X1_DCtx_wksp_bmi2 zfs_HUF_decompress1X1_DCtx_wksp_bmi2
4637 +#define HUF_decompress1X1_DCtx_wksp zfs_HUF_decompress1X1_DCtx_wksp
4638 +#define HUF_decompress1X1_DCtx zfs_HUF_decompress1X1_DCtx
4639 #define HUF_decompress1X1_usingDTable zfs_HUF_decompress1X1_usingDTable
4640 -#define HUF_decompress1X2 zfs_HUF_decompress1X2
4641 -#define HUF_decompress1X2_DCtx zfs_HUF_decompress1X2_DCtx
4642 +#define HUF_decompress1X1 zfs_HUF_decompress1X1
4643 #define HUF_decompress1X2_DCtx_wksp zfs_HUF_decompress1X2_DCtx_wksp
4644 +#define HUF_decompress1X2_DCtx zfs_HUF_decompress1X2_DCtx
4645 #define HUF_decompress1X2_usingDTable zfs_HUF_decompress1X2_usingDTable
4646 -#define HUF_decompress1X_DCtx zfs_HUF_decompress1X_DCtx
4647 +#define HUF_decompress1X2 zfs_HUF_decompress1X2
4648 #define HUF_decompress1X_DCtx_wksp zfs_HUF_decompress1X_DCtx_wksp
4649 -#define HUF_decompress1X_usingDTable zfs_HUF_decompress1X_usingDTable
4650 +#define HUF_decompress1X_DCtx zfs_HUF_decompress1X_DCtx
4651 #define HUF_decompress1X_usingDTable_bmi2 zfs_HUF_decompress1X_usingDTable_bmi2
4652 -#define HUF_decompress4X1 zfs_HUF_decompress4X1
4653 -#define HUF_decompress4X1_DCtx zfs_HUF_decompress4X1_DCtx
4654 +#define HUF_decompress1X_usingDTable zfs_HUF_decompress1X_usingDTable
4655 #define HUF_decompress4X1_DCtx_wksp zfs_HUF_decompress4X1_DCtx_wksp
4656 +#define HUF_decompress4X1_DCtx zfs_HUF_decompress4X1_DCtx
4657 #define HUF_decompress4X1_usingDTable zfs_HUF_decompress4X1_usingDTable
4658 -#define HUF_decompress4X2 zfs_HUF_decompress4X2
4659 -#define HUF_decompress4X2_DCtx zfs_HUF_decompress4X2_DCtx
4660 +#define HUF_decompress4X1 zfs_HUF_decompress4X1
4661 #define HUF_decompress4X2_DCtx_wksp zfs_HUF_decompress4X2_DCtx_wksp
4662 +#define HUF_decompress4X2_DCtx zfs_HUF_decompress4X2_DCtx
4663 #define HUF_decompress4X2_usingDTable zfs_HUF_decompress4X2_usingDTable
4664 +#define HUF_decompress4X2 zfs_HUF_decompress4X2
4665 #define HUF_decompress4X_DCtx zfs_HUF_decompress4X_DCtx
4666 -#define HUF_decompress4X_hufOnly zfs_HUF_decompress4X_hufOnly
4667 +#define HUF_decompress4X_hufOnly_wksp_bmi2 zfs_HUF_decompress4X_hufOnly_wksp_bmi2
4668 #define HUF_decompress4X_hufOnly_wksp zfs_HUF_decompress4X_hufOnly_wksp
4669 -#define HUF_decompress4X_hufOnly_wksp_bmi2 \
4670 - zfs_HUF_decompress4X_hufOnly_wksp_bmi2
4671 -#define HUF_decompress4X_usingDTable zfs_HUF_decompress4X_usingDTable
4672 +#define HUF_decompress4X_hufOnly zfs_HUF_decompress4X_hufOnly
4673 #define HUF_decompress4X_usingDTable_bmi2 zfs_HUF_decompress4X_usingDTable_bmi2
4674 +#define HUF_decompress4X_usingDTable zfs_HUF_decompress4X_usingDTable
4675 +#define HUF_decompress zfs_HUF_decompress
4676 #define HUF_estimateCompressedSize zfs_HUF_estimateCompressedSize
4677 -#define HUF_fillDTableX2Level2 zfs_HUF_fillDTableX2Level2
4678 #define HUF_getErrorName zfs_HUF_getErrorName
4679 #define HUF_getNbBits zfs_HUF_getNbBits
4680 +#define HUF_isError zfs_HUF_isError
4681 #define HUF_optimalTableLog zfs_HUF_optimalTableLog
4682 #define HUF_readCTable zfs_HUF_readCTable
4683 -#define HUF_readDTableX1 zfs_HUF_readDTableX1
4684 #define HUF_readDTableX1_wksp zfs_HUF_readDTableX1_wksp
4685 -#define HUF_readDTableX2 zfs_HUF_readDTableX2
4686 +#define HUF_readDTableX1 zfs_HUF_readDTableX1
4687 #define HUF_readDTableX2_wksp zfs_HUF_readDTableX2_wksp
4688 +#define HUF_readDTableX2 zfs_HUF_readDTableX2
4689 #define HUF_readStats zfs_HUF_readStats
4690 #define HUF_selectDecoder zfs_HUF_selectDecoder
4691 -#define HUF_setMaxHeight zfs_HUF_setMaxHeight
4692 #define HUF_validateCTable zfs_HUF_validateCTable
4693 #define HUF_writeCTable zfs_HUF_writeCTable
4694 -#define LL_base zfs_LL_base
4695 -#define LL_bits zfs_LL_bits
4696 -#define LL_defaultDTable zfs_LL_defaultDTable
4697 -#define LL_defaultNorm zfs_LL_defaultNorm
4698 -#define ML_base zfs_ML_base
4699 -#define ML_bits zfs_ML_bits
4700 -#define ML_defaultDTable zfs_ML_defaultDTable
4701 -#define ML_defaultNorm zfs_ML_defaultNorm
4702 -#define OF_base zfs_OF_base
4703 -#define OF_bits zfs_OF_bits
4704 -#define OF_defaultDTable zfs_OF_defaultDTable
4705 -#define OF_defaultNorm zfs_OF_defaultNorm
4706 #define POOL_add zfs_POOL_add
4707 -#define POOL_create zfs_POOL_create
4708 #define POOL_create_advanced zfs_POOL_create_advanced
4709 +#define POOL_create zfs_POOL_create
4710 #define POOL_free zfs_POOL_free
4711 #define POOL_resize zfs_POOL_resize
4712 #define POOL_sizeof zfs_POOL_sizeof
4713 #define POOL_tryAdd zfs_POOL_tryAdd
4714 +#define ZSTD_adjustCParams zfs_ZSTD_adjustCParams
4715 +#define ZSTD_buildCTable zfs_ZSTD_buildCTable
4716 +#define ZSTD_buildFSETable zfs_ZSTD_buildFSETable
4717 +#define ZSTD_calloc zfs_ZSTD_calloc
4718 +#define ZSTD_CCtx_getParameter zfs_ZSTD_CCtx_getParameter
4719 +#define ZSTD_CCtx_loadDictionary_advanced zfs_ZSTD_CCtx_loadDictionary_advanced
4720 +#define ZSTD_CCtx_loadDictionary_byReference zfs_ZSTD_CCtx_loadDictionary_byReference
4721 +#define ZSTD_CCtx_loadDictionary zfs_ZSTD_CCtx_loadDictionary
4722 #define ZSTD_CCtxParams_getParameter zfs_ZSTD_CCtxParams_getParameter
4723 -#define ZSTD_CCtxParams_init zfs_ZSTD_CCtxParams_init
4724 #define ZSTD_CCtxParams_init_advanced zfs_ZSTD_CCtxParams_init_advanced
4725 +#define ZSTD_CCtxParams_init zfs_ZSTD_CCtxParams_init
4726 #define ZSTD_CCtxParams_reset zfs_ZSTD_CCtxParams_reset
4727 #define ZSTD_CCtxParams_setParameter zfs_ZSTD_CCtxParams_setParameter
4728 -#define ZSTD_CCtx_getParameter zfs_ZSTD_CCtx_getParameter
4729 -#define ZSTD_CCtx_loadDictionary zfs_ZSTD_CCtx_loadDictionary
4730 -#define ZSTD_CCtx_loadDictionary_advanced zfs_ZSTD_CCtx_loadDictionary_advanced
4731 -#define ZSTD_CCtx_loadDictionary_byReference \
4732 - zfs_ZSTD_CCtx_loadDictionary_byReference
4733 #define ZSTD_CCtx_refCDict zfs_ZSTD_CCtx_refCDict
4734 -#define ZSTD_CCtx_refPrefix zfs_ZSTD_CCtx_refPrefix
4735 #define ZSTD_CCtx_refPrefix_advanced zfs_ZSTD_CCtx_refPrefix_advanced
4736 +#define ZSTD_CCtx_refPrefix zfs_ZSTD_CCtx_refPrefix
4737 #define ZSTD_CCtx_reset zfs_ZSTD_CCtx_reset
4738 +#define ZSTD_CCtx_setParametersUsingCCtxParams zfs_ZSTD_CCtx_setParametersUsingCCtxParams
4739 #define ZSTD_CCtx_setParameter zfs_ZSTD_CCtx_setParameter
4740 -#define ZSTD_CCtx_setParametersUsingCCtxParams \
4741 - zfs_ZSTD_CCtx_setParametersUsingCCtxParams
4742 #define ZSTD_CCtx_setPledgedSrcSize zfs_ZSTD_CCtx_setPledgedSrcSize
4743 -#define ZSTD_CStreamInSize zfs_ZSTD_CStreamInSize
4744 -#define ZSTD_CStreamOutSize zfs_ZSTD_CStreamOutSize
4745 -#define ZSTD_DCtx_loadDictionary zfs_ZSTD_DCtx_loadDictionary
4746 -#define ZSTD_DCtx_loadDictionary_advanced zfs_ZSTD_DCtx_loadDictionary_advanced
4747 -#define ZSTD_DCtx_loadDictionary_byReference \
4748 - zfs_ZSTD_DCtx_loadDictionary_byReference
4749 -#define ZSTD_DCtx_refDDict zfs_ZSTD_DCtx_refDDict
4750 -#define ZSTD_DCtx_refPrefix zfs_ZSTD_DCtx_refPrefix
4751 -#define ZSTD_DCtx_refPrefix_advanced zfs_ZSTD_DCtx_refPrefix_advanced
4752 -#define ZSTD_DCtx_reset zfs_ZSTD_DCtx_reset
4753 -#define ZSTD_DCtx_setFormat zfs_ZSTD_DCtx_setFormat
4754 -#define ZSTD_DCtx_setMaxWindowSize zfs_ZSTD_DCtx_setMaxWindowSize
4755 -#define ZSTD_DCtx_setParameter zfs_ZSTD_DCtx_setParameter
4756 -#define ZSTD_DDict_dictContent zfs_ZSTD_DDict_dictContent
4757 -#define ZSTD_DDict_dictSize zfs_ZSTD_DDict_dictSize
4758 -#define ZSTD_DStreamInSize zfs_ZSTD_DStreamInSize
4759 -#define ZSTD_DStreamOutSize zfs_ZSTD_DStreamOutSize
4760 -#define ZSTD_DUBT_findBestMatch zfs_ZSTD_DUBT_findBestMatch
4761 -#define ZSTD_NCountCost zfs_ZSTD_NCountCost
4762 -#define ZSTD_XXH64_digest zfs_ZSTD_XXH64_digest
4763 -#define ZSTD_adjustCParams zfs_ZSTD_adjustCParams
4764 -#define ZSTD_assignParamsToCCtxParams zfs_ZSTD_assignParamsToCCtxParams
4765 -#define ZSTD_buildCTable zfs_ZSTD_buildCTable
4766 -#define ZSTD_buildFSETable zfs_ZSTD_buildFSETable
4767 -#define ZSTD_buildSeqStore zfs_ZSTD_buildSeqStore
4768 -#define ZSTD_buildSeqTable zfs_ZSTD_buildSeqTable
4769 -#define ZSTD_cParam_getBounds zfs_ZSTD_cParam_getBounds
4770 -#define ZSTD_cParam_withinBounds zfs_ZSTD_cParam_withinBounds
4771 -#define ZSTD_calloc zfs_ZSTD_calloc
4772 -#define ZSTD_checkCParams zfs_ZSTD_checkCParams
4773 #define ZSTD_checkContinuity zfs_ZSTD_checkContinuity
4774 -#define ZSTD_compress zfs_ZSTD_compress
4775 +#define ZSTD_checkCParams zfs_ZSTD_checkCParams
4776 #define ZSTD_compress2 zfs_ZSTD_compress2
4777 -#define ZSTD_compressBegin zfs_ZSTD_compressBegin
4778 +#define ZSTD_compress_advanced_internal zfs_ZSTD_compress_advanced_internal
4779 +#define ZSTD_compress_advanced zfs_ZSTD_compress_advanced
4780 +#define ZSTD_compressBegin_advanced_internal zfs_ZSTD_compressBegin_advanced_internal
4781 #define ZSTD_compressBegin_advanced zfs_ZSTD_compressBegin_advanced
4782 -#define ZSTD_compressBegin_advanced_internal \
4783 - zfs_ZSTD_compressBegin_advanced_internal
4784 +#define ZSTD_compressBegin_usingCDict_advanced zfs_ZSTD_compressBegin_usingCDict_advanced
4785 #define ZSTD_compressBegin_usingCDict zfs_ZSTD_compressBegin_usingCDict
4786 -#define ZSTD_compressBegin_usingCDict_advanced \
4787 - zfs_ZSTD_compressBegin_usingCDict_advanced
4788 #define ZSTD_compressBegin_usingDict zfs_ZSTD_compressBegin_usingDict
4789 -#define ZSTD_compressBlock zfs_ZSTD_compressBlock
4790 +#define ZSTD_compressBegin zfs_ZSTD_compressBegin
4791 +#define ZSTD_compressBlock_btlazy2_dictMatchState zfs_ZSTD_compressBlock_btlazy2_dictMatchState
4792 +#define ZSTD_compressBlock_btlazy2_extDict zfs_ZSTD_compressBlock_btlazy2_extDict
4793 #define ZSTD_compressBlock_btlazy2 zfs_ZSTD_compressBlock_btlazy2
4794 -#define ZSTD_compressBlock_btlazy2_dictMatchState \
4795 - zfs_ZSTD_compressBlock_btlazy2_dictMatchState
4796 -#define ZSTD_compressBlock_btlazy2_extDict \
4797 - zfs_ZSTD_compressBlock_btlazy2_extDict
4798 -#define ZSTD_compressBlock_btopt zfs_ZSTD_compressBlock_btopt
4799 -#define ZSTD_compressBlock_btopt_dictMatchState \
4800 - zfs_ZSTD_compressBlock_btopt_dictMatchState
4801 +#define ZSTD_compressBlock_btopt_dictMatchState zfs_ZSTD_compressBlock_btopt_dictMatchState
4802 #define ZSTD_compressBlock_btopt_extDict zfs_ZSTD_compressBlock_btopt_extDict
4803 -#define ZSTD_compressBlock_btultra zfs_ZSTD_compressBlock_btultra
4804 +#define ZSTD_compressBlock_btopt zfs_ZSTD_compressBlock_btopt
4805 #define ZSTD_compressBlock_btultra2 zfs_ZSTD_compressBlock_btultra2
4806 -#define ZSTD_compressBlock_btultra_dictMatchState \
4807 - zfs_ZSTD_compressBlock_btultra_dictMatchState
4808 -#define ZSTD_compressBlock_btultra_extDict \
4809 - zfs_ZSTD_compressBlock_btultra_extDict
4810 +#define ZSTD_compressBlock_btultra_dictMatchState zfs_ZSTD_compressBlock_btultra_dictMatchState
4811 +#define ZSTD_compressBlock_btultra_extDict zfs_ZSTD_compressBlock_btultra_extDict
4812 +#define ZSTD_compressBlock_btultra zfs_ZSTD_compressBlock_btultra
4813 +#define ZSTD_compressBlock_doubleFast_dictMatchState zfs_ZSTD_compressBlock_doubleFast_dictMatchState
4814 +#define ZSTD_compressBlock_doubleFast_extDict zfs_ZSTD_compressBlock_doubleFast_extDict
4815 #define ZSTD_compressBlock_doubleFast zfs_ZSTD_compressBlock_doubleFast
4816 -#define ZSTD_compressBlock_doubleFast_dictMatchState \
4817 - zfs_ZSTD_compressBlock_doubleFast_dictMatchState
4818 -#define ZSTD_compressBlock_doubleFast_extDict \
4819 - zfs_ZSTD_compressBlock_doubleFast_extDict
4820 -#define ZSTD_compressBlock_doubleFast_extDict_generic \
4821 - zfs_ZSTD_compressBlock_doubleFast_extDict_generic
4822 -#define ZSTD_compressBlock_fast zfs_ZSTD_compressBlock_fast
4823 -#define ZSTD_compressBlock_fast_dictMatchState \
4824 - zfs_ZSTD_compressBlock_fast_dictMatchState
4825 +#define ZSTD_compressBlock_fast_dictMatchState zfs_ZSTD_compressBlock_fast_dictMatchState
4826 #define ZSTD_compressBlock_fast_extDict zfs_ZSTD_compressBlock_fast_extDict
4827 -#define ZSTD_compressBlock_fast_extDict_generic \
4828 - zfs_ZSTD_compressBlock_fast_extDict_generic
4829 -#define ZSTD_compressBlock_greedy zfs_ZSTD_compressBlock_greedy
4830 -#define ZSTD_compressBlock_greedy_dictMatchState \
4831 - zfs_ZSTD_compressBlock_greedy_dictMatchState
4832 +#define ZSTD_compressBlock_fast zfs_ZSTD_compressBlock_fast
4833 +#define ZSTD_compressBlock_greedy_dictMatchState zfs_ZSTD_compressBlock_greedy_dictMatchState
4834 #define ZSTD_compressBlock_greedy_extDict zfs_ZSTD_compressBlock_greedy_extDict
4835 -#define ZSTD_compressBlock_internal zfs_ZSTD_compressBlock_internal
4836 -#define ZSTD_compressBlock_lazy zfs_ZSTD_compressBlock_lazy
4837 -#define ZSTD_compressBlock_lazy2 zfs_ZSTD_compressBlock_lazy2
4838 -#define ZSTD_compressBlock_lazy2_dictMatchState \
4839 - zfs_ZSTD_compressBlock_lazy2_dictMatchState
4840 +#define ZSTD_compressBlock_greedy zfs_ZSTD_compressBlock_greedy
4841 +#define ZSTD_compressBlock_lazy2_dictMatchState zfs_ZSTD_compressBlock_lazy2_dictMatchState
4842 #define ZSTD_compressBlock_lazy2_extDict zfs_ZSTD_compressBlock_lazy2_extDict
4843 -#define ZSTD_compressBlock_lazy_dictMatchState \
4844 - zfs_ZSTD_compressBlock_lazy_dictMatchState
4845 +#define ZSTD_compressBlock_lazy2 zfs_ZSTD_compressBlock_lazy2
4846 +#define ZSTD_compressBlock_lazy_dictMatchState zfs_ZSTD_compressBlock_lazy_dictMatchState
4847 #define ZSTD_compressBlock_lazy_extDict zfs_ZSTD_compressBlock_lazy_extDict
4848 +#define ZSTD_compressBlock_lazy zfs_ZSTD_compressBlock_lazy
4849 +#define ZSTD_compressBlock zfs_ZSTD_compressBlock
4850 #define ZSTD_compressBound zfs_ZSTD_compressBound
4851 #define ZSTD_compressCCtx zfs_ZSTD_compressCCtx
4852 #define ZSTD_compressContinue zfs_ZSTD_compressContinue
4853 -#define ZSTD_compressContinue_internal zfs_ZSTD_compressContinue_internal
4854 #define ZSTD_compressEnd zfs_ZSTD_compressEnd
4855 #define ZSTD_compressLiterals zfs_ZSTD_compressLiterals
4856 #define ZSTD_compressRleLiteralsBlock zfs_ZSTD_compressRleLiteralsBlock
4857 -#define ZSTD_compressStream zfs_ZSTD_compressStream
4858 -#define ZSTD_compressStream2 zfs_ZSTD_compressStream2
4859 #define ZSTD_compressStream2_simpleArgs zfs_ZSTD_compressStream2_simpleArgs
4860 +#define ZSTD_compressStream2 zfs_ZSTD_compressStream2
4861 +#define ZSTD_compressStream zfs_ZSTD_compressStream
4862 #define ZSTD_compressSuperBlock zfs_ZSTD_compressSuperBlock
4863 -#define ZSTD_compress_advanced zfs_ZSTD_compress_advanced
4864 -#define ZSTD_compress_advanced_internal zfs_ZSTD_compress_advanced_internal
4865 -#define ZSTD_compress_internal zfs_ZSTD_compress_internal
4866 -#define ZSTD_compress_usingCDict zfs_ZSTD_compress_usingCDict
4867 #define ZSTD_compress_usingCDict_advanced zfs_ZSTD_compress_usingCDict_advanced
4868 +#define ZSTD_compress_usingCDict zfs_ZSTD_compress_usingCDict
4869 #define ZSTD_compress_usingDict zfs_ZSTD_compress_usingDict
4870 +#define ZSTD_compress zfs_ZSTD_compress
4871 #define ZSTD_copyCCtx zfs_ZSTD_copyCCtx
4872 #define ZSTD_copyDCtx zfs_ZSTD_copyDCtx
4873 #define ZSTD_copyDDictParameters zfs_ZSTD_copyDDictParameters
4874 -#define ZSTD_count zfs_ZSTD_count
4875 -#define ZSTD_count_2segments zfs_ZSTD_count_2segments
4876 -#define ZSTD_createCCtx zfs_ZSTD_createCCtx
4877 -#define ZSTD_createCCtxParams zfs_ZSTD_createCCtxParams
4878 +#define ZSTD_cParam_getBounds zfs_ZSTD_cParam_getBounds
4879 #define ZSTD_createCCtx_advanced zfs_ZSTD_createCCtx_advanced
4880 -#define ZSTD_createCDict zfs_ZSTD_createCDict
4881 +#define ZSTD_createCCtxParams zfs_ZSTD_createCCtxParams
4882 +#define ZSTD_createCCtx zfs_ZSTD_createCCtx
4883 #define ZSTD_createCDict_advanced zfs_ZSTD_createCDict_advanced
4884 #define ZSTD_createCDict_byReference zfs_ZSTD_createCDict_byReference
4885 -#define ZSTD_createCStream zfs_ZSTD_createCStream
4886 +#define ZSTD_createCDict zfs_ZSTD_createCDict
4887 #define ZSTD_createCStream_advanced zfs_ZSTD_createCStream_advanced
4888 -#define ZSTD_createDCtx zfs_ZSTD_createDCtx
4889 +#define ZSTD_createCStream zfs_ZSTD_createCStream
4890 #define ZSTD_createDCtx_advanced zfs_ZSTD_createDCtx_advanced
4891 -#define ZSTD_createDDict zfs_ZSTD_createDDict
4892 +#define ZSTD_createDCtx zfs_ZSTD_createDCtx
4893 #define ZSTD_createDDict_advanced zfs_ZSTD_createDDict_advanced
4894 #define ZSTD_createDDict_byReference zfs_ZSTD_createDDict_byReference
4895 -#define ZSTD_createDStream zfs_ZSTD_createDStream
4896 +#define ZSTD_createDDict zfs_ZSTD_createDDict
4897 #define ZSTD_createDStream_advanced zfs_ZSTD_createDStream_advanced
4898 +#define ZSTD_createDStream zfs_ZSTD_createDStream
4899 #define ZSTD_crossEntropyCost zfs_ZSTD_crossEntropyCost
4900 +#define ZSTD_CStreamInSize zfs_ZSTD_CStreamInSize
4901 +#define ZSTD_CStreamOutSize zfs_ZSTD_CStreamOutSize
4902 #define ZSTD_cycleLog zfs_ZSTD_cycleLog
4903 -#define ZSTD_dParam_getBounds zfs_ZSTD_dParam_getBounds
4904 +#define ZSTD_DCtx_loadDictionary_advanced zfs_ZSTD_DCtx_loadDictionary_advanced
4905 +#define ZSTD_DCtx_loadDictionary_byReference zfs_ZSTD_DCtx_loadDictionary_byReference
4906 +#define ZSTD_DCtx_loadDictionary zfs_ZSTD_DCtx_loadDictionary
4907 +#define ZSTD_DCtx_refDDict zfs_ZSTD_DCtx_refDDict
4908 +#define ZSTD_DCtx_refPrefix_advanced zfs_ZSTD_DCtx_refPrefix_advanced
4909 +#define ZSTD_DCtx_refPrefix zfs_ZSTD_DCtx_refPrefix
4910 +#define ZSTD_DCtx_reset zfs_ZSTD_DCtx_reset
4911 +#define ZSTD_DCtx_setFormat zfs_ZSTD_DCtx_setFormat
4912 +#define ZSTD_DCtx_setMaxWindowSize zfs_ZSTD_DCtx_setMaxWindowSize
4913 +#define ZSTD_DCtx_setParameter zfs_ZSTD_DCtx_setParameter
4914 +#define ZSTD_DDict_dictContent zfs_ZSTD_DDict_dictContent
4915 +#define ZSTD_DDict_dictSize zfs_ZSTD_DDict_dictSize
4916 #define ZSTD_decodeLiteralsBlock zfs_ZSTD_decodeLiteralsBlock
4917 #define ZSTD_decodeSeqHeaders zfs_ZSTD_decodeSeqHeaders
4918 #define ZSTD_decodingBufferSize_min zfs_ZSTD_decodingBufferSize_min
4919 -#define ZSTD_decompress zfs_ZSTD_decompress
4920 -#define ZSTD_decompressBegin zfs_ZSTD_decompressBegin
4921 #define ZSTD_decompressBegin_usingDDict zfs_ZSTD_decompressBegin_usingDDict
4922 #define ZSTD_decompressBegin_usingDict zfs_ZSTD_decompressBegin_usingDict
4923 -#define ZSTD_decompressBlock zfs_ZSTD_decompressBlock
4924 +#define ZSTD_decompressBegin zfs_ZSTD_decompressBegin
4925 #define ZSTD_decompressBlock_internal zfs_ZSTD_decompressBlock_internal
4926 +#define ZSTD_decompressBlock zfs_ZSTD_decompressBlock
4927 #define ZSTD_decompressBound zfs_ZSTD_decompressBound
4928 #define ZSTD_decompressContinue zfs_ZSTD_decompressContinue
4929 -#define ZSTD_decompressContinueStream zfs_ZSTD_decompressContinueStream
4930 #define ZSTD_decompressDCtx zfs_ZSTD_decompressDCtx
4931 -#define ZSTD_decompressMultiFrame zfs_ZSTD_decompressMultiFrame
4932 -#define ZSTD_decompressStream zfs_ZSTD_decompressStream
4933 #define ZSTD_decompressStream_simpleArgs zfs_ZSTD_decompressStream_simpleArgs
4934 +#define ZSTD_decompressStream zfs_ZSTD_decompressStream
4935 #define ZSTD_decompress_usingDDict zfs_ZSTD_decompress_usingDDict
4936 #define ZSTD_decompress_usingDict zfs_ZSTD_decompress_usingDict
4937 -#define ZSTD_defaultCParameters zfs_ZSTD_defaultCParameters
4938 -#define ZSTD_did_fieldSize zfs_ZSTD_did_fieldSize
4939 +#define ZSTD_decompress zfs_ZSTD_decompress
4940 +#define ZSTD_dParam_getBounds zfs_ZSTD_dParam_getBounds
4941 +#define ZSTD_DStreamInSize zfs_ZSTD_DStreamInSize
4942 +#define ZSTD_DStreamOutSize zfs_ZSTD_DStreamOutSize
4943 #define ZSTD_encodeSequences zfs_ZSTD_encodeSequences
4944 -#define ZSTD_encodeSequences_default zfs_ZSTD_encodeSequences_default
4945 #define ZSTD_endStream zfs_ZSTD_endStream
4946 +#define ZSTD_estimateCCtxSize_usingCCtxParams zfs_ZSTD_estimateCCtxSize_usingCCtxParams
4947 +#define ZSTD_estimateCCtxSize_usingCParams zfs_ZSTD_estimateCCtxSize_usingCParams
4948 #define ZSTD_estimateCCtxSize zfs_ZSTD_estimateCCtxSize
4949 -#define ZSTD_estimateCCtxSize_usingCCtxParams \
4950 - zfs_ZSTD_estimateCCtxSize_usingCCtxParams
4951 -#define ZSTD_estimateCCtxSize_usingCParams \
4952 - zfs_ZSTD_estimateCCtxSize_usingCParams
4953 -#define ZSTD_estimateCDictSize zfs_ZSTD_estimateCDictSize
4954 #define ZSTD_estimateCDictSize_advanced zfs_ZSTD_estimateCDictSize_advanced
4955 +#define ZSTD_estimateCDictSize zfs_ZSTD_estimateCDictSize
4956 +#define ZSTD_estimateCStreamSize_usingCCtxParams zfs_ZSTD_estimateCStreamSize_usingCCtxParams
4957 +#define ZSTD_estimateCStreamSize_usingCParams zfs_ZSTD_estimateCStreamSize_usingCParams
4958 #define ZSTD_estimateCStreamSize zfs_ZSTD_estimateCStreamSize
4959 -#define ZSTD_estimateCStreamSize_usingCCtxParams \
4960 - zfs_ZSTD_estimateCStreamSize_usingCCtxParams
4961 -#define ZSTD_estimateCStreamSize_usingCParams \
4962 - zfs_ZSTD_estimateCStreamSize_usingCParams
4963 #define ZSTD_estimateDCtxSize zfs_ZSTD_estimateDCtxSize
4964 #define ZSTD_estimateDDictSize zfs_ZSTD_estimateDDictSize
4965 +#define ZSTD_estimateDStreamSize_fromFrame zfs_ZSTD_estimateDStreamSize_fromFrame
4966 #define ZSTD_estimateDStreamSize zfs_ZSTD_estimateDStreamSize
4967 -#define ZSTD_estimateDStreamSize_fromFrame \
4968 - zfs_ZSTD_estimateDStreamSize_fromFrame
4969 -#define ZSTD_fcs_fieldSize zfs_ZSTD_fcs_fieldSize
4970 #define ZSTD_fillDoubleHashTable zfs_ZSTD_fillDoubleHashTable
4971 #define ZSTD_fillHashTable zfs_ZSTD_fillHashTable
4972 #define ZSTD_findDecompressedSize zfs_ZSTD_findDecompressedSize
4973 #define ZSTD_findFrameCompressedSize zfs_ZSTD_findFrameCompressedSize
4974 -#define ZSTD_findFrameSizeInfo zfs_ZSTD_findFrameSizeInfo
4975 #define ZSTD_flushStream zfs_ZSTD_flushStream
4976 #define ZSTD_frameHeaderSize zfs_ZSTD_frameHeaderSize
4977 -#define ZSTD_free zfs_ZSTD_free
4978 -#define ZSTD_freeCCtx zfs_ZSTD_freeCCtx
4979 #define ZSTD_freeCCtxParams zfs_ZSTD_freeCCtxParams
4980 +#define ZSTD_freeCCtx zfs_ZSTD_freeCCtx
4981 #define ZSTD_freeCDict zfs_ZSTD_freeCDict
4982 #define ZSTD_freeCStream zfs_ZSTD_freeCStream
4983 #define ZSTD_freeDCtx zfs_ZSTD_freeDCtx
4984 #define ZSTD_freeDDict zfs_ZSTD_freeDDict
4985 #define ZSTD_freeDStream zfs_ZSTD_freeDStream
4986 +#define ZSTD_free zfs_ZSTD_free
4987 #define ZSTD_fseBitCost zfs_ZSTD_fseBitCost
4988 #define ZSTD_getBlockSize zfs_ZSTD_getBlockSize
4989 -#define ZSTD_getCParams zfs_ZSTD_getCParams
4990 +#define ZSTD_getcBlockSize zfs_ZSTD_getcBlockSize
4991 #define ZSTD_getCParamsFromCCtxParams zfs_ZSTD_getCParamsFromCCtxParams
4992 #define ZSTD_getCParamsFromCDict zfs_ZSTD_getCParamsFromCDict
4993 -#define ZSTD_getCParams_internal zfs_ZSTD_getCParams_internal
4994 -#define ZSTD_getDDict zfs_ZSTD_getDDict
4995 +#define ZSTD_getCParams zfs_ZSTD_getCParams
4996 #define ZSTD_getDecompressedSize zfs_ZSTD_getDecompressedSize
4997 #define ZSTD_getDictID_fromDDict zfs_ZSTD_getDictID_fromDDict
4998 #define ZSTD_getDictID_fromDict zfs_ZSTD_getDictID_fromDict
4999 @@ -371,39 +311,29 @@
5000 #define ZSTD_getErrorName zfs_ZSTD_getErrorName
5001 #define ZSTD_getErrorString zfs_ZSTD_getErrorString
5002 #define ZSTD_getFrameContentSize zfs_ZSTD_getFrameContentSize
5003 -#define ZSTD_getFrameHeader zfs_ZSTD_getFrameHeader
5004 #define ZSTD_getFrameHeader_advanced zfs_ZSTD_getFrameHeader_advanced
5005 +#define ZSTD_getFrameHeader zfs_ZSTD_getFrameHeader
5006 #define ZSTD_getFrameProgression zfs_ZSTD_getFrameProgression
5007 #define ZSTD_getParams zfs_ZSTD_getParams
5008 #define ZSTD_getSeqStore zfs_ZSTD_getSeqStore
5009 #define ZSTD_getSequences zfs_ZSTD_getSequences
5010 -#define ZSTD_getcBlockSize zfs_ZSTD_getcBlockSize
5011 -#define ZSTD_hashPtr zfs_ZSTD_hashPtr
5012 -#define ZSTD_initCDict_internal zfs_ZSTD_initCDict_internal
5013 -#define ZSTD_initCStream zfs_ZSTD_initCStream
5014 #define ZSTD_initCStream_advanced zfs_ZSTD_initCStream_advanced
5015 #define ZSTD_initCStream_internal zfs_ZSTD_initCStream_internal
5016 #define ZSTD_initCStream_srcSize zfs_ZSTD_initCStream_srcSize
5017 +#define ZSTD_initCStream_usingCDict_advanced zfs_ZSTD_initCStream_usingCDict_advanced
5018 #define ZSTD_initCStream_usingCDict zfs_ZSTD_initCStream_usingCDict
5019 -#define ZSTD_initCStream_usingCDict_advanced \
5020 - zfs_ZSTD_initCStream_usingCDict_advanced
5021 #define ZSTD_initCStream_usingDict zfs_ZSTD_initCStream_usingDict
5022 -#define ZSTD_initDDict_internal zfs_ZSTD_initDDict_internal
5023 -#define ZSTD_initDStream zfs_ZSTD_initDStream
5024 +#define ZSTD_initCStream zfs_ZSTD_initCStream
5025 #define ZSTD_initDStream_usingDDict zfs_ZSTD_initDStream_usingDDict
5026 #define ZSTD_initDStream_usingDict zfs_ZSTD_initDStream_usingDict
5027 -#define ZSTD_initFseState zfs_ZSTD_initFseState
5028 +#define ZSTD_initDStream zfs_ZSTD_initDStream
5029 #define ZSTD_initStaticCCtx zfs_ZSTD_initStaticCCtx
5030 #define ZSTD_initStaticCDict zfs_ZSTD_initStaticCDict
5031 #define ZSTD_initStaticCStream zfs_ZSTD_initStaticCStream
5032 #define ZSTD_initStaticDCtx zfs_ZSTD_initStaticDCtx
5033 #define ZSTD_initStaticDDict zfs_ZSTD_initStaticDDict
5034 #define ZSTD_initStaticDStream zfs_ZSTD_initStaticDStream
5035 -#define ZSTD_initStats_ultra zfs_ZSTD_initStats_ultra
5036 #define ZSTD_insertAndFindFirstIndex zfs_ZSTD_insertAndFindFirstIndex
5037 -#define ZSTD_insertAndFindFirstIndexHash3 zfs_ZSTD_insertAndFindFirstIndexHash3
5038 -#define ZSTD_insertAndFindFirstIndex_internal \
5039 - zfs_ZSTD_insertAndFindFirstIndex_internal
5040 #define ZSTD_insertBlock zfs_ZSTD_insertBlock
5041 #define ZSTD_invalidateRepCodes zfs_ZSTD_invalidateRepCodes
5042 #define ZSTD_isError zfs_ZSTD_isError
5044 #define ZSTD_ldm_skipSequences zfs_ZSTD_ldm_skipSequences
5045 #define ZSTD_loadCEntropy zfs_ZSTD_loadCEntropy
5046 #define ZSTD_loadDEntropy zfs_ZSTD_loadDEntropy
5047 -#define ZSTD_loadDictionaryContent zfs_ZSTD_loadDictionaryContent
5048 -#define ZSTD_makeCCtxParamsFromCParams zfs_ZSTD_makeCCtxParamsFromCParams
5049 #define ZSTD_malloc zfs_ZSTD_malloc
5050 #define ZSTD_maxCLevel zfs_ZSTD_maxCLevel
5051 #define ZSTD_minCLevel zfs_ZSTD_minCLevel
5052 @@ -426,14 +354,10 @@
5053 #define ZSTD_nextSrcSizeToDecompress zfs_ZSTD_nextSrcSizeToDecompress
5054 #define ZSTD_noCompressLiterals zfs_ZSTD_noCompressLiterals
5055 #define ZSTD_referenceExternalSequences zfs_ZSTD_referenceExternalSequences
5056 -#define ZSTD_rescaleFreqs zfs_ZSTD_rescaleFreqs
5057 -#define ZSTD_resetCCtx_internal zfs_ZSTD_resetCCtx_internal
5058 -#define ZSTD_resetCCtx_usingCDict zfs_ZSTD_resetCCtx_usingCDict
5059 +#define ZSTD_reset_compressedBlockState zfs_ZSTD_reset_compressedBlockState
5060 #define ZSTD_resetCStream zfs_ZSTD_resetCStream
5061 #define ZSTD_resetDStream zfs_ZSTD_resetDStream
5062 #define ZSTD_resetSeqStore zfs_ZSTD_resetSeqStore
5063 -#define ZSTD_reset_compressedBlockState zfs_ZSTD_reset_compressedBlockState
5064 -#define ZSTD_safecopy zfs_ZSTD_safecopy
5065 #define ZSTD_selectBlockCompressor zfs_ZSTD_selectBlockCompressor
5066 #define ZSTD_selectEncodingType zfs_ZSTD_selectEncodingType
5067 #define ZSTD_seqToCodes zfs_ZSTD_seqToCodes
5068 @@ -444,18 +368,7 @@
5069 #define ZSTD_sizeof_DDict zfs_ZSTD_sizeof_DDict
5070 #define ZSTD_sizeof_DStream zfs_ZSTD_sizeof_DStream
5071 #define ZSTD_toFlushNow zfs_ZSTD_toFlushNow
5072 -#define ZSTD_updateRep zfs_ZSTD_updateRep
5073 -#define ZSTD_updateStats zfs_ZSTD_updateStats
5074 #define ZSTD_updateTree zfs_ZSTD_updateTree
5075 #define ZSTD_versionNumber zfs_ZSTD_versionNumber
5076 #define ZSTD_versionString zfs_ZSTD_versionString
5077 -#define ZSTD_writeFrameHeader zfs_ZSTD_writeFrameHeader
5078 #define ZSTD_writeLastEmptyBlock zfs_ZSTD_writeLastEmptyBlock
5079 -#define algoTime zfs_algoTime
5080 -#define attachDictSizeCutoffs zfs_attachDictSizeCutoffs
5081 -#define g_ctx zfs_g_ctx
5082 -#define g_debuglevel zfs_g_debuglevel
5083 -#define kInverseProbabilityLog256 zfs_kInverseProbabilityLog256
5084 -#define repStartValue zfs_repStartValue
5085 -#define FSE_isError zfs_FSE_isError
5086 -#define HUF_isError zfs_HUF_isError
5087 diff --git a/module/zstd/lib/zstd.c b/module/zstd/lib/zstd.c
5088 index 2766e5b74..9dbba5b82 100644
5089 --- a/module/zstd/lib/zstd.c
5090 +++ b/module/zstd/lib/zstd.c
5091 @@ -7781,7 +7781,7 @@ size_t FSE_writeNCount (void* buffer, size_t bufferSize,
5093 FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog)
5096 + size_t size __attribute__ ((unused));
5097 if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;
5098 size = FSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32);
5099 return (FSE_CTable*)malloc(size);
5100 @@ -12115,7 +12115,7 @@ static size_t ZSTD_seqDecompressedSize(seqStore_t const* seqStore, const seqDef*
5101 const seqDef* const send = sequences + nbSeq;
5102 const seqDef* sp = sstart;
5103 size_t matchLengthSum = 0;
5104 - size_t litLengthSum = 0;
5105 + size_t litLengthSum __attribute__ ((unused)) = 0;
5106 while (send-sp > 0) {
5107 ZSTD_sequenceLength const seqLen = ZSTD_getSequenceLength(seqStore, sp);
5108 litLengthSum += seqLen.litLength;
5109 diff --git a/scripts/dkms.mkconf b/scripts/dkms.mkconf
5110 index 408322fa1..4090efa08 100755
5111 --- a/scripts/dkms.mkconf
5112 +++ b/scripts/dkms.mkconf
5113 @@ -68,7 +68,6 @@ POST_BUILD="scripts/dkms.postbuild
5120 [[ -r \${PACKAGE_CONFIG} ]] \\
5121 diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run
5122 index aefcd9843..19919a00a 100644
5123 --- a/tests/runfiles/common.run
5124 +++ b/tests/runfiles/common.run
5125 @@ -178,7 +178,7 @@ tags = ['functional', 'cli_root', 'zfs_destroy']
5127 [tests/functional/cli_root/zfs_diff]
5128 tests = ['zfs_diff_changes', 'zfs_diff_cliargs', 'zfs_diff_timestamp',
5129 - 'zfs_diff_types', 'zfs_diff_encrypted']
5130 + 'zfs_diff_types', 'zfs_diff_encrypted', 'zfs_diff_mangle']
5131 tags = ['functional', 'cli_root', 'zfs_diff']
5133 [tests/functional/cli_root/zfs_get]
5134 diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run
5135 index c01e1e3c4..94c1cbbc3 100644
5136 --- a/tests/runfiles/linux.run
5137 +++ b/tests/runfiles/linux.run
5138 @@ -94,7 +94,7 @@ tests = ['events_001_pos', 'events_002_pos', 'zed_rc_filter', 'zed_fd_spill']
5139 tags = ['functional', 'events']
5141 [tests/functional/fallocate:Linux]
5142 -tests = ['fallocate_prealloc']
5143 +tests = ['fallocate_prealloc', 'fallocate_zero-range']
5144 tags = ['functional', 'fallocate']
5146 [tests/functional/fault:Linux]
5147 diff --git a/tests/zfs-tests/cmd/file_write/file_write.c b/tests/zfs-tests/cmd/file_write/file_write.c
5148 index 60893c34f..9d2e71b67 100644
5149 --- a/tests/zfs-tests/cmd/file_write/file_write.c
5150 +++ b/tests/zfs-tests/cmd/file_write/file_write.c
5151 @@ -251,7 +251,7 @@ usage(char *prog)
5152 "\t[-s offset] [-c write_count] [-d data]\n\n"
5153 "Where [data] equal to zero causes chars "
5154 "0->%d to be repeated throughout, or [data]\n"
5155 - "equal to 'R' for psudorandom data.\n",
5156 + "equal to 'R' for pseudorandom data.\n",
5160 diff --git a/tests/zfs-tests/include/libtest.shlib b/tests/zfs-tests/include/libtest.shlib
5161 index dd43b02a6..94ab7ffd2 100644
5162 --- a/tests/zfs-tests/include/libtest.shlib
5163 +++ b/tests/zfs-tests/include/libtest.shlib
5164 @@ -4236,6 +4236,22 @@ function punch_hole # offset length file
5168 +function zero_range # offset length file
5176 + fallocate --zero-range --offset $offset --length $length "$file"
5185 # Wait for the specified arcstat to reach non-zero quiescence.
5186 # If echo is 1 echo the value after reaching quiescence, otherwise
5187 diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/Makefile.am
5188 index db90e0585..bfb01dcb8 100644
5189 --- a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/Makefile.am
5190 +++ b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/Makefile.am
5191 @@ -8,6 +8,7 @@ dist_pkgdata_SCRIPTS = \
5192 zfs_diff_changes.ksh \
5193 zfs_diff_cliargs.ksh \
5194 zfs_diff_encrypted.ksh \
5195 + zfs_diff_mangle.ksh \
5196 zfs_diff_timestamp.ksh \
5199 diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_cliargs.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_cliargs.ksh
5200 index 7063bbe9c..67eb18fa4 100755
5201 --- a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_cliargs.ksh
5202 +++ b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_cliargs.ksh
5203 @@ -39,8 +39,8 @@ function cleanup
5204 log_assert "'zfs diff' should only work with supported options."
5207 -typeset goodopts=("" "-F" "-H" "-t" "-FH" "-Ft" "-Ht" "-FHt")
5208 -typeset badopts=("-f" "-h" "-h" "-T" "-Fx" "-Ho" "-tT" "-")
5209 +typeset goodopts=("" "-h" "-t" "-th" "-H" "-Hh" "-Ht" "-Hth" "-F" "-Fh" "-Ft" "-Fth" "-FH" "-FHh" "-FHt" "-FHth")
5210 +typeset badopts=("-f" "-T" "-Fx" "-Ho" "-tT" "-")
5212 DATASET="$TESTPOOL/$TESTFS"
5213 TESTSNAP1="$DATASET@snap1"
5214 diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_mangle.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_mangle.ksh
5215 new file mode 100755
5216 index 000000000..ffce9f068
5218 +++ b/tests/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_mangle.ksh
5222 +# This file and its contents are supplied under the terms of the
5223 +# Common Development and Distribution License ("CDDL"), version 1.0.
5224 +# You may only use this file in accordance with the terms of version
5227 +# A full copy of the text of the CDDL should have accompanied this
5228 +# source. A copy of the CDDL is also available via the Internet at
5229 +# http://www.illumos.org/license/CDDL.
5232 +. $STF_SUITE/include/libtest.shlib
5236 +# 'zfs diff' escapes filenames as expected, 'zfs diff -h' doesn't
5239 +# 1. Prepare a dataset
5240 +# 2. Create some files
5241 +# 3. verify 'zfs diff' mangles them and 'zfs diff -h' doesn't
5244 +verify_runnable "both"
5248 + log_must zfs destroy -r "$DATASET"
5251 +log_assert "'zfs diff' mangles filenames, 'zfs diff -h' doesn't"
5254 +DATASET="$TESTPOOL/$TESTFS/fs"
5255 +TESTSNAP1="$DATASET@snap1"
5257 +# 1. Prepare a dataset
5258 +log_must zfs create "$DATASET"
5259 +MNTPOINT="$(get_prop mountpoint "$DATASET")"
5260 +log_must zfs snapshot "$TESTSNAP1"
5262 +printf '%c\t'"$MNTPOINT/"'%s\n' M '' + 'śmieszny żupan' + 'достопримечательности' | sort > "$MNTPOINT/śmieszny żupan"
5263 +printf '%c\t'"$MNTPOINT/"'%s\n' M '' + '\0305\0233mieszny\0040\0305\0274upan' + '\0320\0264\0320\0276\0321\0201\0321\0202\0320\0276\0320\0277\0321\0200\0320\0270\0320\0274\0320\0265\0321\0207\0320\0260\0321\0202\0320\0265\0320\0273\0321\0214\0320\0275\0320\0276\0321\0201\0321\0202\0320\0270' | sort > "$MNTPOINT/достопримечательности"
5264 +log_must diff -u <(zfs diff -h "$TESTSNAP1" | grep -vF '<xattrdir>' | sort) "$MNTPOINT/śmieszny żupan"
5265 +log_must diff -u <(zfs diff "$TESTSNAP1" | grep -vF '<xattrdir>' | sort) "$MNTPOINT/достопримечательности"
5267 +log_pass "'zfs diff' mangles filenames, 'zfs diff -h' doesn't"
5268 diff --git a/tests/zfs-tests/tests/functional/fallocate/Makefile.am b/tests/zfs-tests/tests/functional/fallocate/Makefile.am
5269 index 5ff366d24..86364d789 100644
5270 --- a/tests/zfs-tests/tests/functional/fallocate/Makefile.am
5271 +++ b/tests/zfs-tests/tests/functional/fallocate/Makefile.am
5272 @@ -3,4 +3,5 @@ dist_pkgdata_SCRIPTS = \
5275 fallocate_prealloc.ksh \
5276 - fallocate_punch-hole.ksh
5277 + fallocate_punch-hole.ksh \
5278 + fallocate_zero-range.ksh
5279 diff --git a/tests/zfs-tests/tests/functional/fallocate/fallocate_punch-hole.ksh b/tests/zfs-tests/tests/functional/fallocate/fallocate_punch-hole.ksh
5280 index ed83561bd..92f4552f5 100755
5281 --- a/tests/zfs-tests/tests/functional/fallocate/fallocate_punch-hole.ksh
5282 +++ b/tests/zfs-tests/tests/functional/fallocate/fallocate_punch-hole.ksh
5283 @@ -60,13 +60,17 @@ function cleanup
5284 [[ -e $TESTDIR ]] && log_must rm -f $FILE
5287 -function check_disk_size
5288 +function check_reported_size
5290 typeset expected_size=$1
5292 - disk_size=$(du $TESTDIR/file | awk '{print $1}')
5293 - if [ $disk_size -ne $expected_size ]; then
5294 - log_fail "Incorrect size: $disk_size != $expected_size"
5295 + if ! [ -e "${FILE}" ]; then
5296 + log_fail "$FILE does not exist"
5299 + reported_size=$(du "${FILE}" | awk '{print $1}')
5300 + if [ "$reported_size" != "$expected_size" ]; then
5301 + log_fail "Incorrect reported size: $reported_size != $expected_size"
5305 @@ -74,9 +78,9 @@ function check_apparent_size
5307 typeset expected_size=$1
5309 - apparent_size=$(stat_size)
5310 - if [ $apparent_size -ne $expected_size ]; then
5311 - log_fail "Incorrect size: $apparent_size != $expected_size"
5312 + apparent_size=$(stat_size "${FILE}")
5313 + if [ "$apparent_size" != "$expected_size" ]; then
5314 + log_fail "Incorrect apparent size: $apparent_size != $expected_size"
5318 @@ -86,25 +90,30 @@ log_onexit cleanup
5320 # Create a dense file and check it is the correct size.
5321 log_must file_write -o create -f $FILE -b $BLKSZ -c 8
5322 -log_must check_disk_size $((131072 * 8))
5323 +sync_pool $TESTPOOL
5324 +log_must check_reported_size 1027
5326 # Punch a hole for the first full block.
5327 log_must punch_hole 0 $BLKSZ $FILE
5328 -log_must check_disk_size $((131072 * 7))
5329 +sync_pool $TESTPOOL
5330 +log_must check_reported_size 899
5332 # Partially punch a hole in the second block.
5333 log_must punch_hole $BLKSZ $((BLKSZ / 2)) $FILE
5334 -log_must check_disk_size $((131072 * 7))
5335 +sync_pool $TESTPOOL
5336 +log_must check_reported_size 899
5338 -# Punch a hole which overlaps the third and forth block.
5339 +# Punch a hole which overlaps the third and fourth block.
5340 log_must punch_hole $(((BLKSZ * 2) + (BLKSZ / 2))) $((BLKSZ)) $FILE
5341 -log_must check_disk_size $((131072 * 7))
5342 +sync_pool $TESTPOOL
5343 +log_must check_reported_size 899
5345 # Punch a hole from the fifth block past the end of file. The apparent
5346 # file size should not change since --keep-size is implied.
5347 apparent_size=$(stat_size $FILE)
5348 log_must punch_hole $((BLKSZ * 4)) $((BLKSZ * 10)) $FILE
5349 -log_must check_disk_size $((131072 * 4))
5350 +sync_pool $TESTPOOL
5351 +log_must check_reported_size 387
5352 log_must check_apparent_size $apparent_size
5354 log_pass "Ensure holes can be punched in files making them sparse"
5355 diff --git a/tests/zfs-tests/tests/functional/fallocate/fallocate_zero-range.ksh b/tests/zfs-tests/tests/functional/fallocate/fallocate_zero-range.ksh
5356 new file mode 100755
5357 index 000000000..e907b0f5d
5359 +++ b/tests/zfs-tests/tests/functional/fallocate/fallocate_zero-range.ksh
5363 +# CDDL HEADER START
5365 +# The contents of this file are subject to the terms of the
5366 +# Common Development and Distribution License (the "License").
5367 +# You may not use this file except in compliance with the License.
5369 +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5370 +# or http://www.opensolaris.org/os/licensing.
5371 +# See the License for the specific language governing permissions
5372 +# and limitations under the License.
5374 +# When distributing Covered Code, include this CDDL HEADER in each
5375 +# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5376 +# If applicable, add the following below this CDDL HEADER, with the
5377 +# fields enclosed by brackets "[]" replaced with your own identifying
5378 +# information: Portions Copyright [yyyy] [name of copyright owner]
5384 +# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
5385 +# Copyright (c) 2021 by The FreeBSD Foundation.
5388 +. $STF_SUITE/include/libtest.shlib
5392 +# Test FALLOC_FL_ZERO_RANGE functionality
5395 +# 1. Create a dense file
5396 +# 2. Zero various ranges in the file and verify the result.
5399 +verify_runnable "global"
5401 +if is_freebsd; then
5402 + log_unsupported "FreeBSD does not implement an analogue to ZERO_RANGE."
5405 +FILE=$TESTDIR/$TESTFILE0
5406 +BLKSZ=$(get_prop recordsize $TESTPOOL)
5410 + [[ -e $TESTDIR ]] && log_must rm -f $FILE
5413 +# Helpfully, this function expects kilobytes, and check_apparent_size expects bytes.
5414 +function check_reported_size
5416 + typeset expected_size=$1
5418 + if ! [ -e "${FILE}" ]; then
5419 + log_fail "$FILE does not exist"
5422 + reported_size=$(du "${FILE}" | awk '{print $1}')
5423 + if [ "$reported_size" != "$expected_size" ]; then
5424 + log_fail "Incorrect reported size: $reported_size != $expected_size"
5428 +function check_apparent_size
5430 + typeset expected_size=$1
5432 + apparent_size=$(stat_size "${FILE}")
5433 + if [ "$apparent_size" != "$expected_size" ]; then
5434 + log_fail "Incorrect apparent size: $apparent_size != $expected_size"
5438 +log_assert "Ensure ranges can be zeroed in files"
5442 +# Create a dense file and check it is the correct size.
5443 +log_must file_write -o create -f $FILE -b $BLKSZ -c 8
5444 +sync_pool $TESTPOOL
5445 +log_must check_reported_size 1027
5447 +# Zero a range covering the first full block.
5448 +log_must zero_range 0 $BLKSZ $FILE
5449 +sync_pool $TESTPOOL
5450 +log_must check_reported_size 899
5452 +# Partially zero a range in the second block.
5453 +log_must zero_range $BLKSZ $((BLKSZ / 2)) $FILE
5454 +sync_pool $TESTPOOL
5455 +log_must check_reported_size 899
5457 +# Zero range which overlaps the third and fourth block.
5458 +log_must zero_range $(((BLKSZ * 2) + (BLKSZ / 2))) $((BLKSZ)) $FILE
5459 +sync_pool $TESTPOOL
5460 +log_must check_reported_size 899
5462 +# Zero range from the fifth block past the end of file, with --keep-size.
5463 +# The apparent file size must not change, since we did specify --keep-size.
5464 +apparent_size=$(stat_size $FILE)
5465 +log_must fallocate --keep-size --zero-range --offset $((BLKSZ * 4)) --length $((BLKSZ * 10)) "$FILE"
5466 +sync_pool $TESTPOOL
5467 +log_must check_reported_size 387
5468 +log_must check_apparent_size $apparent_size
5470 +# Zero range from the fifth block past the end of file. The apparent
5471 +# file size should change since --keep-size is not implied, unlike
5473 +apparent_size=$(stat_size $FILE)
5474 +log_must zero_range $((BLKSZ * 4)) $((BLKSZ * 10)) $FILE
5475 +sync_pool $TESTPOOL
5476 +log_must check_reported_size 387
5477 +log_must check_apparent_size $((BLKSZ * 14))
5479 +log_pass "Ensure ranges can be zeroed in files"
5480 diff --git a/tests/zfs-tests/tests/functional/fallocate/setup.ksh b/tests/zfs-tests/tests/functional/fallocate/setup.ksh
5481 index 32334d396..586ac026a 100755
5482 --- a/tests/zfs-tests/tests/functional/fallocate/setup.ksh
5483 +++ b/tests/zfs-tests/tests/functional/fallocate/setup.ksh
5485 . $STF_SUITE/include/libtest.shlib
5488 -default_setup $DISK
5489 +default_setup_noexit $DISK
5490 +log_must zfs set compression=off $TESTPOOL