aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2026-05-13 19:53:01 +0000
committerColin Percival <cperciva@FreeBSD.org>2026-05-14 23:58:46 +0000
commit409247a6cbd11e3510025e025f3b82184c3de17c (patch)
tree49200e7c219ffc2bb10fec867bc55ded8cbe5686
parent2ebec3c7ead5f5b477a5ab47136562777f2bb495 (diff)
zfs: merge openzfs/zfs@6330a45b0 (zfs-2.4-release) into stable/15
OpenZFS 2.4.2 Notable upstream pull request merges: #18208 6f14581e1 Cleanup allocation class selection #18235 7590972f7 Prevent range tree corruption race by updating dnode_sync() #18255 b06caaeec range_tree: use zfs_panic_recover() for partial-overlap remove #18258 33961142a Fix deadlock on dmu_tx_assign() from vdev_rebuild() #18262 02ed09106 Fix check for .cfi_negate_ra_state on aarch64 #18263 9f92266b7 Fix redundant declaration of dsl_pool_t #18276 3862aadf7 Fix vdev_rebuild_range() tx commit #18290 a94b137aa FreeBSD: Improve dmesg kernel message prefix #18294 938c8c98b draid: fix data corruption after disk clear #18310 b40cd9191 Fix s_active leak in zfsvfs_hold() when z_unmounted is true #18380 9b8ccbd2c draid: fix import failure after disks replacements #18399 4bb759274 Add support for POSIX_FADV_DONTNEED #18403 aba3ed30a fix memleak in spa_errlog.c #18405 e9a8c6e08 draid: allow seq resilver reads from degraded vdevs #18414 da44040bb draid: fix cksum errors after rebuild with degraded disks #18421 e7524594a Fix read corruption after block clone after truncate #18440 b8addf922 dmu_direct: avoid UAF in dmu_write_direct_done() #18473 76fd64ac9 Fix rare cksum errors after rebuild #18482 fc87e269e Initialize vr_last_txg for rebuild #18489 38501e182 Fix long POSIX_FADV_DONTNEED for single block files Approved by: re (cperciva) Obtained from: OpenZFS OpenZFS commit: 6330a45b06d20125de679aae5f63ba14082671ef OpenZFS tag: zfs-2.4.2 (cherry picked from commit a40f24ec28554c2387e766a47d2d4cb910d95865)
-rw-r--r--sys/contrib/openzfs/.github/workflows/checkstyle.yaml7
-rw-r--r--sys/contrib/openzfs/.github/workflows/codeql.yml2
-rwxr-xr-xsys/contrib/openzfs/.github/workflows/scripts/generate-ci-type.py33
-rwxr-xr-xsys/contrib/openzfs/.github/workflows/scripts/merge_summary.awk38
-rwxr-xr-xsys/contrib/openzfs/.github/workflows/scripts/qemu-1-setup.sh43
-rwxr-xr-xsys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh81
-rwxr-xr-xsys/contrib/openzfs/.github/workflows/scripts/qemu-3-deps-vm.sh22
-rwxr-xr-xsys/contrib/openzfs/.github/workflows/scripts/qemu-4-build-vm.sh11
-rwxr-xr-xsys/contrib/openzfs/.github/workflows/scripts/qemu-6-tests.sh4
-rwxr-xr-xsys/contrib/openzfs/.github/workflows/scripts/qemu-7-prepare.sh47
-rwxr-xr-xsys/contrib/openzfs/.github/workflows/scripts/qemu-8-summary.sh8
-rwxr-xr-xsys/contrib/openzfs/.github/workflows/scripts/qemu-9-summary-page.sh4
-rw-r--r--sys/contrib/openzfs/.github/workflows/smatch.yml4
-rw-r--r--sys/contrib/openzfs/.github/workflows/zfs-arm.yml40
-rw-r--r--sys/contrib/openzfs/.github/workflows/zfs-qemu-packages.yml25
-rw-r--r--sys/contrib/openzfs/.github/workflows/zfs-qemu.yml46
-rw-r--r--sys/contrib/openzfs/.github/workflows/zloop.yml7
-rw-r--r--sys/contrib/openzfs/META4
-rw-r--r--sys/contrib/openzfs/Makefile.am1
-rw-r--r--sys/contrib/openzfs/README.md42
-rwxr-xr-xsys/contrib/openzfs/autogen.sh1
-rw-r--r--sys/contrib/openzfs/cmd/Makefile.am1
-rw-r--r--sys/contrib/openzfs/cmd/raidz_test/Makefile.am1
-rw-r--r--sys/contrib/openzfs/cmd/zdb/Makefile.am1
-rw-r--r--sys/contrib/openzfs/cmd/zed/Makefile.am1
-rw-r--r--sys/contrib/openzfs/cmd/zed/zed.d/Makefile.am1
-rw-r--r--sys/contrib/openzfs/cmd/zed/zed_event.c2
-rw-r--r--sys/contrib/openzfs/cmd/zfs/Makefile.am1
-rw-r--r--sys/contrib/openzfs/cmd/zfs/zfs_main.c2
-rw-r--r--sys/contrib/openzfs/cmd/zinject/Makefile.am1
-rw-r--r--sys/contrib/openzfs/cmd/zpool/Makefile.am1
-rw-r--r--sys/contrib/openzfs/cmd/zpool_influxdb/Makefile.am1
-rw-r--r--sys/contrib/openzfs/cmd/zstream/Makefile.am1
-rw-r--r--sys/contrib/openzfs/config/CppCheck.am1
-rw-r--r--sys/contrib/openzfs/config/Rules.am1
-rw-r--r--sys/contrib/openzfs/config/Shellcheck.am1
-rw-r--r--sys/contrib/openzfs/config/Substfiles.am1
-rw-r--r--sys/contrib/openzfs/config/always-arch.m41
-rw-r--r--sys/contrib/openzfs/config/always-compiler-options.m41
-rw-r--r--sys/contrib/openzfs/config/always-cppcheck.m41
-rw-r--r--sys/contrib/openzfs/config/always-parallel.m41
-rw-r--r--sys/contrib/openzfs/config/always-python.m41
-rw-r--r--sys/contrib/openzfs/config/always-pyzfs.m41
-rw-r--r--sys/contrib/openzfs/config/always-sed.m41
-rw-r--r--sys/contrib/openzfs/config/always-shellcheck.m41
-rw-r--r--sys/contrib/openzfs/config/always-system.m41
-rw-r--r--sys/contrib/openzfs/config/ax_compare_version.m41
-rw-r--r--sys/contrib/openzfs/config/ax_count_cpus.m41
-rw-r--r--sys/contrib/openzfs/config/ax_python_devel.m41
-rw-r--r--sys/contrib/openzfs/config/ax_restore_flags.m41
-rw-r--r--sys/contrib/openzfs/config/ax_save_flags.m41
-rw-r--r--sys/contrib/openzfs/config/deb.am21
-rw-r--r--sys/contrib/openzfs/config/find_system_library.m41
-rw-r--r--sys/contrib/openzfs/config/gettext.m41
-rw-r--r--sys/contrib/openzfs/config/host-cpu-c-abi.m41
-rw-r--r--sys/contrib/openzfs/config/iconv.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-access-ok-type.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-acl.m432
-rw-r--r--sys/contrib/openzfs/config/kernel-add-disk.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-assign_str.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-automount.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-bio.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-bio_max_segs.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-blk-queue.m427
-rw-r--r--sys/contrib/openzfs/config/kernel-blkdev.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-block-device-operations.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-commit-metadata.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-config-defined.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-copy-from-user-inatomic.m429
-rw-r--r--sys/contrib/openzfs/config/kernel-cpu_has_feature.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-declare-event-class.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-dentry-alias.m432
-rw-r--r--sys/contrib/openzfs/config/kernel-dentry-operations.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-discard-granularity.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-drop-inode.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-file.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-filelock.m423
-rw-r--r--sys/contrib/openzfs/config/kernel-filemap-splice-read.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-flush_dcache_page.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-fmode-t.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-follow-down-one.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-fpu.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-free-inode.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-fs-context.m436
-rw-r--r--sys/contrib/openzfs/config/kernel-fst-mount.m430
-rw-r--r--sys/contrib/openzfs/config/kernel-fsync-bdev.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-generic_fadvise.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-generic_fillattr.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-generic_io_acct.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-genhd-flags.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-get-disk-ro.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-iattr-vfsid.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-idmap_mnt_api.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-inode-create.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-inode-getattr.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-inode-lookup.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-inode-permission.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-inode-setattr.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-inode-state.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-inode-times.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-insert-inode-locked.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-is_owner_or_cap.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-kasan-enabled.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-kmap-atomic-args.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-kmap-local-page.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-kmem.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-kthread.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-kuid-helpers.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-kuidgid.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-make-request-fn.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-misc-minor.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-mkdir.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-mknod.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-mm-page-flags.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-mm-pagemap.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-namespace.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-objtool.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-pagemap-folio_wait_bit.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-pagemap-readahead-page.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-pde-data.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-percpu.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-pin-user-pages.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-proc-operations.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-reclaim_state.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-register_sysctl_table.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-rename.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-revalidate-disk-size.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-sb-dying.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-sb-wb-err.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-sched.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-security-inode-init.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-set-nlink.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-setattr-prepare.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-sget-args.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-show-options.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-shrink.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-siginfo.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-stdarg.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-strlcpy.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-symlink.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-sysfs.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-timer.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-tmpfile.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-totalhigh_pages.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-totalram-pages-func.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-truncate-setsize.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-types.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-usleep_range.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-vfs-file_range.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-vfs-filemap_dirty_folio.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-vfs-fsync.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-vfs-iov_iter.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-vfs-migrate_folio.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-vfs-migratepage.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-vfs-read_folio.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-vfs-readpages.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-vfs-set_page_dirty.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-vfs-writepage.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-writeback.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-xattr-handler.m41
-rw-r--r--sys/contrib/openzfs/config/kernel-zero_page.m41
-rw-r--r--sys/contrib/openzfs/config/kernel.m422
-rw-r--r--sys/contrib/openzfs/config/lib-ld.m41
-rw-r--r--sys/contrib/openzfs/config/lib-link.m41
-rw-r--r--sys/contrib/openzfs/config/lib-prefix.m41
-rw-r--r--sys/contrib/openzfs/config/mount-helper.m41
-rw-r--r--sys/contrib/openzfs/config/nls.m41
-rw-r--r--sys/contrib/openzfs/config/pkg.m41
-rw-r--r--sys/contrib/openzfs/config/po.m41
-rw-r--r--sys/contrib/openzfs/config/progtest.m41
-rw-r--r--sys/contrib/openzfs/config/rpm.am1
-rw-r--r--sys/contrib/openzfs/config/tgz.am1
-rw-r--r--sys/contrib/openzfs/config/toolchain-cfi.m433
-rw-r--r--sys/contrib/openzfs/config/toolchain-simd.m41
-rw-r--r--sys/contrib/openzfs/config/user-aio.h.m41
-rw-r--r--sys/contrib/openzfs/config/user-backtrace.m41
-rw-r--r--sys/contrib/openzfs/config/user-clock_gettime.m41
-rw-r--r--sys/contrib/openzfs/config/user-dracut.m41
-rw-r--r--sys/contrib/openzfs/config/user-gettext.m41
-rw-r--r--sys/contrib/openzfs/config/user-libaio.m41
-rw-r--r--sys/contrib/openzfs/config/user-libatomic.m41
-rw-r--r--sys/contrib/openzfs/config/user-libblkid.m41
-rw-r--r--sys/contrib/openzfs/config/user-libcrypto.m41
-rw-r--r--sys/contrib/openzfs/config/user-libexec.m41
-rw-r--r--sys/contrib/openzfs/config/user-libfetch.m41
-rw-r--r--sys/contrib/openzfs/config/user-libtirpc.m41
-rw-r--r--sys/contrib/openzfs/config/user-libudev.m41
-rw-r--r--sys/contrib/openzfs/config/user-libunwind.m41
-rw-r--r--sys/contrib/openzfs/config/user-libuuid.m41
-rw-r--r--sys/contrib/openzfs/config/user-makedev.m41
-rw-r--r--sys/contrib/openzfs/config/user-mount-setattr.m427
-rw-r--r--sys/contrib/openzfs/config/user-pam.m41
-rw-r--r--sys/contrib/openzfs/config/user-runstatedir.m41
-rw-r--r--sys/contrib/openzfs/config/user-statx.m42
-rw-r--r--sys/contrib/openzfs/config/user-systemd.m41
-rw-r--r--sys/contrib/openzfs/config/user-sysvinit.m41
-rw-r--r--sys/contrib/openzfs/config/user-udev.m41
-rw-r--r--sys/contrib/openzfs/config/user-zlib.m41
-rw-r--r--sys/contrib/openzfs/config/user.m42
-rw-r--r--sys/contrib/openzfs/config/zfs-build.m44
-rw-r--r--sys/contrib/openzfs/config/zfs-meta.m41
-rw-r--r--sys/contrib/openzfs/configure.ac2
-rw-r--r--sys/contrib/openzfs/contrib/Makefile.am1
-rw-r--r--sys/contrib/openzfs/contrib/bash_completion.d/Makefile.am1
-rw-r--r--sys/contrib/openzfs/contrib/bpftrace/Makefile.am1
-rw-r--r--sys/contrib/openzfs/contrib/debian/Makefile.am1
-rw-r--r--sys/contrib/openzfs/contrib/dracut/Makefile.am1
-rw-r--r--sys/contrib/openzfs/contrib/initramfs/Makefile.am1
-rw-r--r--sys/contrib/openzfs/contrib/initramfs/scripts/zfs8
-rw-r--r--sys/contrib/openzfs/contrib/pam_zfs_key/Makefile.am1
-rw-r--r--sys/contrib/openzfs/contrib/pyzfs/Makefile.am1
-rw-r--r--sys/contrib/openzfs/contrib/zcp/Makefile.am1
-rw-r--r--sys/contrib/openzfs/etc/Makefile.am1
-rw-r--r--sys/contrib/openzfs/etc/systemd/system-generators/zfs-mount-generator.c5
-rw-r--r--sys/contrib/openzfs/include/Makefile.am1
-rw-r--r--sys/contrib/openzfs/include/os/freebsd/Makefile.am1
-rw-r--r--sys/contrib/openzfs/include/os/linux/Makefile.am1
-rw-r--r--sys/contrib/openzfs/include/os/linux/kernel/linux/dcache_compat.h2
-rw-r--r--sys/contrib/openzfs/include/os/linux/kernel/linux/xattr_compat.h17
-rw-r--r--sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vfsops_os.h14
-rw-r--r--sys/contrib/openzfs/include/sys/dbuf.h2
-rw-r--r--sys/contrib/openzfs/include/sys/dmu.h2
-rw-r--r--sys/contrib/openzfs/include/sys/dnode.h13
-rw-r--r--sys/contrib/openzfs/include/sys/spa.h1
-rw-r--r--sys/contrib/openzfs/include/sys/vdev_raidz_impl.h1
-rw-r--r--sys/contrib/openzfs/include/sys/vdev_rebuild.h4
-rw-r--r--sys/contrib/openzfs/lib/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libavl/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libefi/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libicp/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libnvpair/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libspl/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libspl/include/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libspl/os/linux/getmntany.c9
-rw-r--r--sys/contrib/openzfs/lib/libuutil/uu_ident.c2
-rw-r--r--sys/contrib/openzfs/lib/libzdb/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libzfs/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c49
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_diff.c4
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_impl.h17
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_mount.c43
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_pool.c2
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c2
-rw-r--r--sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c11
-rw-r--r--sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c143
-rw-r--r--sys/contrib/openzfs/lib/libzfs_core/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libzfsbootenv/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libzpool/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libzstd/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libzutil/Makefile.am1
-rw-r--r--sys/contrib/openzfs/lib/libzutil/os/linux/zutil_device_path_os.c16
-rw-r--r--sys/contrib/openzfs/man/Makefile.am1
-rw-r--r--sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S4
-rw-r--r--sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S4
-rw-r--r--sys/contrib/openzfs/module/nvpair/nvpair.c5
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/spl/spl_cmn_err.c10
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c4
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c4
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zfs_ctldir.c35
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zfs_uio.c13
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zfs_vfsops.c231
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c44
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zpl_super.c681
-rw-r--r--sys/contrib/openzfs/module/zfs/dbuf.c78
-rw-r--r--sys/contrib/openzfs/module/zfs/dmu.c39
-rw-r--r--sys/contrib/openzfs/module/zfs/dmu_direct.c8
-rw-r--r--sys/contrib/openzfs/module/zfs/dmu_objset.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/dnode.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/dnode_sync.c105
-rw-r--r--sys/contrib/openzfs/module/zfs/dsl_bookmark.c18
-rw-r--r--sys/contrib/openzfs/module/zfs/dsl_dir.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/range_tree.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/spa.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/spa_errlog.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/spa_misc.c48
-rw-r--r--sys/contrib/openzfs/module/zfs/vdev.c29
-rw-r--r--sys/contrib/openzfs/module/zfs/vdev_draid.c76
-rw-r--r--sys/contrib/openzfs/module/zfs/vdev_mirror.c13
-rw-r--r--sys/contrib/openzfs/module/zfs/vdev_raidz.c44
-rw-r--r--sys/contrib/openzfs/module/zfs/vdev_rebuild.c56
-rw-r--r--sys/contrib/openzfs/module/zfs/zfs_ioctl.c1
-rw-r--r--sys/contrib/openzfs/module/zfs/zio.c6
-rw-r--r--sys/contrib/openzfs/rpm/Makefile.am1
-rw-r--r--sys/contrib/openzfs/scripts/Makefile.am1
-rwxr-xr-xsys/contrib/openzfs/scripts/spdxcheck.pl35
-rwxr-xr-xsys/contrib/openzfs/scripts/zfs-tests.sh16
-rw-r--r--sys/contrib/openzfs/tests/Makefile.am1
-rw-r--r--sys/contrib/openzfs/tests/runfiles/common.run15
-rw-r--r--sys/contrib/openzfs/tests/runfiles/linux.run4
-rwxr-xr-xsys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in3
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/Makefile.am1
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore2
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am4
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/clone_after_trunc.c117
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/setlease.c126
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/threadsappend.c8
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg6
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib15
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am11
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_after_trunc.ksh31
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_list/cleanup.ksh30
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_list/setup.ksh32
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_list/zfs_list_009_pos.ksh69
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/fadvise/fadvise_dontneed.ksh70
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/lease/cleanup.ksh26
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/lease/lease_setlease.ksh44
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/lease/setup.ksh27
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib71
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid.ksh12
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged1.ksh7
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged2.ksh14
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_degraded1.ksh136
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_degraded2.ksh152
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare1.ksh13
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare2.ksh8
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare3.ksh28
-rw-r--r--sys/contrib/openzfs/udev/Makefile.am1
-rw-r--r--sys/modules/zfs/zfs_config.h29
-rw-r--r--sys/modules/zfs/zfs_gitrev.h2
319 files changed, 3254 insertions, 837 deletions
diff --git a/sys/contrib/openzfs/.github/workflows/checkstyle.yaml b/sys/contrib/openzfs/.github/workflows/checkstyle.yaml
index a01a4fe8587c..ddcc2b8581fa 100644
--- a/sys/contrib/openzfs/.github/workflows/checkstyle.yaml
+++ b/sys/contrib/openzfs/.github/workflows/checkstyle.yaml
@@ -56,9 +56,10 @@ jobs:
- name: Prepare artifacts
if: failure() && steps.CheckABI.outcome == 'failure'
run: |
- find -name *.abi | tar -cf abi_files.tar -T -
- - uses: actions/upload-artifact@v4
+ find -name *.abi | tar -cjf abi_files.tar.bz2 -T -
+ - uses: actions/upload-artifact@v7
if: failure() && steps.CheckABI.outcome == 'failure'
with:
name: New ABI files (use only if you're sure about interface changes)
- path: abi_files.tar
+ path: abi_files.tar.bz2
+ archive: false
diff --git a/sys/contrib/openzfs/.github/workflows/codeql.yml b/sys/contrib/openzfs/.github/workflows/codeql.yml
index e975d7dd00b9..689fe71fddc3 100644
--- a/sys/contrib/openzfs/.github/workflows/codeql.yml
+++ b/sys/contrib/openzfs/.github/workflows/codeql.yml
@@ -28,7 +28,7 @@ jobs:
echo "MAKEFLAGS=-j$(nproc)" >> $GITHUB_ENV
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
diff --git a/sys/contrib/openzfs/.github/workflows/scripts/generate-ci-type.py b/sys/contrib/openzfs/.github/workflows/scripts/generate-ci-type.py
index 059d6ad3872b..b1910ab630af 100755
--- a/sys/contrib/openzfs/.github/workflows/scripts/generate-ci-type.py
+++ b/sys/contrib/openzfs/.github/workflows/scripts/generate-ci-type.py
@@ -3,13 +3,16 @@
"""
Determine the CI type based on the change list and commit message.
-Prints "quick" if (explicity required by user):
+Output format: "<type> <source>" where source is "manual" (from
+ZFS-CI-Type commit tag) or "auto" (from file change heuristics).
+
+Prints "quick manual" if:
- the *last* commit message contains 'ZFS-CI-Type: quick'
-or if (heuristics):
+or "quick auto" if (heuristics):
- the files changed are not in the list of specified directories, and
- all commit messages do not contain 'ZFS-CI-Type: (full|linux|freebsd)'
-Otherwise prints "full".
+Otherwise prints "full auto" (or "<type> manual" if explicitly requested).
"""
import sys
@@ -58,9 +61,10 @@ if __name__ == '__main__':
head, base = sys.argv[1:3]
- def output_type(type, reason):
- print(f'{prog}: will run {type} CI: {reason}', file=sys.stderr)
- print(type)
+ def output_type(type, source, reason):
+ print(f'{prog}: will run {type} CI ({source}): {reason}',
+ file=sys.stderr)
+ print(f'{type} {source}')
sys.exit(0)
# check last (HEAD) commit message
@@ -70,7 +74,8 @@ if __name__ == '__main__':
for line in last_commit_message_raw.stdout.decode().splitlines():
if line.strip().lower() == 'zfs-ci-type: quick':
- output_type('quick', f'requested by HEAD commit {head}')
+ output_type('quick', 'manual',
+ f'requested by HEAD commit {head}')
# check all commit messages
all_commit_message_raw = subprocess.run([
@@ -84,11 +89,14 @@ if __name__ == '__main__':
if line.startswith('ZFS-CI-Commit:'):
commit_ref = line.lstrip('ZFS-CI-Commit:').rstrip()
if line.strip().lower() == 'zfs-ci-type: freebsd':
- output_type('freebsd', f'requested by commit {commit_ref}')
+ output_type('freebsd', 'manual',
+ f'requested by commit {commit_ref}')
if line.strip().lower() == 'zfs-ci-type: linux':
- output_type('linux', f'requested by commit {commit_ref}')
+ output_type('linux', 'manual',
+ f'requested by commit {commit_ref}')
if line.strip().lower() == 'zfs-ci-type: full':
- output_type('full', f'requested by commit {commit_ref}')
+ output_type('full', 'manual',
+ f'requested by commit {commit_ref}')
# check changed files
changed_files_raw = subprocess.run([
@@ -104,9 +112,10 @@ if __name__ == '__main__':
for r in FULL_RUN_REGEX:
if r.match(f):
output_type(
- 'full',
+ 'full', 'auto',
f'changed file "{f}" matches pattern "{r.pattern}"'
)
# catch-all
- output_type('quick', 'no changed file matches full CI patterns')
+ output_type('quick', 'auto',
+ 'no changed file matches full CI patterns')
diff --git a/sys/contrib/openzfs/.github/workflows/scripts/merge_summary.awk b/sys/contrib/openzfs/.github/workflows/scripts/merge_summary.awk
index 2b00d00226c9..8a4ce9a2be06 100755
--- a/sys/contrib/openzfs/.github/workflows/scripts/merge_summary.awk
+++ b/sys/contrib/openzfs/.github/workflows/scripts/merge_summary.awk
@@ -17,6 +17,7 @@ BEGIN {
pass=0
fail=0
skip=0
+ killed=0
state=""
cl=0
el=0
@@ -49,6 +50,37 @@ BEGIN {
/PASS/{ if (state=="pass_count") {pass += $2}}
/FAIL/{ if (state=="pass_count") {fail += $2}}
/SKIP/{ if (state=="pass_count") {skip += $2}}
+
+# If the test was killed, you'll get a line like:
+#
+# [2026-04-22T03:34:17.694616] Test (Linux): /usr/share/zfs/zfs-tests/tests/functional/io/setup (run as root) [10:00] [KILLED]
+#
+# Parse out the test name minus the /usr/share/zfs/zfs-tests/tests/functional/'
+# part, and include the optional "(Linux): " line, as you can have the killed
+# tests in two categories, like:
+#
+# KILLED (Linux): io/setup
+# KILLED io/setup
+#
+/KILLED/{
+ extra=""
+ for(i=1; i<=NF; i++) {
+ # Look for optional "(Linux):" field
+ if ($i ~ "\\("){
+ extra=$i" "}
+
+ # Look for a field with a '/' in it. It is the test name.
+ if($i ~ "/") {
+ testname=$i
+ # Remove /usr/share/zfs/zfs-test/test/functional string
+ sub(/\/usr\/share\/zfs\/zfs-tests\/tests\/functional\//,"",testname)
+ testname=extra""testname
+ killed_tests[killed] = testname
+ killed++
+ break
+ }
+ }
+}
/Running Time/{
state="";
running[i]=$3;
@@ -106,4 +138,10 @@ END {
asort(unexpected_lines, sorted)
for (j in sorted)
print sorted[j]
+
+ # We don't want to sort killed tests, as the first test that was killed
+ # most likely caused the others to be killed.
+ print "\n\nTests that were killed:"
+ for (j in killed_tests)
+ print " KILLED "killed_tests[j]
}
diff --git a/sys/contrib/openzfs/.github/workflows/scripts/qemu-1-setup.sh b/sys/contrib/openzfs/.github/workflows/scripts/qemu-1-setup.sh
index 3d111561272d..5c41a4d6a497 100755
--- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-1-setup.sh
+++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-1-setup.sh
@@ -6,6 +6,27 @@
set -eu
+# The default runner has a bunch of development tools and other things
+# that we do not need. Remove them here to free up a total of 35GB.
+#
+# First remove packages - this frees up ~10GB
+echo "Disk space before purge:"
+df -h /
+sudo docker image prune --all --force
+sudo docker builder prune -a
+unneeded="microsoft-edge-stable|azure-cli|google-cloud|google-chrome-stable|"\
+"temurin|llvm|firefox|mysql-server|snapd|android|dotnet|haskell|ghcup|"\
+"powershell|julia|swift|miniconda|chromium"
+sudo apt-get -y remove $(dpkg-query -f '${binary:Package}\n' -W | grep -E "'$unneeded'")
+sudo apt-get -y autoremove
+
+# Next, remove unneeded files in /usr. This frees up an additional 25GB.
+sudo rm -fr /usr/local/lib/android /usr/share/dotnet /usr/local/.ghcup \
+ /usr/share/swift /usr/local/share/powershell /usr/local/julia* \
+ /usr/share/miniconda /usr/local/share/chromium
+echo "Disk space after:"
+df -h /
+
# The default 'azure.archive.ubuntu.com' mirrors can be really slow.
# Prioritize the official Ubuntu mirrors.
#
@@ -42,7 +63,7 @@ sudo swapoff -a
# configurations. On one config you get two 75GB block devices, and on the
# other you get a single 150GB block device. Here's what both look like:
#
-# --- Two 75GB block devices ---
+# --- One 150GB block device ---
# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
# sda 8:0 0 150G 0 disk
# ├─sda1 8:1 0 149G 0 part /
@@ -56,7 +77,7 @@ sudo swapoff -a
# lrwxrwxrwx 1 root root 11 Jan 29 18:07 azure_root-part15 -> ../../sda15
# lrwxrwxrwx 1 root root 11 Jan 29 18:07 azure_root-part16 -> ../../sda16
#
-# --- One 150GB block device ---
+# --- Two 75GB block devices ---
# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
# sda 8:0 0 75G 0 disk
# ├─sda1 8:1 0 74G 0 part /
@@ -118,18 +139,20 @@ fi
sudo mkswap $SWAP
sudo swapon $SWAP
+echo "Block devices:"
+lsblk
+
# adjust zfs module parameter and create pool
-exec 1>/dev/null
ARC_MIN=$((1024*1024*256))
ARC_MAX=$((1024*1024*512))
-echo $ARC_MIN | sudo tee /sys/module/zfs/parameters/zfs_arc_min
-echo $ARC_MAX | sudo tee /sys/module/zfs/parameters/zfs_arc_max
-echo 1 | sudo tee /sys/module/zfs/parameters/zvol_use_blk_mq
+echo $ARC_MIN | sudo tee /sys/module/zfs/parameters/zfs_arc_min >/dev/null
+echo $ARC_MAX | sudo tee /sys/module/zfs/parameters/zfs_arc_max >/dev/null
+echo 1 | sudo tee /sys/module/zfs/parameters/zvol_use_blk_mq >/dev/null
sudo zpool create -f -o ashift=12 zpool $DISKS -O relatime=off \
-O atime=off -O xattr=sa -O compression=lz4 -O sync=disabled \
-O redundant_metadata=none -O mountpoint=/mnt/tests
+echo "Status:"
+zpool status
-# no need for some scheduler
-for i in /sys/block/s*/queue/scheduler; do
- echo "none" | sudo tee $i
-done
+echo "Last dmesg:"
+sudo dmesg | tail -n 10
diff --git a/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh b/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh
index 9a18ca659c44..e63aece389c0 100755
--- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh
+++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh
@@ -78,11 +78,6 @@ case "$OS" in
OPTS[0]="--boot"
OPTS[1]="uefi=on"
;;
- fedora41)
- OSNAME="Fedora 41"
- OSv="fedora-unknown"
- URL="https://download.fedoraproject.org/pub/fedora/linux/releases/41/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-41-1.4.x86_64.qcow2"
- ;;
fedora42)
OSNAME="Fedora 42"
OSv="fedora-unknown"
@@ -93,6 +88,11 @@ case "$OS" in
OSv="fedora-unknown"
URL="https://download.fedoraproject.org/pub/fedora/linux/releases/43/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-43-1.6.x86_64.qcow2"
;;
+ fedora44)
+ OSNAME="Fedora 44"
+ OSv="fedora-unknown"
+ URL="https://download.fedoraproject.org/pub/fedora/linux/releases/44/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-44-1.7.x86_64.qcow2"
+ ;;
freebsd13-5r)
FreeBSD="13.5-RELEASE"
OSNAME="FreeBSD $FreeBSD"
@@ -101,13 +101,20 @@ case "$OS" in
KSRC="$FREEBSD_REL/../amd64/$FreeBSD/src.txz"
NIC="rtl8139"
;;
- freebsd14-3r)
- FreeBSD="14.3-RELEASE"
+ freebsd14-4r)
+ FreeBSD="14.4-RELEASE"
OSNAME="FreeBSD $FreeBSD"
OSv="freebsd14.0"
URLxz="$FREEBSD_REL/$FreeBSD/amd64/Latest/FreeBSD-$FreeBSD-amd64-BASIC-CI.raw.xz"
KSRC="$FREEBSD_REL/../amd64/$FreeBSD/src.txz"
;;
+ freebsd15-0r)
+ FreeBSD="15.0-RELEASE"
+ OSNAME="FreeBSD $FreeBSD"
+ OSv="freebsd15.0"
+ URLxz="$FREEBSD_REL/$FreeBSD/amd64/Latest/FreeBSD-$FreeBSD-amd64-BASIC-CI-ufs.raw.xz"
+ KSRC="$FREEBSD_REL/../amd64/$FreeBSD/src.txz"
+ ;;
freebsd13-5s)
FreeBSD="13.5-STABLE"
OSNAME="FreeBSD $FreeBSD"
@@ -116,15 +123,15 @@ case "$OS" in
KSRC="$FREEBSD_SNAP/../amd64/$FreeBSD/src.txz"
NIC="rtl8139"
;;
- freebsd14-3s)
- FreeBSD="14.3-STABLE"
+ freebsd14-4s)
+ FreeBSD="14.4-STABLE"
OSNAME="FreeBSD $FreeBSD"
OSv="freebsd14.0"
URLxz="$FREEBSD_SNAP/$FreeBSD/amd64/Latest/FreeBSD-$FreeBSD-amd64-BASIC-CI-ufs.raw.xz"
KSRC="$FREEBSD_SNAP/../amd64/$FreeBSD/src.txz"
;;
- freebsd15-0s)
- FreeBSD="15.0-STABLE"
+ freebsd15-1s)
+ FreeBSD="15.1-PRERELEASE"
OSNAME="FreeBSD $FreeBSD"
OSv="freebsd14.0"
URLxz="$FREEBSD_SNAP/$FreeBSD/amd64/Latest/FreeBSD-$FreeBSD-amd64-BASIC-CI-ufs.raw.xz"
@@ -193,17 +200,49 @@ DISK="/dev/zvol/zpool/openzfs"
sudo zfs create -ps -b 64k -V 80g zpool/openzfs
while true; do test -b $DISK && break; sleep 1; done
-# we are downloading via axel, curl and wget are mostly slower and
-# require more return value checking
+# We first try to download with 'axel', which is faster than curl, but fallback
+# to curl if that doesn't work. It is hoped that the curl fallback will get
+# around the occasional "ERROR 502: Bad Gateway" errors.
IMG="/mnt/tests/cloud-image"
-if [ ! -z "$URLxz" ]; then
- echo "Loading $URLxz ..."
- time axel -q -o "$IMG" "$URLxz"
- echo "Loading $KSRC ..."
- time axel -q -o ~/src.txz $KSRC
-else
- echo "Loading $URL ..."
- time axel -q -o "$IMG" "$URL"
+for cmd in 'axel -q -o' 'curl --fail -LSs -o' ; do
+ if [ ! -z "$URLxz" ]; then
+ echo "Loading $URLxz with $cmd..."
+ time eval "$cmd $IMG $URLxz" || true
+
+ if [ ! -s ~/src.txz ] ; then
+ echo "Loading $KSRC with $cmd..."
+ time eval "$cmd ~/src.txz $KSRC" || true
+ fi
+ else
+ echo "Loading $URL with $cmd..."
+ time eval "$cmd $IMG $URL" || true
+ fi
+
+ if [ -s "$IMG" ] ; then
+ # Successful download
+ break
+ fi
+done
+
+# SPECIAL CASE
+# FreeBSD sometimes has broken links in their "current/" URL. Go back up a
+# level and look for other images that might work. For example:
+#
+# https://download.freebsd.org/snapshots/CI-IMAGES/16.0-CURRENT/amd64/:
+#
+# 20251110/
+# 20251209/
+# 20260420/
+# current/
+#
+# In this case let's say the raw.xz link in current/ is bad, so look though the
+# other snapshot links for the newest existing raw.xz file.
+if [ ! -z "$URLxz" ] && [ ! -s "$IMG" ] ; then
+ URLxz=$(wget --accept "*.raw.xz" --spider -np --recursive --no-verbose \
+ $(dirname $(dirname $URLxz)) 2>&1 | awk '/200 OK/{print $(NF-2)}' | \
+ sort -n | tail -n 1)
+ echo "Couldn't download FreeBSD raw.xz. Trying fallback snapshot $URLxz"
+ curl --fail -LSs -o $IMG $URLxz
fi
echo "Importing VM image to zvol..."
diff --git a/sys/contrib/openzfs/.github/workflows/scripts/qemu-3-deps-vm.sh b/sys/contrib/openzfs/.github/workflows/scripts/qemu-3-deps-vm.sh
index c8e1a015abd9..6a83ef45fd26 100755
--- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-3-deps-vm.sh
+++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-3-deps-vm.sh
@@ -3,8 +3,11 @@
######################################################################
# 3) install dependencies for compiling and loading
#
-# $1: OS name (like 'fedora41')
-# $2: (optional) Experimental Fedora kernel version, like "6.14" to
+# qemu-3-deps-vm.sh [--poweroff] OS_NAME [FEDORA_VERSION]
+#
+# --poweroff: Power off the VM after installing dependencies
+# OS_NAME: OS name (like 'fedora41')
+# FEDORA_VERSION: (optional) Experimental Fedora kernel version, like "6.14" to
# install instead of Fedora defaults.
######################################################################
@@ -153,6 +156,12 @@ function install_fedora_experimental_kernel {
sudo dnf -y copr disable @kernel-vanilla/mainline
}
+POWEROFF=""
+if [ "$1" == "--poweroff" ] ; then
+ POWEROFF=1
+ shift
+fi
+
# Install dependencies
case "$1" in
almalinux8)
@@ -212,6 +221,11 @@ case "$1" in
sudo apt-get install -yq linux-tools-common libtirpc-dev \
linux-modules-extra-$(uname -r)
sudo apt-get install -yq dh-sequence-dkms
+
+ # Need 'build-essential' explicitly for ARM builder
+ # https://github.com/actions/runner-images/issues/9946
+ sudo apt-get install -yq build-essential
+
echo "##[endgroup]"
echo "##[group]Delete Ubuntu OpenZFS modules"
for i in $(find /lib/modules -name zfs -type d); do sudo rm -rvf $i; done
@@ -306,5 +320,7 @@ esac
# reset cloud-init configuration and poweroff
sudo cloud-init clean --logs
-sleep 2 && sudo poweroff &
+if [ "$POWEROFF" == "1" ] ; then
+ sleep 2 && sudo poweroff &
+fi
exit 0
diff --git a/sys/contrib/openzfs/.github/workflows/scripts/qemu-4-build-vm.sh b/sys/contrib/openzfs/.github/workflows/scripts/qemu-4-build-vm.sh
index 38255cf39966..bbfa2ec85b8f 100755
--- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-4-build-vm.sh
+++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-4-build-vm.sh
@@ -350,7 +350,16 @@ fi
# save some sysinfo
uname -a > /var/tmp/uname.txt
-cd $HOME/zfs
+# Check if we're running this script from within a VM or on the runner itself.
+# Most of the time we will be running in a VM, but the ARM builder actually
+# runs this script on the runner. If we happen to be running on the ARM
+# runner, we will start in the ZFS source directory. If we're running on a VM
+# then we'll just start in our home directory, and will need to 'cd' into our
+# source directory.
+if [ ! -e META ] ; then
+ cd $HOME/zfs
+fi
+
export PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin"
extra=""
diff --git a/sys/contrib/openzfs/.github/workflows/scripts/qemu-6-tests.sh b/sys/contrib/openzfs/.github/workflows/scripts/qemu-6-tests.sh
index 8dad30fe4a5a..c261cbfca06d 100755
--- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-6-tests.sh
+++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-6-tests.sh
@@ -222,9 +222,9 @@ TAGS=$NUM/$DEN
sudo dmesg -c > dmesg-prerun.txt
mount > mount.txt
df -h > df-prerun.txt
-$TDIR/zfs-tests.sh -vKO -s 3GB -T $TAGS
+RV=0
+$TDIR/zfs-tests.sh -vKO -s 3GB -T $TAGS || RV=$?
-RV=$?
df -h > df-postrun.txt
echo $RV > tests-exitcode.txt
sync
diff --git a/sys/contrib/openzfs/.github/workflows/scripts/qemu-7-prepare.sh b/sys/contrib/openzfs/.github/workflows/scripts/qemu-7-prepare.sh
index 98a5c24c2521..51ae82567c2c 100755
--- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-7-prepare.sh
+++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-7-prepare.sh
@@ -13,16 +13,29 @@ source env.txt
mkdir -p $RESPATH
+TARNAME=qemu-$OS
+
# check if building the module has failed
if [ -z ${VMs:-} ]; then
cd $RESPATH
echo ":exclamation: ZFS module didn't build successfully :exclamation:" \
| tee summary.txt | tee /tmp/summary.txt
cp /var/tmp/*.txt .
- tar cf /tmp/qemu-$OS.tar -C $RESPATH -h . || true
+
+ # rename /var/tmp/test_results to /var/tmp/qemu-$OS
+ mv $RESPATH $(dirname $RESPATH)/$TARNAME
+ tar cjf /tmp/$TARNAME.tar.bz2 -C $(dirname $RESPATH) -h $TARNAME || true
+ # move it back to /var/tmp/test_results (needed for next script)
+ mv $(dirname $RESPATH)/$TARNAME $RESPATH
+
exit 0
fi
+if ! grep -q vm /etc/hosts ; then
+ echo "No vm* hostnames, VMs probably didn't startup"
+ exit 0
+fi
+
# build was okay
BASE="$HOME/work/zfs/zfs"
MERGE="$BASE/.github/workflows/scripts/merge_summary.awk"
@@ -38,6 +51,11 @@ cd $RESPATH
# prepare result files for summary
for ((i=1; i<=VMs; i++)); do
+
+ # no results, VM either didn't start or was unreachable, create
+ # the missing directory which is expected by subsequent steps
+ test -d vm$i || mkdir -p vm$i
+
file="vm$i/build-stderr.txt"
test -s $file && mv -f $file build-stderr.txt
@@ -48,12 +66,14 @@ for ((i=1; i<=VMs; i++)); do
test -s $file && mv -f $file uname.txt
file="vm$i/tests-exitcode.txt"
- if [ ! -s $file ]; then
- # XXX - add some tests for kernel panic's here
- # tail -n 80 vm$i/console.txt | grep XYZ
- echo 1 > $file
+ if [ ! -s "$file" ]; then
+ # Print in bold red
+ echo -e "\033[1;31mVM$i didn't finish ZTS and may have crashed!\033[0m" >> extra
+
+ # ENOENT=2
+ echo 2 > "$file"
fi
- rv=$(cat vm$i/tests-exitcode.txt)
+ rv=$(cat "$file")
test $rv != 0 && touch /tmp/have_failed_tests
file="vm$i/current/log"
@@ -76,6 +96,14 @@ done
if [ -s summary ]; then
$MERGE summary | grep -v '^/' > summary.txt
$MERGE summary | $BASE/scripts/zfs-tests-color.sh > /tmp/summary.txt
+
+ # Add in additional 'extra' text at the end, if file is present.
+ if [ -s extra ] ; then
+ echo "" >> /tmp/summary.txt
+ cat extra >> /tmp/summary.txt
+ rm -f extra
+ fi
+
rm -f summary
else
touch summary.txt /tmp/summary.txt
@@ -121,4 +149,9 @@ if [ ! -s uname.txt ]; then
fi
# artifact ready now
-tar cf /tmp/qemu-$OS.tar -C $RESPATH -h . || true
+#
+# rename /var/tmp/test_results to /var/tmp/qemu-$OS
+mv $RESPATH $(dirname $RESPATH)/$TARNAME
+tar cjf /tmp/$TARNAME.tar.bz2 -C $(dirname $RESPATH) -h $TARNAME || true
+# move it back to /var/tmp/test_results (needed for next script)
+mv $(dirname $RESPATH)/$TARNAME $RESPATH
diff --git a/sys/contrib/openzfs/.github/workflows/scripts/qemu-8-summary.sh b/sys/contrib/openzfs/.github/workflows/scripts/qemu-8-summary.sh
index 00a4bf1ae325..39b3d124c794 100755
--- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-8-summary.sh
+++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-8-summary.sh
@@ -37,9 +37,11 @@ function showfile_tail() {
echo "##[endgroup]"
}
-# overview
-cat /tmp/summary.txt
-echo ""
+# overview if available
+if [ -f /tmp/summary.txt -a -s /tmp/summary.txt ]; then
+ cat /tmp/summary.txt
+ echo ""
+fi
if [ -f /tmp/have_failed_tests -a -s /tmp/failed.txt ]; then
echo "Debuginfo of failed tests:"
diff --git a/sys/contrib/openzfs/.github/workflows/scripts/qemu-9-summary-page.sh b/sys/contrib/openzfs/.github/workflows/scripts/qemu-9-summary-page.sh
index 737dda01b565..1200f4de2b94 100755
--- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-9-summary-page.sh
+++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-9-summary-page.sh
@@ -33,7 +33,9 @@ function send2github() {
# first call, generate all summaries
if [ ! -f out-1.md ]; then
logfile="1"
- for tarfile in Logs-functional-*/qemu-*.tar; do
+ # The bz2 files are put into directories with the same name, like:
+ # "qemu-debian12.tar.bz2/qemu-debian12.tar.bz2"
+ for tarfile in qemu-*.tar.bz2/qemu-*.tar.bz2; do
rm -rf vm* *.txt
if [ ! -s "$tarfile" ]; then
output "\n## Functional Tests: unknown\n"
diff --git a/sys/contrib/openzfs/.github/workflows/smatch.yml b/sys/contrib/openzfs/.github/workflows/smatch.yml
index ac6454244f93..305a1f0179bd 100644
--- a/sys/contrib/openzfs/.github/workflows/smatch.yml
+++ b/sys/contrib/openzfs/.github/workflows/smatch.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout smatch
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
with:
repository: error27/smatch
ref: master
@@ -26,7 +26,7 @@ jobs:
cd $GITHUB_WORKSPACE/smatch
make -j$(nproc)
- name: Checkout OpenZFS
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
path: zfs
diff --git a/sys/contrib/openzfs/.github/workflows/zfs-arm.yml b/sys/contrib/openzfs/.github/workflows/zfs-arm.yml
new file mode 100644
index 000000000000..6039e4736c42
--- /dev/null
+++ b/sys/contrib/openzfs/.github/workflows/zfs-arm.yml
@@ -0,0 +1,40 @@
+name: zfs-arm
+
+on:
+ push:
+ pull_request:
+ workflow_dispatch:
+
+jobs:
+ zfs-arm:
+ name: ZFS ARM build
+ runs-on: ubuntu-24.04-arm
+ steps:
+ - uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
+ ref: ${{ github.event.pull_request.head.sha }}
+ - name: Install dependencies
+ timeout-minutes: 20
+ run: |
+ sudo apt-get -y remove firefox || true
+ .github/workflows/scripts/qemu-3-deps-vm.sh ubuntu24
+
+ # We're running the VM scripts locally on the runner, so need to fix
+ # up hostnames to make it work.
+ for ((i=0; i<=3; i++)); do
+ echo "127.0.0.1 vm$i" | sudo tee -a /etc/hosts
+ done
+ - name: Build modules
+ timeout-minutes: 30
+ run: |
+ .github/workflows/scripts/qemu-4-build-vm.sh --enable-debug ubuntu24
+
+ # Quick sanity test since we're not running the full ZTS
+ sudo modprobe zfs
+ sudo dmesg | grep -i zfs
+ truncate -s 100M file
+ sudo zpool create tank ./file
+ zpool status
+
+ echo "Built ZFS successfully on ARM"
diff --git a/sys/contrib/openzfs/.github/workflows/zfs-qemu-packages.yml b/sys/contrib/openzfs/.github/workflows/zfs-qemu-packages.yml
index 7f8ba44b3ae6..c3a7397c6aef 100644
--- a/sys/contrib/openzfs/.github/workflows/zfs-qemu-packages.yml
+++ b/sys/contrib/openzfs/.github/workflows/zfs-qemu-packages.yml
@@ -58,10 +58,10 @@ jobs:
strategy:
fail-fast: false
matrix:
- os: ['almalinux8', 'almalinux9', 'almalinux10', 'fedora41', 'fedora42', 'fedora43']
+ os: ['almalinux8', 'almalinux9', 'almalinux10', 'fedora42', 'fedora43', 'fedora44']
runs-on: ubuntu-24.04
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
@@ -73,7 +73,7 @@ jobs:
- name: Install dependencies
run: |
- .github/workflows/scripts/qemu-3-deps.sh ${{ matrix.os }}
+ .github/workflows/scripts/qemu-3-deps.sh --poweroff ${{ matrix.os }}
- name: Build modules or Test repo
run: |
@@ -104,17 +104,18 @@ jobs:
run: |
rsync -a zfs@vm0:/tmp/repo /tmp || true
.github/workflows/scripts/replace-dupes-with-symlinks.sh /tmp/repo
- tar -cf ${{ matrix.os }}-repo.tar -C /tmp repo
+ tar -cjf ${{ matrix.os }}-repo.tar.bz2 -C /tmp repo
- - uses: actions/upload-artifact@v4
+ - uses: actions/upload-artifact@v7
id: artifact-upload
if: always()
with:
name: ${{ matrix.os }}-repo
- path: ${{ matrix.os }}-repo.tar
+ path: ${{ matrix.os }}-repo.tar.bz2
compression-level: 0
retention-days: 2
if-no-files-found: ignore
+ archive: false
combine_repos:
if: always()
@@ -122,16 +123,16 @@ jobs:
name: "Results"
runs-on: ubuntu-latest
steps:
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v8
id: artifact-download
if: always()
- name: Test Summary
if: always()
run: |
- for i in $(find . -type f -iname "*.tar") ; do
+ for i in $(find . -type f -iname "*.tar.bz2") ; do
tar -xf $i -C /tmp
done
- tar -cf all-repo.tar -C /tmp repo
+ tar -cjf all-repo.tar.bz2 -C /tmp repo
# If we're installing from a repo, print out the summary of the versions
# that got installed using Markdown.
@@ -146,12 +147,12 @@ jobs:
done
fi
- - uses: actions/upload-artifact@v4
+ - uses: actions/upload-artifact@v7
id: artifact-upload2
if: always()
with:
name: all-repo
- path: all-repo.tar
- compression-level: 0
+ path: all-repo.tar.bz2
retention-days: 5
if-no-files-found: ignore
+ archive: false
diff --git a/sys/contrib/openzfs/.github/workflows/zfs-qemu.yml b/sys/contrib/openzfs/.github/workflows/zfs-qemu.yml
index 035c5ddf0841..4b4fd27543fd 100644
--- a/sys/contrib/openzfs/.github/workflows/zfs-qemu.yml
+++ b/sys/contrib/openzfs/.github/workflows/zfs-qemu.yml
@@ -28,37 +28,51 @@ jobs:
test_os: ${{ steps.os.outputs.os }}
ci_type: ${{ steps.os.outputs.ci_type }}
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Generate OS config and CI type
id: os
run: |
ci_type="default"
+ ci_source="auto"
# determine CI type when running on PR
if ${{ github.event_name == 'pull_request' }}; then
head=${{ github.event.pull_request.head.sha }}
base=${{ github.event.pull_request.base.sha }}
- ci_type=$(python3 .github/workflows/scripts/generate-ci-type.py $head $base)
+ read ci_type ci_source <<< "$(python3 .github/workflows/scripts/generate-ci-type.py $head $base)"
fi
case "$ci_type" in
quick)
- os_selection='["almalinux8", "almalinux9", "almalinux10", "debian12", "fedora42", "freebsd15-0s", "ubuntu24"]'
+ os_selection='["almalinux8", "almalinux9", "almalinux10", "debian12", "fedora42", "freebsd15-1s", "ubuntu24"]'
;;
linux)
- os_selection='["almalinux8", "almalinux9", "almalinux10", "centos-stream9", "centos-stream10", "debian11", "debian12", "debian13", "fedora41", "fedora42", "fedora43", "ubuntu22", "ubuntu24"]'
+ os_selection='["almalinux8", "almalinux9", "almalinux10", "centos-stream9", "centos-stream10", "debian11", "debian12", "debian13", "fedora42", "fedora43", "fedora44", "ubuntu22", "ubuntu24"]'
;;
freebsd)
- os_selection='["freebsd13-5r", "freebsd14-3r", "freebsd13-5s", "freebsd14-3s", "freebsd15-0s", "freebsd16-0c"]'
+ os_selection='["freebsd13-5r", "freebsd14-4r", "freebsd13-5s", "freebsd14-4s", "freebsd15-1s", "freebsd16-0c"]'
;;
*)
# default list
- os_selection='["almalinux8", "almalinux9", "almalinux10", "centos-stream9", "centos-stream10", "debian12", "debian13", "fedora42", "fedora43", "freebsd14-3r", "freebsd15-0s", "freebsd16-0c", "ubuntu22", "ubuntu24"]'
+ os_selection='["almalinux8", "almalinux9", "almalinux10", "centos-stream9", "centos-stream10", "debian12", "debian13", "fedora42", "fedora43", "fedora44", "freebsd14-4r", "freebsd15-1s", "freebsd16-0c", "ubuntu22", "ubuntu24"]'
;;
esac
+ # Repository-level override for OS selection.
+ # Set vars.ZTS_OS_OVERRIDE in repo settings to restrict targets
+ # (e.g. '["debian13"]' or '["debian13", "fedora42"]').
+ # Manual ZFS-CI-Type in commit messages bypasses the override.
+ if [ -n "${{ vars.ZTS_OS_OVERRIDE }}" ] && [ "$ci_source" != "manual" ]; then
+ override='${{ vars.ZTS_OS_OVERRIDE }}'
+ if echo "$override" | jq -e 'type == "array"' >/dev/null 2>&1; then
+ os_selection="$override"
+ else
+ echo "::warning::Invalid ZTS_OS_OVERRIDE, using default"
+ fi
+ fi
+
if ${{ github.event.inputs.fedora_kernel_ver != '' }}; then
# They specified a custom kernel version for Fedora.
# Use only Fedora runners.
@@ -84,13 +98,13 @@ jobs:
# debian: debian12, debian13, ubuntu22, ubuntu24
# misc: archlinux, tumbleweed
# FreeBSD variants of november 2025:
- # FreeBSD Release: freebsd13-5r, freebsd14-3r, freebsd15-0r
- # FreeBSD Stable: freebsd13-5s, freebsd14-3s, freebsd15-0s
+ # FreeBSD Release: freebsd13-5r, freebsd14-4r, freebsd15-0r
+ # FreeBSD Stable: freebsd13-5s, freebsd14-4s, freebsd15-1s
# FreeBSD Current: freebsd16-0c
os: ${{ fromJson(needs.test-config.outputs.test_os) }}
runs-on: ubuntu-24.04
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
@@ -104,7 +118,7 @@ jobs:
- name: Install dependencies
timeout-minutes: 60
- run: .github/workflows/scripts/qemu-3-deps.sh ${{ matrix.os }} ${{ github.event.inputs.fedora_kernel_ver }}
+ run: .github/workflows/scripts/qemu-3-deps.sh --poweroff ${{ matrix.os }} ${{ github.event.inputs.fedora_kernel_ver }}
- name: Build modules
timeout-minutes: 30
@@ -125,12 +139,13 @@ jobs:
timeout-minutes: 10
run: .github/workflows/scripts/qemu-7-prepare.sh
- - uses: actions/upload-artifact@v4
+ - uses: actions/upload-artifact@v7
id: artifact-upload
if: always()
with:
name: Logs-functional-${{ matrix.os }}
- path: /tmp/qemu-${{ matrix.os }}.tar
+ path: /tmp/qemu-${{ matrix.os }}.tar.bz2
+ archive: false
if-no-files-found: ignore
- name: Test Summary
@@ -144,10 +159,10 @@ jobs:
needs: [ qemu-vm ]
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
- - uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v8
- name: Generating summary
run: .github/workflows/scripts/qemu-9-summary-page.sh
- name: Generating summary...
@@ -186,7 +201,8 @@ jobs:
run: .github/workflows/scripts/qemu-9-summary-page.sh 18
- name: Generating summary...
run: .github/workflows/scripts/qemu-9-summary-page.sh 19
- - uses: actions/upload-artifact@v4
+ - uses: actions/upload-artifact@v7
with:
name: Summary Files
path: out-*
+ archive: true
diff --git a/sys/contrib/openzfs/.github/workflows/zloop.yml b/sys/contrib/openzfs/.github/workflows/zloop.yml
index 4ae3ccdc5484..7f76a670af95 100644
--- a/sys/contrib/openzfs/.github/workflows/zloop.yml
+++ b/sys/contrib/openzfs/.github/workflows/zloop.yml
@@ -15,7 +15,7 @@ jobs:
WORK_DIR: /mnt/zloop
CORE_DIR: /mnt/zloop/cores
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Install dependencies
@@ -41,6 +41,7 @@ jobs:
sudo modprobe zfs
- name: Tests
run: |
+ [ -r /etc/hostid ] && [ -s /etc/hostid ] || sudo zgenhostid -f
sudo truncate -s 256G /mnt/vdev
sudo zpool create cipool -m $WORK_DIR -O compression=on -o autotrim=on /mnt/vdev
sudo /usr/share/zfs/zloop.sh -t 600 -I 6 -l -m 1 -c $CORE_DIR -f $WORK_DIR -- -T 120 -P 60
@@ -60,7 +61,7 @@ jobs:
if: failure()
run: |
cat $CORE_DIR/*/ztest.zdb
- - uses: actions/upload-artifact@v4
+ - uses: actions/upload-artifact@v7
if: failure()
with:
name: Logs
@@ -68,7 +69,7 @@ jobs:
/mnt/zloop/*/
!/mnt/zloop/cores/*/vdev/
if-no-files-found: ignore
- - uses: actions/upload-artifact@v4
+ - uses: actions/upload-artifact@v7
if: failure()
with:
name: Pool files
diff --git a/sys/contrib/openzfs/META b/sys/contrib/openzfs/META
index c6d7e3e94057..fcce2fae7170 100644
--- a/sys/contrib/openzfs/META
+++ b/sys/contrib/openzfs/META
@@ -1,10 +1,10 @@
Meta: 1
Name: zfs
Branch: 1.0
-Version: 2.4.1
+Version: 2.4.2
Release: 1
Release-Tags: relext
License: CDDL
Author: OpenZFS
-Linux-Maximum: 6.19
+Linux-Maximum: 7.0
Linux-Minimum: 4.18
diff --git a/sys/contrib/openzfs/Makefile.am b/sys/contrib/openzfs/Makefile.am
index 30f78e490b78..f78c38edc3ca 100644
--- a/sys/contrib/openzfs/Makefile.am
+++ b/sys/contrib/openzfs/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
CLEANFILES =
dist_noinst_DATA =
INSTALL_DATA_HOOKS =
diff --git a/sys/contrib/openzfs/README.md b/sys/contrib/openzfs/README.md
index a39b88fedd12..1f823b594433 100644
--- a/sys/contrib/openzfs/README.md
+++ b/sys/contrib/openzfs/README.md
@@ -30,6 +30,42 @@ We have a [Code of Conduct](./CODE_OF_CONDUCT.md).
OpenZFS is released under a CDDL license.
For more details see the NOTICE, LICENSE and COPYRIGHT files; `UCRL-CODE-235197`
-# Supported Kernels
- * The `META` file contains the officially recognized supported Linux kernel versions.
- * Supported FreeBSD versions are any supported branches and releases starting from 13.0-RELEASE.
+# Supported Kernels and Distributions
+
+## Linux
+
+Given the wide variety of Linux environments, we prioritize development and testing on stable, supported kernels and distributions.
+
+### Kernel ([kernel.org](https://kernel.org))
+
+All **longterm** kernels from [kernel.org](https://kernel.org) are supported. **stable** kernels are usually supported in the next OpenZFS release.
+
+**Supported longterm kernels**: **6.18**, **6.12**, **6.6**, **6.1**, **5.15**, **5.10**.
+
+### Red Hat Enterprise Linux (RHEL)
+
+All RHEL (and compatible systems: AlmaLinux OS, Rocky Linux, etc) on the **full** or **maintenance** support tracks are supported.
+
+**Supported RHEL releases**: **8.10**, **9.7**, **10.1**.
+
+### Ubuntu
+
+All Ubuntu **LTS** releases are supported.
+
+**Supported Ubuntu releases**: **24.04 “Noble”**, **22.04 “Jammy”**.
+
+### Debian
+
+All Debian **stable** and **LTS** releases are supported.
+
+**Supported Debian releases**: **13 “Trixie”**, **12 “Bookworm”**, **11 “Bullseye”**.
+
+### Other Distributions
+
+Generally, if a distribution is following an LTS kernel, it should work well with OpenZFS.
+
+## FreeBSD
+
+All FreeBSD releases receiving **security support** are supported by OpenZFS.
+
+**Supported FreeBSD releases**: **15.0**, **14.3**, **13.5**.
diff --git a/sys/contrib/openzfs/autogen.sh b/sys/contrib/openzfs/autogen.sh
index 5cb152474698..7114ac991270 100755
--- a/sys/contrib/openzfs/autogen.sh
+++ b/sys/contrib/openzfs/autogen.sh
@@ -1,3 +1,4 @@
#!/bin/sh
+# SPDX-License-Identifier: CDDL-1.0
autoreconf -fiv "$(dirname "$0")" && rm -rf "$(dirname "$0")"/autom4te.cache
diff --git a/sys/contrib/openzfs/cmd/Makefile.am b/sys/contrib/openzfs/cmd/Makefile.am
index ca94f6b77e06..ef9fdd31a6ae 100644
--- a/sys/contrib/openzfs/cmd/Makefile.am
+++ b/sys/contrib/openzfs/cmd/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
bin_SCRIPTS =
bin_PROGRAMS =
sbin_SCRIPTS =
diff --git a/sys/contrib/openzfs/cmd/raidz_test/Makefile.am b/sys/contrib/openzfs/cmd/raidz_test/Makefile.am
index 635216d65d73..690a5fd4433b 100644
--- a/sys/contrib/openzfs/cmd/raidz_test/Makefile.am
+++ b/sys/contrib/openzfs/cmd/raidz_test/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
raidz_test_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
raidz_test_CPPFLAGS = $(AM_CPPFLAGS) $(LIBZPOOL_CPPFLAGS)
diff --git a/sys/contrib/openzfs/cmd/zdb/Makefile.am b/sys/contrib/openzfs/cmd/zdb/Makefile.am
index 8a4388bd1884..4ab982f60b5d 100644
--- a/sys/contrib/openzfs/cmd/zdb/Makefile.am
+++ b/sys/contrib/openzfs/cmd/zdb/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
zdb_CPPFLAGS = $(AM_CPPFLAGS) $(LIBZPOOL_CPPFLAGS)
zdb_CFLAGS = $(AM_CFLAGS) $(LIBCRYPTO_CFLAGS)
diff --git a/sys/contrib/openzfs/cmd/zed/Makefile.am b/sys/contrib/openzfs/cmd/zed/Makefile.am
index c437ff51dd2b..80e68fa36275 100644
--- a/sys/contrib/openzfs/cmd/zed/Makefile.am
+++ b/sys/contrib/openzfs/cmd/zed/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
include $(srcdir)/%D%/zed.d/Makefile.am
zed_CFLAGS = $(AM_CFLAGS)
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/Makefile.am b/sys/contrib/openzfs/cmd/zed/zed.d/Makefile.am
index c0b161ecf248..4a02f8abfc22 100644
--- a/sys/contrib/openzfs/cmd/zed/zed.d/Makefile.am
+++ b/sys/contrib/openzfs/cmd/zed/zed.d/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
zedconfdir = $(sysconfdir)/zfs/zed.d
dist_zedconf_DATA = \
%D%/zed-functions.sh \
diff --git a/sys/contrib/openzfs/cmd/zed/zed_event.c b/sys/contrib/openzfs/cmd/zed/zed_event.c
index ba7cba304b1d..e252e0999c18 100644
--- a/sys/contrib/openzfs/cmd/zed/zed_event.c
+++ b/sys/contrib/openzfs/cmd/zed/zed_event.c
@@ -238,7 +238,7 @@ _zed_event_value_is_hex(const char *name)
NULL
};
const char **pp;
- char *p;
+ const char *p;
if (!name)
return (0);
diff --git a/sys/contrib/openzfs/cmd/zfs/Makefile.am b/sys/contrib/openzfs/cmd/zfs/Makefile.am
index 8a3c13a1fcfe..357b5b3f4386 100644
--- a/sys/contrib/openzfs/cmd/zfs/Makefile.am
+++ b/sys/contrib/openzfs/cmd/zfs/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
sbin_PROGRAMS += zfs
CPPCHECKTARGETS += zfs
diff --git a/sys/contrib/openzfs/cmd/zfs/zfs_main.c b/sys/contrib/openzfs/cmd/zfs/zfs_main.c
index d39b6fe5f76b..ce948951a028 100644
--- a/sys/contrib/openzfs/cmd/zfs/zfs_main.c
+++ b/sys/contrib/openzfs/cmd/zfs/zfs_main.c
@@ -6928,7 +6928,7 @@ holds_callback(zfs_handle_t *zhp, void *data)
if (cbp->cb_recursive) {
const char *snapname;
- char *delim = strchr(zname, '@');
+ const char *delim = strchr(zname, '@');
if (delim == NULL)
return (0);
diff --git a/sys/contrib/openzfs/cmd/zinject/Makefile.am b/sys/contrib/openzfs/cmd/zinject/Makefile.am
index c90f73fc0165..1467f57c7b59 100644
--- a/sys/contrib/openzfs/cmd/zinject/Makefile.am
+++ b/sys/contrib/openzfs/cmd/zinject/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
sbin_PROGRAMS += zinject
CPPCHECKTARGETS += zinject
diff --git a/sys/contrib/openzfs/cmd/zpool/Makefile.am b/sys/contrib/openzfs/cmd/zpool/Makefile.am
index 5bb6d8160b18..c7a11610ccb8 100644
--- a/sys/contrib/openzfs/cmd/zpool/Makefile.am
+++ b/sys/contrib/openzfs/cmd/zpool/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
zpool_CFLAGS = $(AM_CFLAGS)
zpool_CFLAGS += $(LIBBLKID_CFLAGS) $(LIBUUID_CFLAGS)
diff --git a/sys/contrib/openzfs/cmd/zpool_influxdb/Makefile.am b/sys/contrib/openzfs/cmd/zpool_influxdb/Makefile.am
index b237532ce24e..78be6e1c4b13 100644
--- a/sys/contrib/openzfs/cmd/zpool_influxdb/Makefile.am
+++ b/sys/contrib/openzfs/cmd/zpool_influxdb/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
zfsexec_PROGRAMS += zpool_influxdb
CPPCHECKTARGETS += zpool_influxdb
diff --git a/sys/contrib/openzfs/cmd/zstream/Makefile.am b/sys/contrib/openzfs/cmd/zstream/Makefile.am
index 80ef1ea7ca11..1ccf67a6ce89 100644
--- a/sys/contrib/openzfs/cmd/zstream/Makefile.am
+++ b/sys/contrib/openzfs/cmd/zstream/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
zstream_CPPFLAGS = $(AM_CPPFLAGS) $(LIBZPOOL_CPPFLAGS)
sbin_PROGRAMS += zstream
diff --git a/sys/contrib/openzfs/config/CppCheck.am b/sys/contrib/openzfs/config/CppCheck.am
index 89a067d814ff..53acfc72b307 100644
--- a/sys/contrib/openzfs/config/CppCheck.am
+++ b/sys/contrib/openzfs/config/CppCheck.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
#
# cppcheck for userspace – nodist_*_SOURCES are kernel code and cppcheck goes crazy on them.
#
diff --git a/sys/contrib/openzfs/config/Rules.am b/sys/contrib/openzfs/config/Rules.am
index deffa352ea24..166682925f60 100644
--- a/sys/contrib/openzfs/config/Rules.am
+++ b/sys/contrib/openzfs/config/Rules.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
#
# Default build rules for all user space components, every Makefile.am
# should include these rules and override or extend them as needed.
diff --git a/sys/contrib/openzfs/config/Shellcheck.am b/sys/contrib/openzfs/config/Shellcheck.am
index 87e6494056cf..52c3f82d3a41 100644
--- a/sys/contrib/openzfs/config/Shellcheck.am
+++ b/sys/contrib/openzfs/config/Shellcheck.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
# Global ShellCheck exclusions:
#
# ShellCheck can't follow non-constant source. Use a directive to specify location. [SC1090]
diff --git a/sys/contrib/openzfs/config/Substfiles.am b/sys/contrib/openzfs/config/Substfiles.am
index 2459637abe6e..1604022fb00d 100644
--- a/sys/contrib/openzfs/config/Substfiles.am
+++ b/sys/contrib/openzfs/config/Substfiles.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
subst_sed_cmd = \
-e 's|@abs_top_srcdir[@]|$(abs_top_srcdir)|g' \
-e 's|@bindir[@]|$(bindir)|g' \
diff --git a/sys/contrib/openzfs/config/always-arch.m4 b/sys/contrib/openzfs/config/always-arch.m4
index d73b878916cb..66578274a5dd 100644
--- a/sys/contrib/openzfs/config/always-arch.m4
+++ b/sys/contrib/openzfs/config/always-arch.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Set the target cpu architecture. This allows the
dnl # following syntax to be used in a Makefile.am.
diff --git a/sys/contrib/openzfs/config/always-compiler-options.m4 b/sys/contrib/openzfs/config/always-compiler-options.m4
index 0e96435e3713..1a74c68dfe25 100644
--- a/sys/contrib/openzfs/config/always-compiler-options.m4
+++ b/sys/contrib/openzfs/config/always-compiler-options.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Enabled -fsanitize=address if supported by $CC.
dnl #
diff --git a/sys/contrib/openzfs/config/always-cppcheck.m4 b/sys/contrib/openzfs/config/always-cppcheck.m4
index fa5a3398d923..311c43362e31 100644
--- a/sys/contrib/openzfs/config/always-cppcheck.m4
+++ b/sys/contrib/openzfs/config/always-cppcheck.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check if cppcheck is available.
dnl #
diff --git a/sys/contrib/openzfs/config/always-parallel.m4 b/sys/contrib/openzfs/config/always-parallel.m4
index c1f1ae78e7e7..ba989a8c27bd 100644
--- a/sys/contrib/openzfs/config/always-parallel.m4
+++ b/sys/contrib/openzfs/config/always-parallel.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check if GNU parallel is available.
dnl #
diff --git a/sys/contrib/openzfs/config/always-python.m4 b/sys/contrib/openzfs/config/always-python.m4
index 5a2008124f72..fb19b6bcc927 100644
--- a/sys/contrib/openzfs/config/always-python.m4
+++ b/sys/contrib/openzfs/config/always-python.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # The majority of the python scripts are written to be compatible
dnl # with Python 3.6. This option is intended to
diff --git a/sys/contrib/openzfs/config/always-pyzfs.m4 b/sys/contrib/openzfs/config/always-pyzfs.m4
index 98c1cc230205..d955e67217e9 100644
--- a/sys/contrib/openzfs/config/always-pyzfs.m4
+++ b/sys/contrib/openzfs/config/always-pyzfs.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # ZFS_AC_PYTHON_MODULE(module_name, [action-if-true], [action-if-false])
dnl #
diff --git a/sys/contrib/openzfs/config/always-sed.m4 b/sys/contrib/openzfs/config/always-sed.m4
index 3d7ae285ba1b..0799995584a3 100644
--- a/sys/contrib/openzfs/config/always-sed.m4
+++ b/sys/contrib/openzfs/config/always-sed.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Set the flags used for sed in-place edits.
dnl #
diff --git a/sys/contrib/openzfs/config/always-shellcheck.m4 b/sys/contrib/openzfs/config/always-shellcheck.m4
index 2a9a099746f4..e97117b642e3 100644
--- a/sys/contrib/openzfs/config/always-shellcheck.m4
+++ b/sys/contrib/openzfs/config/always-shellcheck.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check if shellcheck and/or checkbashisms are available.
dnl #
diff --git a/sys/contrib/openzfs/config/always-system.m4 b/sys/contrib/openzfs/config/always-system.m4
index 3a3d4212f8b0..102422d1edf2 100644
--- a/sys/contrib/openzfs/config/always-system.m4
+++ b/sys/contrib/openzfs/config/always-system.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Set the target system
dnl #
diff --git a/sys/contrib/openzfs/config/ax_compare_version.m4 b/sys/contrib/openzfs/config/ax_compare_version.m4
index ffb4997e8b14..b4ae8488d057 100644
--- a/sys/contrib/openzfs/config/ax_compare_version.m4
+++ b/sys/contrib/openzfs/config/ax_compare_version.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: FSFAP
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_compare_version.html
# ===========================================================================
diff --git a/sys/contrib/openzfs/config/ax_count_cpus.m4 b/sys/contrib/openzfs/config/ax_count_cpus.m4
index 5db892553437..118ae38cffeb 100644
--- a/sys/contrib/openzfs/config/ax_count_cpus.m4
+++ b/sys/contrib/openzfs/config/ax_count_cpus.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: FSFAP
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_count_cpus.html
# ===========================================================================
diff --git a/sys/contrib/openzfs/config/ax_python_devel.m4 b/sys/contrib/openzfs/config/ax_python_devel.m4
index 935056cc4c0a..d4183c9eced0 100644
--- a/sys/contrib/openzfs/config/ax_python_devel.m4
+++ b/sys/contrib/openzfs/config/ax_python_devel.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-3.0-or-later WITH Autoconf-exception-macro
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_python_devel.html
# ===========================================================================
diff --git a/sys/contrib/openzfs/config/ax_restore_flags.m4 b/sys/contrib/openzfs/config/ax_restore_flags.m4
index cf03cae79015..111d8327b9b2 100644
--- a/sys/contrib/openzfs/config/ax_restore_flags.m4
+++ b/sys/contrib/openzfs/config/ax_restore_flags.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: FSFAP
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_restore_flags.html
# ===========================================================================
diff --git a/sys/contrib/openzfs/config/ax_save_flags.m4 b/sys/contrib/openzfs/config/ax_save_flags.m4
index d2a054223b91..ec12eaeb4803 100644
--- a/sys/contrib/openzfs/config/ax_save_flags.m4
+++ b/sys/contrib/openzfs/config/ax_save_flags.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: FSFAP
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_save_flags.html
# ===========================================================================
diff --git a/sys/contrib/openzfs/config/deb.am b/sys/contrib/openzfs/config/deb.am
index 3e9a9379712e..1732ab22e070 100644
--- a/sys/contrib/openzfs/config/deb.am
+++ b/sys/contrib/openzfs/config/deb.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
PHONY += deb-kmod deb-dkms deb-utils deb deb-local native-deb-local \
native-deb-utils native-deb-kmod native-deb
@@ -93,17 +94,17 @@ debian:
cp -r contrib/debian debian; chmod +x debian/rules;
native-deb-utils: native-deb-local debian
- while [ -f debian/deb-build.lock ]; do sleep 1; done; \
- echo "native-deb-utils" > debian/deb-build.lock; \
- cp contrib/debian/control debian/control; \
- $(DPKGBUILD) -b -rfakeroot -us -uc; \
- $(RM) -f debian/deb-build.lock
+ while [ -f debian/deb-build.lock ]; do sleep 1; done && \
+ echo "native-deb-utils" > debian/deb-build.lock && \
+ trap '$(RM) -f debian/deb-build.lock' EXIT && \
+ cp contrib/debian/control debian/control && \
+ $(DPKGBUILD) -b -rfakeroot -us -uc
native-deb-kmod: native-deb-local debian
- while [ -f debian/deb-build.lock ]; do sleep 1; done; \
- echo "native-deb-kmod" > debian/deb-build.lock; \
- sh scripts/make_gitrev.sh; \
- fakeroot debian/rules override_dh_binary-modules; \
- $(RM) -f debian/deb-build.lock
+ while [ -f debian/deb-build.lock ]; do sleep 1; done && \
+ echo "native-deb-kmod" > debian/deb-build.lock && \
+ trap '$(RM) -f debian/deb-build.lock' EXIT && \
+ sh scripts/make_gitrev.sh && \
+ fakeroot debian/rules override_dh_binary-modules
native-deb: native-deb-utils native-deb-kmod
diff --git a/sys/contrib/openzfs/config/find_system_library.m4 b/sys/contrib/openzfs/config/find_system_library.m4
index 8b98bd67d2ee..0c985b9e7b61 100644
--- a/sys/contrib/openzfs/config/find_system_library.m4
+++ b/sys/contrib/openzfs/config/find_system_library.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
# find_system_lib.m4 - Macros to search for a system library. -*- Autoconf -*-
dnl requires pkg.m4 from pkg-config
diff --git a/sys/contrib/openzfs/config/gettext.m4 b/sys/contrib/openzfs/config/gettext.m4
index e7832418ea16..32b6eef31f5e 100644
--- a/sys/contrib/openzfs/config/gettext.m4
+++ b/sys/contrib/openzfs/config/gettext.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: FSFULLR
# gettext.m4 serial 70 (gettext-0.20)
dnl Copyright (C) 1995-2014, 2016, 2018 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
diff --git a/sys/contrib/openzfs/config/host-cpu-c-abi.m4 b/sys/contrib/openzfs/config/host-cpu-c-abi.m4
index 4407296d0849..915a72a20aba 100644
--- a/sys/contrib/openzfs/config/host-cpu-c-abi.m4
+++ b/sys/contrib/openzfs/config/host-cpu-c-abi.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: FSFULLR
# host-cpu-c-abi.m4 serial 11
dnl Copyright (C) 2002-2019 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
diff --git a/sys/contrib/openzfs/config/iconv.m4 b/sys/contrib/openzfs/config/iconv.m4
index 99b339a9f89e..2a4d45132d5e 100644
--- a/sys/contrib/openzfs/config/iconv.m4
+++ b/sys/contrib/openzfs/config/iconv.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: FSFULLR
# iconv.m4 serial 21
dnl Copyright (C) 2000-2002, 2007-2014, 2016-2019 Free Software Foundation,
dnl Inc.
diff --git a/sys/contrib/openzfs/config/kernel-access-ok-type.m4 b/sys/contrib/openzfs/config/kernel-access-ok-type.m4
index dc9433458703..34dd99f76b05 100644
--- a/sys/contrib/openzfs/config/kernel-access-ok-type.m4
+++ b/sys/contrib/openzfs/config/kernel-access-ok-type.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 5.0: access_ok() drops 'type' parameter:
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-acl.m4 b/sys/contrib/openzfs/config/kernel-acl.m4
index 3dbd97948189..9350a4c5f00e 100644
--- a/sys/contrib/openzfs/config/kernel-acl.m4
+++ b/sys/contrib/openzfs/config/kernel-acl.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 3.1 API change,
dnl # posix_acl_equiv_mode now wants an umode_t instead of a mode_t
@@ -22,6 +23,35 @@ AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T], [
])
dnl #
+dnl # 7.0 API change
+dnl # posix_acl_to_xattr() now allocates and returns the value.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_POSIX_ACL_TO_XATTR_ALLOC], [
+ ZFS_LINUX_TEST_SRC([posix_acl_to_xattr_alloc], [
+ #include <linux/fs.h>
+ #include <linux/posix_acl_xattr.h>
+ ], [
+ struct user_namespace *ns = NULL;
+ struct posix_acl *acl = NULL;
+ size_t size = 0;
+ gfp_t gfp = 0;
+ void *xattr = NULL;
+ xattr = posix_acl_to_xattr(ns, acl, &size, gfp);
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_POSIX_ACL_TO_XATTR_ALLOC], [
+ AC_MSG_CHECKING([whether posix_acl_to_xattr() allocates its result]);
+ ZFS_LINUX_TEST_RESULT([posix_acl_to_xattr_alloc], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_POSIX_ACL_TO_XATTR_ALLOC, 1,
+ [posix_acl_to_xattr() allocates its result])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+])
+
+dnl #
dnl # 3.1 API change,
dnl # Check if inode_operations contains the function get_acl
dnl #
@@ -173,12 +203,14 @@ AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL], [
AC_DEFUN([ZFS_AC_KERNEL_SRC_ACL], [
ZFS_AC_KERNEL_SRC_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T
+ ZFS_AC_KERNEL_SRC_POSIX_ACL_TO_XATTR_ALLOC
ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_GET_ACL
ZFS_AC_KERNEL_SRC_INODE_OPERATIONS_SET_ACL
])
AC_DEFUN([ZFS_AC_KERNEL_ACL], [
ZFS_AC_KERNEL_POSIX_ACL_EQUIV_MODE_WANTS_UMODE_T
+ ZFS_AC_KERNEL_POSIX_ACL_TO_XATTR_ALLOC
ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL
ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL
])
diff --git a/sys/contrib/openzfs/config/kernel-add-disk.m4 b/sys/contrib/openzfs/config/kernel-add-disk.m4
index 86d81ea325b9..059291ded6a0 100644
--- a/sys/contrib/openzfs/config/kernel-add-disk.m4
+++ b/sys/contrib/openzfs/config/kernel-add-disk.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 5.16 API change
dnl # add_disk grew a must-check return code
diff --git a/sys/contrib/openzfs/config/kernel-assign_str.m4 b/sys/contrib/openzfs/config/kernel-assign_str.m4
index cf4b00e7cbf2..1ddc6571fe8d 100644
--- a/sys/contrib/openzfs/config/kernel-assign_str.m4
+++ b/sys/contrib/openzfs/config/kernel-assign_str.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 6.10 kernel, check number of args of __assign_str() for trace:
dnl
diff --git a/sys/contrib/openzfs/config/kernel-automount.m4 b/sys/contrib/openzfs/config/kernel-automount.m4
index b5f1392d0fcd..a5b5fcacfcbf 100644
--- a/sys/contrib/openzfs/config/kernel-automount.m4
+++ b/sys/contrib/openzfs/config/kernel-automount.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.37 API change
dnl # The dops->d_automount() dentry operation was added as a clean
diff --git a/sys/contrib/openzfs/config/kernel-bio.m4 b/sys/contrib/openzfs/config/kernel-bio.m4
index 8afc9c59ddad..099b11effa13 100644
--- a/sys/contrib/openzfs/config/kernel-bio.m4
+++ b/sys/contrib/openzfs/config/kernel-bio.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 4.8 API,
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-bio_max_segs.m4 b/sys/contrib/openzfs/config/kernel-bio_max_segs.m4
index a90d75455c13..4d495ec714ed 100644
--- a/sys/contrib/openzfs/config/kernel-bio_max_segs.m4
+++ b/sys/contrib/openzfs/config/kernel-bio_max_segs.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 5.12 API change removes BIO_MAX_PAGES in favor of bio_max_segs()
dnl # which will handle the logic of setting the upper-bound to a
diff --git a/sys/contrib/openzfs/config/kernel-blk-queue.m4 b/sys/contrib/openzfs/config/kernel-blk-queue.m4
index cd2b143e89a0..9647f9d36dd4 100644
--- a/sys/contrib/openzfs/config/kernel-blk-queue.m4
+++ b/sys/contrib/openzfs/config/kernel-blk-queue.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.39 API change,
dnl # blk_start_plug() and blk_finish_plug()
@@ -226,6 +227,30 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_MAX_HW_SECTORS], [
])
dnl #
+dnl # 7.0 API change
+dnl # blk_queue_rot() replaces blk_queue_nonrot() (inverted meaning)
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE_ROT], [
+ ZFS_LINUX_TEST_SRC([blk_queue_rot], [
+ #include <linux/blkdev.h>
+ ], [
+ struct request_queue *q __attribute__ ((unused)) = NULL;
+ (void) blk_queue_rot(q);
+ ], [])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE_ROT], [
+ AC_MSG_CHECKING([whether blk_queue_rot() is available])
+ ZFS_LINUX_TEST_RESULT([blk_queue_rot], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_BLK_QUEUE_ROT, 1,
+ [blk_queue_rot() is available])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
+
+dnl #
dnl # 2.6.34 API change
dnl # blk_queue_max_segments() consolidates blk_queue_max_hw_segments()
dnl # and blk_queue_max_phys_segments().
@@ -278,6 +303,7 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_QUEUE], [
ZFS_AC_KERNEL_SRC_BLK_QUEUE_SECURE_ERASE
ZFS_AC_KERNEL_SRC_BLK_QUEUE_MAX_HW_SECTORS
ZFS_AC_KERNEL_SRC_BLK_QUEUE_MAX_SEGMENTS
+ ZFS_AC_KERNEL_SRC_BLK_QUEUE_ROT
ZFS_AC_KERNEL_SRC_BLK_MQ_RQ_HCTX
])
@@ -290,5 +316,6 @@ AC_DEFUN([ZFS_AC_KERNEL_BLK_QUEUE], [
ZFS_AC_KERNEL_BLK_QUEUE_SECURE_ERASE
ZFS_AC_KERNEL_BLK_QUEUE_MAX_HW_SECTORS
ZFS_AC_KERNEL_BLK_QUEUE_MAX_SEGMENTS
+ ZFS_AC_KERNEL_BLK_QUEUE_ROT
ZFS_AC_KERNEL_BLK_MQ_RQ_HCTX
])
diff --git a/sys/contrib/openzfs/config/kernel-blkdev.m4 b/sys/contrib/openzfs/config/kernel-blkdev.m4
index 02011bf39fb2..19275447ebb7 100644
--- a/sys/contrib/openzfs/config/kernel-blkdev.m4
+++ b/sys/contrib/openzfs/config/kernel-blkdev.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.38 API change,
dnl # Added blkdev_get_by_path()
diff --git a/sys/contrib/openzfs/config/kernel-block-device-operations.m4 b/sys/contrib/openzfs/config/kernel-block-device-operations.m4
index 1905340a9c7d..dc7249c2943b 100644
--- a/sys/contrib/openzfs/config/kernel-block-device-operations.m4
+++ b/sys/contrib/openzfs/config/kernel-block-device-operations.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.38 API change
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-commit-metadata.m4 b/sys/contrib/openzfs/config/kernel-commit-metadata.m4
index 49bffbf609d2..1ebf3ab2ffae 100644
--- a/sys/contrib/openzfs/config/kernel-commit-metadata.m4
+++ b/sys/contrib/openzfs/config/kernel-commit-metadata.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.33 API change
dnl # Added eops->commit_metadata() callback to allow the underlying
diff --git a/sys/contrib/openzfs/config/kernel-config-defined.m4 b/sys/contrib/openzfs/config/kernel-config-defined.m4
index 83c40fa6cd8e..e30fd5c17288 100644
--- a/sys/contrib/openzfs/config/kernel-config-defined.m4
+++ b/sys/contrib/openzfs/config/kernel-config-defined.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Certain kernel build options are not supported. These must be
dnl # detected at configure time and cause a build failure. Otherwise
diff --git a/sys/contrib/openzfs/config/kernel-copy-from-user-inatomic.m4 b/sys/contrib/openzfs/config/kernel-copy-from-user-inatomic.m4
deleted file mode 100644
index fec354b2f38e..000000000000
--- a/sys/contrib/openzfs/config/kernel-copy-from-user-inatomic.m4
+++ /dev/null
@@ -1,29 +0,0 @@
-dnl #
-dnl # On certain architectures `__copy_from_user_inatomic`
-dnl # is a GPL exported variable and cannot be used by OpenZFS.
-dnl #
-
-dnl #
-dnl # Checking if `__copy_from_user_inatomic` is available.
-dnl #
-AC_DEFUN([ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC], [
- ZFS_LINUX_TEST_SRC([__copy_from_user_inatomic], [
- #include <linux/uaccess.h>
- ], [
- int result __attribute__ ((unused)) = __copy_from_user_inatomic(NULL, NULL, 0);
- ], [], [ZFS_META_LICENSE])
-])
-
-AC_DEFUN([ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC], [
- AC_MSG_CHECKING([whether __copy_from_user_inatomic is available])
- ZFS_LINUX_TEST_RESULT([__copy_from_user_inatomic_license], [
- AC_MSG_RESULT(yes)
- ], [
- AC_MSG_RESULT(no)
- AC_MSG_ERROR([
- *** The `__copy_from_user_inatomic()` Linux kernel function is
- *** incompatible with the CDDL license and will prevent the module
- *** linking stage from succeeding. OpenZFS cannot be compiled.
- ])
- ])
-])
diff --git a/sys/contrib/openzfs/config/kernel-cpu_has_feature.m4 b/sys/contrib/openzfs/config/kernel-cpu_has_feature.m4
index 608faf0f89fe..a862a06ada6c 100644
--- a/sys/contrib/openzfs/config/kernel-cpu_has_feature.m4
+++ b/sys/contrib/openzfs/config/kernel-cpu_has_feature.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # cpu_has_feature() may referencing GPL-only cpu_feature_keys on powerpc
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-declare-event-class.m4 b/sys/contrib/openzfs/config/kernel-declare-event-class.m4
index 6c78ee858d7d..519d8ee4c954 100644
--- a/sys/contrib/openzfs/config/kernel-declare-event-class.m4
+++ b/sys/contrib/openzfs/config/kernel-declare-event-class.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Ensure the DECLARE_EVENT_CLASS macro is available to non-GPL modules.
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-dentry-alias.m4 b/sys/contrib/openzfs/config/kernel-dentry-alias.m4
new file mode 100644
index 000000000000..0baf1a06d3ce
--- /dev/null
+++ b/sys/contrib/openzfs/config/kernel-dentry-alias.m4
@@ -0,0 +1,32 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
+dnl #
+dnl # 7.1 API change
+dnl # d_u union in struct dentry is now anonmymous, so d_alias must be
+dnl # named directly
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_DENTRY_ALIAS_D_U], [
+ ZFS_LINUX_TEST_SRC([dentry_alias_d_u], [
+ #include <linux/fs.h>
+ #include <linux/dcache.h>
+ #include <linux/list.h>
+ ], [
+ struct inode *inode __attribute__ ((unused)) = NULL;
+ struct dentry *dentry __attribute__ ((unused)) = NULL;
+ hlist_for_each_entry(dentry, &inode->i_dentry,
+ d_u.d_alias) {
+ d_drop(dentry);
+ }
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_DENTRY_ALIAS_D_U], [
+ AC_MSG_CHECKING([whether dentry aliases are in d_u member])
+ ZFS_LINUX_TEST_RESULT([dentry_alias_d_u], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_DENTRY_D_U_ALIASES, 1,
+ [dentry aliases are in d_u member])
+ ],[
+ AC_MSG_RESULT(no)
+ ])
+])
+
diff --git a/sys/contrib/openzfs/config/kernel-dentry-operations.m4 b/sys/contrib/openzfs/config/kernel-dentry-operations.m4
index ce0e6e5be959..c093aad60058 100644
--- a/sys/contrib/openzfs/config/kernel-dentry-operations.m4
+++ b/sys/contrib/openzfs/config/kernel-dentry-operations.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.28 API change
dnl # Added d_obtain_alias() helper function.
diff --git a/sys/contrib/openzfs/config/kernel-discard-granularity.m4 b/sys/contrib/openzfs/config/kernel-discard-granularity.m4
index 61326e67732b..0eeaa57145c3 100644
--- a/sys/contrib/openzfs/config/kernel-discard-granularity.m4
+++ b/sys/contrib/openzfs/config/kernel-discard-granularity.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.33 API change
dnl # Discard granularity and alignment restrictions may now be set.
diff --git a/sys/contrib/openzfs/config/kernel-drop-inode.m4 b/sys/contrib/openzfs/config/kernel-drop-inode.m4
index 6f2b12cadc02..e3a74022fb65 100644
--- a/sys/contrib/openzfs/config/kernel-drop-inode.m4
+++ b/sys/contrib/openzfs/config/kernel-drop-inode.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 6.18 API change
dnl # - generic_drop_inode() renamed to inode_generic_drop()
diff --git a/sys/contrib/openzfs/config/kernel-file.m4 b/sys/contrib/openzfs/config/kernel-file.m4
index 31252544c745..41ee89020d64 100644
--- a/sys/contrib/openzfs/config/kernel-file.m4
+++ b/sys/contrib/openzfs/config/kernel-file.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 6.12 removed f_version from struct file
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-filelock.m4 b/sys/contrib/openzfs/config/kernel-filelock.m4
new file mode 100644
index 000000000000..5e8d7c784692
--- /dev/null
+++ b/sys/contrib/openzfs/config/kernel-filelock.m4
@@ -0,0 +1,23 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
+dnl #
+dnl # 6.3 API change
+dnl # locking support functions (eg generic_setlease) were moved out of
+dnl # linux/fs.h to linux/filelock.h
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_FILELOCK_HEADER], [
+ ZFS_LINUX_TEST_SRC([filelock_header], [
+ #include <linux/fs.h>
+ #include <linux/filelock.h>
+ ], [])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_FILELOCK_HEADER], [
+ AC_MSG_CHECKING([for standalone filelock header])
+ ZFS_LINUX_TEST_RESULT([filelock_header], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_FILELOCK_HEADER, 1, [linux/filelock.h exists])
+ ], [
+ AC_MSG_RESULT(no)
+ ])
+])
+
diff --git a/sys/contrib/openzfs/config/kernel-filemap-splice-read.m4 b/sys/contrib/openzfs/config/kernel-filemap-splice-read.m4
index 4c83b31d738a..b78f1048bd32 100644
--- a/sys/contrib/openzfs/config/kernel-filemap-splice-read.m4
+++ b/sys/contrib/openzfs/config/kernel-filemap-splice-read.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_COPY_SPLICE_READ], [
dnl #
dnl # Kernel 6.5 - generic_file_splice_read was removed in favor
diff --git a/sys/contrib/openzfs/config/kernel-flush_dcache_page.m4 b/sys/contrib/openzfs/config/kernel-flush_dcache_page.m4
index aa916c87d531..63c67eebcebc 100644
--- a/sys/contrib/openzfs/config/kernel-flush_dcache_page.m4
+++ b/sys/contrib/openzfs/config/kernel-flush_dcache_page.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Starting from Linux 5.13, flush_dcache_page() becomes an inline
dnl # function and may indirectly referencing GPL-only symbols:
diff --git a/sys/contrib/openzfs/config/kernel-fmode-t.m4 b/sys/contrib/openzfs/config/kernel-fmode-t.m4
index 5f111e21b443..292f79b9647a 100644
--- a/sys/contrib/openzfs/config/kernel-fmode-t.m4
+++ b/sys/contrib/openzfs/config/kernel-fmode-t.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.28 API change,
dnl # check if fmode_t typedef is defined
diff --git a/sys/contrib/openzfs/config/kernel-follow-down-one.m4 b/sys/contrib/openzfs/config/kernel-follow-down-one.m4
index 38c460d3506e..c4f7b99cebfd 100644
--- a/sys/contrib/openzfs/config/kernel-follow-down-one.m4
+++ b/sys/contrib/openzfs/config/kernel-follow-down-one.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.38 API change
dnl # follow_down() renamed follow_down_one(). The original follow_down()
diff --git a/sys/contrib/openzfs/config/kernel-fpu.m4 b/sys/contrib/openzfs/config/kernel-fpu.m4
index edfde1a02d30..07f9e49ac3d1 100644
--- a/sys/contrib/openzfs/config/kernel-fpu.m4
+++ b/sys/contrib/openzfs/config/kernel-fpu.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Handle differences in kernel FPU code.
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-free-inode.m4 b/sys/contrib/openzfs/config/kernel-free-inode.m4
index baa1c34845bb..e316f1a7f8d8 100644
--- a/sys/contrib/openzfs/config/kernel-free-inode.m4
+++ b/sys/contrib/openzfs/config/kernel-free-inode.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 5.2 API change
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-fs-context.m4 b/sys/contrib/openzfs/config/kernel-fs-context.m4
new file mode 100644
index 000000000000..317ddc21273d
--- /dev/null
+++ b/sys/contrib/openzfs/config/kernel-fs-context.m4
@@ -0,0 +1,36 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
+dnl #
+dnl # 2.6.38 API change
+dnl # The .get_sb callback has been replaced by a .mount callback
+dnl # in the file_system_type structure.
+dnl #
+dnl # 5.2 API change
+dnl # The new fs_context-based filesystem API is introduced, with the old
+dnl # one (via file_system_type.mount) preserved as a compatibility shim.
+dnl #
+dnl # 7.0 API change
+dnl # Compatibility shim removed, so all callers must go through the mount API.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_SRC_FS_CONTEXT], [
+ ZFS_LINUX_TEST_SRC([fs_context], [
+ #include <linux/fs.h>
+ #include <linux/fs_context.h>
+ ],[
+ static struct fs_context fs __attribute__ ((unused)) = { 0 };
+ static struct fs_context *fsp __attribute__ ((unused));
+ fsp = vfs_dup_fs_context(&fs);
+ ])
+])
+
+AC_DEFUN([ZFS_AC_KERNEL_FS_CONTEXT], [
+ AC_MSG_CHECKING([whether fs_context exists])
+ ZFS_LINUX_TEST_RESULT([fs_context], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_FS_CONTEXT, 1, [fs_context exists])
+ ],[
+ AC_MSG_RESULT(no)
+ AC_MSG_ERROR([
+ *** This kernel does not have `struct fs_context`. OpenZFS cannot be compiled.
+ ])
+ ])
+])
diff --git a/sys/contrib/openzfs/config/kernel-fst-mount.m4 b/sys/contrib/openzfs/config/kernel-fst-mount.m4
deleted file mode 100644
index 576f5f0129c5..000000000000
--- a/sys/contrib/openzfs/config/kernel-fst-mount.m4
+++ /dev/null
@@ -1,30 +0,0 @@
-dnl #
-dnl # 2.6.38 API change
-dnl # The .get_sb callback has been replaced by a .mount callback
-dnl # in the file_system_type structure.
-dnl #
-AC_DEFUN([ZFS_AC_KERNEL_SRC_FST_MOUNT], [
- ZFS_LINUX_TEST_SRC([file_system_type_mount], [
- #include <linux/fs.h>
-
- static struct dentry *
- mount(struct file_system_type *fs_type, int flags,
- const char *osname, void *data) {
- struct dentry *d = NULL;
- return (d);
- }
-
- static struct file_system_type fst __attribute__ ((unused)) = {
- .mount = mount,
- };
- ],[])
-])
-
-AC_DEFUN([ZFS_AC_KERNEL_FST_MOUNT], [
- AC_MSG_CHECKING([whether fst->mount() exists])
- ZFS_LINUX_TEST_RESULT([file_system_type_mount], [
- AC_MSG_RESULT(yes)
- ],[
- ZFS_LINUX_TEST_ERROR([fst->mount()])
- ])
-])
diff --git a/sys/contrib/openzfs/config/kernel-fsync-bdev.m4 b/sys/contrib/openzfs/config/kernel-fsync-bdev.m4
index c47e236f705f..b75ebbd873a9 100644
--- a/sys/contrib/openzfs/config/kernel-fsync-bdev.m4
+++ b/sys/contrib/openzfs/config/kernel-fsync-bdev.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 6.6 API change,
dnl # fsync_bdev was removed in favor of sync_blockdev
diff --git a/sys/contrib/openzfs/config/kernel-generic_fadvise.m4 b/sys/contrib/openzfs/config/kernel-generic_fadvise.m4
index 8d122064b229..12b9a78d16b2 100644
--- a/sys/contrib/openzfs/config/kernel-generic_fadvise.m4
+++ b/sys/contrib/openzfs/config/kernel-generic_fadvise.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 5.3 API change
dnl # The generic_fadvise() function is present since 4.19 kernel
diff --git a/sys/contrib/openzfs/config/kernel-generic_fillattr.m4 b/sys/contrib/openzfs/config/kernel-generic_fillattr.m4
index d355f9006bd3..768ee8aaa7cb 100644
--- a/sys/contrib/openzfs/config/kernel-generic_fillattr.m4
+++ b/sys/contrib/openzfs/config/kernel-generic_fillattr.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 5.12 API
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-generic_io_acct.m4 b/sys/contrib/openzfs/config/kernel-generic_io_acct.m4
index da92aad058cb..f2b61cc089ea 100644
--- a/sys/contrib/openzfs/config/kernel-generic_io_acct.m4
+++ b/sys/contrib/openzfs/config/kernel-generic_io_acct.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check for generic io accounting interface.
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-genhd-flags.m4 b/sys/contrib/openzfs/config/kernel-genhd-flags.m4
index 60cc3173397c..69d9798bd549 100644
--- a/sys/contrib/openzfs/config/kernel-genhd-flags.m4
+++ b/sys/contrib/openzfs/config/kernel-genhd-flags.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 5.17 API change,
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-get-disk-ro.m4 b/sys/contrib/openzfs/config/kernel-get-disk-ro.m4
index acfcb69acc10..f89c8efbc12e 100644
--- a/sys/contrib/openzfs/config/kernel-get-disk-ro.m4
+++ b/sys/contrib/openzfs/config/kernel-get-disk-ro.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.x API change
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-iattr-vfsid.m4 b/sys/contrib/openzfs/config/kernel-iattr-vfsid.m4
index 75bc4613b838..4558071228a2 100644
--- a/sys/contrib/openzfs/config/kernel-iattr-vfsid.m4
+++ b/sys/contrib/openzfs/config/kernel-iattr-vfsid.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 6.0 API change
dnl # struct iattr has two unions for the uid and gid
diff --git a/sys/contrib/openzfs/config/kernel-idmap_mnt_api.m4 b/sys/contrib/openzfs/config/kernel-idmap_mnt_api.m4
index d1bdd053203e..e362918b9a89 100644
--- a/sys/contrib/openzfs/config/kernel-idmap_mnt_api.m4
+++ b/sys/contrib/openzfs/config/kernel-idmap_mnt_api.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 5.12 API
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-inode-create.m4 b/sys/contrib/openzfs/config/kernel-inode-create.m4
index 95f8aa2d5220..65817ca9a440 100644
--- a/sys/contrib/openzfs/config/kernel-inode-create.m4
+++ b/sys/contrib/openzfs/config/kernel-inode-create.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE], [
dnl #
dnl # 6.3 API change
diff --git a/sys/contrib/openzfs/config/kernel-inode-getattr.m4 b/sys/contrib/openzfs/config/kernel-inode-getattr.m4
index 73b8213109fb..6d5703386e58 100644
--- a/sys/contrib/openzfs/config/kernel-inode-getattr.m4
+++ b/sys/contrib/openzfs/config/kernel-inode-getattr.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [
dnl #
dnl # Linux 6.3 API
diff --git a/sys/contrib/openzfs/config/kernel-inode-lookup.m4 b/sys/contrib/openzfs/config/kernel-inode-lookup.m4
index c7373056422c..e3b35417425f 100644
--- a/sys/contrib/openzfs/config/kernel-inode-lookup.m4
+++ b/sys/contrib/openzfs/config/kernel-inode-lookup.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 3.6 API change
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-inode-permission.m4 b/sys/contrib/openzfs/config/kernel-inode-permission.m4
index 286f73bb047e..91ab3fbe635e 100644
--- a/sys/contrib/openzfs/config/kernel-inode-permission.m4
+++ b/sys/contrib/openzfs/config/kernel-inode-permission.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_PERMISSION], [
dnl #
dnl # 6.3 API change
diff --git a/sys/contrib/openzfs/config/kernel-inode-setattr.m4 b/sys/contrib/openzfs/config/kernel-inode-setattr.m4
index 9a12acc95a3f..831cc126655b 100644
--- a/sys/contrib/openzfs/config/kernel-inode-setattr.m4
+++ b/sys/contrib/openzfs/config/kernel-inode-setattr.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_SETATTR], [
dnl #
dnl # Linux 6.3 API
diff --git a/sys/contrib/openzfs/config/kernel-inode-state.m4 b/sys/contrib/openzfs/config/kernel-inode-state.m4
index 02ec1380af53..2278f85f7d96 100644
--- a/sys/contrib/openzfs/config/kernel-inode-state.m4
+++ b/sys/contrib/openzfs/config/kernel-inode-state.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 6.19 API change. inode->i_state no longer accessible directly; helper
dnl # functions exist.
diff --git a/sys/contrib/openzfs/config/kernel-inode-times.m4 b/sys/contrib/openzfs/config/kernel-inode-times.m4
index 59988e937929..0c933a1c421e 100644
--- a/sys/contrib/openzfs/config/kernel-inode-times.m4
+++ b/sys/contrib/openzfs/config/kernel-inode-times.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_TIMES], [
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-insert-inode-locked.m4 b/sys/contrib/openzfs/config/kernel-insert-inode-locked.m4
index 348aff9a5770..5774fe3d3621 100644
--- a/sys/contrib/openzfs/config/kernel-insert-inode-locked.m4
+++ b/sys/contrib/openzfs/config/kernel-insert-inode-locked.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.28 API change
dnl # Added insert_inode_locked() helper function.
diff --git a/sys/contrib/openzfs/config/kernel-is_owner_or_cap.m4 b/sys/contrib/openzfs/config/kernel-is_owner_or_cap.m4
index 4e9c002b77f2..6f670e675c6e 100644
--- a/sys/contrib/openzfs/config/kernel-is_owner_or_cap.m4
+++ b/sys/contrib/openzfs/config/kernel-is_owner_or_cap.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.39 API change,
dnl # The is_owner_or_cap() macro was renamed to inode_owner_or_capable(),
diff --git a/sys/contrib/openzfs/config/kernel-kasan-enabled.m4 b/sys/contrib/openzfs/config/kernel-kasan-enabled.m4
index 71b2419995b6..95a8d29b3814 100644
--- a/sys/contrib/openzfs/config/kernel-kasan-enabled.m4
+++ b/sys/contrib/openzfs/config/kernel-kasan-enabled.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 6.18: some architectures and config option causes the kasan_ inline
dnl # functions to reference the GPL-only symbol 'kasan_flag_enabled',
diff --git a/sys/contrib/openzfs/config/kernel-kmap-atomic-args.m4 b/sys/contrib/openzfs/config/kernel-kmap-atomic-args.m4
index cedadf3b3d8b..5352a14c3f17 100644
--- a/sys/contrib/openzfs/config/kernel-kmap-atomic-args.m4
+++ b/sys/contrib/openzfs/config/kernel-kmap-atomic-args.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.37 API change
dnl # kmap_atomic changed from assigning hard-coded named slot to using
diff --git a/sys/contrib/openzfs/config/kernel-kmap-local-page.m4 b/sys/contrib/openzfs/config/kernel-kmap-local-page.m4
index 1990914d493d..207900c095db 100644
--- a/sys/contrib/openzfs/config/kernel-kmap-local-page.m4
+++ b/sys/contrib/openzfs/config/kernel-kmap-local-page.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 5.11 API change
dnl # kmap_atomic() was deprecated in favor of kmap_local_page()
diff --git a/sys/contrib/openzfs/config/kernel-kmem.m4 b/sys/contrib/openzfs/config/kernel-kmem.m4
index f1c0d24125ce..ff42a47def7f 100644
--- a/sys/contrib/openzfs/config/kernel-kmem.m4
+++ b/sys/contrib/openzfs/config/kernel-kmem.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Enabled by default it provides a minimal level of memory tracking.
dnl # A total count of bytes allocated is kept for each alloc and free.
diff --git a/sys/contrib/openzfs/config/kernel-kthread.m4 b/sys/contrib/openzfs/config/kernel-kthread.m4
index 607953146323..469ec6d500df 100644
--- a/sys/contrib/openzfs/config/kernel-kthread.m4
+++ b/sys/contrib/openzfs/config/kernel-kthread.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_KTHREAD_COMPLETE_AND_EXIT], [
dnl #
dnl # 5.17 API,
diff --git a/sys/contrib/openzfs/config/kernel-kuid-helpers.m4 b/sys/contrib/openzfs/config/kernel-kuid-helpers.m4
index 38a439fa6ea9..485669943d2a 100644
--- a/sys/contrib/openzfs/config/kernel-kuid-helpers.m4
+++ b/sys/contrib/openzfs/config/kernel-kuid-helpers.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 3.5 API change,
dnl # Since usernamespaces were introduced in kernel version 3.5, it
diff --git a/sys/contrib/openzfs/config/kernel-kuidgid.m4 b/sys/contrib/openzfs/config/kernel-kuidgid.m4
index b7e441408cb9..e3b35600b554 100644
--- a/sys/contrib/openzfs/config/kernel-kuidgid.m4
+++ b/sys/contrib/openzfs/config/kernel-kuidgid.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 3.8 API change,
dnl # User namespaces, use kuid_t in place of uid_t where available.
diff --git a/sys/contrib/openzfs/config/kernel-make-request-fn.m4 b/sys/contrib/openzfs/config/kernel-make-request-fn.m4
index 66d6a18cd976..7c247829da5a 100644
--- a/sys/contrib/openzfs/config/kernel-make-request-fn.m4
+++ b/sys/contrib/openzfs/config/kernel-make-request-fn.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check for make_request_fn interface.
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-misc-minor.m4 b/sys/contrib/openzfs/config/kernel-misc-minor.m4
index 20fe2cd2f3cd..b972f1ab6762 100644
--- a/sys/contrib/openzfs/config/kernel-misc-minor.m4
+++ b/sys/contrib/openzfs/config/kernel-misc-minor.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Determine an available miscellaneous minor number which can be used
dnl # for the /dev/zfs device. This is needed because kernel module
diff --git a/sys/contrib/openzfs/config/kernel-mkdir.m4 b/sys/contrib/openzfs/config/kernel-mkdir.m4
index 78b32447c593..6f13aefa6c2d 100644
--- a/sys/contrib/openzfs/config/kernel-mkdir.m4
+++ b/sys/contrib/openzfs/config/kernel-mkdir.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Supported mkdir() interfaces checked newest to oldest.
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-mknod.m4 b/sys/contrib/openzfs/config/kernel-mknod.m4
index 6ad3453aaf0a..93b95ea74cd5 100644
--- a/sys/contrib/openzfs/config/kernel-mknod.m4
+++ b/sys/contrib/openzfs/config/kernel-mknod.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_MKNOD], [
dnl #
dnl # 6.3 API change
diff --git a/sys/contrib/openzfs/config/kernel-mm-page-flags.m4 b/sys/contrib/openzfs/config/kernel-mm-page-flags.m4
index d63e8a0060ea..1c7397d19256 100644
--- a/sys/contrib/openzfs/config/kernel-mm-page-flags.m4
+++ b/sys/contrib/openzfs/config/kernel-mm-page-flags.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_MM_PAGE_FLAG_ERROR], [
ZFS_LINUX_TEST_SRC([mm_page_flag_error], [
#include <linux/page-flags.h>
diff --git a/sys/contrib/openzfs/config/kernel-mm-pagemap.m4 b/sys/contrib/openzfs/config/kernel-mm-pagemap.m4
index def6f5f4b3aa..672a31863684 100644
--- a/sys/contrib/openzfs/config/kernel-mm-pagemap.m4
+++ b/sys/contrib/openzfs/config/kernel-mm-pagemap.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_MM_PAGE_SIZE], [
ZFS_LINUX_TEST_SRC([page_size], [
#include <linux/mm.h>
diff --git a/sys/contrib/openzfs/config/kernel-namespace.m4 b/sys/contrib/openzfs/config/kernel-namespace.m4
index 9b0b12e4eab4..f97da8fe48aa 100644
--- a/sys/contrib/openzfs/config/kernel-namespace.m4
+++ b/sys/contrib/openzfs/config/kernel-namespace.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 6.18 API change
dnl # ns->ops->type was moved to ns->ns.ns_type (struct ns_common)
diff --git a/sys/contrib/openzfs/config/kernel-objtool.m4 b/sys/contrib/openzfs/config/kernel-objtool.m4
index 3020440eb388..95cd99c9e492 100644
--- a/sys/contrib/openzfs/config/kernel-objtool.m4
+++ b/sys/contrib/openzfs/config/kernel-objtool.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Detect objtool functionality.
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-pagemap-folio_wait_bit.m4 b/sys/contrib/openzfs/config/kernel-pagemap-folio_wait_bit.m4
index 12d8841f51e6..e263b9be85f8 100644
--- a/sys/contrib/openzfs/config/kernel-pagemap-folio_wait_bit.m4
+++ b/sys/contrib/openzfs/config/kernel-pagemap-folio_wait_bit.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 5.16 no longer allows directly calling wait_on_page_bit, and
dnl # instead requires you to call folio-specific functions. In this case,
diff --git a/sys/contrib/openzfs/config/kernel-pagemap-readahead-page.m4 b/sys/contrib/openzfs/config/kernel-pagemap-readahead-page.m4
index 30f3d56682fb..9a83d6c2650f 100644
--- a/sys/contrib/openzfs/config/kernel-pagemap-readahead-page.m4
+++ b/sys/contrib/openzfs/config/kernel-pagemap-readahead-page.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 6.16 removed readahead_page
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-pde-data.m4 b/sys/contrib/openzfs/config/kernel-pde-data.m4
index 4fc665dfbe2e..66d26a22e8c8 100644
--- a/sys/contrib/openzfs/config/kernel-pde-data.m4
+++ b/sys/contrib/openzfs/config/kernel-pde-data.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 5.17 API: PDE_DATA() renamed to pde_data(),
dnl # 359745d78351c6f5442435f81549f0207ece28aa ("proc: remove PDE_DATA() completely")
diff --git a/sys/contrib/openzfs/config/kernel-percpu.m4 b/sys/contrib/openzfs/config/kernel-percpu.m4
index 12e81892cb6b..14aa04698a49 100644
--- a/sys/contrib/openzfs/config/kernel-percpu.m4
+++ b/sys/contrib/openzfs/config/kernel-percpu.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 5.10 API change,
dnl # The "count" was moved into ref->data, from ref
diff --git a/sys/contrib/openzfs/config/kernel-pin-user-pages.m4 b/sys/contrib/openzfs/config/kernel-pin-user-pages.m4
index fe7aff375208..897c2cfaa1a6 100644
--- a/sys/contrib/openzfs/config/kernel-pin-user-pages.m4
+++ b/sys/contrib/openzfs/config/kernel-pin-user-pages.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check for pin_user_pages_unlocked().
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-proc-operations.m4 b/sys/contrib/openzfs/config/kernel-proc-operations.m4
index 3ae8ce2b6d0d..7546c8d20caf 100644
--- a/sys/contrib/openzfs/config/kernel-proc-operations.m4
+++ b/sys/contrib/openzfs/config/kernel-proc-operations.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 5.6 API Change
dnl # The proc_ops structure was introduced to replace the use of
diff --git a/sys/contrib/openzfs/config/kernel-reclaim_state.m4 b/sys/contrib/openzfs/config/kernel-reclaim_state.m4
index 9936b3c1001f..845789afa3b7 100644
--- a/sys/contrib/openzfs/config/kernel-reclaim_state.m4
+++ b/sys/contrib/openzfs/config/kernel-reclaim_state.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_RECLAIMED], [
dnl #
dnl # 6.4 API change
diff --git a/sys/contrib/openzfs/config/kernel-register_sysctl_table.m4 b/sys/contrib/openzfs/config/kernel-register_sysctl_table.m4
index 8dc17e2d42f9..0be45f436997 100644
--- a/sys/contrib/openzfs/config/kernel-register_sysctl_table.m4
+++ b/sys/contrib/openzfs/config/kernel-register_sysctl_table.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 6.5 removes register_sysctl_table
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-rename.m4 b/sys/contrib/openzfs/config/kernel-rename.m4
index 1c47222bdc30..2f00da3a0c5c 100644
--- a/sys/contrib/openzfs/config/kernel-rename.m4
+++ b/sys/contrib/openzfs/config/kernel-rename.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME], [
dnl #
dnl # 4.9 API change,
diff --git a/sys/contrib/openzfs/config/kernel-revalidate-disk-size.m4 b/sys/contrib/openzfs/config/kernel-revalidate-disk-size.m4
index 13cb92a174e3..835930590912 100644
--- a/sys/contrib/openzfs/config/kernel-revalidate-disk-size.m4
+++ b/sys/contrib/openzfs/config/kernel-revalidate-disk-size.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 5.11 API change
dnl # revalidate_disk_size() has been removed entirely.
diff --git a/sys/contrib/openzfs/config/kernel-sb-dying.m4 b/sys/contrib/openzfs/config/kernel-sb-dying.m4
index 882f3e542357..480d02d3047d 100644
--- a/sys/contrib/openzfs/config/kernel-sb-dying.m4
+++ b/sys/contrib/openzfs/config/kernel-sb-dying.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # SB_DYING exists since Linux 6.6
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-sb-wb-err.m4 b/sys/contrib/openzfs/config/kernel-sb-wb-err.m4
index 814d2ca5323b..61b3e954fdcf 100644
--- a/sys/contrib/openzfs/config/kernel-sb-wb-err.m4
+++ b/sys/contrib/openzfs/config/kernel-sb-wb-err.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
# dnl
# dnl 5.8 (735e4ae5ba28) introduced a superblock scoped errseq_t to use to
# dnl record writeback errors for syncfs() to return. Up until 5.17, when
diff --git a/sys/contrib/openzfs/config/kernel-sched.m4 b/sys/contrib/openzfs/config/kernel-sched.m4
index 8ef4cc6ee4cc..6015d0985aa1 100644
--- a/sys/contrib/openzfs/config/kernel-sched.m4
+++ b/sys/contrib/openzfs/config/kernel-sched.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 3.9 API change,
dnl # Moved things from linux/sched.h to linux/sched/rt.h
diff --git a/sys/contrib/openzfs/config/kernel-security-inode-init.m4 b/sys/contrib/openzfs/config/kernel-security-inode-init.m4
index 4e4bfd29b2ff..52df3c9ade45 100644
--- a/sys/contrib/openzfs/config/kernel-security-inode-init.m4
+++ b/sys/contrib/openzfs/config/kernel-security-inode-init.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 3.2 API change
dnl # The security_inode_init_security() API has been changed to include
diff --git a/sys/contrib/openzfs/config/kernel-set-nlink.m4 b/sys/contrib/openzfs/config/kernel-set-nlink.m4
index fa4f928b27d5..b7abcfdbbf79 100644
--- a/sys/contrib/openzfs/config/kernel-set-nlink.m4
+++ b/sys/contrib/openzfs/config/kernel-set-nlink.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 3.2 API change
dnl # set_nlink()
diff --git a/sys/contrib/openzfs/config/kernel-setattr-prepare.m4 b/sys/contrib/openzfs/config/kernel-setattr-prepare.m4
index b10ddafc054b..cc440b7d964b 100644
--- a/sys/contrib/openzfs/config/kernel-setattr-prepare.m4
+++ b/sys/contrib/openzfs/config/kernel-setattr-prepare.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_SETATTR_PREPARE], [
dnl #
dnl # 4.9 API change
diff --git a/sys/contrib/openzfs/config/kernel-sget-args.m4 b/sys/contrib/openzfs/config/kernel-sget-args.m4
index afa62c797d75..1c8a8d3291be 100644
--- a/sys/contrib/openzfs/config/kernel-sget-args.m4
+++ b/sys/contrib/openzfs/config/kernel-sget-args.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 3.6 API change,
dnl # 'sget' now takes the mount flags as an argument.
diff --git a/sys/contrib/openzfs/config/kernel-show-options.m4 b/sys/contrib/openzfs/config/kernel-show-options.m4
index fd62f30086dc..35e8e984b537 100644
--- a/sys/contrib/openzfs/config/kernel-show-options.m4
+++ b/sys/contrib/openzfs/config/kernel-show-options.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 3.3 API
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-shrink.m4 b/sys/contrib/openzfs/config/kernel-shrink.m4
index c4258f4e40d6..9a762177c668 100644
--- a/sys/contrib/openzfs/config/kernel-shrink.m4
+++ b/sys/contrib/openzfs/config/kernel-shrink.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 3.1 API change
dnl # The super_block structure now stores a per-filesystem shrinker.
diff --git a/sys/contrib/openzfs/config/kernel-siginfo.m4 b/sys/contrib/openzfs/config/kernel-siginfo.m4
index 6ddb0dcc37d2..85342cdf27e6 100644
--- a/sys/contrib/openzfs/config/kernel-siginfo.m4
+++ b/sys/contrib/openzfs/config/kernel-siginfo.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 4.20 API change
dnl # Added kernel_siginfo_t
diff --git a/sys/contrib/openzfs/config/kernel-stdarg.m4 b/sys/contrib/openzfs/config/kernel-stdarg.m4
index 5bc8dd859d6b..52986f5aa53f 100644
--- a/sys/contrib/openzfs/config/kernel-stdarg.m4
+++ b/sys/contrib/openzfs/config/kernel-stdarg.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 5.15 gets rid of -isystem and external <stdarg.h> inclusion
dnl # and ships its own <linux/stdarg.h>. Check if this header file does
diff --git a/sys/contrib/openzfs/config/kernel-strlcpy.m4 b/sys/contrib/openzfs/config/kernel-strlcpy.m4
index d50b0035e9d9..31e53175d29c 100644
--- a/sys/contrib/openzfs/config/kernel-strlcpy.m4
+++ b/sys/contrib/openzfs/config/kernel-strlcpy.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 6.8 removed strlcpy.
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-symlink.m4 b/sys/contrib/openzfs/config/kernel-symlink.m4
index fb6d23f61cbf..eb09b521aaf2 100644
--- a/sys/contrib/openzfs/config/kernel-symlink.m4
+++ b/sys/contrib/openzfs/config/kernel-symlink.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_SYMLINK], [
dnl #
dnl # 6.3 API change that changed the first arg
diff --git a/sys/contrib/openzfs/config/kernel-sysfs.m4 b/sys/contrib/openzfs/config/kernel-sysfs.m4
index bbc77c8fc5c0..7471154493b1 100644
--- a/sys/contrib/openzfs/config/kernel-sysfs.m4
+++ b/sys/contrib/openzfs/config/kernel-sysfs.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 5.2/5.18 API
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-timer.m4 b/sys/contrib/openzfs/config/kernel-timer.m4
index c89ea204e83d..d9dee8a774f8 100644
--- a/sys/contrib/openzfs/config/kernel-timer.m4
+++ b/sys/contrib/openzfs/config/kernel-timer.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 6.2: timer_delete_sync introduced, del_timer_sync deprecated and made
dnl # into a simple wrapper
diff --git a/sys/contrib/openzfs/config/kernel-tmpfile.m4 b/sys/contrib/openzfs/config/kernel-tmpfile.m4
index a711d67ed558..240fca619e5d 100644
--- a/sys/contrib/openzfs/config/kernel-tmpfile.m4
+++ b/sys/contrib/openzfs/config/kernel-tmpfile.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 3.11 API change
dnl # Add support for i_op->tmpfile
diff --git a/sys/contrib/openzfs/config/kernel-totalhigh_pages.m4 b/sys/contrib/openzfs/config/kernel-totalhigh_pages.m4
index 4ecb03a50a51..43fd82cb1b87 100644
--- a/sys/contrib/openzfs/config/kernel-totalhigh_pages.m4
+++ b/sys/contrib/openzfs/config/kernel-totalhigh_pages.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 5.0 API change
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-totalram-pages-func.m4 b/sys/contrib/openzfs/config/kernel-totalram-pages-func.m4
index d0e812a8d2d2..678982e2b77e 100644
--- a/sys/contrib/openzfs/config/kernel-totalram-pages-func.m4
+++ b/sys/contrib/openzfs/config/kernel-totalram-pages-func.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 5.0: totalram_pages is no longer a global variable, and must be
dnl # read via the totalram_pages() helper function.
diff --git a/sys/contrib/openzfs/config/kernel-truncate-setsize.m4 b/sys/contrib/openzfs/config/kernel-truncate-setsize.m4
index 76c82ef3021b..8757e59821bc 100644
--- a/sys/contrib/openzfs/config/kernel-truncate-setsize.m4
+++ b/sys/contrib/openzfs/config/kernel-truncate-setsize.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.35 API change
dnl # Added truncate_setsize() helper function.
diff --git a/sys/contrib/openzfs/config/kernel-types.m4 b/sys/contrib/openzfs/config/kernel-types.m4
index ed76af28337b..556cf5d6e6ee 100644
--- a/sys/contrib/openzfs/config/kernel-types.m4
+++ b/sys/contrib/openzfs/config/kernel-types.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # check if kernel provides definitions for given types
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-usleep_range.m4 b/sys/contrib/openzfs/config/kernel-usleep_range.m4
index 06eb381a3c38..fd6f9521975f 100644
--- a/sys/contrib/openzfs/config/kernel-usleep_range.m4
+++ b/sys/contrib/openzfs/config/kernel-usleep_range.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.36 API compatibility- Added usleep_range timer.
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-vfs-file_range.m4 b/sys/contrib/openzfs/config/kernel-vfs-file_range.m4
index 936f7b4eba4c..1b8cf31ae683 100644
--- a/sys/contrib/openzfs/config/kernel-vfs-file_range.m4
+++ b/sys/contrib/openzfs/config/kernel-vfs-file_range.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # The *_file_range APIs have a long history:
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-vfs-filemap_dirty_folio.m4 b/sys/contrib/openzfs/config/kernel-vfs-filemap_dirty_folio.m4
index 729ca670da03..f3509acdec63 100644
--- a/sys/contrib/openzfs/config/kernel-vfs-filemap_dirty_folio.m4
+++ b/sys/contrib/openzfs/config/kernel-vfs-filemap_dirty_folio.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 5.18 uses filemap_dirty_folio in lieu of
dnl # ___set_page_dirty_nobuffers
diff --git a/sys/contrib/openzfs/config/kernel-vfs-fsync.m4 b/sys/contrib/openzfs/config/kernel-vfs-fsync.m4
index 159efca4532f..13ffd3d95cc6 100644
--- a/sys/contrib/openzfs/config/kernel-vfs-fsync.m4
+++ b/sys/contrib/openzfs/config/kernel-vfs-fsync.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.35 API change,
dnl # Unused 'struct dentry *' removed from vfs_fsync() prototype.
diff --git a/sys/contrib/openzfs/config/kernel-vfs-iov_iter.m4 b/sys/contrib/openzfs/config/kernel-vfs-iov_iter.m4
index dc4e11cef2e9..b1e3b3549db4 100644
--- a/sys/contrib/openzfs/config/kernel-vfs-iov_iter.m4
+++ b/sys/contrib/openzfs/config/kernel-vfs-iov_iter.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check for available iov_iter functionality.
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-vfs-migrate_folio.m4 b/sys/contrib/openzfs/config/kernel-vfs-migrate_folio.m4
index 186cd0581a17..16a210ac5df0 100644
--- a/sys/contrib/openzfs/config/kernel-vfs-migrate_folio.m4
+++ b/sys/contrib/openzfs/config/kernel-vfs-migrate_folio.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 6.0 uses migrate_folio in lieu of migrate_page
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-vfs-migratepage.m4 b/sys/contrib/openzfs/config/kernel-vfs-migratepage.m4
index 05db3af511eb..9ae5c91f008e 100644
--- a/sys/contrib/openzfs/config/kernel-vfs-migratepage.m4
+++ b/sys/contrib/openzfs/config/kernel-vfs-migratepage.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 6.0 gets rid of address_space_operations.migratepage
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-vfs-read_folio.m4 b/sys/contrib/openzfs/config/kernel-vfs-read_folio.m4
index 9ca0faff218d..1eb7f284f42b 100644
--- a/sys/contrib/openzfs/config/kernel-vfs-read_folio.m4
+++ b/sys/contrib/openzfs/config/kernel-vfs-read_folio.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 5.19 uses read_folio in lieu of readpage
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-vfs-readpages.m4 b/sys/contrib/openzfs/config/kernel-vfs-readpages.m4
index be65a0d5e4b4..f66a1390106d 100644
--- a/sys/contrib/openzfs/config/kernel-vfs-readpages.m4
+++ b/sys/contrib/openzfs/config/kernel-vfs-readpages.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 5.18 removes address_space_operations ->readpages in favour of
dnl # ->readahead
diff --git a/sys/contrib/openzfs/config/kernel-vfs-set_page_dirty.m4 b/sys/contrib/openzfs/config/kernel-vfs-set_page_dirty.m4
index 90cb28f3682c..872fb48fc5fe 100644
--- a/sys/contrib/openzfs/config/kernel-vfs-set_page_dirty.m4
+++ b/sys/contrib/openzfs/config/kernel-vfs-set_page_dirty.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 5.14 adds a change to require set_page_dirty to be manually
dnl # wired up in struct address_space_operations. Determine if this needs
diff --git a/sys/contrib/openzfs/config/kernel-vfs-writepage.m4 b/sys/contrib/openzfs/config/kernel-vfs-writepage.m4
index d438e85b457c..8a77ea8139e0 100644
--- a/sys/contrib/openzfs/config/kernel-vfs-writepage.m4
+++ b/sys/contrib/openzfs/config/kernel-vfs-writepage.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Linux 6.16 removes address_space_operations ->writepage
dnl #
diff --git a/sys/contrib/openzfs/config/kernel-writeback.m4 b/sys/contrib/openzfs/config/kernel-writeback.m4
index 334d65ef84b6..fbf56f45a04e 100644
--- a/sys/contrib/openzfs/config/kernel-writeback.m4
+++ b/sys/contrib/openzfs/config/kernel-writeback.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_KERNEL_SRC_WRITEPAGE_T], [
dnl #
dnl # 6.3 API change
diff --git a/sys/contrib/openzfs/config/kernel-xattr-handler.m4 b/sys/contrib/openzfs/config/kernel-xattr-handler.m4
index ea4466d83fcc..b1da84d81afd 100644
--- a/sys/contrib/openzfs/config/kernel-xattr-handler.m4
+++ b/sys/contrib/openzfs/config/kernel-xattr-handler.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # 2.6.35 API change,
dnl # The 'struct xattr_handler' was constified in the generic
diff --git a/sys/contrib/openzfs/config/kernel-zero_page.m4 b/sys/contrib/openzfs/config/kernel-zero_page.m4
index 1461781acb41..812261d88e91 100644
--- a/sys/contrib/openzfs/config/kernel-zero_page.m4
+++ b/sys/contrib/openzfs/config/kernel-zero_page.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # ZERO_PAGE() is an alias for emtpy_zero_page. On certain architectures
dnl # this is a GPL exported variable.
diff --git a/sys/contrib/openzfs/config/kernel.m4 b/sys/contrib/openzfs/config/kernel.m4
index eb2e827d5cbf..05f59745d493 100644
--- a/sys/contrib/openzfs/config/kernel.m4
+++ b/sys/contrib/openzfs/config/kernel.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Default ZFS kernel configuration
dnl #
@@ -72,9 +73,10 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_SETATTR_PREPARE
ZFS_AC_KERNEL_SRC_INSERT_INODE_LOCKED
ZFS_AC_KERNEL_SRC_DENTRY
+ ZFS_AC_KERNEL_SRC_DENTRY_ALIAS_D_U
ZFS_AC_KERNEL_SRC_TRUNCATE_SETSIZE
ZFS_AC_KERNEL_SRC_SECURITY_INODE
- ZFS_AC_KERNEL_SRC_FST_MOUNT
+ ZFS_AC_KERNEL_SRC_FS_CONTEXT
ZFS_AC_KERNEL_SRC_SB_DYING
ZFS_AC_KERNEL_SRC_SET_NLINK
ZFS_AC_KERNEL_SRC_SGET
@@ -118,7 +120,6 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_ADD_DISK
ZFS_AC_KERNEL_SRC_KTHREAD
ZFS_AC_KERNEL_SRC_ZERO_PAGE
- ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC
ZFS_AC_KERNEL_SRC_IDMAP_MNT_API
ZFS_AC_KERNEL_SRC_IDMAP_NO_USERNS
ZFS_AC_KERNEL_SRC_IATTR_VFSID
@@ -140,6 +141,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_NAMESPACE
ZFS_AC_KERNEL_SRC_INODE_GENERIC_DROP
ZFS_AC_KERNEL_SRC_KASAN_ENABLED
+ ZFS_AC_KERNEL_SRC_FILELOCK_HEADER
case "$host_cpu" in
powerpc*)
ZFS_AC_KERNEL_SRC_CPU_HAS_FEATURE
@@ -195,9 +197,10 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_SETATTR_PREPARE
ZFS_AC_KERNEL_INSERT_INODE_LOCKED
ZFS_AC_KERNEL_DENTRY
+ ZFS_AC_KERNEL_DENTRY_ALIAS_D_U
ZFS_AC_KERNEL_TRUNCATE_SETSIZE
ZFS_AC_KERNEL_SECURITY_INODE
- ZFS_AC_KERNEL_FST_MOUNT
+ ZFS_AC_KERNEL_FS_CONTEXT
ZFS_AC_KERNEL_SB_DYING
ZFS_AC_KERNEL_SET_NLINK
ZFS_AC_KERNEL_SGET
@@ -241,7 +244,6 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_ADD_DISK
ZFS_AC_KERNEL_KTHREAD
ZFS_AC_KERNEL_ZERO_PAGE
- ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC
ZFS_AC_KERNEL_IDMAP_MNT_API
ZFS_AC_KERNEL_IDMAP_NO_USERNS
ZFS_AC_KERNEL_IATTR_VFSID
@@ -264,6 +266,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_NAMESPACE
ZFS_AC_KERNEL_INODE_GENERIC_DROP
ZFS_AC_KERNEL_KASAN_ENABLED
+ ZFS_AC_KERNEL_FILELOCK_HEADER
case "$host_cpu" in
powerpc*)
ZFS_AC_KERNEL_CPU_HAS_FEATURE
@@ -447,13 +450,6 @@ AC_DEFUN([ZFS_AC_KERNEL], [
AC_MSG_RESULT([$kernsrcver])
- AX_COMPARE_VERSION([$kernsrcver], [ge], [$ZFS_META_KVER_MIN], [], [
- AC_MSG_ERROR([
- *** Cannot build against kernel version $kernsrcver.
- *** The minimum supported kernel version is $ZFS_META_KVER_MIN.
- ])
- ])
-
AC_ARG_ENABLE([linux-experimental],
AS_HELP_STRING([--enable-linux-experimental],
[Allow building against some unsupported kernel versions]))
@@ -895,7 +891,7 @@ AC_DEFUN([ZFS_LINUX_TEST_ERROR], [
*** incompatible modifications.
***
*** ZFS Version: $ZFS_META_ALIAS
- *** Compatible Kernels: $ZFS_META_KVER_MIN - $ZFS_META_KVER_MAX
+ *** Highest compatible kernel version: $ZFS_META_KVER_MAX
])
])
@@ -1066,7 +1062,7 @@ AC_DEFUN([ZFS_LINUX_REQUIRE_API], [
*** APIs.
***
*** ZFS Version: $ZFS_META_ALIAS
- *** Compatible Kernels: $ZFS_META_KVER_MIN - $ZFS_META_KVER_MAX
+ *** Highest compatible kernel version: $ZFS_META_KVER_MAX
])
], [
AC_MSG_RESULT(no)
diff --git a/sys/contrib/openzfs/config/lib-ld.m4 b/sys/contrib/openzfs/config/lib-ld.m4
index a18719630d59..c4d452fddddf 100644
--- a/sys/contrib/openzfs/config/lib-ld.m4
+++ b/sys/contrib/openzfs/config/lib-ld.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: FSFULLR
# lib-ld.m4 serial 9
dnl Copyright (C) 1996-2003, 2009-2019 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
diff --git a/sys/contrib/openzfs/config/lib-link.m4 b/sys/contrib/openzfs/config/lib-link.m4
index 041f976d79a1..e8adf6d51697 100644
--- a/sys/contrib/openzfs/config/lib-link.m4
+++ b/sys/contrib/openzfs/config/lib-link.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: FSFULLR
# lib-link.m4 serial 28
dnl Copyright (C) 2001-2019 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
diff --git a/sys/contrib/openzfs/config/lib-prefix.m4 b/sys/contrib/openzfs/config/lib-prefix.m4
index f7db2371db45..cad6e0539324 100644
--- a/sys/contrib/openzfs/config/lib-prefix.m4
+++ b/sys/contrib/openzfs/config/lib-prefix.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: FSFULLR
# lib-prefix.m4 serial 14
dnl Copyright (C) 2001-2005, 2008-2019 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
diff --git a/sys/contrib/openzfs/config/mount-helper.m4 b/sys/contrib/openzfs/config/mount-helper.m4
index e559b9ab2734..271066f4e7d9 100644
--- a/sys/contrib/openzfs/config/mount-helper.m4
+++ b/sys/contrib/openzfs/config/mount-helper.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_CONFIG_USER_MOUNT_HELPER], [
AC_ARG_WITH(mounthelperdir,
AS_HELP_STRING([--with-mounthelperdir=DIR],
diff --git a/sys/contrib/openzfs/config/nls.m4 b/sys/contrib/openzfs/config/nls.m4
index b62f61485700..78dad17237b0 100644
--- a/sys/contrib/openzfs/config/nls.m4
+++ b/sys/contrib/openzfs/config/nls.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: FSFULLR
# nls.m4 serial 5 (gettext-0.18)
dnl Copyright (C) 1995-2003, 2005-2006, 2008-2014, 2016, 2019 Free Software
dnl Foundation, Inc.
diff --git a/sys/contrib/openzfs/config/pkg.m4 b/sys/contrib/openzfs/config/pkg.m4
index f9075e56c87a..feb315d776bc 100644
--- a/sys/contrib/openzfs/config/pkg.m4
+++ b/sys/contrib/openzfs/config/pkg.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-or-later WITH Autoconf-exception-generic
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
# serial 12 (pkg-config-0.29.2)
diff --git a/sys/contrib/openzfs/config/po.m4 b/sys/contrib/openzfs/config/po.m4
index 143792dba560..e4643a1d3ddc 100644
--- a/sys/contrib/openzfs/config/po.m4
+++ b/sys/contrib/openzfs/config/po.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: FSFULLR
# po.m4 serial 30 (gettext-0.20)
dnl Copyright (C) 1995-2014, 2016, 2018-2019 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
diff --git a/sys/contrib/openzfs/config/progtest.m4 b/sys/contrib/openzfs/config/progtest.m4
index 5f186b14909c..c9895f70d7ad 100644
--- a/sys/contrib/openzfs/config/progtest.m4
+++ b/sys/contrib/openzfs/config/progtest.m4
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: FSFULLR
# progtest.m4 serial 7 (gettext-0.18.2)
dnl Copyright (C) 1996-2003, 2005, 2008-2019 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
diff --git a/sys/contrib/openzfs/config/rpm.am b/sys/contrib/openzfs/config/rpm.am
index 85c56c0b2e3a..4ccf549b3a7a 100644
--- a/sys/contrib/openzfs/config/rpm.am
+++ b/sys/contrib/openzfs/config/rpm.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
###############################################################################
# Copyright (C) 2007-2013 Lawrence Livermore National Security, LLC.
# Copyright (C) 2007 The Regents of the University of California.
diff --git a/sys/contrib/openzfs/config/tgz.am b/sys/contrib/openzfs/config/tgz.am
index 2499ba42305b..e41d8bcf9bb7 100644
--- a/sys/contrib/openzfs/config/tgz.am
+++ b/sys/contrib/openzfs/config/tgz.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
PHONY += tgz tgz-kmod tgz-utils tgz-local
tgz-local:
diff --git a/sys/contrib/openzfs/config/toolchain-cfi.m4 b/sys/contrib/openzfs/config/toolchain-cfi.m4
new file mode 100644
index 000000000000..f1ad2b23934d
--- /dev/null
+++ b/sys/contrib/openzfs/config/toolchain-cfi.m4
@@ -0,0 +1,33 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
+dnl #
+dnl # Check whether assembler supports .cfi_negate_ra_state on AArch64.
+dnl #
+
+AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_TOOLCHAIN_CFI_PSEUDO_OP], [
+ case "$host_cpu" in
+ aarch64*)
+ AC_CACHE_CHECK([whether assembler supports .cfi_negate_ra_state],
+ [zfs_cv_as_cfi_pseudo_op], [
+ cat > conftest.S <<_ACEOF
+ .text
+conftest:
+ .cfi_startproc
+ .cfi_negate_ra_state
+ ret
+ .cfi_endproc
+_ACEOF
+ if AC_TRY_COMMAND([$CC -c $CFLAGS $CPPFLAGS conftest.S -o conftest.o]) >/dev/null 2>&1; then
+ zfs_cv_as_cfi_pseudo_op=yes
+ else
+ zfs_cv_as_cfi_pseudo_op=no
+ fi
+ rm -f conftest.S conftest.o
+ ])
+
+ AS_IF([test "x$zfs_cv_as_cfi_pseudo_op" = xyes], [
+ AC_DEFINE([HAVE_AS_CFI_PSEUDO_OP], 1,
+ [Define if your assembler supports .cfi_negate_ra_state.])
+ ])
+ ;;
+ esac
+])
diff --git a/sys/contrib/openzfs/config/toolchain-simd.m4 b/sys/contrib/openzfs/config/toolchain-simd.m4
index f18c91007cde..d552c99cd770 100644
--- a/sys/contrib/openzfs/config/toolchain-simd.m4
+++ b/sys/contrib/openzfs/config/toolchain-simd.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Checks if host toolchain supports SIMD instructions
dnl #
diff --git a/sys/contrib/openzfs/config/user-aio.h.m4 b/sys/contrib/openzfs/config/user-aio.h.m4
index 152c0946722f..0176e6bf6068 100644
--- a/sys/contrib/openzfs/config/user-aio.h.m4
+++ b/sys/contrib/openzfs/config/user-aio.h.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # POSIX specifies <aio.h> as part of realtime extensions,
dnl # and is missing from at least uClibc – force fallbacks there
diff --git a/sys/contrib/openzfs/config/user-backtrace.m4 b/sys/contrib/openzfs/config/user-backtrace.m4
index 25706767cdc3..1e5605893732 100644
--- a/sys/contrib/openzfs/config/user-backtrace.m4
+++ b/sys/contrib/openzfs/config/user-backtrace.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl
dnl backtrace(), for userspace assertions. glibc has this directly in libc.
dnl FreeBSD and (sometimes) musl have it in a separate -lexecinfo. It's assumed
diff --git a/sys/contrib/openzfs/config/user-clock_gettime.m4 b/sys/contrib/openzfs/config/user-clock_gettime.m4
index c96024da797b..bb56a3e1d0d9 100644
--- a/sys/contrib/openzfs/config/user-clock_gettime.m4
+++ b/sys/contrib/openzfs/config/user-clock_gettime.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check if librt is required for clock_gettime.
dnl # clock_gettime is generally available in libc on modern systems.
diff --git a/sys/contrib/openzfs/config/user-dracut.m4 b/sys/contrib/openzfs/config/user-dracut.m4
index b9705297f744..71f13d96af3c 100644
--- a/sys/contrib/openzfs/config/user-dracut.m4
+++ b/sys/contrib/openzfs/config/user-dracut.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_CONFIG_USER_DRACUT], [
AC_MSG_CHECKING(for dracut directory)
AC_ARG_WITH([dracutdir],
diff --git a/sys/contrib/openzfs/config/user-gettext.m4 b/sys/contrib/openzfs/config/user-gettext.m4
index 824318eab960..f518acf663f2 100644
--- a/sys/contrib/openzfs/config/user-gettext.m4
+++ b/sys/contrib/openzfs/config/user-gettext.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check if libintl and possibly libiconv are needed for gettext() functionality
dnl #
diff --git a/sys/contrib/openzfs/config/user-libaio.m4 b/sys/contrib/openzfs/config/user-libaio.m4
index 8009bd11b3e6..cbe369794ea0 100644
--- a/sys/contrib/openzfs/config/user-libaio.m4
+++ b/sys/contrib/openzfs/config/user-libaio.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check for libaio - only used for mmap_libaio test cases.
dnl #
diff --git a/sys/contrib/openzfs/config/user-libatomic.m4 b/sys/contrib/openzfs/config/user-libatomic.m4
index d15069f9c445..38c65b7ee03d 100644
--- a/sys/contrib/openzfs/config/user-libatomic.m4
+++ b/sys/contrib/openzfs/config/user-libatomic.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # If -latomic exists and atomic.c doesn't link without it,
dnl # it's needed for __atomic intrinsics.
diff --git a/sys/contrib/openzfs/config/user-libblkid.m4 b/sys/contrib/openzfs/config/user-libblkid.m4
index f2016dcb15cd..a0ad9f983d1b 100644
--- a/sys/contrib/openzfs/config/user-libblkid.m4
+++ b/sys/contrib/openzfs/config/user-libblkid.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check for libblkid. Basic support for detecting ZFS pools
dnl # has existing in blkid since 2008.
diff --git a/sys/contrib/openzfs/config/user-libcrypto.m4 b/sys/contrib/openzfs/config/user-libcrypto.m4
index 7293e1b0b42c..49bba7155a23 100644
--- a/sys/contrib/openzfs/config/user-libcrypto.m4
+++ b/sys/contrib/openzfs/config/user-libcrypto.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check for libcrypto. Used for userspace password derivation via PBKDF2.
dnl #
diff --git a/sys/contrib/openzfs/config/user-libexec.m4 b/sys/contrib/openzfs/config/user-libexec.m4
index 5379c25b4a0c..852c211e181e 100644
--- a/sys/contrib/openzfs/config/user-libexec.m4
+++ b/sys/contrib/openzfs/config/user-libexec.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_CONFIG_USER_ZFSEXEC], [
AC_ARG_WITH(zfsexecdir,
AS_HELP_STRING([--with-zfsexecdir=DIR],
diff --git a/sys/contrib/openzfs/config/user-libfetch.m4 b/sys/contrib/openzfs/config/user-libfetch.m4
index d961c6ca77a1..48183acfa616 100644
--- a/sys/contrib/openzfs/config/user-libfetch.m4
+++ b/sys/contrib/openzfs/config/user-libfetch.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check for a libfetch - either fetch(3) or libcurl.
dnl #
diff --git a/sys/contrib/openzfs/config/user-libtirpc.m4 b/sys/contrib/openzfs/config/user-libtirpc.m4
index aa7ab4a1fd32..3d21787bd6cd 100644
--- a/sys/contrib/openzfs/config/user-libtirpc.m4
+++ b/sys/contrib/openzfs/config/user-libtirpc.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check for libtirpc - may be needed for xdr functionality
dnl #
diff --git a/sys/contrib/openzfs/config/user-libudev.m4 b/sys/contrib/openzfs/config/user-libudev.m4
index 8c3c1d7e0087..784cf465141c 100644
--- a/sys/contrib/openzfs/config/user-libudev.m4
+++ b/sys/contrib/openzfs/config/user-libudev.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check for libudev - needed for vdev auto-online and auto-replace
dnl #
diff --git a/sys/contrib/openzfs/config/user-libunwind.m4 b/sys/contrib/openzfs/config/user-libunwind.m4
index 94865b57fe7d..1f4382117db8 100644
--- a/sys/contrib/openzfs/config/user-libunwind.m4
+++ b/sys/contrib/openzfs/config/user-libunwind.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl
dnl Checks for libunwind, which usually does a better job than backtrace() when
dnl resolving symbols in the stack backtrace. Newer versions have support for
diff --git a/sys/contrib/openzfs/config/user-libuuid.m4 b/sys/contrib/openzfs/config/user-libuuid.m4
index 0cfa83c9926a..b08938e845c0 100644
--- a/sys/contrib/openzfs/config/user-libuuid.m4
+++ b/sys/contrib/openzfs/config/user-libuuid.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check for libuuid
dnl #
diff --git a/sys/contrib/openzfs/config/user-makedev.m4 b/sys/contrib/openzfs/config/user-makedev.m4
index 8986107aef80..ad8b4c236f40 100644
--- a/sys/contrib/openzfs/config/user-makedev.m4
+++ b/sys/contrib/openzfs/config/user-makedev.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # glibc 2.25
dnl #
diff --git a/sys/contrib/openzfs/config/user-mount-setattr.m4 b/sys/contrib/openzfs/config/user-mount-setattr.m4
new file mode 100644
index 000000000000..efcfd66b2e9a
--- /dev/null
+++ b/sys/contrib/openzfs/config/user-mount-setattr.m4
@@ -0,0 +1,27 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
+dnl #
+dnl # Check for mount_setattr() and struct mount_attr availability
+dnl #
+AC_DEFUN([ZFS_AC_CONFIG_USER_MOUNT_SETATTR], [
+ AC_CHECK_FUNC([mount_setattr], [
+ AC_MSG_CHECKING([for struct mount_attr])
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+ #include <sys/mount.h>
+ ]], [[
+ struct mount_attr attr = {
+ .attr_set = MOUNT_ATTR_RDONLY,
+ .attr_clr = MOUNT_ATTR_NOEXEC,
+ };
+ (void) attr;
+ ]])
+ ], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_MOUNT_SETATTR], [1],
+ [mount_setattr() and struct mount_attr
+ are available])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+ ])
+])
diff --git a/sys/contrib/openzfs/config/user-pam.m4 b/sys/contrib/openzfs/config/user-pam.m4
index 9db35808c340..af032c542a9b 100644
--- a/sys/contrib/openzfs/config/user-pam.m4
+++ b/sys/contrib/openzfs/config/user-pam.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_CONFIG_USER_PAM], [
AC_ARG_ENABLE([pam],
AS_HELP_STRING([--enable-pam],
diff --git a/sys/contrib/openzfs/config/user-runstatedir.m4 b/sys/contrib/openzfs/config/user-runstatedir.m4
index ded1362c7b22..29f7eab047ee 100644
--- a/sys/contrib/openzfs/config/user-runstatedir.m4
+++ b/sys/contrib/openzfs/config/user-runstatedir.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl For backwards compatibility; runstatedir added in autoconf 2.70.
AC_DEFUN([ZFS_AC_CONFIG_USER_RUNSTATEDIR], [
if test "x$runstatedir" = x; then
diff --git a/sys/contrib/openzfs/config/user-statx.m4 b/sys/contrib/openzfs/config/user-statx.m4
index 1ba74a40e9b8..d359f48b8579 100644
--- a/sys/contrib/openzfs/config/user-statx.m4
+++ b/sys/contrib/openzfs/config/user-statx.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check for statx() function and STATX_MNT_ID availability
dnl #
@@ -14,6 +15,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER_STATX], [
AC_MSG_CHECKING([for STATX_MNT_ID])
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
+ #define _GNU_SOURCE
#include <sys/stat.h>
]], [[
struct statx stx;
diff --git a/sys/contrib/openzfs/config/user-systemd.m4 b/sys/contrib/openzfs/config/user-systemd.m4
index e4fd0b57c2b7..7e57e11cf4b7 100644
--- a/sys/contrib/openzfs/config/user-systemd.m4
+++ b/sys/contrib/openzfs/config/user-systemd.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_CONFIG_USER_SYSTEMD], [
AC_ARG_ENABLE(systemd,
AS_HELP_STRING([--enable-systemd],
diff --git a/sys/contrib/openzfs/config/user-sysvinit.m4 b/sys/contrib/openzfs/config/user-sysvinit.m4
index cf3c8129f0d2..3594663e3deb 100644
--- a/sys/contrib/openzfs/config/user-sysvinit.m4
+++ b/sys/contrib/openzfs/config/user-sysvinit.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_CONFIG_USER_SYSVINIT], [
AC_ARG_ENABLE(sysvinit,
AS_HELP_STRING([--enable-sysvinit],
diff --git a/sys/contrib/openzfs/config/user-udev.m4 b/sys/contrib/openzfs/config/user-udev.m4
index e6120fc8fef6..4dc02aea4ce4 100644
--- a/sys/contrib/openzfs/config/user-udev.m4
+++ b/sys/contrib/openzfs/config/user-udev.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_CONFIG_USER_UDEV], [
AC_MSG_CHECKING(for udev directories)
AC_ARG_WITH(udevdir,
diff --git a/sys/contrib/openzfs/config/user-zlib.m4 b/sys/contrib/openzfs/config/user-zlib.m4
index 1f3792829bb6..6687d7c77b23 100644
--- a/sys/contrib/openzfs/config/user-zlib.m4
+++ b/sys/contrib/openzfs/config/user-zlib.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Check for zlib
dnl #
diff --git a/sys/contrib/openzfs/config/user.m4 b/sys/contrib/openzfs/config/user.m4
index 62e59ed94437..1ecd4ddde057 100644
--- a/sys/contrib/openzfs/config/user.m4
+++ b/sys/contrib/openzfs/config/user.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # Default ZFS user configuration
dnl #
@@ -18,6 +19,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [
ZFS_AC_CONFIG_USER_LIBUUID
ZFS_AC_CONFIG_USER_LIBBLKID
ZFS_AC_CONFIG_USER_STATX
+ ZFS_AC_CONFIG_USER_MOUNT_SETATTR
])
ZFS_AC_CONFIG_USER_LIBTIRPC
ZFS_AC_CONFIG_USER_LIBCRYPTO
diff --git a/sys/contrib/openzfs/config/zfs-build.m4 b/sys/contrib/openzfs/config/zfs-build.m4
index 161d390466db..77c9154bba5e 100644
--- a/sys/contrib/openzfs/config/zfs-build.m4
+++ b/sys/contrib/openzfs/config/zfs-build.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
AC_DEFUN([ZFS_AC_LICENSE], [
AC_MSG_CHECKING([zfs author])
AC_MSG_RESULT([$ZFS_META_AUTHOR])
@@ -225,7 +226,7 @@ AC_DEFUN([ZFS_AC_OBJTOOL_WERROR], [
],[
AC_MSG_NOTICE([enable-objtool-werror undefined, disabling -Werror ])
OBJTOOL_DISABLE_WERROR=y
- abs_objtool_binary=$kernelsrc/tools/objtool/objtool
+ abs_objtool_binary=$kernelbuild/tools/objtool/objtool
AS_IF([test -x $abs_objtool_binary],[],[
AC_MSG_ERROR([*** objtool binary $abs_objtool_binary not found])
])
@@ -265,6 +266,7 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS], [
ZFS_AC_CONFIG_ALWAYS_CC_ASAN
ZFS_AC_CONFIG_ALWAYS_CC_UBSAN
ZFS_AC_CONFIG_ALWAYS_TOOLCHAIN_SIMD
+ ZFS_AC_CONFIG_ALWAYS_TOOLCHAIN_CFI_PSEUDO_OP
ZFS_AC_CONFIG_ALWAYS_SYSTEM
ZFS_AC_CONFIG_ALWAYS_ARCH
ZFS_AC_CONFIG_CHECK_ARCH_VAR
diff --git a/sys/contrib/openzfs/config/zfs-meta.m4 b/sys/contrib/openzfs/config/zfs-meta.m4
index 20064a0fb595..72d424e2d478 100644
--- a/sys/contrib/openzfs/config/zfs-meta.m4
+++ b/sys/contrib/openzfs/config/zfs-meta.m4
@@ -1,3 +1,4 @@
+dnl # SPDX-License-Identifier: CDDL-1.0
dnl #
dnl # DESCRIPTION:
dnl # Read meta data from the META file. When building from a git repository
diff --git a/sys/contrib/openzfs/configure.ac b/sys/contrib/openzfs/configure.ac
index f4b52e1f7abc..3757b5e2cac8 100644
--- a/sys/contrib/openzfs/configure.ac
+++ b/sys/contrib/openzfs/configure.ac
@@ -41,7 +41,7 @@ AC_CONFIG_MACRO_DIR([config])
AC_CANONICAL_TARGET
AM_MAINTAINER_MODE
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
-AM_INIT_AUTOMAKE([subdir-objects foreign])
+AM_INIT_AUTOMAKE([subdir-objects foreign tar-pax])
# Remove default macros from config.h:
# PACKAGE, PACKAGE_{BUGREPORT,NAME,STRING,TARNAME,VERSION}, STDC_HEADERS, VERSION
AC_CONFIG_HEADERS([zfs_config.h], [
diff --git a/sys/contrib/openzfs/contrib/Makefile.am b/sys/contrib/openzfs/contrib/Makefile.am
index 5b8c1810bbe2..df128de073ec 100644
--- a/sys/contrib/openzfs/contrib/Makefile.am
+++ b/sys/contrib/openzfs/contrib/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
include $(srcdir)/%D%/bash_completion.d/Makefile.am
include $(srcdir)/%D%/debian/Makefile.am
include $(srcdir)/%D%/pyzfs/Makefile.am
diff --git a/sys/contrib/openzfs/contrib/bash_completion.d/Makefile.am b/sys/contrib/openzfs/contrib/bash_completion.d/Makefile.am
index 95d4ffa76e22..bd3e5d9fab56 100644
--- a/sys/contrib/openzfs/contrib/bash_completion.d/Makefile.am
+++ b/sys/contrib/openzfs/contrib/bash_completion.d/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
nodist_bashcompletion_DATA = %D%/zfs %D%/zpool
COMPLETION_FILES = %D%/zfs
SUBSTFILES += $(COMPLETION_FILES)
diff --git a/sys/contrib/openzfs/contrib/bpftrace/Makefile.am b/sys/contrib/openzfs/contrib/bpftrace/Makefile.am
index 4f649cf5433e..33631da09d49 100644
--- a/sys/contrib/openzfs/contrib/bpftrace/Makefile.am
+++ b/sys/contrib/openzfs/contrib/bpftrace/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
dist_noinst_DATA += %D%/taskqlatency.bt %D%/zfs-trace.sh
SHELLCHECKSCRIPTS += %D%/zfs-trace.sh
diff --git a/sys/contrib/openzfs/contrib/debian/Makefile.am b/sys/contrib/openzfs/contrib/debian/Makefile.am
index 3c219856005e..e2281686ce1b 100644
--- a/sys/contrib/openzfs/contrib/debian/Makefile.am
+++ b/sys/contrib/openzfs/contrib/debian/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
dist_noinst_DATA += %D%/changelog.in
dist_noinst_DATA += %D%/clean
dist_noinst_DATA += %D%/control
diff --git a/sys/contrib/openzfs/contrib/dracut/Makefile.am b/sys/contrib/openzfs/contrib/dracut/Makefile.am
index b432ab76a6d8..4e3529626737 100644
--- a/sys/contrib/openzfs/contrib/dracut/Makefile.am
+++ b/sys/contrib/openzfs/contrib/dracut/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
pkgdracut_02dir = $(dracutdir)/modules.d/02zfsexpandknowledge
pkgdracut_02_SCRIPTS = \
%D%/02zfsexpandknowledge/module-setup.sh
diff --git a/sys/contrib/openzfs/contrib/initramfs/Makefile.am b/sys/contrib/openzfs/contrib/initramfs/Makefile.am
index a583341ea2b1..a33b2b54f149 100644
--- a/sys/contrib/openzfs/contrib/initramfs/Makefile.am
+++ b/sys/contrib/openzfs/contrib/initramfs/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
i_tdir = /usr/share/initramfs-tools
dist_i_t_SCRIPTS = \
%D%/zfsunlock
diff --git a/sys/contrib/openzfs/contrib/initramfs/scripts/zfs b/sys/contrib/openzfs/contrib/initramfs/scripts/zfs
index 9d2c086ffdfe..06eb0e295c84 100644
--- a/sys/contrib/openzfs/contrib/initramfs/scripts/zfs
+++ b/sys/contrib/openzfs/contrib/initramfs/scripts/zfs
@@ -674,11 +674,11 @@ setup_snapshot_booting()
then
# Snapshot does not exist (...@<null> ?)
# ask the user for a snapshot to use.
- snap="$(ask_user_snap "${_boot_snap%%@*}")"
+ _boot_snap="$(ask_user_snap "${_boot_snap%%@*}")"
fi
- # Separate the full snapshot ('${snap}') into it's filesystem and
- # snapshot names. Would have been nice with a split() function..
+ # Separate the full snapshot ('${_boot_snap}') into its filesystem and
+ # snapshot names. Would have been nice with a split() function.
_rootfs="${_boot_snap%%@*}"
_snapname="${_boot_snap##*@}"
ZFS_BOOTFS="${_rootfs}_${_snapname}"
@@ -693,7 +693,7 @@ setup_snapshot_booting()
-r -Sname "${ZFS_BOOTFS}")"
for fs in ${_filesystems}
do
- destroy_fs "${_boot_snap}"
+ destroy_fs "${fs}"
done
fi
fi
diff --git a/sys/contrib/openzfs/contrib/pam_zfs_key/Makefile.am b/sys/contrib/openzfs/contrib/pam_zfs_key/Makefile.am
index aaa608b7da2b..c28582fa6771 100644
--- a/sys/contrib/openzfs/contrib/pam_zfs_key/Makefile.am
+++ b/sys/contrib/openzfs/contrib/pam_zfs_key/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
%C%_pam_zfs_key_la_CFLAGS = $(AM_CFLAGS)
%C%_pam_zfs_key_la_CFLAGS += $(LIBCRYPTO_CFLAGS)
diff --git a/sys/contrib/openzfs/contrib/pyzfs/Makefile.am b/sys/contrib/openzfs/contrib/pyzfs/Makefile.am
index 06d9a09d7f1e..467e938144f7 100644
--- a/sys/contrib/openzfs/contrib/pyzfs/Makefile.am
+++ b/sys/contrib/openzfs/contrib/pyzfs/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
dist_noinst_DATA += %D%/libzfs_core %D%/README %D%/LICENSE %D%/docs
SUBSTFILES += %D%/setup.py
diff --git a/sys/contrib/openzfs/contrib/zcp/Makefile.am b/sys/contrib/openzfs/contrib/zcp/Makefile.am
index fc3f01a233cb..13afbe299091 100644
--- a/sys/contrib/openzfs/contrib/zcp/Makefile.am
+++ b/sys/contrib/openzfs/contrib/zcp/Makefile.am
@@ -1 +1,2 @@
+# SPDX-License-Identifier: CDDL-1.0
dist_noinst_DATA += %D%/autosnap.lua
diff --git a/sys/contrib/openzfs/etc/Makefile.am b/sys/contrib/openzfs/etc/Makefile.am
index 808c729cd968..58b3cf563b62 100644
--- a/sys/contrib/openzfs/etc/Makefile.am
+++ b/sys/contrib/openzfs/etc/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
sudoersddir = $(sysconfdir)/sudoers.d
sudoersd_DATA = \
%D%/sudoers.d/zfs
diff --git a/sys/contrib/openzfs/etc/systemd/system-generators/zfs-mount-generator.c b/sys/contrib/openzfs/etc/systemd/system-generators/zfs-mount-generator.c
index 7ad9ff61d8ee..bbd90a7048f7 100644
--- a/sys/contrib/openzfs/etc/systemd/system-generators/zfs-mount-generator.c
+++ b/sys/contrib/openzfs/etc/systemd/system-generators/zfs-mount-generator.c
@@ -202,6 +202,7 @@ line_worker(char *line, const char *cachefile)
void **tofree = tofree_all;
char *toktmp;
+ const char *toktmp2;
/* BEGIN CSTYLED */
const char *dataset = strtok_r(line, "\t", &toktmp);
char *p_mountpoint = strtok_r(NULL, "\t", &toktmp);
@@ -226,8 +227,8 @@ line_worker(char *line, const char *cachefile)
/* END CSTYLED */
size_t pool_len = strlen(dataset);
- if ((toktmp = strchr(dataset, '/')) != NULL)
- pool_len = toktmp - dataset;
+ if ((toktmp2 = strchr(dataset, '/')) != NULL)
+ pool_len = toktmp2 - dataset;
const char *pool = *(tofree++) = strndup(dataset, pool_len);
if (p_nbmand == NULL) {
diff --git a/sys/contrib/openzfs/include/Makefile.am b/sys/contrib/openzfs/include/Makefile.am
index 7588cd0aedc9..c171249b0156 100644
--- a/sys/contrib/openzfs/include/Makefile.am
+++ b/sys/contrib/openzfs/include/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
if BUILD_LINUX
include $(srcdir)/%D%/os/linux/Makefile.am
endif
diff --git a/sys/contrib/openzfs/include/os/freebsd/Makefile.am b/sys/contrib/openzfs/include/os/freebsd/Makefile.am
index d6b6923d033f..8fb0b8c5a0b2 100644
--- a/sys/contrib/openzfs/include/os/freebsd/Makefile.am
+++ b/sys/contrib/openzfs/include/os/freebsd/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
noinst_HEADERS = \
%D%/linux/compiler.h \
%D%/linux/types.h \
diff --git a/sys/contrib/openzfs/include/os/linux/Makefile.am b/sys/contrib/openzfs/include/os/linux/Makefile.am
index e156ca183dbd..c8eab5b9874b 100644
--- a/sys/contrib/openzfs/include/os/linux/Makefile.am
+++ b/sys/contrib/openzfs/include/os/linux/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
if CONFIG_KERNEL
kernel_linuxdir = $(kerneldir)/linux
kernel_linux_HEADERS = \
diff --git a/sys/contrib/openzfs/include/os/linux/kernel/linux/dcache_compat.h b/sys/contrib/openzfs/include/os/linux/kernel/linux/dcache_compat.h
index f94dcda6175b..e27158926917 100644
--- a/sys/contrib/openzfs/include/os/linux/kernel/linux/dcache_compat.h
+++ b/sys/contrib/openzfs/include/os/linux/kernel/linux/dcache_compat.h
@@ -32,7 +32,9 @@
#define dname(dentry) ((char *)((dentry)->d_name.name))
#define dlen(dentry) ((int)((dentry)->d_name.len))
+#ifdef HAVE_DENTRY_D_U_ALIASES
#define d_alias d_u.d_alias
+#endif
#ifdef HAVE_MM_PAGE_FLAGS_STRUCT
/*
diff --git a/sys/contrib/openzfs/include/os/linux/kernel/linux/xattr_compat.h b/sys/contrib/openzfs/include/os/linux/kernel/linux/xattr_compat.h
index f2f7e1ed017f..39645c19094f 100644
--- a/sys/contrib/openzfs/include/os/linux/kernel/linux/xattr_compat.h
+++ b/sys/contrib/openzfs/include/os/linux/kernel/linux/xattr_compat.h
@@ -130,10 +130,27 @@ zpl_acl_from_xattr(const void *value, int size)
return (posix_acl_from_xattr(kcred->user_ns, value, size));
}
+/*
+ * Linux 7.0 API change. posix_acl_to_xattr() changed from filling the
+ * caller-provided buffer to allocating a buffer with enough space and
+ * returning it. We wrap this up by copying the result into the provided
+ * buffer and freeing the allocated buffer.
+ */
static inline int
zpl_acl_to_xattr(struct posix_acl *acl, void *value, int size)
{
+#ifdef HAVE_POSIX_ACL_TO_XATTR_ALLOC
+ size_t s = 0;
+ void *v = posix_acl_to_xattr(kcred->user_ns, acl, &s,
+ kmem_flags_convert(KM_SLEEP));
+ if (v == NULL)
+ return (-ENOMEM);
+ memcpy(value, v, MIN(size, s));
+ kfree(v);
+ return (0);
+#else
return (posix_acl_to_xattr(kcred->user_ns, acl, value, size));
+#endif
}
#endif /* _ZFS_XATTR_H */
diff --git a/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vfsops_os.h b/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vfsops_os.h
index ab46d5f8ca08..123ea71b4de9 100644
--- a/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vfsops_os.h
+++ b/sys/contrib/openzfs/include/os/linux/zfs/sys/zfs_vfsops_os.h
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2018 by Delphix. All rights reserved.
+ * Copyright (c) 2026, TrueNAS.
*/
#ifndef _SYS_FS_ZFS_VFSOPS_H
@@ -73,11 +74,6 @@ typedef struct vfs {
kmutex_t vfs_mntpt_lock;
} vfs_t;
-typedef struct zfs_mnt {
- const char *mnt_osname; /* Objset name */
- char *mnt_data; /* Raw mount options */
-} zfs_mnt_t;
-
struct zfsvfs {
vfs_t *z_vfs; /* generic fs struct */
struct super_block *z_sb; /* generic super_block */
@@ -245,11 +241,15 @@ extern int zfsvfs_create_impl(zfsvfs_t **zfvp, zfsvfs_t *zfsvfs, objset_t *os);
extern void zfsvfs_free(zfsvfs_t *zfsvfs);
extern int zfs_check_global_label(const char *dsname, const char *hexsl);
+extern vfs_t *zfsvfs_vfs_alloc(void);
+extern void zfsvfs_vfs_free(vfs_t *vfsp);
+
extern boolean_t zfs_is_readonly(zfsvfs_t *zfsvfs);
-extern int zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent);
+extern int zfs_domount(struct super_block *sb, const char *osname,
+ vfs_t *mntopts, int silent);
extern void zfs_preumount(struct super_block *sb);
extern int zfs_umount(struct super_block *sb);
-extern int zfs_remount(struct super_block *sb, int *flags, zfs_mnt_t *zm);
+extern int zfs_remount(struct super_block *sb, vfs_t *mntopts, int flags);
extern int zfs_statvfs(struct inode *ip, struct kstatfs *statp);
extern int zfs_vget(struct super_block *sb, struct inode **ipp, fid_t *fidp);
extern int zfs_prune(struct super_block *sb, unsigned long nr_to_scan,
diff --git a/sys/contrib/openzfs/include/sys/dbuf.h b/sys/contrib/openzfs/include/sys/dbuf.h
index baf3b1508335..0b379ee79caa 100644
--- a/sys/contrib/openzfs/include/sys/dbuf.h
+++ b/sys/contrib/openzfs/include/sys/dbuf.h
@@ -411,6 +411,8 @@ void dmu_buf_unlock_parent(dmu_buf_impl_t *db, db_lock_type_t type,
void dbuf_free_range(struct dnode *dn, uint64_t start, uint64_t end,
struct dmu_tx *);
+void dbuf_evict_range(struct dnode *dn, uint64_t start_blkid,
+ uint64_t end_blkid);
void dbuf_new_size(dmu_buf_impl_t *db, int size, dmu_tx_t *tx);
diff --git a/sys/contrib/openzfs/include/sys/dmu.h b/sys/contrib/openzfs/include/sys/dmu.h
index bb623e404955..81c293e72384 100644
--- a/sys/contrib/openzfs/include/sys/dmu.h
+++ b/sys/contrib/openzfs/include/sys/dmu.h
@@ -963,6 +963,8 @@ void dmu_prefetch_by_dnode(dnode_t *dn, int64_t level, uint64_t offset,
void dmu_prefetch_dnode(objset_t *os, uint64_t object, enum zio_priority pri);
int dmu_prefetch_wait(objset_t *os, uint64_t object, uint64_t offset,
uint64_t size);
+void dmu_evict_range(objset_t *os, uint64_t object, uint64_t offset,
+ uint64_t len);
typedef struct dmu_object_info {
/* All sizes are in bytes unless otherwise indicated. */
diff --git a/sys/contrib/openzfs/include/sys/dnode.h b/sys/contrib/openzfs/include/sys/dnode.h
index 8bd1db5b7165..b9ded73efe33 100644
--- a/sys/contrib/openzfs/include/sys/dnode.h
+++ b/sys/contrib/openzfs/include/sys/dnode.h
@@ -652,6 +652,19 @@ extern dnode_sums_t dnode_sums;
#endif
+/*
+ * Assert that we are not modifying the range tree for the syncing TXG from
+ * a non-syncing thread. We verify that either the transaction group is
+ * strictly newer than the one currently syncing (meaning it's being modified
+ * in open context), OR the current thread is the sync thread itself. If this
+ * triggers, it indicates a race where dn_free_ranges is being modified while
+ * dnode_sync() may be iterating over it.
+ */
+#define FREE_RANGE_VERIFY(tx, dn) \
+ ASSERT((tx)->tx_txg > spa_syncing_txg((dn)->dn_objset->os_spa) || \
+ dmu_objset_pool((dn)->dn_objset)->dp_tx.tx_sync_thread == \
+ curthread)
+
#ifdef __cplusplus
}
#endif
diff --git a/sys/contrib/openzfs/include/sys/spa.h b/sys/contrib/openzfs/include/sys/spa.h
index 1a84844c522a..0de8a1867a12 100644
--- a/sys/contrib/openzfs/include/sys/spa.h
+++ b/sys/contrib/openzfs/include/sys/spa.h
@@ -1082,6 +1082,7 @@ extern uint64_t spa_guid(spa_t *spa);
extern uint64_t spa_load_guid(spa_t *spa);
extern uint64_t spa_last_synced_txg(spa_t *spa);
extern uint64_t spa_first_txg(spa_t *spa);
+extern uint64_t spa_open_txg(spa_t *spa);
extern uint64_t spa_syncing_txg(spa_t *spa);
extern uint64_t spa_final_dirty_txg(spa_t *spa);
extern uint64_t spa_version(spa_t *spa);
diff --git a/sys/contrib/openzfs/include/sys/vdev_raidz_impl.h b/sys/contrib/openzfs/include/sys/vdev_raidz_impl.h
index 8c8dcfb077f6..3ff2a4d94620 100644
--- a/sys/contrib/openzfs/include/sys/vdev_raidz_impl.h
+++ b/sys/contrib/openzfs/include/sys/vdev_raidz_impl.h
@@ -119,6 +119,7 @@ typedef struct raidz_col {
uint8_t rc_need_orig_restore:1; /* need to restore from orig_data? */
uint8_t rc_force_repair:1; /* Write good data to this column */
uint8_t rc_allow_repair:1; /* Allow repair I/O to this column */
+ uint8_t rc_tgt_is_dspare:1; /* The target is draid spare vdev */
uint8_t rc_latency_outlier:1; /* Latency outlier for this device */
int rc_shadow_devidx; /* for double write during expansion */
int rc_shadow_error; /* for double write during expansion */
diff --git a/sys/contrib/openzfs/include/sys/vdev_rebuild.h b/sys/contrib/openzfs/include/sys/vdev_rebuild.h
index 17ed94dd9d09..8ecb30659434 100644
--- a/sys/contrib/openzfs/include/sys/vdev_rebuild.h
+++ b/sys/contrib/openzfs/include/sys/vdev_rebuild.h
@@ -70,6 +70,7 @@ typedef struct vdev_rebuild {
zfs_range_tree_t *vr_scan_tree;
kmutex_t vr_io_lock; /* inflight IO lock */
kcondvar_t vr_io_cv; /* inflight IO cv */
+ uint64_t vr_last_txg; /* last used txg */
/* In-core state and progress */
uint64_t vr_scan_offset[TXG_SIZE];
@@ -90,7 +91,8 @@ typedef struct vdev_rebuild {
boolean_t vdev_rebuild_active(vdev_t *);
int vdev_rebuild_load(vdev_t *);
-void vdev_rebuild(vdev_t *);
+void vdev_rebuild(vdev_t *, uint64_t);
+void vdev_rebuild_txgs(vdev_t *, uint64_t *, uint64_t *);
void vdev_rebuild_stop_wait(vdev_t *);
void vdev_rebuild_stop_all(spa_t *);
void vdev_rebuild_restart(spa_t *);
diff --git a/sys/contrib/openzfs/lib/Makefile.am b/sys/contrib/openzfs/lib/Makefile.am
index 050a6cac0a37..1743f40440f6 100644
--- a/sys/contrib/openzfs/lib/Makefile.am
+++ b/sys/contrib/openzfs/lib/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
#
# Shown below is a simplified dependency graph of the OpenZFS provided
# libraries. Administrative commands (`zfs`, `zpool`, etc) interface with
diff --git a/sys/contrib/openzfs/lib/libavl/Makefile.am b/sys/contrib/openzfs/lib/libavl/Makefile.am
index 3b302ee9deae..b10e88aefe59 100644
--- a/sys/contrib/openzfs/lib/libavl/Makefile.am
+++ b/sys/contrib/openzfs/lib/libavl/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
libavl_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS) $(LIBRARY_CFLAGS)
libavl_la_CFLAGS += -fvisibility=hidden
diff --git a/sys/contrib/openzfs/lib/libefi/Makefile.am b/sys/contrib/openzfs/lib/libefi/Makefile.am
index 5c3e57346c86..9088c91a83c4 100644
--- a/sys/contrib/openzfs/lib/libefi/Makefile.am
+++ b/sys/contrib/openzfs/lib/libefi/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
libefi_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS)
libefi_la_CFLAGS += $(LIBUUID_CFLAGS) $(ZLIB_CFLAGS)
libefi_la_CFLAGS += -fvisibility=hidden
diff --git a/sys/contrib/openzfs/lib/libicp/Makefile.am b/sys/contrib/openzfs/lib/libicp/Makefile.am
index 23adba10bc44..10c791ba260a 100644
--- a/sys/contrib/openzfs/lib/libicp/Makefile.am
+++ b/sys/contrib/openzfs/lib/libicp/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
libicp_la_CCASFLAGS = $(AM_CCASFLAGS)
libicp_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS) $(LIBRARY_CFLAGS)
diff --git a/sys/contrib/openzfs/lib/libnvpair/Makefile.am b/sys/contrib/openzfs/lib/libnvpair/Makefile.am
index 0b3f964781b0..b326be736d36 100644
--- a/sys/contrib/openzfs/lib/libnvpair/Makefile.am
+++ b/sys/contrib/openzfs/lib/libnvpair/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
libnvpair_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS) $(LIBRARY_CFLAGS)
libnvpair_la_CFLAGS += $(LIBTIRPC_CFLAGS)
libnvpair_la_CFLAGS += -fvisibility=hidden
diff --git a/sys/contrib/openzfs/lib/libspl/Makefile.am b/sys/contrib/openzfs/lib/libspl/Makefile.am
index 0fd907d3011e..e6ac0ff731f7 100644
--- a/sys/contrib/openzfs/lib/libspl/Makefile.am
+++ b/sys/contrib/openzfs/lib/libspl/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
include $(srcdir)/%D%/include/Makefile.am
libspl_assert_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS) $(LIBUNWIND_CFLAGS)
diff --git a/sys/contrib/openzfs/lib/libspl/include/Makefile.am b/sys/contrib/openzfs/lib/libspl/include/Makefile.am
index 746cb12bf637..2e58dac84230 100644
--- a/sys/contrib/openzfs/lib/libspl/include/Makefile.am
+++ b/sys/contrib/openzfs/lib/libspl/include/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
libspldir = $(includedir)/libspl
libspl_HEADERS = \
%D%/assert.h \
diff --git a/sys/contrib/openzfs/lib/libspl/os/linux/getmntany.c b/sys/contrib/openzfs/lib/libspl/os/linux/getmntany.c
index ee1cdf59b9e5..0e9591c08793 100644
--- a/sys/contrib/openzfs/lib/libspl/os/linux/getmntany.c
+++ b/sys/contrib/openzfs/lib/libspl/os/linux/getmntany.c
@@ -143,7 +143,14 @@ getextmntent(const char *path, struct extmnttab *entry, struct stat64 *statbuf)
}
#ifdef HAVE_STATX_MNT_ID
- if (statx(AT_FDCWD, path, AT_STATX_SYNC_AS_STAT | AT_SYMLINK_NOFOLLOW,
+ /*
+ * Use AT_STATX_SYNC_AS_STAT without AT_SYMLINK_NOFOLLOW so that
+ * symlinks are followed, matching the behavior of stat64() above.
+ * Without this, if path is a symlink crossing a mount boundary,
+ * statx() returns the mnt_id of the symlink's location rather
+ * than the symlink target's mount.
+ */
+ if (statx(AT_FDCWD, path, AT_STATX_SYNC_AS_STAT,
STATX_MNT_ID, &stx) == 0 && (stx.stx_mask & STATX_MNT_ID)) {
have_mnt_id = B_TRUE;
target_mnt_id = stx.stx_mnt_id;
diff --git a/sys/contrib/openzfs/lib/libuutil/uu_ident.c b/sys/contrib/openzfs/lib/libuutil/uu_ident.c
index 87fde4d98086..f0a234c4f92e 100644
--- a/sys/contrib/openzfs/lib/libuutil/uu_ident.c
+++ b/sys/contrib/openzfs/lib/libuutil/uu_ident.c
@@ -76,7 +76,7 @@ is_valid_ident(const char *s, const char *e, int allowdot)
static int
is_valid_component(const char *b, const char *e, uint_t flags)
{
- char *sp;
+ const char *sp;
if (flags & UU_NAME_DOMAIN) {
sp = strchr(b, ',');
diff --git a/sys/contrib/openzfs/lib/libzdb/Makefile.am b/sys/contrib/openzfs/lib/libzdb/Makefile.am
index ec4fd92b984e..4a8f17d079ad 100644
--- a/sys/contrib/openzfs/lib/libzdb/Makefile.am
+++ b/sys/contrib/openzfs/lib/libzdb/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
libzdb_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS)
libzdb_la_CFLAGS += -fvisibility=hidden
diff --git a/sys/contrib/openzfs/lib/libzfs/Makefile.am b/sys/contrib/openzfs/lib/libzfs/Makefile.am
index e2cbca47b9a3..5ac6c0bcaaed 100644
--- a/sys/contrib/openzfs/lib/libzfs/Makefile.am
+++ b/sys/contrib/openzfs/lib/libzfs/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
libzfs_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS)
libzfs_la_CFLAGS += $(LIBCRYPTO_CFLAGS) $(ZLIB_CFLAGS)
libzfs_la_CFLAGS += -fvisibility=hidden
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c b/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c
index e1b91fc47291..98f396ea4616 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c
@@ -708,7 +708,7 @@ zfs_open(libzfs_handle_t *hdl, const char *path, int types)
{
zfs_handle_t *zhp;
char errbuf[ERRBUFLEN];
- char *bookp;
+ const char *bookp;
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN, "cannot open '%s'"), path);
@@ -1701,26 +1701,6 @@ zfs_fix_auto_resv(zfs_handle_t *zhp, nvlist_t *nvl)
return (1);
}
-static boolean_t
-zfs_is_namespace_prop(zfs_prop_t prop)
-{
- switch (prop) {
-
- case ZFS_PROP_ATIME:
- case ZFS_PROP_RELATIME:
- case ZFS_PROP_DEVICES:
- case ZFS_PROP_EXEC:
- case ZFS_PROP_SETUID:
- case ZFS_PROP_READONLY:
- case ZFS_PROP_XATTR:
- case ZFS_PROP_NBMAND:
- return (B_TRUE);
-
- default:
- return (B_FALSE);
- }
-}
-
/*
* Given a property name and value, set the property for the given dataset.
*/
@@ -1778,7 +1758,7 @@ zfs_prop_set_list_flags(zfs_handle_t *zhp, nvlist_t *props, int flags)
int nvl_len = 0;
int added_resv = 0;
zfs_prop_t prop;
- boolean_t nsprop = B_FALSE;
+ uint32_t nspflags = 0;
nvpair_t *elem;
(void) snprintf(errbuf, sizeof (errbuf),
@@ -1825,7 +1805,7 @@ zfs_prop_set_list_flags(zfs_handle_t *zhp, nvlist_t *props, int flags)
elem = nvlist_next_nvpair(nvl, elem)) {
prop = zfs_name_to_prop(nvpair_name(elem));
- nsprop |= zfs_is_namespace_prop(prop);
+ nspflags |= zfs_namespace_prop_flag(prop);
assert(cl_idx < nvl_len);
/*
@@ -1926,8 +1906,8 @@ zfs_prop_set_list_flags(zfs_handle_t *zhp, nvlist_t *props, int flags)
* if one of the options handled by the generic
* Linux namespace layer has been modified.
*/
- if (nsprop && zfs_is_mounted(zhp, NULL))
- ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0);
+ if (nspflags && zfs_is_mounted(zhp, NULL))
+ ret = zfs_mount_setattr(zhp, nspflags);
}
}
@@ -2049,7 +2029,8 @@ zfs_prop_inherit(zfs_handle_t *zhp, const char *propname, boolean_t received)
*/
if (zfs_is_namespace_prop(prop) &&
zfs_is_mounted(zhp, NULL))
- ret = zfs_mount(zhp, MNTOPT_REMOUNT, 0);
+ ret = zfs_mount_setattr(zhp,
+ zfs_namespace_prop_flag(prop));
}
error:
@@ -3148,7 +3129,7 @@ userquota_propname_decode(const char *propname, boolean_t zoned,
zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp)
{
zfs_userquota_prop_t type;
- char *cp;
+ const char *cp;
boolean_t isuser;
boolean_t isgroup;
boolean_t isproject;
@@ -4489,12 +4470,13 @@ zfs_rename(zfs_handle_t *zhp, const char *target, renameflags_t flags)
{
int ret = 0;
zfs_cmd_t zc = {"\0"};
- char *delim;
prop_changelist_t *cl = NULL;
char parent[ZFS_MAX_DATASET_NAME_LEN];
char property[ZFS_MAXPROPLEN];
libzfs_handle_t *hdl = zhp->zfs_hdl;
char errbuf[ERRBUFLEN];
+ const char *delim;
+ char *delim2;
/* if we have the same exact name, just return success */
if (strcmp(zhp->zfs_name, target) == 0)
@@ -4519,11 +4501,11 @@ zfs_rename(zfs_handle_t *zhp, const char *target, renameflags_t flags)
*/
(void) strlcpy(parent, zhp->zfs_name,
sizeof (parent));
- delim = strchr(parent, '@');
+ delim2 = strchr(parent, '@');
if (strchr(target, '@') == NULL)
- *(++delim) = '\0';
+ *(++delim2) = '\0';
else
- *delim = '\0';
+ *delim2 = '\0';
(void) strlcat(parent, target, sizeof (parent));
target = parent;
} else {
@@ -4544,6 +4526,7 @@ zfs_rename(zfs_handle_t *zhp, const char *target, renameflags_t flags)
if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
} else {
+
if (flags.recursive) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"recursive rename must be a snapshot"));
@@ -4599,8 +4582,8 @@ zfs_rename(zfs_handle_t *zhp, const char *target, renameflags_t flags)
}
if (flags.recursive) {
char *parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
- delim = strchr(parentname, '@');
- *delim = '\0';
+ delim2 = strchr(parentname, '@');
+ *delim2 = '\0';
zfs_handle_t *zhrp = zfs_open(zhp->zfs_hdl, parentname,
ZFS_TYPE_DATASET);
free(parentname);
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c b/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c
index 5f50bce531f7..bfe50dbf3106 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_diff.c
@@ -550,8 +550,8 @@ get_snapshot_names(differ_info_t *di, const char *fromsnap,
const char *tosnap)
{
libzfs_handle_t *hdl = di->zhp->zfs_hdl;
- char *atptrf = NULL;
- char *atptrt = NULL;
+ const char *atptrf = NULL;
+ const char *atptrt = NULL;
int fdslen, fsnlen;
int tdslen, tsnlen;
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_impl.h b/sys/contrib/openzfs/lib/libzfs/libzfs_impl.h
index 9053740ec2f0..50af307b555e 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_impl.h
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_impl.h
@@ -91,6 +91,19 @@ struct zfs_handle {
};
/*
+ * Internal namespace property flags for selective remount via
+ * mount_setattr(2). Passed to zfs_mount_setattr().
+ */
+#define ZFS_MNT_PROP_ATIME (1U << 0)
+#define ZFS_MNT_PROP_RELATIME (1U << 1)
+#define ZFS_MNT_PROP_DEVICES (1U << 2)
+#define ZFS_MNT_PROP_EXEC (1U << 3)
+#define ZFS_MNT_PROP_SETUID (1U << 4)
+#define ZFS_MNT_PROP_READONLY (1U << 5)
+#define ZFS_MNT_PROP_XATTR (1U << 6)
+#define ZFS_MNT_PROP_NBMAND (1U << 7)
+
+/*
* This is different from checking zfs_type, because it will also catch
* snapshots of volumes.
*/
@@ -182,6 +195,10 @@ extern prop_changelist_t *changelist_gather(zfs_handle_t *, zfs_prop_t, int,
extern int changelist_unshare(prop_changelist_t *, const enum sa_protocol *);
extern int changelist_haszonedchild(prop_changelist_t *);
+extern boolean_t zfs_is_namespace_prop(zfs_prop_t);
+extern uint32_t zfs_namespace_prop_flag(zfs_prop_t);
+extern boolean_t zfs_is_mountable_internal(zfs_handle_t *);
+extern int zfs_mount_setattr(zfs_handle_t *, uint32_t);
extern void remove_mountpoint(zfs_handle_t *);
extern int create_parents(libzfs_handle_t *, char *, int);
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c b/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c
index 5c9e2199eed4..e68b0db57bb1 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_mount.c
@@ -101,6 +101,47 @@ static const enum sa_protocol share_all_proto[SA_PROTOCOL_COUNT + 1] = {
+/*
+ * Returns B_TRUE if the property is a namespace property that requires
+ * a remount to take effect.
+ */
+boolean_t
+zfs_is_namespace_prop(zfs_prop_t prop)
+{
+ switch (prop) {
+ case ZFS_PROP_ATIME:
+ case ZFS_PROP_RELATIME:
+ case ZFS_PROP_DEVICES:
+ case ZFS_PROP_EXEC:
+ case ZFS_PROP_SETUID:
+ case ZFS_PROP_READONLY:
+ case ZFS_PROP_XATTR:
+ case ZFS_PROP_NBMAND:
+ return (B_TRUE);
+ default:
+ return (B_FALSE);
+ }
+}
+
+/*
+ * Returns the ZFS_MNT_PROP_* flag for a namespace property.
+ */
+uint32_t
+zfs_namespace_prop_flag(zfs_prop_t prop)
+{
+ switch (prop) {
+ case ZFS_PROP_ATIME: return (ZFS_MNT_PROP_ATIME);
+ case ZFS_PROP_RELATIME: return (ZFS_MNT_PROP_RELATIME);
+ case ZFS_PROP_DEVICES: return (ZFS_MNT_PROP_DEVICES);
+ case ZFS_PROP_EXEC: return (ZFS_MNT_PROP_EXEC);
+ case ZFS_PROP_SETUID: return (ZFS_MNT_PROP_SETUID);
+ case ZFS_PROP_READONLY: return (ZFS_MNT_PROP_READONLY);
+ case ZFS_PROP_XATTR: return (ZFS_MNT_PROP_XATTR);
+ case ZFS_PROP_NBMAND: return (ZFS_MNT_PROP_NBMAND);
+ default: return (0);
+ }
+}
+
static boolean_t
dir_is_empty_stat(const char *dirname)
{
@@ -223,7 +264,7 @@ zfs_is_mounted(zfs_handle_t *zhp, char **where)
* that the caller has verified the sanity of mounting the dataset at
* its mountpoint to the extent the caller wants.
*/
-static boolean_t
+boolean_t
zfs_is_mountable_internal(zfs_handle_t *zhp)
{
if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) &&
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c b/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c
index db5cd6dc00ac..42a1ddcf28a6 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c
@@ -581,7 +581,7 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
prop = zpool_name_to_prop(propname);
if (prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname)) {
int err;
- char *fname = strchr(propname, '@') + 1;
+ const char *fname = strchr(propname, '@') + 1;
err = zfeature_lookup_name(fname, NULL);
if (err != 0) {
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c b/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c
index 0e5cecc6cca9..2c38333e18a1 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c
@@ -2684,7 +2684,7 @@ zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd,
char bookname[ZFS_MAX_DATASET_NAME_LEN];
nvlist_t *redact_snaps;
zfs_handle_t *book_zhp;
- char *at, *pound;
+ const char *at, *pound;
int dsnamelen;
pound = strchr(redactbook, '#');
diff --git a/sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c b/sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c
index bc7d68b17eb1..3723769d4e30 100644
--- a/sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c
+++ b/sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_zmount.c
@@ -116,6 +116,17 @@ do_unmount(zfs_handle_t *zhp, const char *mntpt, int flags)
return (0);
}
+/*
+ * FreeBSD does not support mount_setattr(2). Fall back to a full
+ * remount so that the updated namespace property takes effect.
+ */
+int
+zfs_mount_setattr(zfs_handle_t *zhp, uint32_t nspflags)
+{
+ (void) nspflags;
+ return (zfs_mount(zhp, MNTOPT_REMOUNT, 0));
+}
+
int
zfs_mount_delegation_check(void)
{
diff --git a/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c b/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c
index 585d22d9e5b3..8ea72f462048 100644
--- a/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c
+++ b/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_mount_os.c
@@ -410,6 +410,149 @@ do_unmount(zfs_handle_t *zhp, const char *mntpt, int flags)
return (rc ? EINVAL : 0);
}
+#ifdef HAVE_MOUNT_SETATTR
+/*
+ * Build a struct mount_attr for the changed namespace properties.
+ * Parallel to zfs_add_options() but produces mount_setattr(2) input
+ * instead of a mount options string.
+ */
+static void
+zfs_add_options_setattr(zfs_handle_t *zhp, struct mount_attr *attr,
+ uint32_t nspflags)
+{
+ const char *source;
+
+ if (nspflags & ZFS_MNT_PROP_READONLY) {
+ if (getprop_uint64(zhp, ZFS_PROP_READONLY, &source))
+ attr->attr_set |= MOUNT_ATTR_RDONLY;
+ else
+ attr->attr_clr |= MOUNT_ATTR_RDONLY;
+ }
+ if (nspflags & ZFS_MNT_PROP_EXEC) {
+ if (getprop_uint64(zhp, ZFS_PROP_EXEC, &source))
+ attr->attr_clr |= MOUNT_ATTR_NOEXEC;
+ else
+ attr->attr_set |= MOUNT_ATTR_NOEXEC;
+ }
+ if (nspflags & ZFS_MNT_PROP_SETUID) {
+ if (getprop_uint64(zhp, ZFS_PROP_SETUID, &source))
+ attr->attr_clr |= MOUNT_ATTR_NOSUID;
+ else
+ attr->attr_set |= MOUNT_ATTR_NOSUID;
+ }
+ if (nspflags & ZFS_MNT_PROP_DEVICES) {
+ if (getprop_uint64(zhp, ZFS_PROP_DEVICES, &source))
+ attr->attr_clr |= MOUNT_ATTR_NODEV;
+ else
+ attr->attr_set |= MOUNT_ATTR_NODEV;
+ }
+ if (nspflags & (ZFS_MNT_PROP_ATIME | ZFS_MNT_PROP_RELATIME)) {
+ uint64_t atime = getprop_uint64(zhp, ZFS_PROP_ATIME, &source);
+ uint64_t relatime = getprop_uint64(zhp,
+ ZFS_PROP_RELATIME, &source);
+
+ attr->attr_clr |= MOUNT_ATTR__ATIME;
+ if (!atime)
+ attr->attr_set |= MOUNT_ATTR_NOATIME;
+ else if (relatime)
+ attr->attr_set |= MOUNT_ATTR_RELATIME;
+ else
+ attr->attr_set |= MOUNT_ATTR_STRICTATIME;
+ }
+}
+#endif /* HAVE_MOUNT_SETATTR */
+
+/*
+ * Selectively update per-mount VFS flags for the changed namespace
+ * properties using mount_setattr(2). Unlike a full remount via mount(2),
+ * this only modifies the specified flags without resetting others --
+ * avoiding clobbering temporary mount flags set by the administrator.
+ *
+ * For non-legacy datasets, the single known mountpoint is used.
+ * For legacy datasets, /proc/mounts is iterated since legacy datasets
+ * can be mounted at multiple locations.
+ *
+ * Falls back to a full remount via zfs_mount() when mount_setattr(2)
+ * is not available (ENOSYS), except for legacy mounts where a full
+ * remount would clobber temporary flags.
+ */
+int
+zfs_mount_setattr(zfs_handle_t *zhp, uint32_t nspflags)
+{
+#ifdef HAVE_MOUNT_SETATTR
+ struct mount_attr attr = { 0 };
+ char mntpt_prop[ZFS_MAXPROPLEN];
+ boolean_t legacy = B_FALSE;
+ libzfs_handle_t *hdl = zhp->zfs_hdl;
+ FILE *mnttab;
+ struct mnttab entry;
+ int ret = 0;
+
+ if (!zfs_is_mountable_internal(zhp))
+ return (0);
+
+ zfs_add_options_setattr(zhp, &attr, nspflags);
+ if (attr.attr_set == 0 && attr.attr_clr == 0)
+ return (0);
+
+ if (zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type,
+ B_FALSE)) {
+ verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mntpt_prop,
+ sizeof (mntpt_prop), NULL, NULL, 0, B_FALSE) == 0);
+ legacy = (strcmp(mntpt_prop, ZFS_MOUNTPOINT_LEGACY) == 0);
+ }
+
+ if (!legacy) {
+ char *mntpt = NULL;
+
+ if (!zfs_is_mounted(zhp, &mntpt))
+ return (0);
+
+ ret = mount_setattr(AT_FDCWD, mntpt, 0,
+ &attr, sizeof (attr));
+ free(mntpt);
+ if (ret != 0) {
+ if (errno == ENOSYS)
+ return (zfs_mount(zhp, MNTOPT_REMOUNT, 0));
+ return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
+ dgettext(TEXT_DOMAIN, "cannot set mount "
+ "attributes for '%s'"), zhp->zfs_name));
+ }
+ return (0);
+ }
+
+ /* Legacy: iterate /proc/mounts for all mountpoints. */
+ if ((mnttab = fopen(MNTTAB, "re")) == NULL)
+ return (0);
+
+ while (getmntent(mnttab, &entry) == 0) {
+ if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)
+ continue;
+ if (strcmp(entry.mnt_special, zhp->zfs_name) != 0)
+ continue;
+
+ ret = mount_setattr(AT_FDCWD, entry.mnt_mountp, 0,
+ &attr, sizeof (attr));
+ if (ret != 0) {
+ if (errno == ENOSYS) {
+ ret = 0;
+ break;
+ }
+ ret = zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
+ dgettext(TEXT_DOMAIN, "cannot set mount "
+ "attributes for '%s'"), zhp->zfs_name);
+ break;
+ }
+ }
+
+ (void) fclose(mnttab);
+ return (ret);
+#else
+ (void) nspflags;
+ return (zfs_mount(zhp, MNTOPT_REMOUNT, 0));
+#endif
+}
+
int
zfs_mount_delegation_check(void)
{
diff --git a/sys/contrib/openzfs/lib/libzfs_core/Makefile.am b/sys/contrib/openzfs/lib/libzfs_core/Makefile.am
index 42ac6081cc99..ec7aa95aa025 100644
--- a/sys/contrib/openzfs/lib/libzfs_core/Makefile.am
+++ b/sys/contrib/openzfs/lib/libzfs_core/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
libzfs_core_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS)
libzfs_core_la_CFLAGS += -fvisibility=hidden
diff --git a/sys/contrib/openzfs/lib/libzfsbootenv/Makefile.am b/sys/contrib/openzfs/lib/libzfsbootenv/Makefile.am
index 118f154821fc..d0d57e72554e 100644
--- a/sys/contrib/openzfs/lib/libzfsbootenv/Makefile.am
+++ b/sys/contrib/openzfs/lib/libzfsbootenv/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
libzfsbootenv_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS)
libzfsbootenv_la_CFLAGS += -fvisibility=hidden
diff --git a/sys/contrib/openzfs/lib/libzpool/Makefile.am b/sys/contrib/openzfs/lib/libzpool/Makefile.am
index 4658e025ea53..fb1255711c13 100644
--- a/sys/contrib/openzfs/lib/libzpool/Makefile.am
+++ b/sys/contrib/openzfs/lib/libzpool/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
libzpool_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS) $(LIBRARY_CFLAGS)
libzpool_la_CFLAGS += $(ZLIB_CFLAGS)
diff --git a/sys/contrib/openzfs/lib/libzstd/Makefile.am b/sys/contrib/openzfs/lib/libzstd/Makefile.am
index 856175137906..0788342d9b37 100644
--- a/sys/contrib/openzfs/lib/libzstd/Makefile.am
+++ b/sys/contrib/openzfs/lib/libzstd/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
libzstd_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS)
libzstd_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBZPOOL_CPPFLAGS)
diff --git a/sys/contrib/openzfs/lib/libzutil/Makefile.am b/sys/contrib/openzfs/lib/libzutil/Makefile.am
index 519906235f7f..5e085ec6c1f0 100644
--- a/sys/contrib/openzfs/lib/libzutil/Makefile.am
+++ b/sys/contrib/openzfs/lib/libzutil/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
libzutil_la_CFLAGS = $(AM_CFLAGS) $(LIBRARY_CFLAGS)
libzutil_la_CFLAGS += $(LIBBLKID_CFLAGS) $(LIBUDEV_CFLAGS)
libzutil_la_CFLAGS += -fvisibility=hidden
diff --git a/sys/contrib/openzfs/lib/libzutil/os/linux/zutil_device_path_os.c b/sys/contrib/openzfs/lib/libzutil/os/linux/zutil_device_path_os.c
index 8ed062bf9b37..64e05f52d95e 100644
--- a/sys/contrib/openzfs/lib/libzutil/os/linux/zutil_device_path_os.c
+++ b/sys/contrib/openzfs/lib/libzutil/os/linux/zutil_device_path_os.c
@@ -218,7 +218,8 @@ zfs_get_pci_slots_sys_path(const char *dev_name)
char *address2 = NULL;
char *path = NULL;
char buf[MAXPATHLEN];
- char *tmp;
+ const char *tmp;
+ char *tmp2;
/* If they preface 'dev' with a path (like "/dev") then strip it off */
tmp = strrchr(dev_name, '/');
@@ -240,9 +241,9 @@ zfs_get_pci_slots_sys_path(const char *dev_name)
* be "0000:01:00.0" while /sys/bus/pci/slots/0/address will be
* "0000:01:00". Just NULL terminate at the '.' so they match.
*/
- tmp = strrchr(address1, '.');
- if (tmp != NULL)
- *tmp = '\0';
+ tmp2 = strrchr(address1, '.');
+ if (tmp2 != NULL)
+ *tmp2 = '\0';
dp = opendir("/sys/bus/pci/slots/");
if (dp == NULL) {
@@ -311,6 +312,7 @@ zfs_get_enclosure_sysfs_path(const char *dev_name)
DIR *dp = NULL;
struct dirent *ep;
char buf[MAXPATHLEN];
+ const char *tmp0;
char *tmp1 = NULL;
char *tmp2 = NULL;
char *tmp3 = NULL;
@@ -322,9 +324,9 @@ zfs_get_enclosure_sysfs_path(const char *dev_name)
return (NULL);
/* If they preface 'dev' with a path (like "/dev") then strip it off */
- tmp1 = strrchr(dev_name, '/');
- if (tmp1 != NULL)
- dev_name = tmp1 + 1; /* +1 since we want the chr after '/' */
+ tmp0 = strrchr(dev_name, '/');
+ if (tmp0 != NULL)
+ dev_name = tmp0 + 1; /* +1 since we want the chr after '/' */
tmpsize = asprintf(&tmp1, "/sys/block/%s/device", dev_name);
if (tmpsize == -1 || tmp1 == NULL) {
diff --git a/sys/contrib/openzfs/man/Makefile.am b/sys/contrib/openzfs/man/Makefile.am
index 7a63641c1c39..6112fdee5ace 100644
--- a/sys/contrib/openzfs/man/Makefile.am
+++ b/sys/contrib/openzfs/man/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
dist_noinst_man_MANS = \
%D%/man1/cstyle.1
diff --git a/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S b/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S
index 4e78f47121d2..a05e64b29419 100644
--- a/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S
+++ b/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse2.S
@@ -34,8 +34,8 @@
#if defined(__aarch64__)
-/* make gcc <= 9 happy */
-#if !defined(LD_VERSION) || LD_VERSION >= 233010000
+/* check for .cfi_negate_ra_state assembler support */
+#if defined(HAVE_AS_CFI_PSEUDO_OP)
#define CFI_NEGATE_RA_STATE .cfi_negate_ra_state
#else
#define CFI_NEGATE_RA_STATE
diff --git a/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S b/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S
index 41da0aff6953..19f5408d4ef5 100644
--- a/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S
+++ b/sys/contrib/openzfs/module/icp/asm-aarch64/blake3/b3_aarch64_sse41.S
@@ -34,8 +34,8 @@
#if defined(__aarch64__)
-/* make gcc <= 9 happy */
-#if !defined(LD_VERSION) || LD_VERSION >= 233010000
+/* check for .cfi_negate_ra_state assembler support */
+#if defined(HAVE_AS_CFI_PSEUDO_OP)
#define CFI_NEGATE_RA_STATE .cfi_negate_ra_state
#else
#define CFI_NEGATE_RA_STATE
diff --git a/sys/contrib/openzfs/module/nvpair/nvpair.c b/sys/contrib/openzfs/module/nvpair/nvpair.c
index 14fbddb60f6b..07ac102145e2 100644
--- a/sys/contrib/openzfs/module/nvpair/nvpair.c
+++ b/sys/contrib/openzfs/module/nvpair/nvpair.c
@@ -1923,8 +1923,9 @@ nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep,
{
nvpair_t *nvp;
const char *np;
- char *sepp = NULL;
- char *idxp, *idxep;
+ const char *sepp = NULL;
+ const char *idxp;
+ char *idxep;
nvlist_t **nva;
long idx = 0;
int n;
diff --git a/sys/contrib/openzfs/module/os/freebsd/spl/spl_cmn_err.c b/sys/contrib/openzfs/module/os/freebsd/spl/spl_cmn_err.c
index 7b1bfd1caa07..5b2b0e5089c0 100644
--- a/sys/contrib/openzfs/module/os/freebsd/spl/spl_cmn_err.c
+++ b/sys/contrib/openzfs/module/os/freebsd/spl/spl_cmn_err.c
@@ -40,21 +40,21 @@ vcmn_err(int ce, const char *fmt, va_list adx)
prefix = NULL; /* silence unwitty compilers */
switch (ce) {
case CE_CONT:
- prefix = "Solaris(cont): ";
+ prefix = "zfs(cont): ";
break;
case CE_NOTE:
- prefix = "Solaris: NOTICE: ";
+ prefix = "zfs: NOTICE: ";
break;
case CE_WARN:
- prefix = "Solaris: WARNING: ";
+ prefix = "zfs: WARNING: ";
break;
case CE_PANIC:
- prefix = "Solaris(panic): ";
+ prefix = "zfs(panic): ";
break;
case CE_IGNORE:
break;
default:
- panic("Solaris: unknown severity level");
+ panic("zfs: unknown severity level");
}
if (ce == CE_PANIC) {
vsnprintf(buf, sizeof (buf), fmt, adx);
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
index 1b3eeb4353fe..6e52d90e0940 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
@@ -6767,10 +6767,12 @@ zfs_freebsd_advise(struct vop_advise_args *ap)
dmu_prefetch(os, zp->z_id, 0, start, len,
ZIO_PRIORITY_ASYNC_READ);
break;
+ case POSIX_FADV_DONTNEED:
+ dmu_evict_range(os, zp->z_id, start, len);
+ break;
case POSIX_FADV_NORMAL:
case POSIX_FADV_RANDOM:
case POSIX_FADV_SEQUENTIAL:
- case POSIX_FADV_DONTNEED:
case POSIX_FADV_NOREUSE:
/* ignored for now */
break;
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c b/sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c
index 1bd3500e9f66..ab7457b04e2e 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c
@@ -445,7 +445,11 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
v->vdev_has_securetrim = bdev_secure_discard_supported(bdev);
/* Inform the ZIO pipeline that we are non-rotational */
+#ifdef HAVE_BLK_QUEUE_ROT
+ v->vdev_nonrot = !blk_queue_rot(bdev_get_queue(bdev));
+#else
v->vdev_nonrot = blk_queue_nonrot(bdev_get_queue(bdev));
+#endif
/* Physical volume size in bytes for the partition */
*psize = bdev_capacity(bdev);
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_ctldir.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_ctldir.c
index 79fd8911102d..ff87f6aa2366 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_ctldir.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_ctldir.c
@@ -1201,8 +1201,10 @@ zfsctl_snapshot_mount(struct path *path, int flags)
error = zfsctl_snapshot_name(zfsvfs, dname(dentry),
ZFS_MAX_DATASET_NAME_LEN, full_name);
- if (error)
+ if (error) {
+ zfs_exit(zfsvfs, FTAG);
goto error;
+ }
if (is_current_chrooted() == 0) {
/*
@@ -1220,6 +1222,7 @@ zfsctl_snapshot_mount(struct path *path, int flags)
error = get_root_path(&mnt_path, m, MAXPATHLEN);
if (error != 0) {
kmem_free(m, MAXPATHLEN);
+ zfs_exit(zfsvfs, FTAG);
goto error;
}
mutex_enter(&zfsvfs->z_vfs->vfs_mntpt_lock);
@@ -1253,6 +1256,33 @@ zfsctl_snapshot_mount(struct path *path, int flags)
zfs_snapshot_no_setuid ? "nosuid" : "suid");
/*
+ * Release z_teardown_lock before potentially blocking operations
+ * (cv_wait for concurrent mounts, call_usermodehelper for the mount
+ * helper). Holding z_teardown_lock(R) across call_usermodehelper
+ * deadlocks with namespace_sem: the mount helper needs
+ * namespace_sem(W) via move_mount, while /proc/self/mountinfo
+ * readers hold namespace_sem(R) and need z_teardown_lock(R) via
+ * zpl_show_devname. A concurrent zfs_suspend_fs queuing
+ * z_teardown_lock(W) blocks new readers, completing the cycle.
+ * See https://github.com/openzfs/zfs/issues/18409
+ *
+ * Releasing the lock allows zfs_suspend_fs to proceed during
+ * the mount, so dmu_objset_hold in zpl_get_tree can transiently
+ * fail with ENOENT during the clone swap. The mount helper
+ * fails, this function returns EISDIR, and the VFS silently
+ * falls back to the ctldir stub (empty directory). The caller
+ * gets the stub inode instead of the real snapshot root until
+ * the next access retries the automount.
+ *
+ * Safe because everything below operates on local string copies
+ * (full_name, full_path) or uses its own synchronization
+ * (zfs_snapshot_lock, se_mtx). The parent zfsvfs pointer
+ * remains valid because we hold a path reference to the
+ * automount trigger dentry.
+ */
+ zfs_exit(zfsvfs, FTAG);
+
+ /*
* Check if snapshot is already being mounted. If found, wait for
* pending mount to complete before returning success.
*/
@@ -1366,8 +1396,7 @@ zfsctl_snapshot_mount(struct path *path, int flags)
error:
kmem_free(full_name, ZFS_MAX_DATASET_NAME_LEN);
kmem_free(full_path, MAXPATHLEN);
-
- zfs_exit(zfsvfs, FTAG);
+ kmem_free(options, 7);
return (error);
}
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_uio.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_uio.c
index 8f9b161995f4..bfce9e6b5202 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_uio.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_uio.c
@@ -234,6 +234,8 @@ zfs_uiomove_iter(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio,
boolean_t revert)
{
size_t cnt = MIN(n, uio->uio_resid);
+ size_t oldcnt = cnt;
+ int error = 0;
if (rw == UIO_READ)
cnt = copy_to_iter(p, cnt, uio->uio_iter);
@@ -249,16 +251,21 @@ zfs_uiomove_iter(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio,
return (EFAULT);
/*
- * Revert advancing the uio_iter. This is set by zfs_uiocopy()
- * to avoid consuming the uio and its iov_iter structure.
+ * When revert is set this is a zfs_uiocopy() which should not
+ * consume the uio and its iov_iter structure. Otherwise, it's
+ * a zfs_uiomove() which is expected to update the uio. Partial
+ * copies are allowed for both copy and move but EFAULT should
+ * be returned for zfs_uiomove().
*/
if (revert)
iov_iter_revert(uio->uio_iter, cnt);
+ else if (cnt != oldcnt)
+ error = EFAULT;
uio->uio_resid -= cnt;
uio->uio_loffset += cnt;
- return (0);
+ return (error);
}
int
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_vfsops.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_vfsops.c
index 8a7d14ab6119..a3a7b5f5ac34 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_vfsops.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_vfsops.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 by Delphix. All rights reserved.
+ * Copyright (c) 2026, TrueNAS.
*/
/* Portions Copyright 2010 Robert Milkowski */
@@ -64,53 +65,15 @@
#include <linux/fs.h>
#include "zfs_comutil.h"
-enum {
- TOKEN_RO,
- TOKEN_RW,
- TOKEN_SETUID,
- TOKEN_NOSETUID,
- TOKEN_EXEC,
- TOKEN_NOEXEC,
- TOKEN_DEVICES,
- TOKEN_NODEVICES,
- TOKEN_DIRXATTR,
- TOKEN_SAXATTR,
- TOKEN_XATTR,
- TOKEN_NOXATTR,
- TOKEN_ATIME,
- TOKEN_NOATIME,
- TOKEN_RELATIME,
- TOKEN_NORELATIME,
- TOKEN_NBMAND,
- TOKEN_NONBMAND,
- TOKEN_MNTPOINT,
- TOKEN_LAST,
-};
-
-static const match_table_t zpl_tokens = {
- { TOKEN_RO, MNTOPT_RO },
- { TOKEN_RW, MNTOPT_RW },
- { TOKEN_SETUID, MNTOPT_SETUID },
- { TOKEN_NOSETUID, MNTOPT_NOSETUID },
- { TOKEN_EXEC, MNTOPT_EXEC },
- { TOKEN_NOEXEC, MNTOPT_NOEXEC },
- { TOKEN_DEVICES, MNTOPT_DEVICES },
- { TOKEN_NODEVICES, MNTOPT_NODEVICES },
- { TOKEN_DIRXATTR, MNTOPT_DIRXATTR },
- { TOKEN_SAXATTR, MNTOPT_SAXATTR },
- { TOKEN_XATTR, MNTOPT_XATTR },
- { TOKEN_NOXATTR, MNTOPT_NOXATTR },
- { TOKEN_ATIME, MNTOPT_ATIME },
- { TOKEN_NOATIME, MNTOPT_NOATIME },
- { TOKEN_RELATIME, MNTOPT_RELATIME },
- { TOKEN_NORELATIME, MNTOPT_NORELATIME },
- { TOKEN_NBMAND, MNTOPT_NBMAND },
- { TOKEN_NONBMAND, MNTOPT_NONBMAND },
- { TOKEN_MNTPOINT, MNTOPT_MNTPOINT "=%s" },
- { TOKEN_LAST, NULL },
-};
+vfs_t *
+zfsvfs_vfs_alloc(void)
+{
+ vfs_t *vfsp = kmem_zalloc(sizeof (vfs_t), KM_SLEEP);
+ mutex_init(&vfsp->vfs_mntpt_lock, NULL, MUTEX_DEFAULT, NULL);
+ return (vfsp);
+}
-static void
+void
zfsvfs_vfs_free(vfs_t *vfsp)
{
if (vfsp != NULL) {
@@ -121,139 +84,6 @@ zfsvfs_vfs_free(vfs_t *vfsp)
}
}
-static int
-zfsvfs_parse_option(char *option, int token, substring_t *args, vfs_t *vfsp)
-{
- switch (token) {
- case TOKEN_RO:
- vfsp->vfs_readonly = B_TRUE;
- vfsp->vfs_do_readonly = B_TRUE;
- break;
- case TOKEN_RW:
- vfsp->vfs_readonly = B_FALSE;
- vfsp->vfs_do_readonly = B_TRUE;
- break;
- case TOKEN_SETUID:
- vfsp->vfs_setuid = B_TRUE;
- vfsp->vfs_do_setuid = B_TRUE;
- break;
- case TOKEN_NOSETUID:
- vfsp->vfs_setuid = B_FALSE;
- vfsp->vfs_do_setuid = B_TRUE;
- break;
- case TOKEN_EXEC:
- vfsp->vfs_exec = B_TRUE;
- vfsp->vfs_do_exec = B_TRUE;
- break;
- case TOKEN_NOEXEC:
- vfsp->vfs_exec = B_FALSE;
- vfsp->vfs_do_exec = B_TRUE;
- break;
- case TOKEN_DEVICES:
- vfsp->vfs_devices = B_TRUE;
- vfsp->vfs_do_devices = B_TRUE;
- break;
- case TOKEN_NODEVICES:
- vfsp->vfs_devices = B_FALSE;
- vfsp->vfs_do_devices = B_TRUE;
- break;
- case TOKEN_DIRXATTR:
- vfsp->vfs_xattr = ZFS_XATTR_DIR;
- vfsp->vfs_do_xattr = B_TRUE;
- break;
- case TOKEN_SAXATTR:
- vfsp->vfs_xattr = ZFS_XATTR_SA;
- vfsp->vfs_do_xattr = B_TRUE;
- break;
- case TOKEN_XATTR:
- vfsp->vfs_xattr = ZFS_XATTR_SA;
- vfsp->vfs_do_xattr = B_TRUE;
- break;
- case TOKEN_NOXATTR:
- vfsp->vfs_xattr = ZFS_XATTR_OFF;
- vfsp->vfs_do_xattr = B_TRUE;
- break;
- case TOKEN_ATIME:
- vfsp->vfs_atime = B_TRUE;
- vfsp->vfs_do_atime = B_TRUE;
- break;
- case TOKEN_NOATIME:
- vfsp->vfs_atime = B_FALSE;
- vfsp->vfs_do_atime = B_TRUE;
- break;
- case TOKEN_RELATIME:
- vfsp->vfs_relatime = B_TRUE;
- vfsp->vfs_do_relatime = B_TRUE;
- break;
- case TOKEN_NORELATIME:
- vfsp->vfs_relatime = B_FALSE;
- vfsp->vfs_do_relatime = B_TRUE;
- break;
- case TOKEN_NBMAND:
- vfsp->vfs_nbmand = B_TRUE;
- vfsp->vfs_do_nbmand = B_TRUE;
- break;
- case TOKEN_NONBMAND:
- vfsp->vfs_nbmand = B_FALSE;
- vfsp->vfs_do_nbmand = B_TRUE;
- break;
- case TOKEN_MNTPOINT:
- if (vfsp->vfs_mntpoint != NULL)
- kmem_strfree(vfsp->vfs_mntpoint);
- vfsp->vfs_mntpoint = match_strdup(&args[0]);
- if (vfsp->vfs_mntpoint == NULL)
- return (SET_ERROR(ENOMEM));
- break;
- default:
- break;
- }
-
- return (0);
-}
-
-/*
- * Parse the raw mntopts and return a vfs_t describing the options.
- */
-static int
-zfsvfs_parse_options(char *mntopts, vfs_t **vfsp)
-{
- vfs_t *tmp_vfsp;
- int error;
-
- tmp_vfsp = kmem_zalloc(sizeof (vfs_t), KM_SLEEP);
- mutex_init(&tmp_vfsp->vfs_mntpt_lock, NULL, MUTEX_DEFAULT, NULL);
-
- if (mntopts != NULL) {
- substring_t args[MAX_OPT_ARGS];
- char *tmp_mntopts, *p, *t;
- int token;
-
- tmp_mntopts = t = kmem_strdup(mntopts);
- if (tmp_mntopts == NULL)
- return (SET_ERROR(ENOMEM));
-
- while ((p = strsep(&t, ",")) != NULL) {
- if (!*p)
- continue;
-
- args[0].to = args[0].from = NULL;
- token = match_token(p, zpl_tokens, args);
- error = zfsvfs_parse_option(p, token, args, tmp_vfsp);
- if (error) {
- kmem_strfree(tmp_mntopts);
- zfsvfs_vfs_free(tmp_vfsp);
- return (error);
- }
- }
-
- kmem_strfree(tmp_mntopts);
- }
-
- *vfsp = tmp_vfsp;
-
- return (0);
-}
-
boolean_t
zfs_is_readonly(zfsvfs_t *zfsvfs)
{
@@ -1486,20 +1316,16 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
static atomic_long_t zfs_bdi_seq = ATOMIC_LONG_INIT(0);
int
-zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent)
+zfs_domount(struct super_block *sb, const char *osname,
+ vfs_t *vfs, int silent)
{
- const char *osname = zm->mnt_osname;
struct inode *root_inode = NULL;
uint64_t recordsize;
int error = 0;
zfsvfs_t *zfsvfs = NULL;
- vfs_t *vfs = NULL;
int canwrite;
int dataset_visible_zone;
- ASSERT(zm);
- ASSERT(osname);
-
dataset_visible_zone = zone_dataset_visible(osname, &canwrite);
/*
@@ -1511,10 +1337,6 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent)
return (SET_ERROR(EPERM));
}
- error = zfsvfs_parse_options(zm->mnt_data, &vfs);
- if (error)
- return (error);
-
/*
* If a non-writable filesystem is being mounted without the
* read-only flag, pretend it was set, as done for snapshots.
@@ -1523,16 +1345,12 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent)
vfs->vfs_readonly = B_TRUE;
error = zfsvfs_create(osname, vfs->vfs_readonly, &zfsvfs);
- if (error) {
- zfsvfs_vfs_free(vfs);
+ if (error)
goto out;
- }
if ((error = dsl_prop_get_integer(osname, "recordsize",
- &recordsize, NULL))) {
- zfsvfs_vfs_free(vfs);
+ &recordsize, NULL)))
goto out;
- }
vfs->vfs_data = zfsvfs;
zfsvfs->z_vfs = vfs;
@@ -1614,6 +1432,13 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent)
out:
if (error) {
if (zfsvfs != NULL) {
+ /*
+ * We're returning error, so the caller still owns
+ * the mount options vfs_t. Remove them from zfsvfs
+ * so we don't try to free them.
+ */
+ zfsvfs->z_vfs = NULL;
+
dmu_objset_disown(zfsvfs->z_os, B_TRUE, zfsvfs);
zfsvfs_free(zfsvfs);
}
@@ -1704,24 +1529,16 @@ zfs_umount(struct super_block *sb)
}
int
-zfs_remount(struct super_block *sb, int *flags, zfs_mnt_t *zm)
+zfs_remount(struct super_block *sb, vfs_t *vfsp, int flags)
{
zfsvfs_t *zfsvfs = sb->s_fs_info;
- vfs_t *vfsp;
boolean_t issnap = dmu_objset_is_snapshot(zfsvfs->z_os);
- int error;
if ((issnap || !spa_writeable(dmu_objset_spa(zfsvfs->z_os))) &&
- !(*flags & SB_RDONLY)) {
- *flags |= SB_RDONLY;
+ !(flags & SB_RDONLY))
return (EROFS);
- }
- error = zfsvfs_parse_options(zm->mnt_data, &vfsp);
- if (error)
- return (error);
-
- if (!zfs_is_readonly(zfsvfs) && (*flags & SB_RDONLY))
+ if (!zfs_is_readonly(zfsvfs) && (flags & SB_RDONLY))
txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0);
zfs_unregister_callbacks(zfsvfs);
@@ -1732,7 +1549,7 @@ zfs_remount(struct super_block *sb, int *flags, zfs_mnt_t *zm)
if (!issnap)
(void) zfs_register_callbacks(vfsp);
- return (error);
+ return (0);
}
int
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c b/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c
index f7691c02d163..ffe227796f0a 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c
@@ -43,6 +43,9 @@
#ifdef HAVE_VFS_FILEMAP_DIRTY_FOLIO
#include <linux/writeback.h>
#endif
+#ifdef HAVE_FILELOCK_HEADER
+#include <linux/filelock.h>
+#endif
/*
* When using fallocate(2) to preallocate space, inflate the requested
@@ -776,34 +779,23 @@ zpl_fadvise(struct file *filp, loff_t offset, loff_t len, int advice)
if ((error = zpl_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
return (error);
- switch (advice) {
- case POSIX_FADV_SEQUENTIAL:
- case POSIX_FADV_WILLNEED:
+ if (advice == POSIX_FADV_WILLNEED) {
+ loff_t rlen = len ? len : i_size_read(ip) - offset;
+ dmu_prefetch(os, zp->z_id, 0, offset, rlen,
+ ZIO_PRIORITY_ASYNC_READ);
+ if (!zn_has_cached_data(zp, offset, offset + rlen - 1)) {
+ zfs_exit(zfsvfs, FTAG);
+ return (error);
+ }
+ }
+
#ifdef HAVE_GENERIC_FADVISE
- if (zn_has_cached_data(zp, offset, offset + len - 1))
- error = generic_fadvise(filp, offset, len, advice);
+ error = generic_fadvise(filp, offset, len, advice);
#endif
- /*
- * Pass on the caller's size directly, but note that
- * dmu_prefetch_max will effectively cap it. If there
- * really is a larger sequential access pattern, perhaps
- * dmu_zfetch will detect it.
- */
- if (len == 0)
- len = i_size_read(ip) - offset;
- dmu_prefetch(os, zp->z_id, 0, offset, len,
- ZIO_PRIORITY_ASYNC_READ);
- break;
- case POSIX_FADV_NORMAL:
- case POSIX_FADV_RANDOM:
- case POSIX_FADV_DONTNEED:
- case POSIX_FADV_NOREUSE:
- /* ignored for now */
- break;
- default:
- error = -EINVAL;
- break;
+ if (error == 0 && advice == POSIX_FADV_DONTNEED) {
+ loff_t rlen = len ? len : i_size_read(ip) - offset;
+ dmu_evict_range(os, zp->z_id, offset, rlen);
}
zfs_exit(zfsvfs, FTAG);
@@ -1242,6 +1234,7 @@ const struct file_operations zpl_file_operations = {
.mmap = zpl_mmap,
.fsync = zpl_fsync,
.fallocate = zpl_fallocate,
+ .setlease = generic_setlease,
.copy_file_range = zpl_copy_file_range,
#ifdef HAVE_VFS_CLONE_FILE_RANGE
.clone_file_range = zpl_clone_file_range,
@@ -1264,6 +1257,7 @@ const struct file_operations zpl_dir_file_operations = {
.read = generic_read_dir,
.iterate_shared = zpl_iterate,
.fsync = zpl_fsync,
+ .setlease = generic_setlease,
.unlocked_ioctl = zpl_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = zpl_compat_ioctl,
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zpl_super.c b/sys/contrib/openzfs/module/os/linux/zfs/zpl_super.c
index 347b352506e5..2cd0f17c860f 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zpl_super.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zpl_super.c
@@ -24,6 +24,7 @@
* Copyright (c) 2023, Datto Inc. All rights reserved.
* Copyright (c) 2025, Klara, Inc.
* Copyright (c) 2025, Rob Norris <robn@despairlabs.com>
+ * Copyright (c) 2026, TrueNAS.
*/
@@ -35,6 +36,8 @@
#include <linux/iversion.h>
#include <linux/version.h>
#include <linux/vfs_compat.h>
+#include <linux/fs_context.h>
+#include <linux/fs_parser.h>
/*
* What to do when the last reference to an inode is released. If 0, the kernel
@@ -265,21 +268,6 @@ zpl_statfs(struct dentry *dentry, struct kstatfs *statp)
}
static int
-zpl_remount_fs(struct super_block *sb, int *flags, char *data)
-{
- zfs_mnt_t zm = { .mnt_osname = NULL, .mnt_data = data };
- fstrans_cookie_t cookie;
- int error;
-
- cookie = spl_fstrans_mark();
- error = -zfs_remount(sb, flags, &zm);
- spl_fstrans_unmark(cookie);
- ASSERT3S(error, <=, 0);
-
- return (error);
-}
-
-static int
__zpl_show_devname(struct seq_file *seq, zfsvfs_t *zfsvfs)
{
int error;
@@ -354,21 +342,6 @@ zpl_show_options(struct seq_file *seq, struct dentry *root)
}
static int
-zpl_fill_super(struct super_block *sb, void *data, int silent)
-{
- zfs_mnt_t *zm = (zfs_mnt_t *)data;
- fstrans_cookie_t cookie;
- int error;
-
- cookie = spl_fstrans_mark();
- error = -zfs_domount(sb, zm, silent);
- spl_fstrans_unmark(cookie);
- ASSERT3S(error, <=, 0);
-
- return (error);
-}
-
-static int
zpl_test_super(struct super_block *s, void *data)
{
zfsvfs_t *zfsvfs = s->s_fs_info;
@@ -383,17 +356,477 @@ zpl_test_super(struct super_block *s, void *data)
return (zfsvfs != NULL && os == zfsvfs->z_os);
}
-static struct super_block *
-zpl_mount_impl(struct file_system_type *fs_type, int flags, zfs_mnt_t *zm)
+static void
+zpl_kill_sb(struct super_block *sb)
+{
+ zfs_preumount(sb);
+ kill_anon_super(sb);
+}
+
+void
+zpl_prune_sb(uint64_t nr_to_scan, void *arg)
+{
+ struct super_block *sb = (struct super_block *)arg;
+ int objects = 0;
+
+ /*
+ * Ensure the superblock is not in the process of being torn down.
+ */
+#ifdef HAVE_SB_DYING
+ if (down_read_trylock(&sb->s_umount)) {
+ if (!(sb->s_flags & SB_DYING) && sb->s_root &&
+ (sb->s_flags & SB_BORN)) {
+ (void) zfs_prune(sb, nr_to_scan, &objects);
+ }
+ up_read(&sb->s_umount);
+ }
+#else
+ if (down_read_trylock(&sb->s_umount)) {
+ if (!hlist_unhashed(&sb->s_instances) &&
+ sb->s_root && (sb->s_flags & SB_BORN)) {
+ (void) zfs_prune(sb, nr_to_scan, &objects);
+ }
+ up_read(&sb->s_umount);
+ }
+#endif
+}
+
+/*
+ * Mount option parsing.
+ *
+ * The kernel receives a set of "stringy" mount options, typically a
+ * comma-separated list through mount(2) or fsconfig(2). These are split into a
+ * set of struct fs_parameter, and then vfs_parse_fs_param() is called for
+ * each. That function will handle (and consume) some options directly, and
+ * other subsystems (mainly security modules) are given the opportunity to
+ * consume them too. Any left over are passed to zpl_parse_param(). Our job is
+ * to use them to fill in the vfs_t we've attached previously to
+ * fc->fs_private, ready for the mount or remount call when it comes.
+ *
+ * Historically, mount options have been generated, removed, modified and
+ * otherwise complicated by multiple different actors over a long time: the
+ * kernel itself, the original mount(8) utility and later libmount,
+ * mount.zfs(8), libzfs and the ZFS tools that use it, and any program using
+ * the various mount APIs that have come and gone over the years. This is
+ * further complicated by cross-pollination between OpenSolaris/illumos, Linux
+ * and FreeBSD. Long story short: we could see all sorts of things, and we need
+ * to at least try not to break old userspace programs.
+ *
+ * At time of writing, this is my best understanding of all the options we
+ * might reasonably see, and where and how they're handled.
+ *
+ *
+ * These are common options for all filesystems that are processed by the
+ * kernel directly, without zpl_parse_param() being called. They're a bit of a
+ * mixed bag, but are ultimately all available to us via either sb->s_flags or
+ * fc->sb_flags:
+ *
+ * dirsync: set SB_DIRSYNC
+ * lazytime: set SB_LAZYTIME
+ * mand: set SB_MANDLOCK
+ * ro: set SB_RDONLY
+ * sync: set SB_SYNCHRONOUS
+ *
+ * async: clear SB_SYNCHRONOUS
+ * nolazytime: clear SB_LAZYTIME
+ * nomand: clear SB_MANDLOCK
+ * rw: clear SB_RDONLY
+ *
+ * Fortunately, almost all of these are handled directly by the kernel. 'mand'
+ * and 'nomand' are swallowed by the kernel ('mand' emits a warning in the
+ * kernel log), but it and the corresponding dataset property have been a no-op
+ * in OpenZFS for years, so there's nothing for us to do there.
+ *
+ * The only tricky one is SB_RDONLY ('ro'/'rw'), which can be both a mount and
+ * a superblock option. While we won't receive the "stringy" options, the
+ * kernel will set it for us in fc->sb_flags, and we've always had special
+ * handling for it at mount and remount time (eg handling snapshot mounts), so
+ * it's not a problem to do nothing here because we will sort it out later.
+ *
+ *
+ * These are options that we may receive as "stringy" options but also as mount
+ * flags.
+ *
+ * exec: clear MS_NOEXEC
+ * noexec: set MS_NOEXEC
+ * suid: clear MS_NOSUID
+ * nosuid: set MS_NOSUID
+ * dev: clear MS_NODEV
+ * nodev: set MS_NODEV
+ * atime: clear MS_NOATIME
+ * noatime: set MS_NOATIME
+ * relatime: set MS_RELATIME
+ * norelatime: clear MS_RELATIME
+ *
+ * In testing, it appears that recent libmount will convert them, but our own
+ * mount code (libzfs_mount) may not. We will be called for the stringy
+ * versions, but not for the flags. The flags will later be available on
+ * vfsmount->mnt_flags, not set on the vfs_t. This tends not to matter in
+ * practice, as almost all mounts come through libzfs (via zfs-mount(8) or
+ * mount.zfs(8)) and so as strings, and when they do come through flags, they
+ * will still be reported correctly via mountinfo and by zfs-get(8), which has
+ * special handling for "temporary" properties. Also, we never use these
+ * internally for any decisions; 'exec', 'suid' and 'dev' are handled in the
+ * kernel, and the kernel provides helpers for 'atime' and 'relatime'. The
+ * only place the difference is observable is through zfs_get_temporary_prop(),
+ * which is only used by the zfs.get_prop() Lua call.
+ *
+ * This is fixable by getting at vfsmount->mnt_flags, but this is not readily
+ * available until after the mount operation is completed, and with some
+ * effort. This is all very low impact, so it's left for future improvement.
+ *
+ *
+ * These are true OpenZFS-specific mount options. They give the equivalent
+ * of temporarily setting the pool properties as follows:
+ *
+ * strictatime atime=on, relatime=off
+ *
+ * xattr: xattr=sa
+ * saxattr: xattr=sa
+ * dirxattr: xattr=dir
+ * noxattr: xattr=off
+ *
+ *
+ * mntpoint= provides the canonical mount point for a snapshot mount. This
+ * is an assist for the snapshot automounter call out to userspace, to
+ * understand where the snapshot is mounted even when triggered from an
+ * alternate mount namespace (eg inside a chroot).
+ *
+ * mntpoint= vfs->vfs_mntpoint=...
+ *
+ *
+ * These are used for coordination inside libzfs, and should not make it
+ * to the kernel, but it does not strip them, so we handle them and ignore
+ * them.
+ *
+ * defaults
+ * zfsutil
+ * remount
+ *
+ *
+ * These are specific to SELinux. When that security module is running, it
+ * will consume them, but if not, they will be passed through to us. libzfs
+ * adds them unconditionally, so we will always see them when SELinux is not
+ * running, and ignore them.
+ *
+ * fscontext
+ * defcontext
+ * rootcontext
+ * context
+ *
+ *
+ * When preparing a remount, libmount will read /proc/self/mountinfo and add
+ * any unrecognised flags it finds there to the options. So, we have to accept
+ * anything that __zpl_show_options() can produce.
+ *
+ * posixacl
+ * noacl
+ * casesensitive
+ * caseinsensitive
+ * casemixed
+ *
+ *
+ * mount(8) has a notion of "sloppy" options. According to the documentation,
+ * when the -s switch is provided, unrecognised mount options will be ignored.
+ * Only the Linux NFS and SMB filesystems support it, and traditionally
+ * OpenZFS has too. however, it appears massively underspecified and
+ * inconsistent. Depending on the interplay between mount(8), the mount helper
+ * (eg mount.zfs(8)) and libmount, -s may cause unknown options to be filtered
+ * in userspace, _or_ an additional option 'sloppy' to be passed to the kernel
+ * either before or after the "unknown" option, _or_ nothing at all happens
+ * and the unknown option to be passed through to the kernel as-is. The
+ * kernel NFS and SMB filesystems both expect to see an explicit option
+ * 'sloppy' and use this to either ignore or reject unknown options, but as
+ * described, it's very easy for that option to not appear, or appear too late.
+ *
+ * OpenZFS has a test for this in the test suite, and it's documented in
+ * mount.zfs(8), so to support it we accept 'sloppy' and ignore it, and all
+ * other unknown options produce a notice in the kernel log, and are also
+ * ignored. This allows the "feature" to continue to work, while avoiding
+ * the additional housekeeping for the 'sloppy' option.
+ *
+ * sloppy
+ *
+ *
+ * Finally, all filesystems get automatic handling for the 'source' option,
+ * that is, the "name" of the filesystem (the first column of df(1)'s output).
+ * However, this only happens if the handler does not otherwise handle
+ * the 'source' option. Since we handle _all_ options because of 'sloppy', we
+ * deal with this explicitly by calling into the kernel's helper for this,
+ * vfs_parse_fs_param_source(), which sets up fc->source.
+ *
+ * source
+ *
+ *
+ * Thank you for reading this far. I hope you find what you are looking for,
+ * in this life or the next.
+ *
+ * -- robn, 2026-03-26
+ */
+
+enum {
+ Opt_exec, Opt_suid, Opt_dev,
+ Opt_atime, Opt_relatime, Opt_strictatime,
+ Opt_saxattr, Opt_dirxattr, Opt_noxattr,
+ Opt_mntpoint,
+
+ Opt_ignore, Opt_warn,
+};
+
+static const struct fs_parameter_spec zpl_param_spec[] = {
+ fsparam_flag_no("exec", Opt_exec),
+ fsparam_flag_no("suid", Opt_suid),
+ fsparam_flag_no("dev", Opt_dev),
+
+ fsparam_flag_no("atime", Opt_atime),
+ fsparam_flag_no("relatime", Opt_relatime),
+ fsparam_flag("strictatime", Opt_strictatime),
+
+ fsparam_flag("xattr", Opt_saxattr),
+ fsparam_flag("saxattr", Opt_saxattr),
+ fsparam_flag("dirxattr", Opt_dirxattr),
+ fsparam_flag("noxattr", Opt_noxattr),
+
+ fsparam_string("mntpoint", Opt_mntpoint),
+
+ fsparam_flag("defaults", Opt_ignore),
+ fsparam_flag("zfsutil", Opt_ignore),
+ fsparam_flag("remount", Opt_ignore),
+
+ fsparam_string("fscontext", Opt_ignore),
+ fsparam_string("defcontext", Opt_ignore),
+ fsparam_string("rootcontext", Opt_ignore),
+ fsparam_string("context", Opt_ignore),
+
+ fsparam_flag("posixacl", Opt_ignore),
+ fsparam_flag("noacl", Opt_ignore),
+ fsparam_flag("casesensitive", Opt_ignore),
+ fsparam_flag("caseinsensitive", Opt_ignore),
+ fsparam_flag("casemixed", Opt_ignore),
+
+ fsparam_flag("sloppy", Opt_ignore),
+
+ {}
+};
+
+static int
+zpl_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
- struct super_block *s;
+ vfs_t *vfs = fc->fs_private;
+
+ /* Handle 'source' explicitly so we don't trip on it as an unknown. */
+ int opt = vfs_parse_fs_param_source(fc, param);
+ if (opt != -ENOPARAM)
+ return (opt);
+
+ struct fs_parse_result result;
+ opt = fs_parse(fc, zpl_param_spec, param, &result);
+ if (opt == -ENOPARAM) {
+ /*
+ * Convert unknowns to warnings, to work around the whole
+ * "sloppy option" mess.
+ */
+ opt = Opt_warn;
+ }
+ if (opt < 0)
+ return (opt);
+
+ switch (opt) {
+ case Opt_exec:
+ vfs->vfs_exec = !result.negated;
+ vfs->vfs_do_exec = B_TRUE;
+ break;
+ case Opt_suid:
+ vfs->vfs_setuid = !result.negated;
+ vfs->vfs_do_setuid = B_TRUE;
+ break;
+ case Opt_dev:
+ vfs->vfs_devices = !result.negated;
+ vfs->vfs_do_devices = B_TRUE;
+ break;
+
+ case Opt_atime:
+ vfs->vfs_atime = !result.negated;
+ vfs->vfs_do_atime = B_TRUE;
+ break;
+ case Opt_relatime:
+ vfs->vfs_relatime = !result.negated;
+ vfs->vfs_do_relatime = B_TRUE;
+ break;
+ case Opt_strictatime:
+ vfs->vfs_atime = B_TRUE;
+ vfs->vfs_do_atime = B_TRUE;
+ vfs->vfs_relatime = B_FALSE;
+ vfs->vfs_do_relatime = B_TRUE;
+ break;
+
+ case Opt_saxattr:
+ vfs->vfs_xattr = ZFS_XATTR_SA;
+ vfs->vfs_do_xattr = B_TRUE;
+ break;
+ case Opt_dirxattr:
+ vfs->vfs_xattr = ZFS_XATTR_DIR;
+ vfs->vfs_do_xattr = B_TRUE;
+ break;
+ case Opt_noxattr:
+ vfs->vfs_xattr = ZFS_XATTR_OFF;
+ vfs->vfs_do_xattr = B_TRUE;
+ break;
+
+ case Opt_mntpoint:
+ if (vfs->vfs_mntpoint != NULL)
+ kmem_strfree(vfs->vfs_mntpoint);
+ vfs->vfs_mntpoint = kmem_strdup(param->string);
+ break;
+
+ case Opt_ignore:
+ break;
+
+ case Opt_warn:
+ cmn_err(CE_NOTE,
+ "ZFS: ignoring unknown mount option: %s", param->key);
+ break;
+
+ default:
+ return (-SET_ERROR(EINVAL));
+ }
+
+ return (0);
+}
+
+/*
+ * Before Linux 5.8, the kernel's individual parameter parsing had a list of
+ * "forbidden" options that would always be rejected early. These were options
+ * that should be specified by MS_* flags, to be set on the superblock
+ * directly. However, it was inconsistently applied (eg it had various "*atime"
+ * options but not "atime", and also caused problems when it was not in sync
+ * with the version of libmount in use. It was deemed needlessly restrictive
+ * and was dropped in torvalds/linux@9193ae87a8af.
+ *
+ * Unfortunately, some of the options on this list are used by OpenZFS, so
+ * we need to see them. These include the aforementioned "*atime", "dev",
+ * "exec" and "suid".
+ *
+ * There is no easy compile-time check available to detect this, so we use
+ * a simple version check that should make it available everywhere needed,
+ * most notably RHEL8's 4.18+extras, which has backported fs_context support
+ * but does not include the 5.8 commit.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)
+#define HAVE_FORBIDDEN_SB_FLAGS 1
+#endif
+
+#ifdef HAVE_FORBIDDEN_SB_FLAGS
+/*
+ * The typical path for options parsing through mount(2) is:
+ *
+ * ksys_mount
+ * do_mount
+ * generic_parse_monolithic
+ * vfs_parse_fs_string
+ * vfs_parse_fs_param
+ * zpl_parse_param
+ *
+ * vfs_parse_fs_param() calls the internal vfs_parse_sb_flag(), which is
+ * where the "forbidden" flags are applied. If it makes it through there,
+ * it will later call fc->parse_param() ie zpl_parse_param(). We can't
+ * intercept this chain in the middle anywhere; the earliest thing we can
+ * override is generic_parse_monolithic(), substituting our own by setting
+ * fc->parse_monolithic and doing the parsing work ourselves.
+ *
+ * Fortunately, generic_parse_monolithic() is almost entirely splitting the
+ * incoming parameter string on comma and handing off to the rest of the
+ * pipeline. This is easily replaced (almost entirely by reviving a few bits
+ * of our old options parser).
+ *
+ * To keep the change as narrow as possible, we reuse zpl_param_spec and
+ * zpl_parse_param() as much as possible. Once we've parsed the option, we call
+ * fs_parse(zpl_param_spec) to find out if the option is actually one we
+ * explicitly care about. If it is, we call zpl_parse_param() directly,
+ * avoiding vfs_parse_fs_param() and so the risk of being rejected. If it is
+ * not one we explicitly care about, we call zpl_parse_param() as normal,
+ * letting the kernel reject it if it wishes. If it doesn't, it will end up
+ * back in zpl_parse_param() via fc->parse_param, and we can ignore or warn
+ * about it we normally would.
+ */
+static int
+zpl_parse_monolithic(struct fs_context *fc, void *data)
+{
+ char *mntopts = data;
+
+ if (mntopts == NULL)
+ return (0);
+
+ /*
+ * Because we supply a .parse_monolithic callback, the kernel does
+ * no consideration of the options blob at all. Because of this, we
+ * have to give LSMs a first look at it. They will remove any options
+ * of interest to them (eg the SELinux *context= options).
+ */
+ int err = security_sb_eat_lsm_opts(mntopts, &fc->security);
+ if (err)
+ return (err);
+
+ char *key;
+ while ((key = strsep(&mntopts, ",")) != NULL) {
+ if (!*key)
+ continue;
+
+ struct fs_parameter param = {
+ .key = key,
+ };
+
+ char *value = strchr(key, '=');
+ if (value != NULL) {
+ /* Key starts with '='. Kernel ignores, we will too. */
+ if (value == key)
+ continue;
+ *value++ = '\0';
+
+ /* key=value is a "string" type, set up for that */
+ param.string = value;
+ param.type = fs_value_is_string;
+ param.size = strlen(value);
+ } else {
+ /* unadorned key is a "flag" type */
+ param.type = fs_value_is_flag;
+ }
+
+ /* Check if this is one of our options. */
+ struct fs_parse_result result;
+ int opt = fs_parse(fc, zpl_param_spec, &param, &result);
+ if (opt >= 0) {
+ /*
+ * We already know this one of our options, so a
+ * failure here would be nonsensical.
+ */
+ VERIFY0(zpl_parse_param(fc, &param));
+ } else {
+ /*
+ * Not one of our option, send it through the kernel's
+ * standard parameter handling.
+ */
+ err = vfs_parse_fs_param(fc, &param);
+ if (err < 0)
+ return (err);
+ }
+ }
+
+ return (0);
+}
+#endif /* HAVE_FORBIDDEN_SB_FLAGS */
+
+static int
+zpl_get_tree(struct fs_context *fc)
+{
+ struct super_block *sb;
objset_t *os;
boolean_t issnap = B_FALSE;
int err;
- err = dmu_objset_hold(zm->mnt_osname, FTAG, &os);
+ err = dmu_objset_hold(fc->source, FTAG, &os);
if (err)
- return (ERR_PTR(-err));
+ return (-err);
/*
* The dsl pool lock must be released prior to calling sget().
@@ -405,7 +838,8 @@ zpl_mount_impl(struct file_system_type *fs_type, int flags, zfs_mnt_t *zm)
dsl_dataset_long_hold(dmu_objset_ds(os), FTAG);
dsl_pool_rele(dmu_objset_pool(os), FTAG);
- s = sget(fs_type, zpl_test_super, set_anon_super, flags, os);
+ sb = sget(fc->fs_type, zpl_test_super, set_anon_super,
+ fc->sb_flags, os);
/*
* Recheck with the lock held to prevent mounting the wrong dataset
@@ -415,93 +849,161 @@ zpl_mount_impl(struct file_system_type *fs_type, int flags, zfs_mnt_t *zm)
* also s_umount lock is not held there so it would race with
* zfs_umount and zfsvfs can be freed.
*/
- if (!IS_ERR(s) && s->s_fs_info != NULL) {
- zfsvfs_t *zfsvfs = s->s_fs_info;
+ if (!IS_ERR(sb) && sb->s_fs_info != NULL) {
+ zfsvfs_t *zfsvfs = sb->s_fs_info;
if (zpl_enter(zfsvfs, FTAG) == 0) {
if (os != zfsvfs->z_os)
- err = -SET_ERROR(EBUSY);
+ err = SET_ERROR(EBUSY);
issnap = zfsvfs->z_issnap;
zpl_exit(zfsvfs, FTAG);
} else {
- err = -SET_ERROR(EBUSY);
+ err = SET_ERROR(EBUSY);
}
}
dsl_dataset_long_rele(dmu_objset_ds(os), FTAG);
dsl_dataset_rele(dmu_objset_ds(os), FTAG);
- if (IS_ERR(s))
- return (ERR_CAST(s));
+ if (IS_ERR(sb))
+ return (PTR_ERR(sb));
if (err) {
- deactivate_locked_super(s);
- return (ERR_PTR(err));
+ deactivate_locked_super(sb);
+ return (-err);
}
- if (s->s_root == NULL) {
- err = zpl_fill_super(s, zm, flags & SB_SILENT ? 1 : 0);
+ if (sb->s_root == NULL) {
+ vfs_t *vfs = fc->fs_private;
+
+ /* Apply readonly flag as mount option */
+ if (fc->sb_flags & SB_RDONLY) {
+ vfs->vfs_readonly = B_TRUE;
+ vfs->vfs_do_readonly = B_TRUE;
+ }
+
+ fstrans_cookie_t cookie = spl_fstrans_mark();
+ err = zfs_domount(sb, fc->source, vfs,
+ fc->sb_flags & SB_SILENT ? 1 : 0);
+ spl_fstrans_unmark(cookie);
+
if (err) {
- deactivate_locked_super(s);
- return (ERR_PTR(err));
+ deactivate_locked_super(sb);
+ return (-err);
}
- s->s_flags |= SB_ACTIVE;
- } else if (!issnap && ((flags ^ s->s_flags) & SB_RDONLY)) {
+
+ /*
+ * zfsvfs has taken ownership of the mount options, so we
+ * need to ensure we don't free them.
+ */
+ fc->fs_private = NULL;
+
+ sb->s_flags |= SB_ACTIVE;
+ } else if (!issnap && ((fc->sb_flags ^ sb->s_flags) & SB_RDONLY)) {
/*
* Skip ro check for snap since snap is always ro regardless
* ro flag is passed by mount or not.
*/
- deactivate_locked_super(s);
- return (ERR_PTR(-EBUSY));
+ deactivate_locked_super(sb);
+ return (-SET_ERROR(EBUSY));
}
- return (s);
+ struct dentry *root = dget(sb->s_root);
+ if (IS_ERR(root))
+ return (PTR_ERR(root));
+
+ fc->root = root;
+ return (0);
}
-static struct dentry *
-zpl_mount(struct file_system_type *fs_type, int flags,
- const char *osname, void *data)
+static int
+zpl_reconfigure(struct fs_context *fc)
{
- zfs_mnt_t zm = { .mnt_osname = osname, .mnt_data = data };
+ fstrans_cookie_t cookie;
+ int error;
- struct super_block *sb = zpl_mount_impl(fs_type, flags, &zm);
- if (IS_ERR(sb))
- return (ERR_CAST(sb));
+ cookie = spl_fstrans_mark();
+ error = -zfs_remount(fc->root->d_sb, fc->fs_private, fc->sb_flags);
+ spl_fstrans_unmark(cookie);
+ ASSERT3S(error, <=, 0);
- return (dget(sb->s_root));
-}
+ if (error == 0) {
+ /*
+ * zfsvfs has taken ownership of the mount options, so we
+ * need to ensure we don't free them.
+ */
+ fc->fs_private = NULL;
+ }
-static void
-zpl_kill_sb(struct super_block *sb)
-{
- zfs_preumount(sb);
- kill_anon_super(sb);
+ return (error);
}
-void
-zpl_prune_sb(uint64_t nr_to_scan, void *arg)
+static int
+zpl_dup_fc(struct fs_context *fc, struct fs_context *src_fc)
{
- struct super_block *sb = (struct super_block *)arg;
- int objects = 0;
+ vfs_t *src_vfs = src_fc->fs_private;
+ if (src_vfs == NULL)
+ return (0);
+
+ vfs_t *vfs = zfsvfs_vfs_alloc();
+ if (vfs == NULL)
+ return (-SET_ERROR(ENOMEM));
/*
- * Ensure the superblock is not in the process of being torn down.
+ * This is annoying, but a straight memcpy() would require us to
+ * reinitialise the lock.
*/
-#ifdef HAVE_SB_DYING
- if (down_read_trylock(&sb->s_umount)) {
- if (!(sb->s_flags & SB_DYING) && sb->s_root &&
- (sb->s_flags & SB_BORN)) {
- (void) zfs_prune(sb, nr_to_scan, &objects);
- }
- up_read(&sb->s_umount);
- }
-#else
- if (down_read_trylock(&sb->s_umount)) {
- if (!hlist_unhashed(&sb->s_instances) &&
- sb->s_root && (sb->s_flags & SB_BORN)) {
- (void) zfs_prune(sb, nr_to_scan, &objects);
- }
- up_read(&sb->s_umount);
- }
+ vfs->vfs_xattr = src_vfs->vfs_xattr;
+ vfs->vfs_readonly = src_vfs->vfs_readonly;
+ vfs->vfs_do_readonly = src_vfs->vfs_do_readonly;
+ vfs->vfs_setuid = src_vfs->vfs_setuid;
+ vfs->vfs_do_setuid = src_vfs->vfs_do_setuid;
+ vfs->vfs_exec = src_vfs->vfs_exec;
+ vfs->vfs_do_exec = src_vfs->vfs_do_exec;
+ vfs->vfs_devices = src_vfs->vfs_devices;
+ vfs->vfs_do_devices = src_vfs->vfs_do_devices;
+ vfs->vfs_do_xattr = src_vfs->vfs_do_xattr;
+ vfs->vfs_atime = src_vfs->vfs_atime;
+ vfs->vfs_do_atime = src_vfs->vfs_do_atime;
+ vfs->vfs_relatime = src_vfs->vfs_relatime;
+ vfs->vfs_do_relatime = src_vfs->vfs_do_relatime;
+ vfs->vfs_nbmand = src_vfs->vfs_nbmand;
+ vfs->vfs_do_nbmand = src_vfs->vfs_do_nbmand;
+
+ mutex_enter(&src_vfs->vfs_mntpt_lock);
+ if (src_vfs->vfs_mntpoint != NULL)
+ vfs->vfs_mntpoint = kmem_strdup(src_vfs->vfs_mntpoint);
+ mutex_exit(&src_vfs->vfs_mntpt_lock);
+
+ fc->fs_private = vfs;
+ return (0);
+}
+
+static void
+zpl_free_fc(struct fs_context *fc)
+{
+ zfsvfs_vfs_free(fc->fs_private);
+}
+
+const struct fs_context_operations zpl_fs_context_operations = {
+#ifdef HAVE_FORBIDDEN_SB_FLAGS
+ .parse_monolithic = zpl_parse_monolithic,
#endif
+ .parse_param = zpl_parse_param,
+ .get_tree = zpl_get_tree,
+ .reconfigure = zpl_reconfigure,
+ .dup = zpl_dup_fc,
+ .free = zpl_free_fc,
+};
+
+static int
+zpl_init_fs_context(struct fs_context *fc)
+{
+ fc->fs_private = zfsvfs_vfs_alloc();
+ if (fc->fs_private == NULL)
+ return (-SET_ERROR(ENOMEM));
+
+ fc->ops = &zpl_fs_context_operations;
+
+ return (0);
}
const struct super_operations zpl_super_operations = {
@@ -517,7 +1019,6 @@ const struct super_operations zpl_super_operations = {
.put_super = zpl_put_super,
.sync_fs = zpl_sync_fs,
.statfs = zpl_statfs,
- .remount_fs = zpl_remount_fs,
.show_devname = zpl_show_devname,
.show_options = zpl_show_options,
.show_stats = NULL,
@@ -560,7 +1061,7 @@ struct file_system_type zpl_fs_type = {
#else
.fs_flags = FS_USERNS_MOUNT,
#endif
- .mount = zpl_mount,
+ .init_fs_context = zpl_init_fs_context,
.kill_sb = zpl_kill_sb,
};
diff --git a/sys/contrib/openzfs/module/zfs/dbuf.c b/sys/contrib/openzfs/module/zfs/dbuf.c
index e5fe400c475e..ee9a2270a86c 100644
--- a/sys/contrib/openzfs/module/zfs/dbuf.c
+++ b/sys/contrib/openzfs/module/zfs/dbuf.c
@@ -1481,8 +1481,12 @@ dbuf_read_hole(dmu_buf_impl_t *db, dnode_t *dn, blkptr_t *bp)
* Recheck BP_IS_HOLE() after dnode_block_freed() in case dnode_sync()
* processes the delete record and clears the bp while we are waiting
* for the dn_mtx (resulting in a "no" from block_freed).
+ *
+ * If bp != db->db_blkptr, it means that it was overridden (by a block
+ * clone or direct I/O write). We cannot rely on dnode_block_freed as
+ * the range can be freed in an earlier TXG but overridden in later.
*/
- if (!is_hole && db->db_level == 0)
+ if (!is_hole && db->db_level == 0 && bp == db->db_blkptr)
is_hole = dnode_block_freed(dn, db->db_blkid) || BP_IS_HOLE(bp);
if (is_hole) {
@@ -2078,6 +2082,65 @@ dbuf_free_range(dnode_t *dn, uint64_t start_blkid, uint64_t end_blkid,
kmem_free(db_search, sizeof (dmu_buf_impl_t));
}
+/*
+ * Advisory eviction of level-0 dbufs in [start_blkid, end_blkid] for
+ * the given dnode. Dirty dbufs carry a reference, so they will be
+ * evicted once their sync is completed.
+ */
+void
+dbuf_evict_range(dnode_t *dn, uint64_t start_blkid, uint64_t end_blkid)
+{
+ dmu_buf_impl_t *db_marker;
+ dmu_buf_impl_t *db, *db_next;
+ avl_index_t where;
+
+ db_marker = kmem_alloc(sizeof (dmu_buf_impl_t), KM_SLEEP);
+ db_marker->db_level = 0;
+ db_marker->db_blkid = start_blkid;
+ db_marker->db_state = DB_SEARCH;
+
+ mutex_enter(&dn->dn_dbufs_mtx);
+ db = avl_find(&dn->dn_dbufs, db_marker, &where);
+ ASSERT0P(db);
+ db = avl_nearest(&dn->dn_dbufs, where, AVL_AFTER);
+
+ for (; db != NULL; db = db_next) {
+ if (db->db_level != 0 || db->db_blkid > end_blkid)
+ break;
+
+ mutex_enter(&db->db_mtx);
+ if (db->db_state != DB_EVICTING &&
+ zfs_refcount_is_zero(&db->db_holds)) {
+ /*
+ * Clean and unreferenced: evict immediately.
+ * Use the marker pattern from dnode_evict_dbufs()
+ * because dbuf_destroy() may recursively remove
+ * the parent indirect dbuf from dn_dbufs, which
+ * could be the node db_next would point to.
+ */
+ db_marker->db_level = db->db_level;
+ db_marker->db_blkid = db->db_blkid;
+ db_marker->db_state = DB_MARKER;
+ db_marker->db_parent =
+ (void *)((uintptr_t)db - 1);
+ avl_insert_here(&dn->dn_dbufs, db_marker,
+ db, AVL_BEFORE);
+ dbuf_destroy(db);
+ db_next = AVL_NEXT(&dn->dn_dbufs, db_marker);
+ avl_remove(&dn->dn_dbufs, db_marker);
+ } else {
+ /* Referenced (possibly dirty): evict when released. */
+ db->db_pending_evict = TRUE;
+ db->db_partial_read = FALSE;
+ mutex_exit(&db->db_mtx);
+ db_next = AVL_NEXT(&dn->dn_dbufs, db);
+ }
+ }
+ mutex_exit(&dn->dn_dbufs_mtx);
+
+ kmem_free(db_marker, sizeof (dmu_buf_impl_t));
+}
+
void
dbuf_new_size(dmu_buf_impl_t *db, int size, dmu_tx_t *tx)
{
@@ -2202,6 +2265,17 @@ dbuf_dirty_lightweight(dnode_t *dn, uint64_t blkid, dmu_tx_t *tx)
mutex_enter(&dn->dn_mtx);
int txgoff = tx->tx_txg & TXG_MASK;
+
+ /*
+ * Assert that we are not modifying the range tree for the syncing
+ * TXG from a non-syncing thread. We verify that the tx's
+ * transaction group is strictly newer than the one currently
+ * syncing (meaning we are in open context). If this triggers,
+ * it indicates a race where syncing dn_free_range tree is
+ * being modified while dnode_sync() may be iterating over it.
+ */
+ ASSERT(tx->tx_txg > spa_syncing_txg(dn->dn_objset->os_spa));
+
if (dn->dn_free_ranges[txgoff] != NULL) {
zfs_range_tree_clear(dn->dn_free_ranges[txgoff], blkid, 1);
}
@@ -2389,6 +2463,7 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
db->db_blkid != DMU_SPILL_BLKID) {
mutex_enter(&dn->dn_mtx);
if (dn->dn_free_ranges[txgoff] != NULL) {
+ FREE_RANGE_VERIFY(tx, dn);
zfs_range_tree_clear(dn->dn_free_ranges[txgoff],
db->db_blkid, 1);
}
@@ -5446,6 +5521,7 @@ EXPORT_SYMBOL(dbuf_whichblock);
EXPORT_SYMBOL(dbuf_read);
EXPORT_SYMBOL(dbuf_unoverride);
EXPORT_SYMBOL(dbuf_free_range);
+EXPORT_SYMBOL(dbuf_evict_range);
EXPORT_SYMBOL(dbuf_new_size);
EXPORT_SYMBOL(dbuf_release_bp);
EXPORT_SYMBOL(dbuf_dirty);
diff --git a/sys/contrib/openzfs/module/zfs/dmu.c b/sys/contrib/openzfs/module/zfs/dmu.c
index 5690f8afad00..ad654b163195 100644
--- a/sys/contrib/openzfs/module/zfs/dmu.c
+++ b/sys/contrib/openzfs/module/zfs/dmu.c
@@ -899,6 +899,41 @@ dmu_prefetch_dnode(objset_t *os, uint64_t object, zio_priority_t pri)
}
/*
+ * Advisory cache eviction for a byte range of an object.
+ */
+void
+dmu_evict_range(objset_t *os, uint64_t object, uint64_t offset, uint64_t len)
+{
+ dnode_t *dn;
+
+ if (len == 0)
+ return;
+ if (dnode_hold(os, object, FTAG, &dn) != 0)
+ return;
+
+ /*
+ * Exclude the last block if the range end is not block-aligned:
+ * a sequential access may continue into that block. The first
+ * block is included even when partially covered since backwards
+ * access patterns are rare.
+ */
+ rw_enter(&dn->dn_struct_rwlock, RW_READER);
+ uint64_t start, end;
+ if (dn->dn_datablkshift != 0) {
+ start = dbuf_whichblock(dn, 0, offset);
+ end = dbuf_whichblock(dn, 0, offset + len);
+ } else {
+ start = (offset >= dn->dn_datablksz);
+ end = (offset + len >= dn->dn_datablksz);
+ }
+ if (end > start)
+ dbuf_evict_range(dn, start, end - 1);
+ rw_exit(&dn->dn_struct_rwlock);
+
+ dnode_rele(dn, FTAG);
+}
+
+/*
* Get the next "chunk" of file data to free. We traverse the file from
* the end so that the file gets shorter over time (if we crash in the
* middle, this will leave us in a better state). We find allocated file
@@ -2517,9 +2552,7 @@ dmu_write_policy(objset_t *os, dnode_t *dn, int level, int wp, zio_prop_t *zp)
memset(zp->zp_salt, 0, ZIO_DATA_SALT_LEN);
memset(zp->zp_iv, 0, ZIO_DATA_IV_LEN);
memset(zp->zp_mac, 0, ZIO_DATA_MAC_LEN);
- zp->zp_zpl_smallblk = (DMU_OT_IS_FILE(zp->zp_type) ||
- zp->zp_type == DMU_OT_ZVOL) ?
- os->os_zpl_special_smallblock : 0;
+ zp->zp_zpl_smallblk = os->os_zpl_special_smallblock;
zp->zp_storage_type = dn ? dn->dn_storage_type : DMU_OT_NONE;
ASSERT3U(zp->zp_compress, !=, ZIO_COMPRESS_INHERIT);
diff --git a/sys/contrib/openzfs/module/zfs/dmu_direct.c b/sys/contrib/openzfs/module/zfs/dmu_direct.c
index d44c686088fc..5b00698da728 100644
--- a/sys/contrib/openzfs/module/zfs/dmu_direct.c
+++ b/sys/contrib/openzfs/module/zfs/dmu_direct.c
@@ -91,6 +91,7 @@ dmu_write_direct_done(zio_t *zio)
dmu_sync_arg_t *dsa = zio->io_private;
dbuf_dirty_record_t *dr = dsa->dsa_dr;
dmu_buf_impl_t *db = dr->dr_dbuf;
+ dmu_tx_t *tx = dsa->dsa_tx;
abd_free(zio->io_abd);
@@ -101,6 +102,11 @@ dmu_write_direct_done(zio_t *zio)
db->db_state = DB_UNCACHED;
mutex_exit(&db->db_mtx);
+ /*
+ * dmu_sync_done() owns dsa and frees it after publishing the final
+ * override state. The direct-I/O error path still needs the original
+ * open-context tx to roll the dirty record back with dbuf_undirty().
+ */
dmu_sync_done(zio, NULL, zio->io_private);
if (zio->io_error != 0) {
@@ -120,7 +126,7 @@ dmu_write_direct_done(zio_t *zio)
* calling dbuf_undirty().
*/
mutex_enter(&db->db_mtx);
- VERIFY3B(dbuf_undirty(db, dsa->dsa_tx), ==, B_FALSE);
+ VERIFY3B(dbuf_undirty(db, tx), ==, B_FALSE);
mutex_exit(&db->db_mtx);
}
diff --git a/sys/contrib/openzfs/module/zfs/dmu_objset.c b/sys/contrib/openzfs/module/zfs/dmu_objset.c
index 5a815b59e37b..d64116093193 100644
--- a/sys/contrib/openzfs/module/zfs/dmu_objset.c
+++ b/sys/contrib/openzfs/module/zfs/dmu_objset.c
@@ -3011,7 +3011,7 @@ dmu_objset_get_user(objset_t *os)
int
dmu_fsname(const char *snapname, char *buf)
{
- char *atp = strchr(snapname, '@');
+ const char *atp = strchr(snapname, '@');
if (atp == NULL)
return (SET_ERROR(EINVAL));
if (atp - snapname >= ZFS_MAX_DATASET_NAME_LEN)
diff --git a/sys/contrib/openzfs/module/zfs/dnode.c b/sys/contrib/openzfs/module/zfs/dnode.c
index e0cc4a7e13e0..be0e3de9bb23 100644
--- a/sys/contrib/openzfs/module/zfs/dnode.c
+++ b/sys/contrib/openzfs/module/zfs/dnode.c
@@ -2409,6 +2409,8 @@ done:
mutex_enter(&dn->dn_mtx);
{
int txgoff = tx->tx_txg & TXG_MASK;
+
+ FREE_RANGE_VERIFY(tx, dn);
if (dn->dn_free_ranges[txgoff] == NULL) {
dn->dn_free_ranges[txgoff] =
zfs_range_tree_create_flags(
diff --git a/sys/contrib/openzfs/module/zfs/dnode_sync.c b/sys/contrib/openzfs/module/zfs/dnode_sync.c
index 046ceddb3609..0e070c69dcd6 100644
--- a/sys/contrib/openzfs/module/zfs/dnode_sync.c
+++ b/sys/contrib/openzfs/module/zfs/dnode_sync.c
@@ -440,24 +440,6 @@ dnode_sync_free_range_impl(dnode_t *dn, uint64_t blkid, uint64_t nblks,
}
}
-typedef struct dnode_sync_free_range_arg {
- dnode_t *dsfra_dnode;
- dmu_tx_t *dsfra_tx;
- boolean_t dsfra_free_indirects;
-} dnode_sync_free_range_arg_t;
-
-static void
-dnode_sync_free_range(void *arg, uint64_t blkid, uint64_t nblks)
-{
- dnode_sync_free_range_arg_t *dsfra = arg;
- dnode_t *dn = dsfra->dsfra_dnode;
-
- mutex_exit(&dn->dn_mtx);
- dnode_sync_free_range_impl(dn, blkid, nblks,
- dsfra->dsfra_free_indirects, dsfra->dsfra_tx);
- mutex_enter(&dn->dn_mtx);
-}
-
/*
* Try to kick all the dnode's dbufs out of the cache...
*/
@@ -635,6 +617,64 @@ dnode_sync_free(dnode_t *dn, dmu_tx_t *tx)
}
/*
+ * We cannot simply detach the range tree (set dn_free_ranges to NULL)
+ * before processing it because dnode_block_freed() relies on it to
+ * correctly identify blocks that have been freed in the current TXG
+ * (for dbuf_read() calls on holes). If we detached it early, a concurrent
+ * reader might see the block as valid on disk and return stale data
+ * instead of zeros.
+ *
+ * We also can't use zfs_range_tree_walk() nor zfs_range_tree_vacate()
+ * with a callback that drops dn_mtx (dnode_sync_free_range()). This is
+ * unsafe because another thread (spa_sync_deferred_frees() ->
+ * dnode_free_range()) could acquire dn_mtx and modify the tree while the
+ * walk or vacate was in progress. This leads to tree corruption or panic
+ * when we resume.
+ *
+ * To fix the race while maintaining visibility, we process the tree
+ * incrementally. We pick a segment, drop the lock to sync it, and
+ * re-acquire the lock to remove it. By always restarting from the head
+ * of the tree, we ensure we are never using an invalid iterator.
+ * We use zfs_range_tree_clear() instead of ..._remove() because the range
+ * might have already been removed while the lock was dropped (specifically
+ * in the dbuf_dirty path mentioned above). ..._clear() handles this
+ * gracefully, while ..._remove() would panic on a missing segment.
+ */
+static void
+dnode_sync_free_ranges(dnode_t *dn, dmu_tx_t *tx)
+{
+ int txgoff = tx->tx_txg & TXG_MASK;
+
+ mutex_enter(&dn->dn_mtx);
+ zfs_range_tree_t *rt = dn->dn_free_ranges[txgoff];
+ if (rt != NULL) {
+ boolean_t freeing_dnode = dn->dn_free_txg > 0 &&
+ dn->dn_free_txg <= tx->tx_txg;
+ zfs_range_seg_t *rs;
+
+ if (freeing_dnode) {
+ ASSERT(zfs_range_tree_contains(rt, 0,
+ dn->dn_maxblkid + 1));
+ }
+
+ while ((rs = zfs_range_tree_first(rt)) != NULL) {
+ uint64_t start = zfs_rs_get_start(rs, rt);
+ uint64_t size = zfs_rs_get_end(rs, rt) - start;
+
+ mutex_exit(&dn->dn_mtx);
+ dnode_sync_free_range_impl(dn, start, size,
+ freeing_dnode, tx);
+ mutex_enter(&dn->dn_mtx);
+
+ zfs_range_tree_clear(rt, start, size);
+ }
+ zfs_range_tree_destroy(rt);
+ dn->dn_free_ranges[txgoff] = NULL;
+ }
+ mutex_exit(&dn->dn_mtx);
+}
+
+/*
* Write out the dnode's dirty buffers.
* Does not wait for zio completions.
*/
@@ -781,32 +821,7 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
}
/* process all the "freed" ranges in the file */
- if (dn->dn_free_ranges[txgoff] != NULL) {
- dnode_sync_free_range_arg_t dsfra;
- dsfra.dsfra_dnode = dn;
- dsfra.dsfra_tx = tx;
- dsfra.dsfra_free_indirects = freeing_dnode;
- mutex_enter(&dn->dn_mtx);
- if (freeing_dnode) {
- ASSERT(zfs_range_tree_contains(
- dn->dn_free_ranges[txgoff], 0,
- dn->dn_maxblkid + 1));
- }
- /*
- * Because dnode_sync_free_range() must drop dn_mtx during its
- * processing, using it as a callback to zfs_range_tree_vacate()
- * is not safe. No other operations (besides destroy) are
- * allowed once zfs_range_tree_vacate() has begun, and dropping
- * dn_mtx would leave a window open for another thread to
- * observe that invalid (and unsafe) state.
- */
- zfs_range_tree_walk(dn->dn_free_ranges[txgoff],
- dnode_sync_free_range, &dsfra);
- zfs_range_tree_vacate(dn->dn_free_ranges[txgoff], NULL, NULL);
- zfs_range_tree_destroy(dn->dn_free_ranges[txgoff]);
- dn->dn_free_ranges[txgoff] = NULL;
- mutex_exit(&dn->dn_mtx);
- }
+ dnode_sync_free_ranges(dn, tx);
if (freeing_dnode) {
dn->dn_objset->os_freed_dnodes++;
@@ -828,7 +843,7 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
}
/*
- * This must be done after dnode_sync_free_range()
+ * This must be done after dnode_sync_free_ranges()
* and dnode_increase_indirection(). See dnode_new_blkid()
* for an explanation of the high bit being set.
*/
diff --git a/sys/contrib/openzfs/module/zfs/dsl_bookmark.c b/sys/contrib/openzfs/module/zfs/dsl_bookmark.c
index ee574c499f9f..8c18079d056e 100644
--- a/sys/contrib/openzfs/module/zfs/dsl_bookmark.c
+++ b/sys/contrib/openzfs/module/zfs/dsl_bookmark.c
@@ -39,10 +39,10 @@
static int
dsl_bookmark_hold_ds(dsl_pool_t *dp, const char *fullname,
- dsl_dataset_t **dsp, const void *tag, char **shortnamep)
+ dsl_dataset_t **dsp, const void *tag, const char **shortnamep)
{
char buf[ZFS_MAX_DATASET_NAME_LEN];
- char *hashp;
+ const char *hashp;
if (strlen(fullname) >= ZFS_MAX_DATASET_NAME_LEN)
return (SET_ERROR(ENAMETOOLONG));
@@ -105,7 +105,7 @@ int
dsl_bookmark_lookup(dsl_pool_t *dp, const char *fullname,
dsl_dataset_t *later_ds, zfs_bookmark_phys_t *bmp)
{
- char *shortname;
+ const char *shortname;
dsl_dataset_t *ds;
int error;
@@ -219,7 +219,7 @@ dsl_bookmark_create_check_impl(dsl_pool_t *dp,
int error;
dsl_dataset_t *newbm_ds;
- char *newbm_short;
+ const char *newbm_short;
zfs_bookmark_phys_t bmark_phys;
error = dsl_bookmark_hold_ds(dp, newbm, &newbm_ds, FTAG, &newbm_short);
@@ -329,7 +329,7 @@ dsl_bookmark_create_check(void *arg, dmu_tx_t *tx)
}
static dsl_bookmark_node_t *
-dsl_bookmark_node_alloc(char *shortname)
+dsl_bookmark_node_alloc(const char *shortname)
{
dsl_bookmark_node_t *dbn = kmem_alloc(sizeof (*dbn), KM_SLEEP);
dbn->dbn_name = spa_strdup(shortname);
@@ -445,7 +445,7 @@ dsl_bookmark_create_sync_impl_snap(const char *bookmark, const char *snapshot,
dsl_pool_t *dp = dmu_tx_pool(tx);
objset_t *mos = dp->dp_meta_objset;
dsl_dataset_t *snapds, *bmark_fs;
- char *shortname;
+ const char *shortname;
boolean_t bookmark_redacted;
uint64_t *dsredactsnaps;
uint64_t dsnumsnaps;
@@ -535,7 +535,7 @@ dsl_bookmark_create_sync_impl_book(
{
dsl_pool_t *dp = dmu_tx_pool(tx);
dsl_dataset_t *bmark_fs_source, *bmark_fs_new;
- char *source_shortname, *new_shortname;
+ const char *source_shortname, *new_shortname;
zfs_bookmark_phys_t source_phys;
VERIFY0(dsl_bookmark_hold_ds(dp, source_name, &bmark_fs_source, FTAG,
@@ -1106,7 +1106,7 @@ dsl_bookmark_destroy_check(void *arg, dmu_tx_t *tx)
dsl_dataset_t *ds;
zfs_bookmark_phys_t bm;
int error;
- char *shortname;
+ const char *shortname;
error = dsl_bookmark_hold_ds(dp, fullname, &ds,
FTAG, &shortname);
@@ -1162,7 +1162,7 @@ dsl_bookmark_destroy_sync(void *arg, dmu_tx_t *tx)
for (nvpair_t *pair = nvlist_next_nvpair(dbda->dbda_success, NULL);
pair != NULL; pair = nvlist_next_nvpair(dbda->dbda_success, pair)) {
dsl_dataset_t *ds;
- char *shortname;
+ const char *shortname;
uint64_t zap_cnt;
VERIFY0(dsl_bookmark_hold_ds(dp, nvpair_name(pair),
diff --git a/sys/contrib/openzfs/module/zfs/dsl_dir.c b/sys/contrib/openzfs/module/zfs/dsl_dir.c
index 6ce1890cfea1..2253b868b53c 100644
--- a/sys/contrib/openzfs/module/zfs/dsl_dir.c
+++ b/sys/contrib/openzfs/module/zfs/dsl_dir.c
@@ -417,7 +417,7 @@ dsl_dir_namelen(dsl_dir_t *dd)
static int
getcomponent(const char *path, char *component, const char **nextp)
{
- char *p;
+ const char *p;
if ((path == NULL) || (path[0] == '\0'))
return (SET_ERROR(ENOENT));
diff --git a/sys/contrib/openzfs/module/zfs/range_tree.c b/sys/contrib/openzfs/module/zfs/range_tree.c
index d73195f1a21f..3835023f580a 100644
--- a/sys/contrib/openzfs/module/zfs/range_tree.c
+++ b/sys/contrib/openzfs/module/zfs/range_tree.c
@@ -531,7 +531,7 @@ zfs_range_tree_remove_impl(zfs_range_tree_t *rt, uint64_t start, uint64_t size,
}
if (!(rstart <= start && rend >= end)) {
- panic("zfs: rt=%s: removing segment "
+ zfs_panic_recover("zfs: rt=%s: removing segment "
"(offset=%llx size=%llx) not completely overlapped by "
"existing one (offset=%llx size=%llx)",
ZFS_RT_NAME(rt),
diff --git a/sys/contrib/openzfs/module/zfs/spa.c b/sys/contrib/openzfs/module/zfs/spa.c
index a9050997472d..1ad94fd1bf7f 100644
--- a/sys/contrib/openzfs/module/zfs/spa.c
+++ b/sys/contrib/openzfs/module/zfs/spa.c
@@ -8480,7 +8480,7 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing,
if (rebuild) {
newvd->vdev_rebuild_txg = txg;
- vdev_rebuild(tvd);
+ vdev_rebuild(tvd, txg);
} else {
newvd->vdev_resilver_txg = txg;
diff --git a/sys/contrib/openzfs/module/zfs/spa_errlog.c b/sys/contrib/openzfs/module/zfs/spa_errlog.c
index 7252fd534bdf..afa9e9d0efd4 100644
--- a/sys/contrib/openzfs/module/zfs/spa_errlog.c
+++ b/sys/contrib/openzfs/module/zfs/spa_errlog.c
@@ -468,7 +468,7 @@ check_filesystem(spa_t *spa, uint64_t head_ds, zbookmark_err_phys_t *zep,
kmem_free(zc, sizeof (*zc));
out:
- kmem_free(snap_obj_array, sizeof (*snap_obj_array));
+ kmem_free(snap_obj_array, snap_count * sizeof (*snap_obj_array));
return (error);
}
diff --git a/sys/contrib/openzfs/module/zfs/spa_misc.c b/sys/contrib/openzfs/module/zfs/spa_misc.c
index bed159eb7cff..7217b670a1ba 100644
--- a/sys/contrib/openzfs/module/zfs/spa_misc.c
+++ b/sys/contrib/openzfs/module/zfs/spa_misc.c
@@ -1891,6 +1891,12 @@ spa_syncing_txg(spa_t *spa)
return (spa->spa_syncing_txg);
}
+uint64_t
+spa_open_txg(spa_t *spa)
+{
+ return (spa->spa_dsl_pool->dp_tx.tx_open_txg);
+}
+
/*
* Return the last txg where data can be dirtied. The final txgs
* will be used to just clear out any deferred frees that remain.
@@ -2119,6 +2125,12 @@ spa_preferred_class(spa_t *spa, const zio_t *zio)
boolean_t tried_special = (mc == spa_special_class(spa));
const zio_prop_t *zp = &zio->io_prop;
+ /* Gang children should always use the class of their parents. */
+ if (zio->io_flags & ZIO_FLAG_GANG_CHILD) {
+ ASSERT(mc != NULL);
+ return (mc);
+ }
+
/*
* Override object type for the purposes of selecting a storage class.
* Primarily for DMU_OTN_ types where we can't explicitly control their
@@ -2143,39 +2155,23 @@ spa_preferred_class(spa_t *spa, const zio_t *zio)
return (spa_normal_class(spa));
}
- /* Indirect blocks for user data can land in special if allowed */
- if (zp->zp_level > 0 &&
- (DMU_OT_IS_FILE(objtype) || objtype == DMU_OT_ZVOL)) {
- if (zfs_user_indirect_is_special && spa_has_special(spa) &&
- !tried_special)
- return (spa_special_class(spa));
- else
- return (spa_normal_class(spa));
- }
+ if (!spa_has_special(spa) || tried_special)
+ return (spa_normal_class(spa));
- if (DMU_OT_IS_METADATA(objtype) || zp->zp_level > 0) {
- if (spa_has_special(spa) && !tried_special)
- return (spa_special_class(spa));
- else
- return (spa_normal_class(spa));
- }
+ if (DMU_OT_IS_METADATA(objtype) ||
+ (zfs_user_indirect_is_special && zp->zp_level > 0))
+ return (spa_special_class(spa));
/*
- * Allow small file or zvol blocks in special class if opted in by
- * the special_smallblk property. However, always leave a reserve of
+ * Allow small blocks in special class. However, leave a reserve of
* zfs_special_class_metadata_reserve_pct exclusively for metadata.
*/
- if ((DMU_OT_IS_FILE(objtype) || objtype == DMU_OT_ZVOL) &&
- spa_has_special(spa) && !tried_special &&
- zio->io_size <= zp->zp_zpl_smallblk) {
+ if (zio->io_size <= zp->zp_zpl_smallblk) {
metaslab_class_t *special = spa_special_class(spa);
- uint64_t alloc = metaslab_class_get_alloc(special);
- uint64_t space = metaslab_class_get_space(special);
- uint64_t limit =
- (space * (100 - zfs_special_class_metadata_reserve_pct))
- / 100;
+ uint64_t limit = metaslab_class_get_space(special) *
+ (100 - zfs_special_class_metadata_reserve_pct) / 100;
- if (alloc < limit)
+ if (metaslab_class_get_alloc(special) < limit)
return (special);
}
diff --git a/sys/contrib/openzfs/module/zfs/vdev.c b/sys/contrib/openzfs/module/zfs/vdev.c
index 6d44bd41b0de..71bb247c6235 100644
--- a/sys/contrib/openzfs/module/zfs/vdev.c
+++ b/sys/contrib/openzfs/module/zfs/vdev.c
@@ -31,6 +31,7 @@
* Copyright (c) 2019, Datto Inc. All rights reserved.
* Copyright (c) 2021, 2025, Klara, Inc.
* Copyright (c) 2021, 2023 Hewlett Packard Enterprise Development LP.
+ * Copyright (c) 2026, Seagate Technology, LLC.
*/
#include <sys/zfs_context.h>
@@ -3094,8 +3095,11 @@ vdev_dtl_dirty(vdev_t *vd, vdev_dtl_type_t t, uint64_t txg, uint64_t size)
ASSERT(spa_writeable(vd->vdev_spa));
mutex_enter(&vd->vdev_dtl_lock);
- if (!zfs_range_tree_contains(rt, txg, size))
+ if (!zfs_range_tree_contains(rt, txg, size)) {
+ /* Clear whatever is there already. */
+ zfs_range_tree_clear(rt, txg, size);
zfs_range_tree_add(rt, txg, size);
+ }
mutex_exit(&vd->vdev_dtl_lock);
}
@@ -5212,11 +5216,13 @@ vdev_stat_update(zio_t *zio, uint64_t psize)
if (type == ZIO_TYPE_WRITE && txg != 0 &&
(!(flags & ZIO_FLAG_IO_REPAIR) ||
(flags & ZIO_FLAG_SCAN_THREAD) ||
+ zio->io_priority == ZIO_PRIORITY_REBUILD ||
spa->spa_claiming)) {
/*
* This is either a normal write (not a repair), or it's
* a repair induced by the scrub thread, or it's a repair
- * made by zil_claim() during spa_load() in the first txg.
+ * made by zil_claim() during spa_load() in the first txg,
+ * or its repair induced by rebuild (sequential resilver).
* In the normal case, we commit the DTL change in the same
* txg as the block was born. In the scrub-induced repair
* case, we know that scrubs run in first-pass syncing context,
@@ -5227,27 +5233,38 @@ vdev_stat_update(zio_t *zio, uint64_t psize)
* self-healing writes triggered by normal (non-scrubbing)
* reads, because we have no transactional context in which to
* do so -- and it's not clear that it'd be desirable anyway.
+ *
+ * For rebuild, since we don't have any information about BPs
+ * and txgs that are being rebuilt, we need to add all known
+ * txgs (starting from TXG_INITIAL) to DTL so that during
+ * healing resilver we would be able to check all txgs at
+ * vdev_draid_need_resilver().
*/
+ uint64_t size = 1;
if (vd->vdev_ops->vdev_op_leaf) {
uint64_t commit_txg = txg;
if (flags & ZIO_FLAG_SCAN_THREAD) {
ASSERT(flags & ZIO_FLAG_IO_REPAIR);
ASSERT(spa_sync_pass(spa) == 1);
- vdev_dtl_dirty(vd, DTL_SCRUB, txg, 1);
+ vdev_dtl_dirty(vd, DTL_SCRUB, txg, size);
commit_txg = spa_syncing_txg(spa);
} else if (spa->spa_claiming) {
ASSERT(flags & ZIO_FLAG_IO_REPAIR);
commit_txg = spa_first_txg(spa);
+ } else if (zio->io_priority == ZIO_PRIORITY_REBUILD) {
+ ASSERT(flags & ZIO_FLAG_IO_REPAIR);
+ vdev_rebuild_txgs(vd->vdev_top, &txg, &size);
+ commit_txg = spa_open_txg(spa);
}
ASSERT(commit_txg >= spa_syncing_txg(spa));
- if (vdev_dtl_contains(vd, DTL_MISSING, txg, 1))
+ if (vdev_dtl_contains(vd, DTL_MISSING, txg, size))
return;
for (pvd = vd; pvd != rvd; pvd = pvd->vdev_parent)
- vdev_dtl_dirty(pvd, DTL_PARTIAL, txg, 1);
+ vdev_dtl_dirty(pvd, DTL_PARTIAL, txg, size);
vdev_dirty(vd->vdev_top, VDD_DTL, vd, commit_txg);
}
if (vd != rvd)
- vdev_dtl_dirty(vd, DTL_MISSING, txg, 1);
+ vdev_dtl_dirty(vd, DTL_MISSING, txg, size);
}
}
diff --git a/sys/contrib/openzfs/module/zfs/vdev_draid.c b/sys/contrib/openzfs/module/zfs/vdev_draid.c
index 8588cfee3f7d..576d88c3c7b4 100644
--- a/sys/contrib/openzfs/module/zfs/vdev_draid.c
+++ b/sys/contrib/openzfs/module/zfs/vdev_draid.c
@@ -23,6 +23,7 @@
* Copyright (c) 2018 Intel Corporation.
* Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
* Copyright (c) 2025, Klara, Inc.
+ * Copyright (c) 2026, Wasabi Technologies, Inc.
*/
#include <sys/zfs_context.h>
@@ -1161,7 +1162,7 @@ vdev_draid_get_astart(vdev_t *vd, const uint64_t start)
/*
* Allocatable space for dRAID is (children - nspares) * sizeof(smallest child)
* rounded down to the last full slice. So each child must provide at least
- * 1 / (children - nspares) of its asize.
+ * 1 / (children - nspares) of its asize rounded up to VDEV_DRAID_ROWHEIGHT.
*/
static uint64_t
vdev_draid_min_asize(vdev_t *vd)
@@ -1171,7 +1172,9 @@ vdev_draid_min_asize(vdev_t *vd)
ASSERT3P(vd->vdev_ops, ==, &vdev_draid_ops);
return (VDEV_DRAID_REFLOW_RESERVE +
- (vd->vdev_min_asize + vdc->vdc_ndisks - 1) / (vdc->vdc_ndisks));
+ ((vd->vdev_min_asize + vdc->vdc_ndisks - 1) / (vdc->vdc_ndisks) +
+ VDEV_DRAID_ROWHEIGHT - 1) / VDEV_DRAID_ROWHEIGHT *
+ VDEV_DRAID_ROWHEIGHT);
}
/*
@@ -1189,7 +1192,7 @@ vdev_draid_min_alloc(vdev_t *vd)
}
/*
- * Returns true if the txg range does not exist on any leaf vdev.
+ * Returns false if the txg range exists on any leaf vdev, true otherwise.
*
* A dRAID spare does not fit into the DTL model. While it has child vdevs
* there is no redundancy among them, and the effective child vdev is
@@ -1247,8 +1250,7 @@ vdev_draid_missing(vdev_t *vd, uint64_t physical_offset, uint64_t txg,
if (vd == NULL)
return (B_TRUE);
- return (vdev_draid_missing(vd, physical_offset,
- txg, size));
+ return (vdev_draid_missing(vd, physical_offset, txg, size));
}
return (vdev_dtl_contains(vd, DTL_MISSING, txg, size));
@@ -1452,13 +1454,6 @@ vdev_draid_group_missing(vdev_t *vd, uint64_t offset, uint64_t txg,
/* Transaction group is known to be partially replicated. */
if (vdev_draid_partial(cvd, physical_offset, txg, size))
return (B_TRUE);
-
- /*
- * Always check groups with active distributed spares
- * because any vdev failure in the pool will affect them.
- */
- if (vdev_draid_find_spare(cvd) != NULL)
- return (B_TRUE);
}
return (B_FALSE);
@@ -1914,12 +1909,34 @@ vdev_draid_io_start_read(zio_t *zio, raidz_row_t *rr)
}
if (vdev_draid_missing(cvd, rc->rc_offset, zio->io_txg, 1)) {
+ vdev_t *svd;
+
if (c >= rr->rr_firstdatacol)
rr->rr_missingdata++;
else
rr->rr_missingparity++;
rc->rc_error = SET_ERROR(ESTALE);
rc->rc_skipped = 1;
+
+ /*
+ * If this child has draid spare attached, and that
+ * spare by rc_offset maps to another spare, the repair
+ * would go to that spare, and we want all mirrored
+ * children on it to be updated with the repaired data,
+ * even when we cannot vouch for it during rebuilds
+ * (which don't have checksums). Otherwise, we will have
+ * a lot of checksum errors on that spares during scrub.
+ * The worst thing that can happen in this case is that
+ * we will update the reserved spare column on some
+ * device with unverified data, which is harmless.
+ */
+ if ((svd = vdev_draid_find_spare(cvd)) != NULL) {
+ svd = vdev_draid_spare_get_child(svd,
+ rc->rc_offset);
+ if (svd && (svd->vdev_ops == &vdev_spare_ops ||
+ svd->vdev_ops == &vdev_replacing_ops))
+ rc->rc_tgt_is_dspare = 1;
+ }
continue;
}
@@ -1937,34 +1954,15 @@ vdev_draid_io_start_read(zio_t *zio, raidz_row_t *rr)
vdev_t *svd;
/*
- * Sequential rebuilds need to always consider the data
- * on the child being rebuilt to be stale. This is
- * important when all columns are available to aid
- * known reconstruction in identifing which columns
- * contain incorrect data.
- *
- * Furthermore, all repairs need to be constrained to
- * the devices being rebuilt because without a checksum
- * we cannot verify the data is actually correct and
- * performing an incorrect repair could result in
- * locking in damage and making the data unrecoverable.
+ * Repairs need to be constrained to the devices being
+ * rebuilt since without a checksum we cannot verify the
+ * data is actually correct and performing an incorrect
+ * repair could result in locking in the damage and
+ * making the data unrecoverable.
*/
- if (zio->io_priority == ZIO_PRIORITY_REBUILD) {
- if (vdev_draid_rebuilding(cvd)) {
- if (c >= rr->rr_firstdatacol)
- rr->rr_missingdata++;
- else
- rr->rr_missingparity++;
- rc->rc_error = SET_ERROR(ESTALE);
- rc->rc_skipped = 1;
- rc->rc_allow_repair = 1;
- continue;
- } else {
- rc->rc_allow_repair = 0;
- }
- } else {
- rc->rc_allow_repair = 1;
- }
+ if (zio->io_priority == ZIO_PRIORITY_REBUILD &&
+ !vdev_draid_rebuilding(cvd))
+ rc->rc_allow_repair = 0;
/*
* If this child is a distributed spare then the
diff --git a/sys/contrib/openzfs/module/zfs/vdev_mirror.c b/sys/contrib/openzfs/module/zfs/vdev_mirror.c
index 18efdaac006f..35a4a5bebecf 100644
--- a/sys/contrib/openzfs/module/zfs/vdev_mirror.c
+++ b/sys/contrib/openzfs/module/zfs/vdev_mirror.c
@@ -669,18 +669,19 @@ vdev_mirror_io_start(zio_t *zio)
}
while (children--) {
- mc = &mm->mm_child[c];
- c++;
+ mc = &mm->mm_child[c++];
/*
- * When sequentially resilvering only issue write repair
- * IOs to the vdev which is being rebuilt since performance
- * is limited by the slowest child. This is an issue for
- * faster replacement devices such as distributed spares.
+ * When sequentially resilvering and the integrity of the data
+ * is speculative (ZIO_FLAG_SPECULATIVE), issue write repair IOs
+ * only to the vdev which is being rebuilt. Existing data on
+ * other children must never be overwritten with unconfirmed
+ * data to avoid unrecoverable damage to the pool.
*/
if ((zio->io_priority == ZIO_PRIORITY_REBUILD) &&
(zio->io_flags & ZIO_FLAG_IO_REPAIR) &&
!(zio->io_flags & ZIO_FLAG_SCRUB) &&
+ (zio->io_flags & ZIO_FLAG_SPECULATIVE) &&
mm->mm_rebuilding && !mc->mc_rebuilding) {
continue;
}
diff --git a/sys/contrib/openzfs/module/zfs/vdev_raidz.c b/sys/contrib/openzfs/module/zfs/vdev_raidz.c
index 520ddd692bda..6eb8d44cb286 100644
--- a/sys/contrib/openzfs/module/zfs/vdev_raidz.c
+++ b/sys/contrib/openzfs/module/zfs/vdev_raidz.c
@@ -25,6 +25,7 @@
* Copyright (c) 2012, 2020 by Delphix. All rights reserved.
* Copyright (c) 2016 Gvozden Nešković. All rights reserved.
* Copyright (c) 2025, Klara, Inc.
+ * Copyright (c) 2026, Wasabi Technologies, Inc.
*/
#include <sys/zfs_context.h>
@@ -3104,6 +3105,7 @@ vdev_raidz_io_done_verified(zio_t *zio, raidz_row_t *rr)
int parity_errors = 0;
int parity_untried = 0;
int data_errors = 0;
+ zio_flag_t add_flags = 0;
ASSERT3U(zio->io_type, ==, ZIO_TYPE_READ);
@@ -3134,10 +3136,30 @@ vdev_raidz_io_done_verified(zio_t *zio, raidz_row_t *rr)
* Note that we also regenerate parity when resilvering so we
* can write it out to failed devices later.
*/
- if (parity_errors + parity_untried <
- rr->rr_firstdatacol - data_errors ||
- (zio->io_flags & ZIO_FLAG_RESILVER)) {
+ boolean_t parity_verify = (parity_errors + parity_untried) <
+ (rr->rr_firstdatacol - data_errors);
+ if (parity_verify || (zio->io_flags & ZIO_FLAG_RESILVER)) {
int n = raidz_parity_verify(zio, rr);
+ /*
+ * In, Reed-Solomon encoding, if we have ndata+1 columns and
+ * the parity doesn't match, it means the data integrity is
+ * compromised. We shouldn't try to repair anything in this
+ * case.
+ */
+ if (parity_verify && n > 0 &&
+ zio->io_priority == ZIO_PRIORITY_REBUILD)
+ return;
+ /*
+ * If we have only ndata columns, the data integrity will
+ * be checked by the checksums normally, but not in case
+ * of rebuild when we don't have checksums. In this case,
+ * we add ZIO_FLAG_SPECULATIVE and try to not spread
+ * unverified data. For example, when the target vdev happens
+ * to be the mirroring spare vdev, we would repair only that
+ * child in it which is being rebuilt.
+ */
+ if (!parity_verify && zio->io_priority == ZIO_PRIORITY_REBUILD)
+ add_flags |= ZIO_FLAG_SPECULATIVE;
unexpected_errors += n;
}
@@ -3163,13 +3185,27 @@ vdev_raidz_io_done_verified(zio_t *zio, raidz_row_t *rr)
*/
ASSERT0(zio->io_flags & ZIO_FLAG_DIO_READ);
+ /*
+ * When the target vdev is draid spare, we should clear
+ * ZIO_FLAG_SPECULATIVE. First, if that draid spare maps
+ * to another spare having an online/degraded disk, that
+ * disk must be repaired also. Otherwise, the scrub will
+ * detect a lot of cksum errors later. Second, since it
+ * is draid spare, there is no harm in updating its
+ * content on any vdev it maps to because the space is
+ * reserved as a spare anyway.
+ */
+ zio_flag_t aflags = add_flags;
+ if (rc->rc_tgt_is_dspare)
+ aflags &= ~ZIO_FLAG_SPECULATIVE;
+
zio_nowait(zio_vdev_child_io(zio, NULL, cvd,
rc->rc_offset, rc->rc_abd, rc->rc_size,
ZIO_TYPE_WRITE,
zio->io_priority == ZIO_PRIORITY_REBUILD ?
ZIO_PRIORITY_REBUILD : ZIO_PRIORITY_ASYNC_WRITE,
ZIO_FLAG_IO_REPAIR | (unexpected_errors ?
- ZIO_FLAG_SELF_HEAL : 0), NULL, NULL));
+ ZIO_FLAG_SELF_HEAL : 0) | aflags, NULL, NULL));
}
}
diff --git a/sys/contrib/openzfs/module/zfs/vdev_rebuild.c b/sys/contrib/openzfs/module/zfs/vdev_rebuild.c
index 30be1f851eb3..de691f73e939 100644
--- a/sys/contrib/openzfs/module/zfs/vdev_rebuild.c
+++ b/sys/contrib/openzfs/module/zfs/vdev_rebuild.c
@@ -23,7 +23,7 @@
*
* Copyright (c) 2018, Intel Corporation.
* Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
- * Copyright (c) 2022 Hewlett Packard Enterprise Development LP.
+ * Copyright (c) 2022, 2026 Hewlett Packard Enterprise Development LP.
* Copyright (c) 2024 by Delphix. All rights reserved.
*/
@@ -233,7 +233,7 @@ vdev_rebuild_initiate_sync(void *arg, dmu_tx_t *tx)
mutex_enter(&vd->vdev_rebuild_lock);
memset(vrp, 0, sizeof (uint64_t) * REBUILD_PHYS_ENTRIES);
vrp->vrp_rebuild_state = VDEV_REBUILD_ACTIVE;
- vrp->vrp_min_txg = 0;
+ vrp->vrp_min_txg = TXG_INITIAL;
vrp->vrp_max_txg = dmu_tx_get_txg(tx);
vrp->vrp_start_time = gethrestime_sec();
vrp->vrp_scan_time_ms = 0;
@@ -278,7 +278,7 @@ vdev_rebuild_log_notify(spa_t *spa, vdev_t *vd, const char *name)
* active for the duration of the rebuild, then revert to the enabled state.
*/
static void
-vdev_rebuild_initiate(vdev_t *vd)
+vdev_rebuild_initiate(vdev_t *vd, uint64_t txg)
{
spa_t *spa = vd->vdev_spa;
@@ -286,8 +286,7 @@ vdev_rebuild_initiate(vdev_t *vd)
ASSERT(MUTEX_HELD(&vd->vdev_rebuild_lock));
ASSERT(!vd->vdev_rebuilding);
- dmu_tx_t *tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
- VERIFY0(dmu_tx_assign(tx, DMU_TX_WAIT | DMU_TX_SUSPEND));
+ dmu_tx_t *tx = dmu_tx_create_assigned(spa_get_dsl(spa), txg);
vd->vdev_rebuilding = B_TRUE;
@@ -416,7 +415,7 @@ vdev_rebuild_reset_sync(void *arg, dmu_tx_t *tx)
ASSERT0P(vd->vdev_rebuild_thread);
vrp->vrp_last_offset = 0;
- vrp->vrp_min_txg = 0;
+ vrp->vrp_min_txg = TXG_INITIAL;
vrp->vrp_max_txg = dmu_tx_get_txg(tx);
vrp->vrp_bytes_scanned = 0;
vrp->vrp_bytes_issued = 0;
@@ -594,6 +593,7 @@ vdev_rebuild_range(vdev_rebuild_t *vr, uint64_t start, uint64_t size)
dmu_tx_t *tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
VERIFY0(dmu_tx_assign(tx, DMU_TX_WAIT | DMU_TX_SUSPEND));
uint64_t txg = dmu_tx_get_txg(tx);
+ vr->vr_last_txg = txg;
spa_config_enter(spa, SCL_STATE_ALL, vd, RW_READER);
mutex_enter(&vd->vdev_rebuild_lock);
@@ -617,7 +617,6 @@ vdev_rebuild_range(vdev_rebuild_t *vr, uint64_t start, uint64_t size)
return (SET_ERROR(EINTR));
}
mutex_exit(&vd->vdev_rebuild_lock);
- dmu_tx_commit(tx);
vr->vr_scan_offset[txg & TXG_MASK] = start + size;
vr->vr_pass_bytes_issued += size;
@@ -627,6 +626,9 @@ vdev_rebuild_range(vdev_rebuild_t *vr, uint64_t start, uint64_t size)
abd_alloc(psize, B_FALSE), psize, vdev_rebuild_cb, vr,
ZIO_PRIORITY_REBUILD, ZIO_FLAG_RAW | ZIO_FLAG_CANFAIL |
ZIO_FLAG_RESILVER, NULL));
+ /* vdev_rebuild_cb releases SCL_STATE_ALL */
+
+ dmu_tx_commit(tx);
return (0);
}
@@ -763,6 +765,7 @@ vdev_rebuild_thread(void *arg)
vdev_t *vd = arg;
spa_t *spa = vd->vdev_spa;
vdev_t *rvd = spa->spa_root_vdev;
+ dsl_pool_t *dp = spa_get_dsl(spa);
int error = 0;
/*
@@ -770,9 +773,8 @@ vdev_rebuild_thread(void *arg)
* is not required for a correct rebuild, but we do want rebuilds to
* emulate the resilver behavior as much as possible.
*/
- dsl_pool_t *dsl = spa_get_dsl(spa);
- if (dsl_scan_scrubbing(dsl))
- dsl_scan_cancel(dsl);
+ if (dsl_scan_scrubbing(dp))
+ dsl_scan_cancel(dp);
spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
mutex_enter(&vd->vdev_rebuild_lock);
@@ -823,6 +825,7 @@ vdev_rebuild_thread(void *arg)
uint64_t limit = (arc_c_max / 2) / MAX(rvd->vdev_children, 1);
vr->vr_bytes_inflight_max = MIN(limit, MAX(1ULL << 20,
zfs_rebuild_vdev_limit * vd->vdev_children));
+ vr->vr_last_txg = 0;
/*
* Removal of vdevs from the vdev tree may eliminate the need
@@ -854,7 +857,7 @@ vdev_rebuild_thread(void *arg)
if (zfs_range_tree_space(msp->ms_allocating[j])) {
mutex_exit(&msp->ms_lock);
mutex_exit(&msp->ms_sync_lock);
- txg_wait_synced(dsl, 0);
+ txg_wait_synced(dp, 0);
mutex_enter(&msp->ms_sync_lock);
mutex_enter(&msp->ms_lock);
break;
@@ -909,8 +912,16 @@ vdev_rebuild_thread(void *arg)
error = vdev_rebuild_ranges(vr);
zfs_range_tree_vacate(vr->vr_scan_tree, NULL, NULL);
- spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
+ /*
+ * Allow rebuilt ranges to be sync-ed before enabling metaslab
+ * to avoid any interfering allocations. Otherwise, we might
+ * see checksum errors after scrub.
+ */
+ if (vr->vr_last_txg != 0)
+ txg_wait_synced(dp, vr->vr_last_txg);
+
metaslab_enable(msp, B_FALSE, B_FALSE);
+ spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
if (error != 0)
break;
@@ -931,7 +942,6 @@ vdev_rebuild_thread(void *arg)
spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);
- dsl_pool_t *dp = spa_get_dsl(spa);
dmu_tx_t *tx = dmu_tx_create_dd(dp->dp_mos_dir);
VERIFY0(dmu_tx_assign(tx, DMU_TX_WAIT | DMU_TX_SUSPEND));
@@ -1015,7 +1025,7 @@ vdev_rebuild_active(vdev_t *vd)
* top-level vdev is currently actively rebuilding.
*/
void
-vdev_rebuild(vdev_t *vd)
+vdev_rebuild(vdev_t *vd, uint64_t txg)
{
vdev_rebuild_t *vr = &vd->vdev_rebuild_config;
vdev_rebuild_phys_t *vrp __maybe_unused = &vr->vr_rebuild_phys;
@@ -1039,7 +1049,7 @@ vdev_rebuild(vdev_t *vd)
if (!vd->vdev_rebuild_reset_wanted)
vd->vdev_rebuild_reset_wanted = B_TRUE;
} else {
- vdev_rebuild_initiate(vd);
+ vdev_rebuild_initiate(vd, txg);
}
mutex_exit(&vd->vdev_rebuild_lock);
}
@@ -1128,6 +1138,22 @@ vdev_rebuild_stop_all(spa_t *spa)
}
/*
+ * Return rebuild transaction groups range. It's used to populate DTLs
+ * of the non-writable devices during the rebuild so that they could be
+ * healed correctly, in case they are cleared, and not miss the data
+ * that was written to their spares during the rebuild.
+ */
+void
+vdev_rebuild_txgs(vdev_t *vd, uint64_t *min_txg, uint64_t *size)
+{
+ vdev_rebuild_t *vr = &vd->vdev_rebuild_config;
+ vdev_rebuild_phys_t *vrp = &vr->vr_rebuild_phys;
+
+ *min_txg = vrp->vrp_min_txg;
+ *size = vrp->vrp_max_txg - vrp->vrp_min_txg;
+}
+
+/*
* Rebuild statistics reported per top-level vdev.
*/
int
diff --git a/sys/contrib/openzfs/module/zfs/zfs_ioctl.c b/sys/contrib/openzfs/module/zfs/zfs_ioctl.c
index 3bbc9107ae2e..4fcfd18e5005 100644
--- a/sys/contrib/openzfs/module/zfs/zfs_ioctl.c
+++ b/sys/contrib/openzfs/module/zfs/zfs_ioctl.c
@@ -1439,6 +1439,7 @@ zfsvfs_hold(const char *name, const void *tag, zfsvfs_t **zfvp,
* objset from the zfsvfs.
*/
ZFS_TEARDOWN_EXIT(*zfvp, tag);
+ zfs_vfs_rele(*zfvp);
return (SET_ERROR(EBUSY));
}
}
diff --git a/sys/contrib/openzfs/module/zfs/zio.c b/sys/contrib/openzfs/module/zfs/zio.c
index a48854563044..f94edf20a69c 100644
--- a/sys/contrib/openzfs/module/zfs/zio.c
+++ b/sys/contrib/openzfs/module/zfs/zio.c
@@ -1669,9 +1669,11 @@ zio_vdev_child_io(zio_t *pio, blkptr_t *bp, vdev_t *vd, uint64_t offset,
/*
* If we've decided to do a repair, the write is not speculative --
- * even if the original read was.
+ * even if the original read was. Rebuild is an exception since we
+ * cannot always ensure its data integrity.
*/
- if (flags & ZIO_FLAG_IO_REPAIR)
+ if ((flags & ZIO_FLAG_IO_REPAIR) &&
+ pio->io_priority != ZIO_PRIORITY_REBUILD)
flags &= ~ZIO_FLAG_SPECULATIVE;
/*
diff --git a/sys/contrib/openzfs/rpm/Makefile.am b/sys/contrib/openzfs/rpm/Makefile.am
index af7b25021eac..207f02c48867 100644
--- a/sys/contrib/openzfs/rpm/Makefile.am
+++ b/sys/contrib/openzfs/rpm/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
dist_noinst_DATA += \
%D%/generic/zfs-dkms.spec.in \
%D%/generic/zfs-kmod.spec.in \
diff --git a/sys/contrib/openzfs/scripts/Makefile.am b/sys/contrib/openzfs/scripts/Makefile.am
index bff5f8b78a85..df2fae42fce0 100644
--- a/sys/contrib/openzfs/scripts/Makefile.am
+++ b/sys/contrib/openzfs/scripts/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
scriptsdir = $(datadir)/$(PACKAGE)
dist_noinst_SCRIPTS = \
%D%/commitcheck.sh \
diff --git a/sys/contrib/openzfs/scripts/spdxcheck.pl b/sys/contrib/openzfs/scripts/spdxcheck.pl
index 4d4e14368beb..cde11167be5c 100755
--- a/sys/contrib/openzfs/scripts/spdxcheck.pl
+++ b/sys/contrib/openzfs/scripts/spdxcheck.pl
@@ -82,6 +82,11 @@ my $tagged_patterns = q(
man/man?/*.?
man/man?/*.?.in
+ # Build system
+ *.ac
+ *.am
+ *.m4
+
# Unsuffixed programs (or generated of same)
cmd/zarcstat.in
cmd/zarcsummary
@@ -98,8 +103,6 @@ my $tagged_patterns = q(
# Misc items that have clear licensing info but aren't easily matched,
# or are the first of a class that we aren't ready to match yet.
- config/ax_code_coverage.m4
- configure.ac
module/lua/README.zfs
scripts/kmodtool
tests/zfs-tests/tests/functional/inheritance/README.config
@@ -143,7 +146,6 @@ my $untagged_patterns = q(
tests/zfs-tests/tests/functional/tmpfile/tmpfile_003_pos.c
tests/zfs-tests/tests/functional/tmpfile/tmpfile_test.c
- autogen.sh
contrib/bpftrace/zfs-trace.sh
contrib/pyzfs/docs/source/conf.py
contrib/pyzfs/libzfs_core/test/__init__.py
@@ -162,6 +164,16 @@ my $untagged_patterns = q(
tests/zfs-tests/include/tunables.cfg
tests/zfs-tests/include/zpool_script.shlib
tests/zfs-tests/tests/functional/mv_files/random_creation.ksh
+
+ # These Makefiles are not present in master since they were merged
+ # into the larger libraries. It was only after that big Makefile merge
+ # that they got their SPDX lines. Since this branch does not include
+ # the big Makefile merge, we have to whitelist these older Makefile
+ # since they don't have SPDX lines.
+ lib/libshare/Makefile.am
+ lib/libtpool/Makefile.am
+ lib/libunicode/Makefile.am
+ lib/libuutil/Makefile.am
);
# For files expected to have a license tags, these are the acceptable tags by
@@ -192,8 +204,18 @@ my @path_license_tags = (
'module/icp' => ['Apache-2.0', 'CDDL-1.0'],
'contrib/icp' => ['Apache-2.0', 'CDDL-1.0'],
- # Python bindings are always Apache-2.0
- 'contrib/pyzfs' => ['Apache-2.0'],
+ # Python bindings are always Apache-2.0; CDDL is available for build
+ # files in that dir.
+ 'contrib/pyzfs' => ['Apache-2.0', 'CDDL-1.0'],
+
+ # Common licenses for autoconf macros; some of these are complex
+ # with exceptions, so we don't have a "generic" list as such, just
+ # a list of all the ones currently in use.
+ 'config' => [
+ 'CDDL-1.0', 'LGPL-2.1-or-later', 'FSFAP', 'FSFULLR',
+ 'GPL-2.0-or-later WITH Autoconf-exception-generic',
+ 'GPL-3.0-or-later WITH Autoconf-exception-macro',
+ ],
);
# This is a list of "special case" license tags that are in use in the tree,
@@ -239,9 +261,6 @@ my %override_file_license_tags = (
'OpenSSL-standalone' => [qw(
module/icp/asm-x86_64/aes/aes_aesni.S
)],
- 'LGPL-2.1-or-later' => [qw(
- config/ax_code_coverage.m4
- )],
# Legacy inclusions of BSD-2-Clause files in Linux SPL.
'BSD-2-Clause' => [qw(
diff --git a/sys/contrib/openzfs/scripts/zfs-tests.sh b/sys/contrib/openzfs/scripts/zfs-tests.sh
index 09a15bafc27e..697c3f304d81 100755
--- a/sys/contrib/openzfs/scripts/zfs-tests.sh
+++ b/sys/contrib/openzfs/scripts/zfs-tests.sh
@@ -294,6 +294,16 @@ constrain_path() {
SYSTEM_DIRS="/usr/local/bin /usr/local/sbin"
SYSTEM_DIRS="$SYSTEM_DIRS /usr/bin /usr/sbin /bin /sbin $LIBEXEC_DIR"
+ SYSTEM_FILES="$SYSTEM_FILES_COMMON"
+ ZFSTEST_FILES="$ZFSTEST_FILES_COMMON"
+ if [ "$UNAME" = "FreeBSD" ] ; then
+ SYSTEM_FILES="$SYSTEM_FILES $SYSTEM_FILES_FREEBSD"
+ ZFSTEST_FILES="$ZFSTEST_FILES $ZFSTEST_FILES_FREEBSD"
+ else
+ SYSTEM_FILES="$SYSTEM_FILES $SYSTEM_FILES_LINUX"
+ ZFSTEST_FILES="$ZFSTEST_FILES $ZFSTEST_FILES_LINUX"
+ fi
+
if [ "$INTREE" = "yes" ]; then
# Constrained path set to $(top_builddir)/tests/zfs-tests/bin
STF_PATH="$BIN_DIR"
@@ -326,12 +336,6 @@ constrain_path() {
fi
# Standard system utilities
- SYSTEM_FILES="$SYSTEM_FILES_COMMON"
- if [ "$UNAME" = "FreeBSD" ] ; then
- SYSTEM_FILES="$SYSTEM_FILES $SYSTEM_FILES_FREEBSD"
- else
- SYSTEM_FILES="$SYSTEM_FILES $SYSTEM_FILES_LINUX"
- fi
create_links "$SYSTEM_DIRS" "$SYSTEM_FILES"
# Exceptions
diff --git a/sys/contrib/openzfs/tests/Makefile.am b/sys/contrib/openzfs/tests/Makefile.am
index 12e9c9f9daf2..b007a3d7e5fc 100644
--- a/sys/contrib/openzfs/tests/Makefile.am
+++ b/sys/contrib/openzfs/tests/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
include $(srcdir)/%D%/zfs-tests/Makefile.am
diff --git a/sys/contrib/openzfs/tests/runfiles/common.run b/sys/contrib/openzfs/tests/runfiles/common.run
index 4cbde6a37177..623496916849 100644
--- a/sys/contrib/openzfs/tests/runfiles/common.run
+++ b/sys/contrib/openzfs/tests/runfiles/common.run
@@ -83,7 +83,8 @@ tests = ['block_cloning_clone_mmap_cached',
'block_cloning_replay', 'block_cloning_replay_encrypted',
'block_cloning_lwb_buffer_overflow', 'block_cloning_clone_mmap_write',
'block_cloning_rlimit_fsize', 'block_cloning_large_offset',
- 'block_cloning_after_device_removal']
+ 'block_cloning_after_device_removal',
+ 'block_cloning_after_trunc']
tags = ['functional', 'block_cloning']
[tests/functional/bootfs]
@@ -251,6 +252,10 @@ tests = ['zfs_inherit_001_neg', 'zfs_inherit_002_neg', 'zfs_inherit_003_pos',
'zfs_inherit_mountpoint']
tags = ['functional', 'cli_root', 'zfs_inherit']
+[tests/functional/cli_root/zfs_list]
+tests = ['zfs_list_009_pos']
+tags = ['functional', 'cli_root', 'zfs_list']
+
[tests/functional/cli_root/zfs_load-key]
tests = ['zfs_load-key', 'zfs_load-key_all', 'zfs_load-key_file',
'zfs_load-key_https', 'zfs_load-key_location', 'zfs_load-key_noop',
@@ -736,7 +741,7 @@ tests = ['exec_001_pos', 'exec_002_neg']
tags = ['functional', 'exec']
[tests/functional/fadvise]
-tests = ['fadvise_willneed']
+tests = ['fadvise_dontneed', 'fadvise_willneed']
tags = ['functional', 'fadvise']
[tests/functional/failmode]
@@ -913,8 +918,10 @@ timeout = 1200
[tests/functional/redundancy]
tests = ['redundancy_draid', 'redundancy_draid1', 'redundancy_draid2',
'redundancy_draid3', 'redundancy_draid_damaged1',
- 'redundancy_draid_damaged2', 'redundancy_draid_spare1',
- 'redundancy_draid_spare2', 'redundancy_draid_spare3', 'redundancy_mirror',
+ 'redundancy_draid_damaged2', 'redundancy_draid_degraded1',
+ 'redundancy_draid_degraded2',
+ 'redundancy_draid_spare1', 'redundancy_draid_spare2',
+ 'redundancy_draid_spare3', 'redundancy_mirror',
'redundancy_raidz', 'redundancy_raidz1', 'redundancy_raidz2',
'redundancy_raidz3', 'redundancy_stripe']
tags = ['functional', 'redundancy']
diff --git a/sys/contrib/openzfs/tests/runfiles/linux.run b/sys/contrib/openzfs/tests/runfiles/linux.run
index a65633dd8cfb..2717bf53d0b1 100644
--- a/sys/contrib/openzfs/tests/runfiles/linux.run
+++ b/sys/contrib/openzfs/tests/runfiles/linux.run
@@ -141,6 +141,10 @@ pre =
post =
tags = ['functional', 'largest_pool']
+[tests/functional/lease:Linux]
+tests = ['lease_setlease']
+tags = ['functional', 'lease']
+
[tests/functional/longname:Linux]
tests = ['longname_001_pos', 'longname_002_pos', 'longname_003_pos']
tags = ['functional', 'longname']
diff --git a/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in b/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in
index a3d3679714ea..cef9b4db6d43 100755
--- a/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in
+++ b/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in
@@ -252,8 +252,6 @@ maybe = {
'projectquota/setup': ['SKIP', exec_reason],
'raidz/raidz_002_pos': ['FAIL', known_reason],
'raidz/raidz_expand_001_pos': ['FAIL', 16421],
- 'redundancy/redundancy_draid_spare1': ['FAIL', known_reason],
- 'redundancy/redundancy_draid_spare3': ['FAIL', known_reason],
'removal/removal_condense_export': ['FAIL', known_reason],
'renameat2/setup': ['SKIP', renameat2_reason],
'reservation/reservation_008_pos': ['FAIL', 7741],
@@ -321,6 +319,7 @@ elif sys.platform.startswith('linux'):
'bclone/bclone_samefs_data': ['SKIP', cfr_reason],
'bclone/bclone_samefs_embedded': ['SKIP', cfr_reason],
'bclone/bclone_samefs_hole': ['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_after_trunc': ['SKIP', cfr_reason],
'block_cloning/block_cloning_clone_mmap_cached': ['SKIP', cfr_reason],
'block_cloning/block_cloning_clone_mmap_write':
['SKIP', cfr_reason],
diff --git a/sys/contrib/openzfs/tests/zfs-tests/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/Makefile.am
index 8a4b13d0acbb..d544f8b1a962 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/Makefile.am
+++ b/sys/contrib/openzfs/tests/zfs-tests/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
SUBDIRS += %D%/tests
include $(srcdir)/%D%/cmd/Makefile.am
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore b/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore
index 62f1684acfb4..4bdca0acf52b 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore
@@ -2,6 +2,7 @@
/btree_test
/chg_usr_exec
/clonefile
+/clone_after_trunc
/clone_mmap_cached
/clone_mmap_write
/crypto_test
@@ -58,3 +59,4 @@
/sha2_test
/idmap_util
/statx
+/setlease
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am
index 85c3cf3c35a8..9cd526d65b6d 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
scripts_zfs_tests_bindir = $(datadir)/$(PACKAGE)/zfs-tests/bin
@@ -34,6 +35,8 @@ scripts_zfs_tests_bin_PROGRAMS += %D%/crypto_test
%C%_crypto_test_SOURCES = %D%/crypto_test.c
%C%_crypto_test_LDADD = libzpool.la
+scripts_zfs_tests_bin_PROGRAMS += %D%/clone_after_trunc
+%C%_clone_after_trunc_LDADD = -lpthread
if WANT_DEVNAME2DEVID
scripts_zfs_tests_bin_PROGRAMS += %D%/devname2devid
@@ -132,6 +135,7 @@ scripts_zfs_tests_bin_PROGRAMS += %D%/statx
scripts_zfs_tests_bin_PROGRAMS += %D%/xattrtest
scripts_zfs_tests_bin_PROGRAMS += %D%/zed_fd_spill-zedlet
scripts_zfs_tests_bin_PROGRAMS += %D%/idmap_util
+scripts_zfs_tests_bin_PROGRAMS += %D%/setlease
%C%_idmap_util_LDADD = libspl.la
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/clone_after_trunc.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/clone_after_trunc.c
new file mode 100644
index 000000000000..631432928984
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/clone_after_trunc.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: CDDL-1.0
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#if defined(_GNU_SOURCE) && defined(__linux__)
+_Static_assert(sizeof (loff_t) == sizeof (off_t),
+ "loff_t and off_t must be the same size");
+#endif
+
+ssize_t
+copy_file_range(int, off_t *, int, off_t *, size_t, unsigned int)
+ __attribute__((weak));
+
+#define FILE_SIZE (1024 * 1024)
+#define RECORD_SIZE (128 * 1024)
+#define NUM_THREADS 64
+
+const char *dir;
+volatile int failed;
+
+static void *
+run_test(void *arg)
+{
+ int thread_id = (int)(long)arg;
+
+ char src_path[PATH_MAX], dst_path[PATH_MAX];
+ snprintf(src_path, PATH_MAX, "%s/src-%d", dir, thread_id);
+ snprintf(dst_path, PATH_MAX, "%s/dst-%d", dir, thread_id);
+
+ unsigned char *write_buf = malloc(FILE_SIZE);
+ unsigned char *read_buf = malloc(FILE_SIZE);
+
+ // Write out expected data.
+ memset(write_buf, 0xAA, FILE_SIZE);
+ int src = open(src_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (write(src, write_buf, FILE_SIZE) != FILE_SIZE)
+ perror("write");
+ close(src);
+
+ // Create destination file so we exercise O_TRUNC.
+ int dst = open(dst_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (write(dst, write_buf, FILE_SIZE) != FILE_SIZE)
+ perror("write");
+ fsync(dst);
+ close(dst);
+
+ // Open file with O_TRUNC and perform copy.
+ src = open(src_path, O_RDONLY);
+ dst = open(dst_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+
+ off_t off_in = 0, off_out = 0;
+ ssize_t ret =
+ copy_file_range(src, &off_in, dst, &off_out, FILE_SIZE, 0);
+ if (ret != FILE_SIZE)
+ perror("copy_file_range");
+ close(src);
+ close(dst);
+
+ // Read back
+ dst = open(dst_path, O_RDONLY);
+ if (read(dst, read_buf, FILE_SIZE) != FILE_SIZE)
+ perror("read");
+ close(dst);
+
+ // Bug check
+ if (memcmp(write_buf, read_buf, FILE_SIZE) != 0) {
+ failed = 1;
+ fprintf(stderr, "[%d]: FAIL\n", thread_id);
+
+ int all_zeros = 1;
+ for (int i = 0; i < RECORD_SIZE; i++) {
+ if (read_buf[i] != 0) {
+ all_zeros = 0;
+ break;
+ }
+ }
+
+ if (all_zeros) {
+ fprintf(stderr, "[%d]: ALL ZERO\n", thread_id);
+ }
+ }
+
+ unlink(src_path);
+ unlink(dst_path);
+ free(write_buf);
+ free(read_buf);
+ return (NULL);
+}
+
+int
+main(int argc, const char **argv)
+{
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s <dir>\n", argv[0]);
+ return (1);
+ }
+ dir = argv[1];
+
+ pthread_t threads[NUM_THREADS];
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ pthread_create(&threads[i], NULL, run_test, (void *)(long)i);
+ }
+ for (int i = 0; i < NUM_THREADS; i++) {
+ pthread_join(threads[i], NULL);
+ }
+
+ return (failed);
+}
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/setlease.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/setlease.c
new file mode 100644
index 000000000000..12bcbd91beb5
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/setlease.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: CDDL-1.0
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2026, TrueNAS.
+ */
+
+/*
+ * This is a sanity check test for the F_SETLEASE and F_GETLEASE fcntl() calls.
+ * We use the generic kernel implementation, but we want to be alerted if it
+ * ever breaks.
+ *
+ * This is not a comprehensive test. It would be nice if it could be!
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+static int
+get_lease(int fd) {
+ int r = fcntl(fd, F_GETLEASE);
+ if (r < 0) {
+ perror("fcntl(GETLEASE)");
+ exit(2);
+ }
+ return (r);
+}
+
+static int
+set_lease(int fd, int lease) {
+ return (fcntl(fd, F_SETLEASE, lease) < 0 ? errno : 0);
+}
+
+static const char *lease_str[] = {
+ [F_RDLCK] = "RDLCK",
+ [F_WRLCK] = "WRLCK",
+ [F_UNLCK] = "UNLCK",
+};
+
+static void
+assert_lease(int fd, int expect) {
+ int got = get_lease(fd);
+ if (got != expect) {
+ fprintf(stderr, "ASSERT_LEASE: expected %s [%d], got %s [%d]\n",
+ lease_str[expect], expect, lease_str[got], got);
+ abort();
+ }
+ printf("ok: lease is %s\n", lease_str[got]);
+}
+
+static void
+assert_set_lease(int fd, int lease) {
+ int err = set_lease(fd, lease);
+ if (err != 0) {
+ fprintf(stderr, "ASSERT_SET_LEASE: tried %s [%d], error: %s\n",
+ lease_str[lease], lease, strerror(err));
+ abort();
+ }
+ printf("ok: set lease to %s\n", lease_str[lease]);
+}
+
+int
+main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <filename>\n", argv[0]);
+ exit(1);
+ }
+
+ /* create and open file, read+write */
+ int fd = open(argv[1], O_CREAT|O_RDONLY, S_IRWXU|S_IRWXG|S_IRWXO);
+ if (fd < 0) {
+ perror("open");
+ exit(2);
+ }
+ printf("ok: opened file RDONLY\n");
+
+ /* fd starts with no lease */
+ assert_lease(fd, F_UNLCK);
+
+ /* fd is readonly, so can take read lease */
+ assert_set_lease(fd, F_RDLCK);
+ /* confirm read lease */
+ assert_lease(fd, F_RDLCK);
+
+ /* no other openers, so can take write lease */
+ assert_set_lease(fd, F_WRLCK);
+ /* confirm write lease */
+ assert_lease(fd, F_WRLCK);
+
+ /* release lease */
+ assert_set_lease(fd, F_UNLCK);
+ /* confirm lease released */
+ assert_lease(fd, F_UNLCK);
+
+ close(fd);
+
+ return (0);
+}
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/threadsappend.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/threadsappend.c
index bdbb2881f529..ed0d74c3c279 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/threadsappend.c
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/threadsappend.c
@@ -87,7 +87,7 @@ usage(void)
int
main(int argc, char **argv)
{
- pthread_t tid;
+ pthread_t tid[2];
int ret = 0;
long ncpus = 0;
int i;
@@ -120,7 +120,7 @@ main(int argc, char **argv)
}
for (i = 0; i < 2; i++) {
- ret = pthread_create(&tid, NULL, go, (void *)&i);
+ ret = pthread_create(&tid[i], NULL, go, (void *)&i);
if (ret != 0) {
(void) fprintf(stderr,
"zfs_threadsappend: thr_create(#%d) "
@@ -129,8 +129,8 @@ main(int argc, char **argv)
}
}
- while (pthread_join(tid, NULL) == 0)
- continue;
+ for (i = 0; i < 2; i++)
+ (void) pthread_join(tid[i], NULL);
return (0);
}
diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg b/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg
index 1c4d25e152a7..2ac7d62bb7e5 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg
+++ b/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg
@@ -182,10 +182,11 @@ export ZFS_FILES='zdb
zfs_ids_to_path
zpool_influxdb'
-export ZFSTEST_FILES='badsend
+export ZFSTEST_FILES_COMMON='badsend
btree_test
chg_usr_exec
clonefile
+ clone_after_trunc
clone_mmap_cached
clone_mmap_write
crypto_test
@@ -241,3 +242,6 @@ export ZFSTEST_FILES='badsend
zfs_diff-socket
dosmode_readonly_write
idmap_util'
+
+export ZFSTEST_FILES_LINUX='
+ setlease'
diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib b/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib
index 3d697726a763..23460d66590a 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib
+++ b/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib
@@ -3139,6 +3139,21 @@ function wait_scrubbed #pool timeout
done
}
+# Wait for a pool to be resilvered
+#
+# $1 pool name
+# $2 timeout
+#
+function wait_resilvered #pool timeout
+{
+ typeset timeout=${2:-300}
+ typeset pool=${1:-$TESTPOOL}
+ for (( timer = 0; timer < $timeout; timer++ )); do
+ is_pool_resilvered $pool && break;
+ sleep 1;
+ done
+}
+
# Backup the zed.rc in our test directory so that we can edit it for our test.
#
# Returns: Backup file name. You will need to pass this to zed_rc_restore().
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am
index 99477a74326a..27a6edc31f86 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
CLEANFILES =
dist_noinst_DATA =
include $(top_srcdir)/config/Substfiles.am
@@ -492,6 +493,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/block_cloning/block_cloning_rlimit_fsize.ksh \
functional/block_cloning/block_cloning_large_offset.ksh \
functional/block_cloning/block_cloning_after_device_removal.ksh \
+ functional/block_cloning/block_cloning_after_trunc.ksh \
functional/bootfs/bootfs_001_pos.ksh \
functional/bootfs/bootfs_002_neg.ksh \
functional/bootfs/bootfs_003_pos.ksh \
@@ -765,6 +767,9 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zfs_jail/cleanup.ksh \
functional/cli_root/zfs_jail/setup.ksh \
functional/cli_root/zfs_jail/zfs_jail_001_pos.ksh \
+ functional/cli_root/zfs_list/cleanup.ksh \
+ functional/cli_root/zfs_list/setup.ksh \
+ functional/cli_root/zfs_list/zfs_list_009_pos.ksh \
functional/cli_root/zfs_load-key/cleanup.ksh \
functional/cli_root/zfs_load-key/setup.ksh \
functional/cli_root/zfs_load-key/zfs_load-key_all.ksh \
@@ -1561,6 +1566,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/exec/exec_002_neg.ksh \
functional/exec/setup.ksh \
functional/fadvise/cleanup.ksh \
+ functional/fadvise/fadvise_dontneed.ksh \
functional/fadvise/fadvise_willneed.ksh \
functional/fadvise/setup.ksh \
functional/failmode/cleanup.ksh \
@@ -1655,6 +1661,9 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/io/psync.ksh \
functional/io/setup.ksh \
functional/io/sync.ksh \
+ functional/lease/cleanup.ksh \
+ functional/lease/lease_setlease.ksh \
+ functional/lease/setup.ksh \
functional/l2arc/cleanup.ksh \
functional/l2arc/l2arc_arcstats_pos.ksh \
functional/l2arc/l2arc_l2miss_pos.ksh \
@@ -1886,6 +1895,8 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/redundancy/redundancy_draid3.ksh \
functional/redundancy/redundancy_draid_damaged1.ksh \
functional/redundancy/redundancy_draid_damaged2.ksh \
+ functional/redundancy/redundancy_draid_degraded1.ksh \
+ functional/redundancy/redundancy_draid_degraded2.ksh \
functional/redundancy/redundancy_draid.ksh \
functional/redundancy/redundancy_draid_spare1.ksh \
functional/redundancy/redundancy_draid_spare2.ksh \
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_after_trunc.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_after_trunc.ksh
new file mode 100755
index 000000000000..977ec16042b7
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_after_trunc.ksh
@@ -0,0 +1,31 @@
+#!/bin/ksh -p
+# SPDX-License-Identifier: CDDL-1.0
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+#
+# DESCRIPTION:
+# When a block is truncated and then cloned to, a read data corruption can occur.
+# This is a regression test for #18412.
+#
+
+verify_runnable "global"
+
+claim="No read data corruption when cloning blocks after a truncate"
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
+
+# Run for a few times to increase the likelihood of bug triggering.
+for i in {0..50}; do
+ log_must clone_after_trunc /$TESTPOOL/
+done
+
+log_pass $claim
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_list/cleanup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_list/cleanup.ksh
new file mode 100755
index 000000000000..138dfe0473cc
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_list/cleanup.ksh
@@ -0,0 +1,30 @@
+#!/bin/ksh -p
+# SPDX-License-Identifier: CDDL-1.0
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2026 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_list/setup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_list/setup.ksh
new file mode 100755
index 000000000000..912fcfc40f69
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_list/setup.ksh
@@ -0,0 +1,32 @@
+#!/bin/ksh -p
+# SPDX-License-Identifier: CDDL-1.0
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2026 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_setup $DISKS
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_list/zfs_list_009_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_list/zfs_list_009_pos.ksh
new file mode 100755
index 000000000000..758aa7608d3e
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_list/zfs_list_009_pos.ksh
@@ -0,0 +1,69 @@
+#!/bin/ksh -p
+# SPDX-License-Identifier: CDDL-1.0
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2026 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# 'zfs list -Ho name <path>' follows symlinks when resolving the path to
+# a dataset name. A symlink that crosses a mount boundary must resolve to
+# the dataset owning the symlink's target, not the dataset containing the
+# symlink itself.
+#
+# STRATEGY:
+# 1. Create two child datasets: ds1 and ds2.
+# 2. Place a symlink inside ds1 that points into ds2.
+# 3. Verify that 'zfs list -Ho name <symlink>' returns ds2.
+#
+
+verify_runnable "global"
+
+DS1="$TESTPOOL/$TESTFS/ds1"
+DS2="$TESTPOOL/$TESTFS/ds2"
+LINK="$TESTDIR/ds1/link_to_ds2"
+
+function cleanup
+{
+ rm -f "$LINK"
+ datasetexists "$DS1" && log_must zfs destroy "$DS1"
+ datasetexists "$DS2" && log_must zfs destroy "$DS2"
+}
+
+log_onexit cleanup
+
+log_assert "'zfs list -Ho name' follows symlinks when resolving a path."
+
+log_must zfs create "$DS1"
+log_must zfs create "$DS2"
+log_must ln -s "$TESTDIR/ds2" "$LINK"
+
+result=$(zfs list -Ho name "$LINK")
+if [[ "$result" != "$DS2" ]]; then
+ log_fail "'zfs list -Ho name $LINK' returned '$result', expected '$DS2'"
+fi
+
+log_pass "'zfs list -Ho name' correctly follows a symlink crossing a mount boundary."
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fadvise/fadvise_dontneed.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fadvise/fadvise_dontneed.ksh
new file mode 100755
index 000000000000..53f3ad999d3b
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fadvise/fadvise_dontneed.ksh
@@ -0,0 +1,70 @@
+#!/bin/ksh -p
+# SPDX-License-Identifier: CDDL-1.0
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Test that POSIX_FADV_DONTNEED evicts data from the ZFS dbuf cache.
+#
+# STRATEGY:
+# 1. Write blocks to a file and sync, so they land in the dbuf LRU cache
+# 2. Record cache_count from dbufstats
+# 3. Call file_fadvise with POSIX_FADV_DONTNEED on the file
+# 4. Verify that cache_count decreased
+# 5. Sanity-check eviction for single-block files.
+#
+
+verify_runnable "global"
+
+FILE0=$TESTDIR/$TESTFILE0
+FILE1=$TESTDIR/$TESTFILE1
+BLKSZ=$(get_prop recordsize $TESTPOOL)
+
+function cleanup
+{
+ [[ -e $TESTDIR ]] && log_must rm -Rf $TESTDIR/*
+}
+
+log_assert "Ensure POSIX_FADV_DONTNEED evicts data from the dbuf cache"
+
+log_onexit cleanup
+
+log_must file_write -o create -f $FILE0 -b $BLKSZ -c 100
+sync_pool $TESTPOOL
+
+evicts1=$(kstat dbufstats.cache_count)
+
+log_must file_fadvise -f $FILE0 -a POSIX_FADV_DONTNEED
+
+evicts2=$(kstat dbufstats.cache_count)
+log_note "cache_count before=$evicts1 after=$evicts2"
+
+log_must [ $evicts1 -gt $evicts2 ]
+
+log_must file_write -o create -f $FILE1 -b 12000 -c 1
+sync_pool $TESTPOOL
+
+log_must file_fadvise -f $FILE1 -a POSIX_FADV_DONTNEED
+
+log_pass "POSIX_FADV_DONTNEED evicts data from the dbuf cache"
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/lease/cleanup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/lease/cleanup.ksh
new file mode 100755
index 000000000000..5e73dd34936e
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/lease/cleanup.ksh
@@ -0,0 +1,26 @@
+#!/bin/ksh -p
+# SPDX-License-Identifier: CDDL-1.0
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/lease/lease_setlease.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/lease/lease_setlease.ksh
new file mode 100755
index 000000000000..8647d01995c3
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/lease/lease_setlease.ksh
@@ -0,0 +1,44 @@
+#!/bin/ksh -p
+# SPDX-License-Identifier: CDDL-1.0
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2026, TrueNAS.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+leasefile=/$TESTPOOL/leasefile
+
+function cleanup
+{
+ rm -f $leasefile
+}
+
+log_assert "F_SETLEASE is supported"
+log_onexit cleanup
+
+log_must setlease $leasefile
+
+log_pass "F_SETLEASE is supported"
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/lease/setup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/lease/setup.ksh
new file mode 100755
index 000000000000..09da91b0f93f
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/lease/setup.ksh
@@ -0,0 +1,27 @@
+#!/bin/ksh -p
+# SPDX-License-Identifier: CDDL-1.0
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib
index 65435554bdbe..b9b69e47df3e 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib
@@ -52,7 +52,7 @@ function cleanup
#
function cksum_pool
{
- typeset -i cksum=$(zpool status $1 | awk '
+ typeset -i cksum=$(zpool status -p $1 | awk '
!NF { isvdev = 0 }
isvdev { errors += $NF }
/CKSUM$/ { isvdev = 1 }
@@ -349,3 +349,72 @@ function recover_bad_missing_devs
return 0
}
+
+#
+# Given a dRAID pool issue a scrub and verify the current pool status
+# aligns with the expected status based on the 'replace_mode' passed.
+# Valid modes are:
+#
+# 1. healing - The pool is perfectly intact. No checksum errors have
+# been reported and the scrub didn't make any repairs. This is the
+# expected state after a healing resilver of a healthy pool.
+#
+# 2. sequential - The pool is fully intact. There should never be a
+# checksum error.
+#
+# 3. damaged - The pool was intentionally silently damaged. Checksum
+# errors are expected to be reported as the damaged blocks are
+# detected and repaired.
+#
+# In all of these cases a scrub must be able to successfully repair the
+# pool and result in no data loss.
+#
+function verify_draid_pool
+{
+ typeset pool=${1:-$TESTPOOL}
+ typeset replace_mode=${2:-healing}
+
+ log_note "verify_draid_pool $pool $replace_mode"
+ log_must zpool scrub -w $pool
+
+ typeset -i cksum=$(cksum_pool $pool)
+
+ if [[ "$replace_mode" = "healing" ]]; then
+ if [[ $cksum -gt 0 ]]; then
+ log_must zpool status -v $pool
+ log_fail "Unexpected CKSUM errors found for $pool ($cksum)"
+ fi
+
+ if ! check_pool_status $pool "scan" "repaired 0B"; then
+ log_must zpool status -v $pool
+ log_fail "Unexpected repair IO found for $pool ($cksum)"
+ fi
+ elif [[ "$replace_mode" = "sequential" ]]; then
+ if [[ $cksum -gt 0 ]]; then
+ log_must zpool status -v $pool
+ log_fail "Unexpected CKSUM errors found for $pool ($cksum)"
+ fi
+ elif [[ "$replace_mode" = "damaged" ]]; then
+ if [[ $cksum -lt 1 ]]; then
+ log_must zpool status -v $pool
+ log_fail "Expected CKSUM errors missing for $pool ($cksum)"
+ fi
+
+ if check_pool_status $pool "scan" "repaired 0B"; then
+ log_must zpool status -v $pool
+ log_fail "Expected repair IO missing for $pool ($cksum)"
+ fi
+ else
+ log_fail "Invalid replace_mode=$replace_mode"
+ fi
+
+ if ! check_pool_status $pool "scan" "with 0 errors"; then
+ log_must zpool status -v $pool
+ log_fail "Unexpected repair errors found for $pool"
+ fi
+
+ if ! check_pool_status $pool "errors" "No known data errors"; then
+ log_must zpool status -v $pool
+ log_fail "Unexpected data errors found for $pool"
+ fi
+}
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid.ksh
index a1356f619009..81a01c07a3fd 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid.ksh
@@ -86,8 +86,7 @@ function test_selfheal # <pool> <parity> <dir>
# from the files which were read. Before overwriting additional
# devices we need to repair all of the blocks in the pool.
#
- log_must zpool scrub -w $pool
- log_must check_pool_status $pool "errors" "No known data errors"
+ log_must verify_draid_pool $pool "damaged"
log_must zpool clear $pool
@@ -104,8 +103,7 @@ function test_selfheal # <pool> <parity> <dir>
log_must eval "find $mntpnt -type f -exec cksum {} + >> /dev/null 2>&1"
log_must check_pool_status $pool "errors" "No known data errors"
- log_must zpool scrub -w $pool
- log_must check_pool_status $pool "errors" "No known data errors"
+ log_must verify_draid_pool $pool "damaged"
log_must zpool clear $pool
}
@@ -182,8 +180,7 @@ function test_scrub # <pool> <parity> <dir>
log_must zpool import -o cachefile=none -d $dir $pool
- log_must zpool scrub -w $pool
- log_must check_pool_status $pool "errors" "No known data errors"
+ log_must verify_draid_pool $pool "damaged"
log_must zpool clear $pool
@@ -196,8 +193,7 @@ function test_scrub # <pool> <parity> <dir>
log_must zpool import -o cachefile=none -d $dir $pool
- log_must zpool scrub -w $pool
- log_must check_pool_status $pool "errors" "No known data errors"
+ log_must verify_draid_pool $pool "damaged"
log_must zpool clear $pool
}
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged1.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged1.ksh
index cafd63166013..56b12373af52 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged1.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged1.ksh
@@ -89,12 +89,7 @@ function test_sequential_resilver # <pool> <parity> <dir>
log_must zpool replace -fsw $pool $dir/dev-$i $spare
done
- log_must zpool scrub -w $pool
- log_must zpool status $pool
-
- log_mustnot check_pool_status $pool "scan" "repaired 0B"
- log_must check_pool_status $pool "errors" "No known data errors"
- log_must check_pool_status $pool "scan" "with 0 errors"
+ log_must verify_draid_pool $pool "damaged"
}
log_onexit cleanup
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged2.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged2.ksh
index 46bf9f950864..3dfb760be07d 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged2.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_damaged2.ksh
@@ -121,12 +121,7 @@ for nparity in 1 2 3; do
# Scrub the pool after the sequential resilver and verify
# that the silent damage was repaired by the scrub.
- log_must zpool scrub -w $TESTPOOL
- log_must zpool status $TESTPOOL
- log_must check_pool_status $TESTPOOL "errors" \
- "No known data errors"
- log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
- log_mustnot check_pool_status $TESTPOOL "scan" "repaired 0B"
+ log_must verify_draid_pool $TESTPOOL "damaged"
done
for nspare in 0 1 2; do
@@ -145,12 +140,7 @@ for nparity in 1 2 3; do
done
log_must zpool clear $TESTPOOL
- log_must zpool scrub -w $TESTPOOL
- log_must zpool status $TESTPOOL
-
- log_must check_pool_status $TESTPOOL "errors" "No known data errors"
- log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
- log_must check_pool_status $TESTPOOL "scan" "repaired 0B"
+ log_must verify_draid_pool $TESTPOOL "healing"
log_must zpool destroy "$TESTPOOL"
done
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_degraded1.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_degraded1.ksh
new file mode 100755
index 000000000000..31444850f76c
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_degraded1.ksh
@@ -0,0 +1,136 @@
+#!/bin/ksh -p
+# SPDX-License-Identifier: CDDL-1.0
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2026 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/redundancy/redundancy.kshlib
+
+#
+# DESCRIPTION:
+# When sequentially resilvering a dRAID pool with multiple vdevs
+# and N faulted vdevs, where N=parity, ensure that when another leaf
+# is marked degraded the pool can still be sequentially resilvered
+# without introducing new checksum errors. Note we've exhausted
+# the available redundancy so no silent correction can be tolerated.
+#
+# STRATEGY:
+# 1. Create block device files for the test draid pool
+# 2. For each parity value [1..3]
+# - create draid pool
+# - fill it with some directories/files
+# - fault N=parity vdevs eliminating any redundancy
+# - force fault an additional vdev causing it to be degraded
+# - replace the degraded (but online) vdev using a sequential
+# resilver. The minimum pool redundancy requirements are met so
+# reconstruction is possible when reading from all online vdevs.
+# - verify that the draid spare was correctly reconstructed and
+# no checksum errors were introduced.
+# - destroy the draid pool
+#
+
+typeset -r devs=7
+typeset -r dev_size_mb=512
+
+typeset -a disks
+
+prefetch_disable=$(get_tunable PREFETCH_DISABLE)
+rebuild_scrub_enabled=$(get_tunable REBUILD_SCRUB_ENABLED)
+
+function cleanup
+{
+ poolexists "$TESTPOOL" && destroy_pool "$TESTPOOL"
+
+ for i in {0..$devs}; do
+ rm -f "$TEST_BASE_DIR/dev-$i"
+ done
+
+ set_tunable32 PREFETCH_DISABLE $prefetch_disable
+ set_tunable32 REBUILD_SCRUB_ENABLED $rebuild_scrub_enabled
+}
+
+function test_sequential_resilver # <pool> <parity> <dir>
+{
+ typeset pool=$1
+ typeset nparity=$2
+ typeset dir=$3
+
+ # Fault N=parity devices
+ for (( i=0; i<$nparity; i=i+1 )); do
+ log_must zpool offline -f $pool $dir/dev-$i
+ done
+
+ # Parity is exhausted, faulting another device marks it degraded
+ log_must zpool offline -f $pool $dir/dev-$nparity
+
+ # Replace the degraded vdev with a distributed spare
+ spare=draid${nparity}-0-0
+ log_must zpool replace -fsw $pool $dir/dev-$nparity $spare
+
+ log_must verify_draid_pool $pool "sequential"
+}
+
+log_onexit cleanup
+
+log_must set_tunable32 PREFETCH_DISABLE 1
+log_must set_tunable32 REBUILD_SCRUB_ENABLED 0
+
+# Disk files which will be used by pool
+for i in {0..$(($devs - 1))}; do
+ device=$TEST_BASE_DIR/dev-$i
+ log_must truncate -s ${dev_size_mb}M $device
+ disks[${#disks[*]}+1]=$device
+done
+
+# Disk file which will be attached
+log_must truncate -s 512M $TEST_BASE_DIR/dev-$devs
+
+for nparity in 1 2 3; do
+ raid=draid${nparity}:${nparity}s
+ dir=$TEST_BASE_DIR
+
+ log_must zpool create -O compression=off -f -o cachefile=none $TESTPOOL $raid ${disks[@]}
+ log_must zfs set primarycache=metadata $TESTPOOL
+
+ log_must zfs create $TESTPOOL/fs
+ log_must fill_fs /$TESTPOOL/fs 1 512 102400 1 R
+
+ log_must zfs create -o compress=on $TESTPOOL/fs2
+ log_must fill_fs /$TESTPOOL/fs2 1 512 102400 1 R
+
+ log_must zfs create -o compress=on -o recordsize=8k $TESTPOOL/fs3
+ log_must fill_fs /$TESTPOOL/fs3 1 512 102400 1 R
+
+ log_must zpool export $TESTPOOL
+ log_must zpool import -o cachefile=none -d $dir $TESTPOOL
+
+ log_must check_pool_status $TESTPOOL "errors" "No known data errors"
+
+ test_sequential_resilver $TESTPOOL $nparity $dir
+
+ log_must zpool destroy "$TESTPOOL"
+done
+
+log_pass "draid degraded device(s) test succeeded."
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_degraded2.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_degraded2.ksh
new file mode 100755
index 000000000000..22e1f2dfb310
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_degraded2.ksh
@@ -0,0 +1,152 @@
+#!/bin/ksh -p
+# SPDX-License-Identifier: CDDL-1.0
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or https://opensource.org/licenses/CDDL-1.0.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2026 by Lawrence Livermore National Security, LLC.
+# Copyright (c) 2026 by Wasabi Technologies, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/redundancy/redundancy.kshlib
+
+#
+# DESCRIPTION:
+# When sequentially resilvering a dRAID pool with multiple vdevs
+# and N faulted vdevs, where N=parity, ensure that when another leaf
+# is marked degraded the pool can still be sequentially resilvered
+# without introducing new checksum errors. Note we've exhausted
+# the available redundancy so no silent correction can be tolerated.
+#
+# This test is very similar to redundancy_draid_degraded1 and is
+# based on it. The difference is that 1) we always have some faulted
+# vdev which is already resilvered, and 2) we resilver the most
+# recently faulted, but marked degraded due to redundancy exhaustion,
+# vdev also.
+#
+# STRATEGY:
+# 1. Create block device files for the test draid pool
+# 2. For each parity value [1..3]
+# - create draid pool
+# - fill it with some directories/files
+# - fault one vdev and resilver it
+# - fault N=parity vdevs eliminating any redundancy
+# - force fault an additional vdev causing it to be degraded
+# - replace faulted vdevs using a sequential resilver.
+# The minimum pool redundancy requirements are met so
+# reconstruction is possible when reading from all online vdevs.
+# - verify that the draid spare was correctly reconstructed and
+# no checksum errors were introduced.
+# - destroy the draid pool
+#
+
+typeset -r devs=13
+typeset -r dev_size_mb=512
+
+typeset -a disks
+
+prefetch_disable=$(get_tunable PREFETCH_DISABLE)
+rebuild_scrub_enabled=$(get_tunable REBUILD_SCRUB_ENABLED)
+scan_suspend_progress=$(get_tunable SCAN_SUSPEND_PROGRESS)
+
+function cleanup
+{
+ poolexists "$TESTPOOL" && destroy_pool "$TESTPOOL"
+
+ for i in {0..$devs}; do
+ rm -f "$TEST_BASE_DIR/dev-$i"
+ done
+
+ set_tunable32 PREFETCH_DISABLE $prefetch_disable
+ set_tunable32 REBUILD_SCRUB_ENABLED $rebuild_scrub_enabled
+ set_tunable32 SCAN_SUSPEND_PROGRESS $scan_suspend_progress
+}
+
+function test_sequential_resilver # <pool> <parity> <dir>
+{
+ typeset pool=$1
+ typeset nparity=$2
+ typeset dir=$3
+
+ # Fault N=parity devices
+ for (( i=0; i<$nparity; i++ )); do
+ log_must zpool offline -f $pool $dir/dev-$i
+ done
+
+ # Parity is exhausted, faulting another device marks it degraded
+ log_must zpool offline -f $pool $dir/dev-$nparity
+
+ # Replace all faulted vdevs with distributed spares
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+ for (( i=0; i<$((nparity+1)); i++ )); do
+ spare=draid${nparity}-0-$i
+ log_must zpool replace -fs $pool $dir/dev-$i $spare
+ done
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+
+ log_must zpool wait -t resilver $pool
+
+ log_must verify_draid_pool $pool "sequential"
+}
+
+log_onexit cleanup
+
+log_must set_tunable32 PREFETCH_DISABLE 1
+log_must set_tunable32 REBUILD_SCRUB_ENABLED 0
+
+# Disk files which will be used by pool
+for i in {0..$(($devs - 1))}; do
+ device=$TEST_BASE_DIR/dev-$i
+ log_must truncate -s ${dev_size_mb}M $device
+ disks[${#disks[*]}+1]=$device
+done
+
+# Disk file which will be attached
+log_must truncate -s 512M $TEST_BASE_DIR/dev-$devs
+
+for nparity in 3; do
+ raid=draid${nparity}:$((nparity+2))s
+ dir=$TEST_BASE_DIR
+
+ log_must zpool create -O compression=off -f -o cachefile=none $TESTPOOL $raid ${disks[@]}
+ log_must zfs set primarycache=metadata $TESTPOOL
+
+ log_must zfs create $TESTPOOL/fs
+ log_must fill_fs /$TESTPOOL/fs 1 512 102400 1 R
+
+ log_must zfs create -o compress=on $TESTPOOL/fs2
+ log_must fill_fs /$TESTPOOL/fs2 1 512 102400 1 R
+
+ log_must zfs create -o compress=on -o recordsize=8k $TESTPOOL/fs3
+ log_must fill_fs /$TESTPOOL/fs3 1 512 102400 1 R
+
+ log_must zpool export $TESTPOOL
+ log_must zpool import -o cachefile=none -d $dir $TESTPOOL
+
+ log_must check_pool_status $TESTPOOL "errors" "No known data errors"
+
+ test_sequential_resilver $TESTPOOL $nparity $dir
+
+ log_must zpool destroy "$TESTPOOL"
+done
+
+log_pass "draid degraded device(s) test succeeded."
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare1.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare1.ksh
index b0f312f26e60..e5d16910ddcd 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare1.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare1.ksh
@@ -19,6 +19,7 @@
#
# Copyright (c) 2019, Datto Inc. All rights reserved.
# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
+# Copyright (c) 2026, Seagate Technology, LLC.
#
. $STF_SUITE/include/libtest.shlib
@@ -82,10 +83,9 @@ for replace_mode in "healing" "sequential"; do
log_must check_vdev_state spare-$i "DEGRADED"
log_must check_vdev_state $spare_vdev "ONLINE"
log_must check_hotspare_state $TESTPOOL $spare_vdev "INUSE"
- log_must zpool detach $TESTPOOL $fault_vdev
- log_must verify_pool $TESTPOOL
- log_must check_pool_status $TESTPOOL "scan" "repaired 0B"
- log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
+ # Preserve the 1st faulted vdev for the next test.
+ [[ $i -eq 0 ]] || log_must zpool detach $TESTPOOL $fault_vdev
+ log_must verify_draid_pool $TESTPOOL $replace_mode
(( i += 1 ))
done
@@ -93,6 +93,11 @@ for replace_mode in "healing" "sequential"; do
log_must is_data_valid $TESTPOOL
log_must check_pool_status $TESTPOOL "errors" "No known data errors"
+ # Verify that after clearing the 1st faulted vdev, all is healed.
+ log_must zpool clear $TESTPOOL "$BASEDIR/vdev0"
+ log_must wait_resilvered $TESTPOOL
+ log_must verify_draid_pool $TESTPOOL $replace_mode
+
cleanup
done
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare2.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare2.ksh
index 288f02392b43..6f94161b47fe 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare2.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare2.ksh
@@ -60,9 +60,9 @@ log_must zpool offline -f $TESTPOOL $BASEDIR/vdev9
log_must zpool replace -w $TESTPOOL $BASEDIR/vdev9 draid1-0-2
# Verify, refill and verify the pool contents.
-verify_pool $TESTPOOL
+log_must verify_draid_pool $TESTPOOL "healing"
refill_test_env $TESTPOOL
-verify_pool $TESTPOOL
+log_must verify_draid_pool $TESTPOOL "healing"
# Bring everything back online and check for errors.
log_must zpool clear $TESTPOOL
@@ -72,9 +72,7 @@ log_must wait_hotspare_state $TESTPOOL draid1-0-0 "AVAIL"
log_must wait_hotspare_state $TESTPOOL draid1-0-1 "AVAIL"
log_must wait_hotspare_state $TESTPOOL draid1-0-2 "AVAIL"
-log_must zpool scrub -w $TESTPOOL
-log_must check_pool_status $TESTPOOL "scan" "repaired 0B"
-log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
+log_must verify_draid_pool $TESTPOOL "healing"
log_must is_data_valid $TESTPOOL
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare3.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare3.ksh
index 425c30a4984c..f1485375fdf1 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare3.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare3.ksh
@@ -111,9 +111,7 @@ for replace_mode in "healing" "sequential"; do
log_must zpool detach $TESTPOOL $BASEDIR/vdev7
log_must check_vdev_state $TESTPOOL draid1-0-0 "ONLINE"
log_must check_hotspare_state $TESTPOOL draid1-0-0 "INUSE"
- log_must verify_pool $TESTPOOL
- log_must check_pool_status $TESTPOOL "scan" "repaired 0B"
- log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
+ log_must verify_draid_pool $TESTPOOL $replace_mode
# Distributed spare in mirror with original device faulted
log_must zpool offline -f $TESTPOOL $BASEDIR/vdev8
@@ -122,9 +120,7 @@ for replace_mode in "healing" "sequential"; do
log_must check_vdev_state $TESTPOOL spare-8 "DEGRADED"
log_must check_vdev_state $TESTPOOL draid1-0-1 "ONLINE"
log_must check_hotspare_state $TESTPOOL draid1-0-1 "INUSE"
- log_must verify_pool $TESTPOOL
- log_must check_pool_status $TESTPOOL "scan" "repaired 0B"
- log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
+ log_must verify_draid_pool $TESTPOOL $replace_mode
# Distributed spare in mirror with original device still online
log_must check_vdev_state $TESTPOOL $BASEDIR/vdev9 "ONLINE"
@@ -132,9 +128,7 @@ for replace_mode in "healing" "sequential"; do
log_must check_vdev_state $TESTPOOL spare-9 "ONLINE"
log_must check_vdev_state $TESTPOOL draid1-0-2 "ONLINE"
log_must check_hotspare_state $TESTPOOL draid1-0-2 "INUSE"
- log_must verify_pool $TESTPOOL
- log_must check_pool_status $TESTPOOL "scan" "repaired 0B"
- log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
+ log_must verify_draid_pool $TESTPOOL $replace_mode
# Normal faulted device replacement
new_vdev0="$BASEDIR/new_vdev0"
@@ -143,9 +137,7 @@ for replace_mode in "healing" "sequential"; do
log_must check_vdev_state $TESTPOOL $BASEDIR/vdev0 "FAULTED"
log_must zpool replace -w $flags $TESTPOOL $BASEDIR/vdev0 $new_vdev0
log_must check_vdev_state $TESTPOOL $new_vdev0 "ONLINE"
- log_must verify_pool $TESTPOOL
- log_must check_pool_status $TESTPOOL "scan" "repaired 0B"
- log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
+ log_must verify_draid_pool $TESTPOOL $replace_mode
# Distributed spare faulted device replacement
log_must zpool offline -f $TESTPOOL $BASEDIR/vdev2
@@ -154,9 +146,7 @@ for replace_mode in "healing" "sequential"; do
log_must check_vdev_state $TESTPOOL spare-2 "DEGRADED"
log_must check_vdev_state $TESTPOOL draid1-0-3 "ONLINE"
log_must check_hotspare_state $TESTPOOL draid1-0-3 "INUSE"
- log_must verify_pool $TESTPOOL
- log_must check_pool_status $TESTPOOL "scan" "repaired 0B"
- log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
+ log_must verify_draid_pool $TESTPOOL $replace_mode
# Normal online device replacement
new_vdev1="$BASEDIR/new_vdev1"
@@ -164,9 +154,7 @@ for replace_mode in "healing" "sequential"; do
log_must check_vdev_state $TESTPOOL $BASEDIR/vdev1 "ONLINE"
log_must zpool replace -w $flags $TESTPOOL $BASEDIR/vdev1 $new_vdev1
log_must check_vdev_state $TESTPOOL $new_vdev1 "ONLINE"
- log_must verify_pool $TESTPOOL
- log_must check_pool_status $TESTPOOL "scan" "repaired 0B"
- log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
+ log_must verify_draid_pool $TESTPOOL $replace_mode
# Distributed spare online device replacement (then fault)
log_must zpool replace -w $flags $TESTPOOL $BASEDIR/vdev3 draid1-0-4
@@ -176,9 +164,7 @@ for replace_mode in "healing" "sequential"; do
log_must zpool offline -f $TESTPOOL $BASEDIR/vdev3
log_must check_vdev_state $TESTPOOL $BASEDIR/vdev3 "FAULTED"
log_must check_vdev_state $TESTPOOL spare-3 "DEGRADED"
- log_must verify_pool $TESTPOOL
- log_must check_pool_status $TESTPOOL "scan" "repaired 0B"
- log_must check_pool_status $TESTPOOL "scan" "with 0 errors"
+ log_must verify_draid_pool $TESTPOOL $replace_mode
# Verify the original data is valid
log_must is_data_valid $TESTPOOL
diff --git a/sys/contrib/openzfs/udev/Makefile.am b/sys/contrib/openzfs/udev/Makefile.am
index 6fd645b5c22f..c4990ecc709c 100644
--- a/sys/contrib/openzfs/udev/Makefile.am
+++ b/sys/contrib/openzfs/udev/Makefile.am
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: CDDL-1.0
udevrule_DATA = \
%D%/rules.d/69-vdev.rules \
%D%/rules.d/60-zvol.rules \
diff --git a/sys/modules/zfs/zfs_config.h b/sys/modules/zfs/zfs_config.h
index 635fb0a7e91f..e3e3437d438a 100644
--- a/sys/modules/zfs/zfs_config.h
+++ b/sys/modules/zfs/zfs_config.h
@@ -26,6 +26,9 @@
/* Define if you have [rt] */
#define HAVE_AIO_H 1
+/* Define if your assembler supports .cfi_negate_ra_state. */
+/* #undef HAVE_AS_CFI_PSEUDO_OP */
+
#ifdef __amd64__
#ifndef RESCUE
/* Define if host toolchain supports AVX */
@@ -195,6 +198,9 @@
/* backing_dev_info is available through queue gendisk */
/* #undef HAVE_BLK_QUEUE_DISK_BDI */
+/* blk_queue_rot() is available */
+/* #undef HAVE_BLK_QUEUE_ROT */
+
/* blk_queue_secure_erase() is available */
/* #undef HAVE_BLK_QUEUE_SECURE_ERASE */
@@ -238,6 +244,9 @@
/* DECLARE_EVENT_CLASS() is available */
/* #undef HAVE_DECLARE_EVENT_CLASS */
+/* dentry aliases are in d_u member */
+/* #undef HAVE_DENTRY_D_U_ALIASES */
+
/* 3-arg dequeue_signal() takes a type argument */
/* #undef HAVE_DEQUEUE_SIGNAL_3ARG_TYPE */
@@ -271,6 +280,9 @@
/* fault_in_iov_iter_readable() is available */
/* #undef HAVE_FAULT_IN_IOV_ITER_READABLE */
+/* linux/filelock.h exists */
+/* #undef HAVE_FILELOCK_HEADER */
+
/* file->f_version exists */
/* #undef HAVE_FILE_F_VERSION */
@@ -283,6 +295,9 @@
/* fsync_bdev() is declared in include/blkdev.h */
/* #undef HAVE_FSYNC_BDEV */
+/* fs_context exists */
+/* #undef HAVE_FS_CONTEXT */
+
/* yes */
/* #undef HAVE_GENERIC_FADVISE */
@@ -523,6 +538,9 @@
/* page_size() is available */
/* #undef HAVE_MM_PAGE_SIZE */
+/* mount_setattr() and struct mount_attr are available */
+/* #undef HAVE_MOUNT_SETATTR */
+
/* Define if host toolchain supports MOVBE */
#define HAVE_MOVBE 1
@@ -547,6 +565,9 @@
/* pin_user_pages_unlocked() is available */
/* #undef HAVE_PIN_USER_PAGES_UNLOCKED */
+/* posix_acl_to_xattr() allocates its result */
+/* #undef HAVE_POSIX_ACL_TO_XATTR_ALLOC */
+
/* proc_handler ctl_table arg is const */
/* #undef HAVE_PROC_HANDLER_CTL_TABLE_CONST */
@@ -865,7 +886,7 @@
/* #undef ZFS_DEVICE_MINOR */
/* Define the project alias string. */
-#define ZFS_META_ALIAS "zfs-2.4.1-1-FreeBSD_g1c702dda3"
+#define ZFS_META_ALIAS "zfs-2.4.2-1-FreeBSD_g6330a45b0"
/* Define the project author. */
#define ZFS_META_AUTHOR "OpenZFS"
@@ -874,7 +895,7 @@
/* #undef ZFS_META_DATA */
/* Define the maximum compatible kernel version. */
-#define ZFS_META_KVER_MAX "6.19"
+#define ZFS_META_KVER_MAX "7.0"
/* Define the minimum compatible kernel version. */
#define ZFS_META_KVER_MIN "4.18"
@@ -895,10 +916,10 @@
#define ZFS_META_NAME "zfs"
/* Define the project release. */
-#define ZFS_META_RELEASE "1-FreeBSD_g1c702dda3"
+#define ZFS_META_RELEASE "1-FreeBSD_g6330a45b0"
/* Define the project version. */
-#define ZFS_META_VERSION "2.4.1"
+#define ZFS_META_VERSION "2.4.2"
/* count is located in percpu_ref.data */
/* #undef ZFS_PERCPU_REF_COUNT_IN_DATA */
diff --git a/sys/modules/zfs/zfs_gitrev.h b/sys/modules/zfs/zfs_gitrev.h
index 320f6dbf3bbd..03efa90ba633 100644
--- a/sys/modules/zfs/zfs_gitrev.h
+++ b/sys/modules/zfs/zfs_gitrev.h
@@ -1 +1 @@
-#define ZFS_META_GITREV "zfs-2.4.1-0-g1c702dda3-dirty"
+#define ZFS_META_GITREV "zfs-2.4.2-0-g6330a45b0"