diff options
| author | Martin Matuska <mm@FreeBSD.org> | 2026-05-13 19:53:01 +0000 |
|---|---|---|
| committer | Colin Percival <cperciva@FreeBSD.org> | 2026-05-14 23:58:46 +0000 |
| commit | 409247a6cbd11e3510025e025f3b82184c3de17c (patch) | |
| tree | 49200e7c219ffc2bb10fec867bc55ded8cbe5686 | |
| parent | 2ebec3c7ead5f5b477a5ab47136562777f2bb495 (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)
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, ¶m, &result); + if (opt >= 0) { + /* + * We already know this one of our options, so a + * failure here would be nonsensical. + */ + VERIFY0(zpl_parse_param(fc, ¶m)); + } else { + /* + * Not one of our option, send it through the kernel's + * standard parameter handling. + */ + err = vfs_parse_fs_param(fc, ¶m); + 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" |
