diff options
| author | Martin Matuska <mm@FreeBSD.org> | 2026-05-02 07:17:59 +0000 |
|---|---|---|
| committer | Martin Matuska <mm@FreeBSD.org> | 2026-05-02 07:18:34 +0000 |
| commit | f9590540c524607d22fa7e718c758725c4365375 (patch) | |
| tree | 0c2c76b7ad7d89bd0ce31dda4ac4adda32ebd934 | |
| parent | 069681afd58a711eb7407be4a9c9a05f787d250f (diff) | |
| parent | 84ffe564dff1b7f69d397817ef292cbe2c5ebad3 (diff) | |
zfs: merge openzfs/zfs@84ffe564d
Notable upstream pull request merges:
#18387 656285140 Handle raidz errors <= nparity rather than ignoring
#18401 1cebe8a38 libzfs: report invalid permission name in zfs allow
#18430 513710ed2 Fix "panic: cache_vop_rename: lingering negative entry"
#18440 37e3a260f dmu_direct: avoid UAF in dmu_write_direct_done()
#18445 2eee4ac1e Fix: draid autopkgtests fail on s390x architecture
#18448 8da472973 key lookup failure should always return EACCES
#18456 4a58ab8ce zfs.4: document five missing module parameters
Obtained from: OpenZFS
OpenZFS commit: 84ffe564dff1b7f69d397817ef292cbe2c5ebad3
70 files changed, 890 insertions, 268 deletions
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 9d6cc3c6d3e2..5c41a4d6a497 100755 --- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-1-setup.sh +++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-1-setup.sh @@ -63,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 / @@ -77,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 / @@ -139,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 3d78885a9ca3..f4e70c31c4cd 100755 --- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh +++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-2-start.sh @@ -188,17 +188,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-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 5e18f4bf49c1..51ae82567c2c 100755 --- a/sys/contrib/openzfs/.github/workflows/scripts/qemu-7-prepare.sh +++ b/sys/contrib/openzfs/.github/workflows/scripts/qemu-7-prepare.sh @@ -51,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 @@ -61,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" @@ -89,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 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/.mailmap b/sys/contrib/openzfs/.mailmap index 377a511bead6..87d9530f4241 100644 --- a/sys/contrib/openzfs/.mailmap +++ b/sys/contrib/openzfs/.mailmap @@ -32,7 +32,9 @@ Andrew Walker <awalker@ixsystems.com> Benedikt Neuffer <github@itfriend.de> Chengfei Zhu <chengfeix.zhu@intel.com> ChenHao Lu <18302010006@fudan.edu.cn> +Chris Jacobs <idefix2020dev@gmail.com> Chris Lindee <chris.lindee+github@gmail.com> +Colin K. Williams <colin@li-nk.org> Colm Buckley <colm@tuatha.org> Crag Wang <crag0715@gmail.com> Damian Szuberski <szuberskidamian@gmail.com> @@ -192,6 +194,7 @@ Kyle Evans <kevans@FreeBSD.org> <kevans91@users.noreply.github.com> Laurențiu Nicola <lnicola@dend.ro> <lnicola@users.noreply.github.com> loli10K <ezomori.nozomu@gmail.com> <loli10K@users.noreply.github.com> Lorenz Hüdepohl <dev@stellardeath.org> <lhuedepohl@users.noreply.github.com> +Louis Leseur <louis.leseur@gmail.com> <51127370+teapot9@users.noreply.github.com> Luís Henriques <henrix@camandro.org> <73643340+lumigch@users.noreply.github.com> Marcin Skarbek <git@skarbek.name> <mskarbek@users.noreply.github.com> Matt Fiddaman <github@m.fiddaman.uk> <81489167+matt-fidd@users.noreply.github.com> @@ -212,6 +215,7 @@ Peter Wirdemo <peter.wirdemo@gmail.com> <4224155+pewo@users.noreply.github.com> Petros Koutoupis <petros@petroskoutoupis.com> <pkoutoupis@users.noreply.github.com> Ping Huang <huangping@smartx.com> <101400146+hpingfs@users.noreply.github.com> Piotr P. Stefaniak <pstef@freebsd.org> <pstef@users.noreply.github.com> +Pranav P <pranavsdreams@gmail.com> <49746983+pranavkaruvally@users.noreply.github.com> Richard Allen <belperite@gmail.com> <33836503+belperite@users.noreply.github.com> Rich Ercolani <rincebrain@gmail.com> <214141+rincebrain@users.noreply.github.com> Rick Macklem <rmacklem@uoguelph.ca> <64620010+rmacklem@users.noreply.github.com> @@ -223,6 +227,7 @@ Samuel Wycliffe <samuelwycliffe@gmail.com> <50765275+npc203@users.noreply.github Savyasachee Jha <hi@savyasacheejha.com> <savyajha@users.noreply.github.com> Scott Colby <scott@scolby.com> <scolby33@users.noreply.github.com> Sean Eric Fagan <kithrup@mac.com> <kithrup@users.noreply.github.com> +Shelvacu <git@shelvacu.com> <1731537+shelvacu@users.noreply.github.com> Shreshth Srivastava <shreshthsrivastava2@gmail.com> <66148173+Shreshth3@users.noreply.github.com> Spencer Kinny <spencerkinny1995@gmail.com> <30333052+Spencer-Kinny@users.noreply.github.com> Srikanth N S <srikanth.nagasubbaraoseetharaman@hpe.com> <75025422+nssrikanth@users.noreply.github.com> @@ -245,3 +250,4 @@ XDTG <click1799@163.com> <35128600+XDTG@users.noreply.github.com> xtouqh <xtouqh@hotmail.com> <72357159+xtouqh@users.noreply.github.com> Yuri Pankov <yuripv@FreeBSD.org> <113725409+yuripv@users.noreply.github.com> Yuri Pankov <yuripv@FreeBSD.org> <82001006+yuripv@users.noreply.github.com> +ZhengYuan Huang <gality369@gmail.com> <68463495+Gality369@users.noreply.github.com> diff --git a/sys/contrib/openzfs/AUTHORS b/sys/contrib/openzfs/AUTHORS index 11aea0171651..fc83b1fe748c 100644 --- a/sys/contrib/openzfs/AUTHORS +++ b/sys/contrib/openzfs/AUTHORS @@ -144,17 +144,18 @@ CONTRIBUTORS: Chris Davidson <christopher.davidson@gmail.com> Chris Dunlap <cdunlap@llnl.gov> Chris Dunlop <chris@onthe.net.au> + Chris Jacobs <idefix2020dev@gmail.com> Chris Lindee <chris.lindee+github@gmail.com> Chris McDonough <chrism@plope.com> Chris Peredun <chris.peredun@ixsystems.com> Chris Siden <chris.siden@delphix.com> Chris Siebenmann <cks.github@cs.toronto.edu> Christer Ekholm <che@chrekh.se> - Christos Longros <chris.longros@gmail.com> Christian Kohlschütter <christian@kohlschutter.com> Christian Neukirchen <chneukirchen@gmail.com> Christian Schwarz <me@cschwarz.com> Christopher Voltz <cjunk@voltz.ws> + Christos Longros <chris.longros@gmail.com> Christ Schlacta <aarcane@aarcane.info> Chris Wedgwood <cw@f00f.org> Chris Williamson <chris.williamson@delphix.com> @@ -167,6 +168,7 @@ CONTRIBUTORS: Clint Armstrong <clint@clintarmstrong.net> Coleman Kane <ckane@colemankane.org> Colin Ian King <colin.king@canonical.com> + Colin K. Williams <colin@li-nk.org> Colin Percival <cperciva@tarsnap.com> Colm Buckley <colm@tuatha.org> Cong Zhang <congzhangzh@users.noreply.github.com> @@ -258,6 +260,8 @@ CONTRIBUTORS: Garrett D'Amore <garrett@nexenta.com> Garrett Fields <ghfields@gmail.com> Garrison Jensen <garrison.jensen@gmail.com> + Garth Snyder <garth@garthsnyder.com> + Gary Guo <gary@garyguo.net> Gary Mills <gary_mills@fastmail.fm> Gaurav Kumar <gauravk.18@gmail.com> GeLiXin <ge.lixin@zte.com.cn> @@ -328,6 +332,7 @@ CONTRIBUTORS: James Wah <james@laird-wah.net> Jan Engelhardt <jengelh@inai.de> Jan Kryl <jan.kryl@nexenta.com> + Jan Martin Mikkelsen <janm-github@transactionware.com> Jan Sanislo <oystr@cs.washington.edu> Jaron Kent-Dobias <jaron@kent-dobias.com> Jason Cohen <jwittlincohen@gmail.com> @@ -377,6 +382,7 @@ CONTRIBUTORS: Jo Zzsi <jozzsicsataban@gmail.com> João Carlos Mendes Luís <jonny@jonny.eng.br> JT Pennington <jt.pennington@klarasystems.com> + Juhyung Park <qkrwngud825@gmail.com> Julian Brunner <julian.brunner@gmail.com> Julian Heuking <JulianH@beckhoff.com> jumbi77 <jumbi77@users.noreply.github.com> @@ -433,6 +439,7 @@ CONTRIBUTORS: lorddoskias <lorddoskias@gmail.com> Lorenz Brun <lorenz@dolansoft.org> Lorenz Hüdepohl <dev@stellardeath.org> + Louis Leseur <louis.leseur@gmail.com> louwrentius <louwrentius@gmail.com> Lukas Wunner <lukas@wunner.de> luozhengzheng <luo.zhengzheng@zte.com.cn> @@ -448,6 +455,7 @@ CONTRIBUTORS: Marcel Telka <marcel.telka@nexenta.com> Marcel Wysocki <maci.stgn@gmail.com> Marcin Skarbek <git@skarbek.name> + Marc Sladek <marc@sladek.dev> Mariusz Zaborski <mariusz.zaborski@klarasystems.com> Mark Johnston <markj@FreeBSD.org> Mark Maybee <mark.maybee@delphix.com> @@ -495,6 +503,7 @@ CONTRIBUTORS: Mike Swanson <mikeonthecomputer@gmail.com> Milan Jurik <milan.jurik@xylab.cz> Minsoo Choo <minsoochoo0122@proton.me> + mischivus <mischivus@users.noreply.github.com> mnrx <mnrx@users.noreply.github.com> Mohamed Tawfik <m_tawfik@aucegypt.edu> Morgan Jones <mjones@rice.edu> @@ -557,6 +566,7 @@ CONTRIBUTORS: Piotr P. Stefaniak <pstef@freebsd.org> poscat <poscat@poscat.moe> Prakash Surya <prakash.surya@delphix.com> + Pranav P <pranavsdreams@gmail.com> Prasad Joshi <prasadjoshi124@gmail.com> privb0x23 <privb0x23@users.noreply.github.com> P.SCH <p88@yahoo.com> @@ -627,6 +637,7 @@ CONTRIBUTORS: Shampavman <sham.pavman@nexenta.com> Shaun Tancheff <shaun@aeonazure.com> Shawn Bayern <sbayern@law.fsu.edu> + Shelvacu <git@shelvacu.com> Shengqi Chen <harry-chen@outlook.com> SHENGYI HONG <aokblast@FreeBSD.org> Shen Yan <shenyanxxxy@qq.com> @@ -671,6 +682,7 @@ CONTRIBUTORS: Tim Connors <tconnors@rather.puzzling.org> Tim Crawford <tcrawford@datto.com> Tim Haley <Tim.Haley@Sun.COM> + Tim Hatch <tim@timhatch.com> timor <timor.dd@googlemail.com> Timothy Day <tday141@gmail.com> Tim Schumacher <timschumi@gmx.de> @@ -737,6 +749,7 @@ CONTRIBUTORS: Zach Dykstra <dykstra.zachary@gmail.com> zgock <zgock@nuc.base.zgock-lab.net> Zhao Yongming <zym@apache.org> + ZhengYuan Huang <gality369@gmail.com> Zhenlei Huang <zlei@FreeBSD.org> Zhu Chuang <chuang@melty.land> Érico Nogueira <erico.erc@gmail.com> diff --git a/sys/contrib/openzfs/META b/sys/contrib/openzfs/META index 260bd7e401ec..ab1b8955d245 100644 --- a/sys/contrib/openzfs/META +++ b/sys/contrib/openzfs/META @@ -6,5 +6,5 @@ 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/cmd/zinject/zinject.c b/sys/contrib/openzfs/cmd/zinject/zinject.c index 37ff92a816f4..1b5fd595830d 100644 --- a/sys/contrib/openzfs/cmd/zinject/zinject.c +++ b/sys/contrib/openzfs/cmd/zinject/zinject.c @@ -229,6 +229,7 @@ static const struct errstr errstrtable[] = { { ECHILD, "dtl" }, { EILSEQ, "corrupt" }, { ENOSYS, "noop" }, + { EFAULT, "io-prefail" }, { 0, NULL }, }; @@ -308,7 +309,8 @@ usage(void) "\t\tlabel. Label injection can either be 'nvlist', 'uber',\n " "\t\t'pad1', or 'pad2'.\n" "\t\t'errno' can be 'nxio' (the default), 'io', 'dtl',\n" - "\t\t'corrupt' (bit flip), or 'noop' (successfully do nothing).\n" + "\t\t'corrupt' (bit flip), 'io-prefail' (unsuccessfully do\n" + "\t\tnothing) or 'noop' (successfully do nothing).\n" "\t\t'frequency' is a value between 0.0001 and 100.0 that limits\n" "\t\tdevice error injection to a percentage of the IOs.\n" "\n" @@ -1026,7 +1028,8 @@ main(int argc, char **argv) if (error < 0) { (void) fprintf(stderr, "invalid error type " "'%s': must be one of: io decompress " - "decrypt nxio dtl corrupt noop\n", + "decrypt nxio dtl corrupt noop " + "io-prefail\n", optarg); usage(); libzfs_fini(g_zfs); 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/initramfs/scripts/zfs b/sys/contrib/openzfs/contrib/initramfs/scripts/zfs index 9d2c086ffdfe..1b3bd531064a 100644 --- a/sys/contrib/openzfs/contrib/initramfs/scripts/zfs +++ b/sys/contrib/openzfs/contrib/initramfs/scripts/zfs @@ -514,9 +514,9 @@ destroy_fs() _destroy_fs="${1}" [ "${quiet}" != "y" ] && \ - zfs_log_begin_msg "Destroying '${destroy_fs}'" + zfs_log_begin_msg "Destroying '${_destroy_fs}'" - ZFS_CMD="${ZFS} destroy ${destroy_fs}" + ZFS_CMD="${ZFS} destroy ${_destroy_fs}" ZFS_STDERR="$(${ZFS_CMD} 2>&1)" ZFS_ERROR="${?}" if [ "${ZFS_ERROR}" != 0 ] @@ -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/include/libzfs_core.h b/sys/contrib/openzfs/include/libzfs_core.h index deb810230b48..22f190913c95 100644 --- a/sys/contrib/openzfs/include/libzfs_core.h +++ b/sys/contrib/openzfs/include/libzfs_core.h @@ -93,8 +93,6 @@ _LIBZFS_CORE_H int lzc_send(const char *, const char *, int, enum lzc_send_flags); _LIBZFS_CORE_H int lzc_send_resume(const char *, const char *, int, enum lzc_send_flags, uint64_t, uint64_t); -_LIBZFS_CORE_H int lzc_send_space(const char *, const char *, - enum lzc_send_flags, uint64_t *); struct dmu_replay_record; diff --git a/sys/contrib/openzfs/include/sys/zio.h b/sys/contrib/openzfs/include/sys/zio.h index acb0a03a36b2..c3a199ce813c 100644 --- a/sys/contrib/openzfs/include/sys/zio.h +++ b/sys/contrib/openzfs/include/sys/zio.h @@ -243,6 +243,7 @@ typedef uint64_t zio_flag_t; #define ZIO_FLAG_REEXECUTED (1ULL << 30) #define ZIO_FLAG_DELEGATED (1ULL << 31) #define ZIO_FLAG_PREALLOCATED (1ULL << 32) +#define ZIO_FLAG_POSTREAD (1ULL << 33) #define ZIO_ALLOCATOR_NONE (-1) #define ZIO_HAS_ALLOCATOR(zio) ((zio)->io_allocator != ZIO_ALLOCATOR_NONE) diff --git a/sys/contrib/openzfs/include/zfs_fletcher.h b/sys/contrib/openzfs/include/zfs_fletcher.h index d450f7f5e8a7..4cd8cabfab9e 100644 --- a/sys/contrib/openzfs/include/zfs_fletcher.h +++ b/sys/contrib/openzfs/include/zfs_fletcher.h @@ -60,6 +60,8 @@ _ZFS_FLETCHER_H int fletcher_2_incremental_native(void *, size_t, void *); _ZFS_FLETCHER_H int fletcher_2_incremental_byteswap(void *, size_t, void *); _ZFS_FLETCHER_H void fletcher_4_native_varsize(const void *, uint64_t, zio_cksum_t *); +_ZFS_FLETCHER_H void fletcher_4_byteswap_varsize(const void *, uint64_t, + zio_cksum_t *); _ZFS_FLETCHER_H void fletcher_4_byteswap(const void *, uint64_t, const void *, zio_cksum_t *); _ZFS_FLETCHER_H int fletcher_4_incremental_native(void *, size_t, void *); diff --git a/sys/contrib/openzfs/lib/libspl/os/linux/mnttab.c b/sys/contrib/openzfs/lib/libspl/os/linux/mnttab.c index 25fa132ac6fc..f51219e898e6 100644 --- a/sys/contrib/openzfs/lib/libspl/os/linux/mnttab.c +++ b/sys/contrib/openzfs/lib/libspl/os/linux/mnttab.c @@ -125,7 +125,14 @@ getextmntent(const char *path, struct mnttab *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/libzfs/libzfs.abi b/sys/contrib/openzfs/lib/libzfs/libzfs.abi index 6349fca09bcb..ad28c8766303 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs.abi +++ b/sys/contrib/openzfs/lib/libzfs/libzfs.abi @@ -189,6 +189,7 @@ <elf-symbol name='fletcher_2_incremental_native' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='fletcher_2_native' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='fletcher_4_byteswap' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='fletcher_4_byteswap_varsize' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='fletcher_4_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='fletcher_4_impl_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='fletcher_4_incremental_byteswap' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> @@ -1668,8 +1669,103 @@ </function-decl> </abi-instr> <abi-instr address-size='64' path='lib/libspl/os/linux/mnttab.c' language='LANG_C99'> + <array-type-def dimensions='1' type-id='d315442e' size-in-bits='16' id='811205dc'> + <subrange length='1' type-id='7359adad' id='52f813b4'/> + </array-type-def> + <array-type-def dimensions='1' type-id='d3130597' size-in-bits='768' id='f63f23b9'> + <subrange length='12' type-id='7359adad' id='84827bdc'/> + </array-type-def> + <typedef-decl name='__u16' type-id='8efea9e5' id='d315442e'/> + <typedef-decl name='__s32' type-id='95e97e5e' id='3158a266'/> + <typedef-decl name='__u32' type-id='f0981eeb' id='3f1a6b60'/> + <typedef-decl name='__s64' type-id='1eb56b1e' id='49659421'/> + <typedef-decl name='__u64' type-id='3a47d82b' id='d3130597'/> + <class-decl name='statx_timestamp' size-in-bits='128' is-struct='yes' visibility='default' id='94101016'> + <data-member access='public' layout-offset-in-bits='0'> + <var-decl name='tv_sec' type-id='49659421' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='64'> + <var-decl name='tv_nsec' type-id='3f1a6b60' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='96'> + <var-decl name='__reserved' type-id='3158a266' visibility='default'/> + </data-member> + </class-decl> + <class-decl name='statx' size-in-bits='2048' is-struct='yes' visibility='default' id='720b04c5'> + <data-member access='public' layout-offset-in-bits='0'> + <var-decl name='stx_mask' type-id='3f1a6b60' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='32'> + <var-decl name='stx_blksize' type-id='3f1a6b60' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='64'> + <var-decl name='stx_attributes' type-id='d3130597' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='128'> + <var-decl name='stx_nlink' type-id='3f1a6b60' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='160'> + <var-decl name='stx_uid' type-id='3f1a6b60' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='192'> + <var-decl name='stx_gid' type-id='3f1a6b60' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='224'> + <var-decl name='stx_mode' type-id='d315442e' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='240'> + <var-decl name='__spare0' type-id='811205dc' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='256'> + <var-decl name='stx_ino' type-id='d3130597' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='320'> + <var-decl name='stx_size' type-id='d3130597' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='384'> + <var-decl name='stx_blocks' type-id='d3130597' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='448'> + <var-decl name='stx_attributes_mask' type-id='d3130597' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='512'> + <var-decl name='stx_atime' type-id='94101016' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='640'> + <var-decl name='stx_btime' type-id='94101016' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='768'> + <var-decl name='stx_ctime' type-id='94101016' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='896'> + <var-decl name='stx_mtime' type-id='94101016' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='1024'> + <var-decl name='stx_rdev_major' type-id='3f1a6b60' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='1056'> + <var-decl name='stx_rdev_minor' type-id='3f1a6b60' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='1088'> + <var-decl name='stx_dev_major' type-id='3f1a6b60' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='1120'> + <var-decl name='stx_dev_minor' type-id='3f1a6b60' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='1152'> + <var-decl name='stx_mnt_id' type-id='d3130597' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='1216'> + <var-decl name='__spare2' type-id='d3130597' visibility='default'/> + </data-member> + <data-member access='public' layout-offset-in-bits='1280'> + <var-decl name='__spare3' type-id='f63f23b9' visibility='default'/> + </data-member> + </class-decl> <pointer-type-def type-id='56fe4a37' size-in-bits='64' id='b6b61d2f'/> <qualified-type-def type-id='b6b61d2f' restrict='yes' id='3cad23cd'/> + <pointer-type-def type-id='720b04c5' size-in-bits='64' id='936b8e35'/> + <qualified-type-def type-id='936b8e35' restrict='yes' id='31d265b7'/> <function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='e75a27e9'/> <parameter type-id='3cad23cd'/> @@ -1681,6 +1777,14 @@ <parameter type-id='822cd80b'/> <return type-id='95e97e5e'/> </function-decl> + <function-decl name='statx' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='95e97e5e'/> + <parameter type-id='9d26089a'/> + <parameter type-id='95e97e5e'/> + <parameter type-id='f0981eeb'/> + <parameter type-id='31d265b7'/> + <return type-id='95e97e5e'/> + </function-decl> </abi-instr> <abi-instr address-size='64' path='lib/libspl/procfs_list.c' language='LANG_C99'> <class-decl name='procfs_list' size-in-bits='768' is-struct='yes' visibility='default' id='0f4d3b87'> @@ -3830,6 +3934,10 @@ <parameter type-id='80f4b756'/> <return type-id='58603c44'/> </function-decl> + <function-decl name='zfs_prop_user' mangled-name='zfs_prop_user' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_user'> + <parameter type-id='80f4b756'/> + <return type-id='c19b74c3'/> + </function-decl> <function-decl name='nvlist_add_uint64' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='5ce45b60'/> <parameter type-id='80f4b756'/> @@ -3854,9 +3962,6 @@ <parameter type-id='7d3cd834'/> <return type-id='95e97e5e'/> </function-decl> - <function-decl name='fnvlist_alloc' visibility='default' binding='global' size-in-bits='64'> - <return type-id='5ce45b60'/> - </function-decl> <function-decl name='__ctype_b_loc' visibility='default' binding='global' size-in-bits='64'> <return type-id='c59e1ef0'/> </function-decl> @@ -4529,10 +4634,6 @@ <parameter type-id='c19b74c3'/> <return type-id='c19b74c3'/> </function-decl> - <function-decl name='zfs_prop_user' mangled-name='zfs_prop_user' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_user'> - <parameter type-id='80f4b756'/> - <return type-id='c19b74c3'/> - </function-decl> <function-decl name='zfs_prop_userquota' mangled-name='zfs_prop_userquota' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_userquota'> <parameter type-id='80f4b756'/> <return type-id='c19b74c3'/> @@ -4642,6 +4743,9 @@ <parameter type-id='7d3cd834'/> <return type-id='95e97e5e'/> </function-decl> + <function-decl name='fnvlist_alloc' visibility='default' binding='global' size-in-bits='64'> + <return type-id='5ce45b60'/> + </function-decl> <function-decl name='fnvlist_free' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='5ce45b60'/> <return type-id='48b5725f'/> @@ -4909,6 +5013,12 @@ <parameter type-id='80f4b756' name='path'/> <return type-id='95e97e5e'/> </function-decl> + <function-decl name='zfs_create_ancestors_props' mangled-name='zfs_create_ancestors_props' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_create_ancestors_props'> + <parameter type-id='b0382bb3' name='hdl'/> + <parameter type-id='80f4b756' name='path'/> + <parameter type-id='5ce45b60' name='props'/> + <return type-id='95e97e5e'/> + </function-decl> <function-decl name='zfs_create' mangled-name='zfs_create' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_create'> <parameter type-id='b0382bb3' name='hdl'/> <parameter type-id='80f4b756' name='path'/> @@ -5155,6 +5265,19 @@ <parameter type-id='0d41d328'/> <return type-id='95e97e5e'/> </function-decl> + <function-decl name='zfs_is_namespace_prop' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='58603c44'/> + <return type-id='c19b74c3'/> + </function-decl> + <function-decl name='zfs_namespace_prop_flag' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='58603c44'/> + <return type-id='8f92235e'/> + </function-decl> + <function-decl name='zfs_mount_setattr' visibility='default' binding='global' size-in-bits='64'> + <parameter type-id='9200a744'/> + <parameter type-id='8f92235e'/> + <return type-id='95e97e5e'/> + </function-decl> <function-decl name='zpool_name_valid' visibility='default' binding='global' size-in-bits='64'> <parameter type-id='b0382bb3'/> <parameter type-id='c19b74c3'/> @@ -8337,6 +8460,7 @@ <parameter type-id='b0382bb3'/> <parameter type-id='26a90f95'/> <parameter type-id='95e97e5e'/> + <parameter type-id='5ce45b60'/> <return type-id='95e97e5e'/> </function-decl> <function-decl name='zfs_send_progress' mangled-name='zfs_send_progress' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_send_progress'> @@ -10331,6 +10455,12 @@ <parameter type-id='c24fc2ee' name='zcp'/> <return type-id='48b5725f'/> </function-decl> + <function-decl name='fletcher_4_byteswap_varsize' mangled-name='fletcher_4_byteswap_varsize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_byteswap_varsize'> + <parameter type-id='eaa32e2f' name='buf'/> + <parameter type-id='9c313c2d' name='size'/> + <parameter type-id='c24fc2ee' name='zcp'/> + <return type-id='48b5725f'/> + </function-decl> <function-decl name='fletcher_4_byteswap' mangled-name='fletcher_4_byteswap' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fletcher_4_byteswap'> <parameter type-id='eaa32e2f' name='buf'/> <parameter type-id='9c313c2d' name='size'/> diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c b/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c index e5a7ca9ba3f5..923bbd995de5 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_dataset.c @@ -5138,7 +5138,7 @@ zfs_set_fsacl(zfs_handle_t *zhp, boolean_t un, nvlist_t *nvl) err = zfs_error(hdl, EZFS_BADVERSION, errbuf); break; case EINVAL: - err = zfs_error(hdl, EZFS_BADTYPE, errbuf); + err = zfs_error(hdl, EZFS_BADPERM, errbuf); break; case ENOENT: err = zfs_error(hdl, EZFS_NOENT, errbuf); 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 7d8768d12dda..991ef3dfbb94 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 @@ -406,7 +406,11 @@ do_unmount(zfs_handle_t *zhp, const char *mntpt, int flags) argv[count] = (char *)mntpt; rc = libzfs_run_process(argv[0], argv, STDOUT_VERBOSE|STDERR_VERBOSE); - return (rc ? EINVAL : 0); + if (rc == 0) + return (0); + if (rc > 0 && geteuid() != 0) + return (EPERM); + return (EINVAL); } #ifdef HAVE_MOUNT_SETATTR diff --git a/sys/contrib/openzfs/man/man4/zfs.4 b/sys/contrib/openzfs/man/man4/zfs.4 index 82b0a890e0b4..c1fe65d2ad90 100644 --- a/sys/contrib/openzfs/man/man4/zfs.4 +++ b/sys/contrib/openzfs/man/man4/zfs.4 @@ -745,6 +745,13 @@ depends on kernel configuration. This is the minimum allocation size that will use scatter (page-based) ABDs. Smaller allocations will use linear ABDs. . +.It Sy zfs_active_allocator Ns = Ns Sy dynamic Pq charp +Select the SPA metaslab allocator. +Valid values are +.Sy dynamic +and +.Sy cursor . +. .It Sy zfs_arc_dnode_limit Ns = Ns Sy 0 Ns B Pq u64 When the number of bytes consumed by dnodes in the ARC exceeds this number of bytes, try to unpin some of it in response to demand for non-metadata. @@ -937,6 +944,13 @@ If equivalent to the greater of the number of online CPUs and .Sy 4 . . +.It Sy zfs_arc_no_grow_shift Ns = Ns Sy 5 Pq uint +If less than +.Sy arc_c No >> Sy zfs_arc_no_grow_shift +free memory is available, the ARC is not allowed to grow. +This parameter is +.Fx Ns -specific . +. .It Sy zfs_arc_overflow_shift Ns = Ns Sy 8 Pq int The ARC size is considered to be overflowing if it exceeds the current ARC target size @@ -1034,6 +1048,11 @@ The timeout is scaled based on a percentage of the last lwb latency to avoid significantly impacting the latency of each individual transaction record (itx). . +.It Sy zfs_compressed_arc_enabled Ns = Ns Sy 1 Ns | Ns 0 Pq int +Enables storing ARC buffers in their on-disk compressed form, reducing +memory pressure. +When disabled, buffers are decompressed before being cached. +. .It Sy zfs_condense_indirect_commit_entry_delay_ms Ns = Ns Sy 0 Ns ms Pq int Vdev indirection layer (used for device removal) sleeps for this many milliseconds during mapping generation. @@ -1690,6 +1709,11 @@ which have the .Em no_root_squash option set. . +.It Sy zfs_snapshot_history_enabled Ns = Ns Sy 1 Ns | Ns 0 Pq int +Whether snapshot creation and destruction events are recorded in the pool +history log, viewable with +.Nm zpool Cm history . +. .It Sy zfs_snapshot_no_setuid Ns = Ns Sy 0 Ns | Ns 1 Pq int Whether to disable .Em setuid/setgid @@ -2181,6 +2205,10 @@ working on a scrub between TXG flushes. .It Sy zfs_scrub_error_blocks_per_txg Ns = Ns Sy 4096 Pq uint Error blocks to be scrubbed in one txg. . +.It Sy zfs_scan_blkstats Ns = Ns Sy 0 Ns | Ns 1 Pq int +When enabled, ZFS counts blocks by type and indirection level during a scrub. +The counts are kept in memory for debugging and are not exposed to userspace. +. .It Sy zfs_scan_checkpoint_intval Ns = Ns Sy 7200 Ns s Po 2 hour Pc Pq uint To preserve progress across reboots, the sequential scan algorithm periodically needs to stop metadata scanning and issue all the verification I/O to disk. @@ -2388,6 +2416,13 @@ and may need to load new metaslabs to satisfy these allocations. .It Sy zfs_sync_pass_rewrite Ns = Ns Sy 2 Pq uint Rewrite new block pointers starting in this pass. . +.It Sy zfs_scrub_partial_writes Ns = Ns Sy 1 Ns | Ns 0 Pq int +If a write to a multi-disk vdev fails, but the data is recoverable, the data is +persisted on disk but may not be as redundant as the vdev usually ensures. +If this tunable is set, we issue a read after such a write error to detect the +full extent of the problem and attempt to recover from it. +Note: This currently only works with RAID-Z and dRAID. +. .It Sy zfs_trim_extent_bytes_max Ns = Ns Sy 134217728 Ns B Po 128 MiB Pc Pq uint Maximum size of TRIM command. Larger ranges will be split into chunks no larger than this value before diff --git a/sys/contrib/openzfs/man/man8/zinject.8 b/sys/contrib/openzfs/man/man8/zinject.8 index 092af93211c8..cda6d337864f 100644 --- a/sys/contrib/openzfs/man/man8/zinject.8 +++ b/sys/contrib/openzfs/man/man8/zinject.8 @@ -237,8 +237,10 @@ for an ECHILD error, for an EIO error where reopening the device will succeed, .It Sy nxio for an ENXIO error where reopening the device will fail, or +.It Sy io-prefail +to drop the IO without executing it and return failure, or .It Sy noop -to drop the IO without executing it, and return success. +to drop the IO without executing it and return success. .El .Pp For EIO and ENXIO, the "failed" reads or writes still occur. diff --git a/sys/contrib/openzfs/man/man8/zpool-labelclear.8 b/sys/contrib/openzfs/man/man8/zpool-labelclear.8 index b807acaaede3..65b2f6c4fd3e 100644 --- a/sys/contrib/openzfs/man/man8/zpool-labelclear.8 +++ b/sys/contrib/openzfs/man/man8/zpool-labelclear.8 @@ -50,6 +50,15 @@ is a cache device, it also removes the L2ARC header The .Ar device must not be part of an active pool configuration. +.Pp +This overwrites pool metadata, making all data on the +.Ar device +inaccessible without specialized recovery tools. +Unlike +.Nm zpool Cm destroy , +this cannot be undone by ZFS tooling. +Only use this when you don't care about the data on the +.Ar device . .Bl -tag -width Ds .It Fl f Treat exported or foreign devices as inactive. diff --git a/sys/contrib/openzfs/man/man8/zpool.8 b/sys/contrib/openzfs/man/man8/zpool.8 index 3bfef780b298..4b07f96bbcbc 100644 --- a/sys/contrib/openzfs/man/man8/zpool.8 +++ b/sys/contrib/openzfs/man/man8/zpool.8 @@ -108,7 +108,9 @@ specified. Destroys the given pool, freeing up any devices for other use. .It Xr zpool-labelclear 8 Removes ZFS label information from the specified -.Ar device . +.Ar device , +making all data inaccessible without specialized recovery tools. +Cannot be undone with ZFS tooling. .El . .Ss Virtual Devices 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 6e52d90e0940..4dd9ed88d433 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 @@ -3524,7 +3524,7 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp, ZRENAMING, NULL)); } } - if (error == 0) { + if (error == 0 && zfsvfs->z_use_namecache) { cache_vop_rename(sdvp, *svpp, tdvp, *tvpp, scnp, tcnp); } } 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/zcommon/zfs_fletcher.c b/sys/contrib/openzfs/module/zcommon/zfs_fletcher.c index 1a7dde1dd8f6..5f6f37157ff7 100644 --- a/sys/contrib/openzfs/module/zcommon/zfs_fletcher.c +++ b/sys/contrib/openzfs/module/zcommon/zfs_fletcher.c @@ -499,6 +499,13 @@ fletcher_4_native_varsize(const void *buf, uint64_t size, zio_cksum_t *zcp) fletcher_4_scalar_native((fletcher_4_ctx_t *)zcp, buf, size); } +void +fletcher_4_byteswap_varsize(const void *buf, uint64_t size, zio_cksum_t *zcp) +{ + ZIO_SET_CHECKSUM(zcp, 0, 0, 0, 0); + fletcher_4_scalar_byteswap((fletcher_4_ctx_t *)zcp, buf, size); +} + static inline void fletcher_4_byteswap_impl(const void *buf, uint64_t size, zio_cksum_t *zcp) { diff --git a/sys/contrib/openzfs/module/zfs/arc.c b/sys/contrib/openzfs/module/zfs/arc.c index be31cff50059..c28cb9114dd8 100644 --- a/sys/contrib/openzfs/module/zfs/arc.c +++ b/sys/contrib/openzfs/module/zfs/arc.c @@ -1874,7 +1874,7 @@ arc_hdr_authenticate(arc_buf_hdr_t *hdr, spa_t *spa, uint64_t dsobj) if (ret == 0) arc_hdr_clear_flags(hdr, ARC_FLAG_NOAUTH); - else if (ret == ENOENT) + else if (ret == EACCES) ret = 0; if (free_abd) 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/dsl_crypt.c b/sys/contrib/openzfs/module/zfs/dsl_crypt.c index 9207737f908b..56004f7fc902 100644 --- a/sys/contrib/openzfs/module/zfs/dsl_crypt.c +++ b/sys/contrib/openzfs/module/zfs/dsl_crypt.c @@ -2677,23 +2677,16 @@ int spa_crypt_get_salt(spa_t *spa, uint64_t dsobj, uint8_t *salt) { int ret; - dsl_crypto_key_t *dck = NULL; + dsl_crypto_key_t *dck; /* look up the key from the spa's keystore */ ret = spa_keystore_lookup_key(spa, dsobj, FTAG, &dck); if (ret != 0) - goto error; + return (SET_ERROR(EACCES)); ret = zio_crypt_key_get_salt(&dck->dck_key, salt); - if (ret != 0) - goto error; - spa_keystore_dsl_key_rele(spa, dck, FTAG); - return (0); -error: - if (dck != NULL) - spa_keystore_dsl_key_rele(spa, dck, FTAG); return (ret); } @@ -2708,9 +2701,7 @@ spa_do_crypt_objset_mac_abd(boolean_t generate, spa_t *spa, uint64_t dsobj, abd_t *abd, uint_t datalen, boolean_t byteswap) { int ret; - dsl_crypto_key_t *dck = NULL; - void *buf = abd_borrow_buf_copy(abd, datalen); - objset_phys_t *osp = buf; + dsl_crypto_key_t *dck; uint8_t portable_mac[ZIO_OBJSET_MAC_LEN]; uint8_t local_mac[ZIO_OBJSET_MAC_LEN]; const uint8_t zeroed_mac[ZIO_OBJSET_MAC_LEN] = {0}; @@ -2718,15 +2709,19 @@ spa_do_crypt_objset_mac_abd(boolean_t generate, spa_t *spa, uint64_t dsobj, /* look up the key from the spa's keystore */ ret = spa_keystore_lookup_key(spa, dsobj, FTAG, &dck); if (ret != 0) - goto error; + return (SET_ERROR(EACCES)); + + void *buf = abd_borrow_buf_copy(abd, datalen); + objset_phys_t *osp = buf; /* calculate both HMACs */ ret = zio_crypt_do_objset_hmacs(&dck->dck_key, buf, datalen, byteswap, portable_mac, local_mac); - if (ret != 0) - goto error; - spa_keystore_dsl_key_rele(spa, dck, FTAG); + if (ret != 0) { + abd_return_buf(abd, buf, datalen); + return (ret); + } /* if we are generating encode the HMACs in the objset_phys_t */ if (generate) { @@ -2760,14 +2755,7 @@ spa_do_crypt_objset_mac_abd(boolean_t generate, spa_t *spa, uint64_t dsobj, } abd_return_buf(abd, buf, datalen); - return (0); - -error: - if (dck != NULL) - spa_keystore_dsl_key_rele(spa, dck, FTAG); - abd_return_buf(abd, buf, datalen); - return (ret); } int @@ -2775,23 +2763,22 @@ spa_do_crypt_mac_abd(boolean_t generate, spa_t *spa, uint64_t dsobj, abd_t *abd, uint_t datalen, uint8_t *mac) { int ret; - dsl_crypto_key_t *dck = NULL; - uint8_t *buf = abd_borrow_buf_copy(abd, datalen); + dsl_crypto_key_t *dck; uint8_t digestbuf[ZIO_DATA_MAC_LEN]; /* look up the key from the spa's keystore */ ret = spa_keystore_lookup_key(spa, dsobj, FTAG, &dck); if (ret != 0) - goto error; + return (SET_ERROR(EACCES)); + uint8_t *buf = abd_borrow_buf_copy(abd, datalen); /* perform the hmac */ ret = zio_crypt_do_hmac(&dck->dck_key, buf, datalen, digestbuf, ZIO_DATA_MAC_LEN); - if (ret != 0) - goto error; - - abd_return_buf(abd, buf, datalen); spa_keystore_dsl_key_rele(spa, dck, FTAG); + abd_return_buf(abd, buf, datalen); + if (ret != 0) + return (ret); /* * Truncate and fill in mac buffer if we were asked to generate a MAC. @@ -2806,12 +2793,6 @@ spa_do_crypt_mac_abd(boolean_t generate, spa_t *spa, uint64_t dsobj, abd_t *abd, return (SET_ERROR(ECKSUM)); return (0); - -error: - if (dck != NULL) - spa_keystore_dsl_key_rele(spa, dck, FTAG); - abd_return_buf(abd, buf, datalen); - return (ret); } /* diff --git a/sys/contrib/openzfs/module/zfs/vdev_draid.c b/sys/contrib/openzfs/module/zfs/vdev_draid.c index c76557e80c9b..8f556b868784 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_draid.c +++ b/sys/contrib/openzfs/module/zfs/vdev_draid.c @@ -505,7 +505,11 @@ verify_perms(uint8_t *perms, uint64_t children, uint64_t nperms, int permssz = sizeof (uint8_t) * children * nperms; zio_cksum_t cksum; +#if defined(_ZFS_BIG_ENDIAN) + fletcher_4_byteswap_varsize(perms, permssz, &cksum); +#else fletcher_4_native_varsize(perms, permssz, &cksum); +#endif if (checksum != cksum.zc_word[0]) { kmem_free(counts, countssz); diff --git a/sys/contrib/openzfs/module/zfs/vdev_raidz.c b/sys/contrib/openzfs/module/zfs/vdev_raidz.c index aa44acbf39cb..2db7422e772e 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_raidz.c +++ b/sys/contrib/openzfs/module/zfs/vdev_raidz.c @@ -406,6 +406,16 @@ static unsigned long raidz_io_aggregate_rows = 4; */ static int zfs_scrub_after_expand = 1; +/* + * If there are errors when writing, but few enough that the data is + * recoverable, then ZFS used to silently move on, leaving the data not 100% + * redundant. If this tunable is set, we issue a read after that case occurs, + * allowing the normal error recovery process to handle it. + * + * NOTE: Currently applies only to raidz and draid. + */ +static int zfs_scrub_partial_writes = 1; + static void vdev_raidz_row_free(raidz_row_t *rr) { @@ -3641,6 +3651,7 @@ vdev_raidz_io_done_write_impl(zio_t *zio, raidz_row_t *rr) { int normal_errors = 0; int shadow_errors = 0; + int retryable_errors = 0; ASSERT3U(rr->rr_missingparity, <=, rr->rr_firstdatacol); ASSERT3U(rr->rr_missingdata, <=, rr->rr_cols - rr->rr_firstdatacol); @@ -3657,6 +3668,11 @@ vdev_raidz_io_done_write_impl(zio_t *zio, raidz_row_t *rr) ASSERT(rc->rc_shadow_error != ECKSUM); shadow_errors++; } + if (rc->rc_error || rc->rc_shadow_error) { + vdev_t *cvd = zio->io_vd->vdev_child[rc->rc_devidx]; + if (!(vdev_is_dead(cvd) || cvd->vdev_cant_write)) + retryable_errors++; + } } /* @@ -3676,6 +3692,8 @@ vdev_raidz_io_done_write_impl(zio_t *zio, raidz_row_t *rr) shadow_errors > rr->rr_firstdatacol) { zio->io_error = zio_worst_error(zio->io_error, vdev_raidz_worst_error(rr)); + } else if (retryable_errors && zfs_scrub_partial_writes) { + zio->io_flags |= ZIO_FLAG_POSTREAD; } } @@ -5528,6 +5546,9 @@ ZFS_MODULE_PARAM(zfs_vdev, raidz_, io_aggregate_rows, ULONG, ZMOD_RW, ZFS_MODULE_PARAM(zfs, zfs_, scrub_after_expand, INT, ZMOD_RW, "For expanded RAIDZ, automatically start a pool scrub when expansion " "completes"); +ZFS_MODULE_PARAM(zfs, zfs_, scrub_partial_writes, INT, ZMOD_RW, + "Issue reads after writes with recoverable failures to ensure " + "integrity"); ZFS_MODULE_PARAM(zfs_vdev, vdev_, read_sit_out_secs, ULONG, ZMOD_RW, "Raidz/draid slow disk sit out time period in seconds"); ZFS_MODULE_PARAM(zfs_vdev, vdev_, raidz_outlier_check_interval_ms, U64, diff --git a/sys/contrib/openzfs/module/zfs/zio.c b/sys/contrib/openzfs/module/zfs/zio.c index 5c2c984c34b6..94b44561bd98 100644 --- a/sys/contrib/openzfs/module/zfs/zio.c +++ b/sys/contrib/openzfs/module/zfs/zio.c @@ -1676,10 +1676,10 @@ zio_vdev_child_io(zio_t *pio, blkptr_t *bp, vdev_t *vd, uint64_t offset, * have already processed the original allocating I/O. */ if (flags & ZIO_FLAG_ALLOC_THROTTLED && - (vd != vd->vdev_top || (flags & ZIO_FLAG_IO_RETRY))) { + (vd != vd->vdev_top || (flags & ZIO_FLAG_IO_RETRY)) && + type == ZIO_TYPE_WRITE) { ASSERT(pio->io_metaslab_class != NULL); ASSERT(pio->io_metaslab_class->mc_alloc_throttle_enabled); - ASSERT(type == ZIO_TYPE_WRITE); ASSERT(priority == ZIO_PRIORITY_ASYNC_WRITE); ASSERT(!(flags & ZIO_FLAG_IO_REPAIR)); ASSERT(!(pio->io_flags & ZIO_FLAG_IO_REWRITE) || @@ -4779,11 +4779,17 @@ zio_vdev_io_start(zio_t *zio) } zio->io_delay = gethrtime(); - if (zio_handle_device_injection(vd, zio, ENOSYS) != 0) { + int error = zio_handle_device_injections(vd, zio, ENOSYS, + EFAULT); + if (error == ENOSYS || (error == EFAULT && + !(zio->io_flags & ZIO_FLAG_IO_REPAIR))) { /* * "no-op" injections return success, but do no actual - * work. Just return it. + * work. Just return it. "io-prefail" injections are + * similar, but don't return success. */ + if (error == EFAULT) + zio->io_error = EIO; zio_delay_interrupt(zio); return (NULL); } @@ -5513,6 +5519,12 @@ zio_dva_throttle_done(zio_t *zio) } } +static void +zio_done_postread_done(zio_t *zio) +{ + abd_free(zio->io_abd); +} + static zio_t * zio_done(zio_t *zio) { @@ -5843,6 +5855,24 @@ zio_done(zio_t *zio) zfs_ereport_free_checksum(zcr); } + if (zio->io_flags & ZIO_FLAG_POSTREAD) { + ASSERT3U(zio->io_type, ==, ZIO_TYPE_WRITE); + zl = NULL; + zio_t *pio = zio_walk_parents(zio, &zl); + blkptr_t *bp = zio->io_bp; + abd_t *abd = abd_alloc_for_io(BP_GET_PSIZE(bp), B_FALSE); + zio_priority_t prio = zio->io_priority == + ZIO_PRIORITY_SYNC_WRITE ? ZIO_PRIORITY_SYNC_READ : + ZIO_PRIORITY_SCRUB; + zio_t *cio = zio_vdev_child_io(pio, zio->io_bp, zio->io_vd, + zio->io_offset, abd, zio->io_size, ZIO_TYPE_READ, prio, + ZIO_FLAG_SCRUB | ZIO_FLAG_RAW | ZIO_FLAG_CANFAIL | + ZIO_FLAG_RESILVER | ZIO_FLAG_DONT_PROPAGATE, + zio_done_postread_done, NULL); + cio->io_flags &= ~ZIO_FLAG_ALLOC_THROTTLED; + zio_nowait(cio); + } + /* * It is the responsibility of the done callback to ensure that this * particular zio is no longer discoverable for adoption, and as diff --git a/sys/contrib/openzfs/tests/runfiles/common.run b/sys/contrib/openzfs/tests/runfiles/common.run index 243d28e8bc49..63913663a7b2 100644 --- a/sys/contrib/openzfs/tests/runfiles/common.run +++ b/sys/contrib/openzfs/tests/runfiles/common.run @@ -254,6 +254,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', @@ -912,7 +916,7 @@ tags = ['functional', 'redacted_send'] tests = ['raidz_001_neg', 'raidz_002_pos', 'raidz_expand_001_pos', 'raidz_expand_002_pos', 'raidz_expand_003_neg', 'raidz_expand_003_pos', 'raidz_expand_004_pos', 'raidz_expand_005_pos', 'raidz_expand_006_neg', - 'raidz_expand_007_neg'] + 'raidz_expand_007_neg', 'raidz_zinject'] tags = ['functional', 'raidz'] timeout = 1200 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 874a23a87574..22da0fc5cc13 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 @@ -173,9 +173,6 @@ if sys.platform.startswith('freebsd'): 'cli_root/zpool_resilver/zpool_resilver_concurrent': ['SKIP', na_reason], 'zoned_uid/setup': ['SKIP', na_reason], - 'cli_root/zpool_wait/zpool_wait_trim_basic': ['SKIP', trim_reason], - 'cli_root/zpool_wait/zpool_wait_trim_cancel': ['SKIP', trim_reason], - 'cli_root/zpool_wait/zpool_wait_trim_flag': ['SKIP', trim_reason], 'cli_root/zfs_unshare/zfs_unshare_008_pos': ['SKIP', na_reason], 'cp_files/cp_files_002_pos': ['SKIP', na_reason], 'link_count/link_count_001': ['SKIP', na_reason], diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib b/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib index 974e19c04269..39e63bed7bf0 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib +++ b/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib @@ -2021,6 +2021,26 @@ function wait_sit_out #pool vdev timeout # # Check the output of 'zpool status -v <pool>', +# and to see if the counts of <device> contain the <regex> specified. +# +# Return 0 is contain, 1 otherwise +# +function check_pool_device # pool device regex <verbose> +{ + typeset pool=$1 + typeset device=$2 + typeset regex=$3 + typeset verbose=${4:-false} + + scan=$(zpool status -v "$pool" 2>/dev/null | grep $device) + if [[ $verbose == true ]]; then + log_note $scan + fi + echo $scan | grep -qi "$regex" +} + +# +# Check the output of 'zpool status -v <pool>', # and to see if the content of <token> contain the <keyword> specified. # # Return 0 is contain, 1 otherwise diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am index cf04950a9612..3d98f43f848d 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am @@ -772,6 +772,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 \ @@ -1884,6 +1887,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/raidz/raidz_expand_005_pos.ksh \ functional/raidz/raidz_expand_006_neg.ksh \ functional/raidz/raidz_expand_007_neg.ksh \ + functional/raidz/raidz_zinject.ksh \ functional/raidz/setup.ksh \ functional/redacted_send/cleanup.ksh \ functional/redacted_send/redacted_compressed.ksh \ 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/cli_root/zinject/zinject_args.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zinject/zinject_args.ksh index 19351dc8f2df..93c320da6fde 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zinject/zinject_args.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zinject/zinject_args.ksh @@ -48,7 +48,7 @@ function cleanup function test_device_fault { - typeset -a errno=("io" "decompress" "decrypt" "nxio" "dtl" "corrupt" "noop") + typeset -a errno=("io" "decompress" "decrypt" "nxio" "dtl" "corrupt" "noop" "io-prefail") for e in ${errno[@]}; do log_must eval \ "zinject -d $DISK1 -e $e -T read -f 0.001 $TESTPOOL" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_parallel_admin.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_parallel_admin.ksh index 0bddfd08032b..2f866140dd8f 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_parallel_admin.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_export/zpool_export_parallel_admin.ksh @@ -64,7 +64,7 @@ log_must zpool create -f $TESTPOOL1 mirror ${DEVICE_DIR}/disk0 ${DEVICE_DIR}/dis log_must zinject -P export -s 10 $TESTPOOL1 -log_must zpool export $TESTPOOL1 & +log_must_busy zpool export $TESTPOOL1 & zpool set comment=hello $TESTPOOL1 zpool reguid $TESTPOOL1 & diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/setup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/setup.ksh index 7be2a316a873..483cb3738c72 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/setup.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/setup.ksh @@ -25,7 +25,6 @@ verify_runnable "global" if is_freebsd; then - log_unsupported "FreeBSD has no hole punching mechanism for the time being." diskinfo -v $DISKS | grep -qE 'No.*# TRIM/UNMAP support' && log_unsupported "DISKS do not support discard (TRIM/UNMAP)" else diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_online_offline.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_online_offline.ksh index 9e130d87e6e3..3d42a58102a8 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_online_offline.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_online_offline.ksh @@ -40,7 +40,7 @@ DISK1=${DISKS%% *} DISK2="$(echo $DISKS | cut -d' ' -f2)" -log_must zpool create -f $TESTPOOL mirror $DISK1 $DISK2 -O recordsize=4k +log_must zpool create -f -O recordsize=4k $TESTPOOL mirror $DISK1 $DISK2 sync_and_rewrite_some_data_a_few_times $TESTPOOL log_must zpool trim -r 1 $TESTPOOL $DISK1 diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_partial.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_partial.ksh index 6cf22fee18b3..e37f8e44c1af 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_partial.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_partial.ksh @@ -35,6 +35,12 @@ # 5. Run 'zpool trim' to perform a full TRIM. # 6. Verify the disk is less than 10% of its original size. +# On FreeBSD, manual 'zpool trim' does not reclaim space on file +# vdevs stored on a ZFS filesystem within the test framework. +if is_freebsd; then + log_unsupported "Manual trim on file vdevs not supported on FreeBSD" +fi + function cleanup { if poolexists $TESTPOOL; then @@ -69,19 +75,19 @@ log_must zpool create -O compression=off $TESTPOOL "$LARGEFILE" log_must mkfile $(( floor(LARGESIZE * 0.80) )) /$TESTPOOL/file sync_all_pools -new_size=$(du -B1 "$LARGEFILE" | cut -f1) +new_size=$(du -k "$LARGEFILE" | awk '{print $1 * 1024}') log_must test $new_size -le $LARGESIZE log_must test $new_size -gt $(( floor(LARGESIZE * 0.70) )) # Expand the pool to create new unallocated metaslabs. log_must zpool export $TESTPOOL -log_must dd if=/dev/urandom of=$LARGEFILE conv=notrunc,nocreat \ +log_must dd if=/dev/urandom of=$LARGEFILE conv=notrunc \ seek=$((LARGESIZE / (1024 * 1024))) bs=$((1024 * 1024)) \ count=$((3 * LARGESIZE / (1024 * 1024))) log_must zpool import -d $TESTDIR $TESTPOOL log_must zpool online -e $TESTPOOL "$LARGEFILE" -new_size=$(du -B1 "$LARGEFILE" | cut -f1) +new_size=$(du -k "$LARGEFILE" | awk '{print $1 * 1024}') log_must test $new_size -gt $((4 * floor(LARGESIZE * 0.70) )) # Perform a partial trim, we expect it to skip most of the new metaslabs @@ -90,12 +96,11 @@ log_must set_tunable64 TRIM_METASLAB_SKIP 1 log_must zpool trim $TESTPOOL log_must set_tunable64 TRIM_METASLAB_SKIP 0 -sync_all_pools while [[ "$(trim_progress $TESTPOOL $LARGEFILE)" -lt "100" ]]; do sleep 0.5 done -new_size=$(du -B1 "$LARGEFILE" | cut -f1) +new_size=$(du -k "$LARGEFILE" | awk '{print $1 * 1024}') log_must test $new_size -gt $LARGESIZE # Perform a full trim, all metaslabs will be trimmed the pool vdev @@ -103,12 +108,11 @@ log_must test $new_size -gt $LARGESIZE # space usage of the new metaslabs. log_must zpool trim $TESTPOOL -sync_all_pools while [[ "$(trim_progress $TESTPOOL $LARGEFILE)" -lt "100" ]]; do sleep 0.5 done -new_size=$(du -B1 "$LARGEFILE" | cut -f1) +new_size=$(du -k "$LARGEFILE" | awk '{print $1 * 1024}') log_must test $new_size -le $(( 2 * LARGESIZE)) log_must test $new_size -gt $(( floor(LARGESIZE * 0.70) )) diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_start_and_cancel_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_start_and_cancel_neg.ksh index fafe57355e22..e42ee020d505 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_start_and_cancel_neg.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_start_and_cancel_neg.ksh @@ -40,7 +40,7 @@ DISK2="$(echo $DISKS | cut -d' ' -f2)" DISK3="$(echo $DISKS | cut -d' ' -f3)" log_must zpool list -v -log_must zpool create -f $TESTPOOL $DISK1 $DISK2 $DISK3 -O recordsize=4k +log_must zpool create -f -O recordsize=4k $TESTPOOL $DISK1 $DISK2 $DISK3 sync_and_rewrite_some_data_a_few_times $TESTPOOL log_must zpool trim -r 1 $TESTPOOL $DISK1 diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_trimmed.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_trimmed.ksh index 9c1fcf42ff49..c5dac5b140c6 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_trimmed.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_verify_trimmed.ksh @@ -34,6 +34,12 @@ # 3. Trim the pool and verify the file vdev is again sparse. # +# On FreeBSD, manual 'zpool trim' does not reclaim space on file +# vdevs stored on a ZFS filesystem within the test framework. +if is_freebsd; then + log_unsupported "Manual trim on file vdevs not supported on FreeBSD" +fi + function cleanup { if poolexists $TESTPOOL; then @@ -59,7 +65,7 @@ log_must mkdir "$TESTDIR" log_must truncate -s $LARGESIZE "$LARGEFILE" log_must zpool create $TESTPOOL "$LARGEFILE" -original_size=$(du -B1 "$LARGEFILE" | cut -f1) +original_size=$(du -k "$LARGEFILE" | awk '{print $1 * 1024}') log_must zpool initialize $TESTPOOL @@ -67,8 +73,8 @@ while [[ "$(initialize_progress $TESTPOOL $LARGEFILE)" -lt "100" ]]; do sleep 0.5 done -new_size=$(du -B1 "$LARGEFILE" | cut -f1) -log_must within_tolerance $new_size $LARGESIZE $((128 * 1024 * 1024)) +new_size=$(du -k "$LARGEFILE" | awk '{print $1 * 1024}') +log_must within_tolerance $new_size $LARGESIZE $((200 * 1024 * 1024)) log_must zpool trim $TESTPOOL @@ -76,7 +82,7 @@ while [[ "$(trim_progress $TESTPOOL $LARGEFILE)" -lt "100" ]]; do sleep 0.5 done -new_size=$(du -B1 "$LARGEFILE" | cut -f1) +new_size=$(du -k "$LARGEFILE" | awk '{print $1 * 1024}') log_must within_tolerance $new_size $original_size $((128 * 1024 * 1024)) log_pass "Trimmed appropriate amount of disk space" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_basic.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_basic.ksh index 504eec11d70e..785556229908 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_basic.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_basic.ksh @@ -46,10 +46,6 @@ function trim_in_progress zpool status -t "$pool" | grep "trimmed, started" } -if is_freebsd; then - log_unsupported "FreeBSD has no hole punching mechanism for the time being." -fi - typeset -r FILE_VDEV="$TESTDIR/file_vdev" typeset pid diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_cancel.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_cancel.ksh index b94e7a50ce91..44372d657388 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_cancel.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_cancel.ksh @@ -59,10 +59,6 @@ function do_test bkgrnd_proc_succeeded $pid } -if is_freebsd; then - log_unsupported "FreeBSD has no hole punching mechanism for the time being." -fi - typeset pid typeset -r FILE_VDEV="$TESTDIR/file_vdev1" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_flag.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_flag.ksh index a6b7cabb1c4a..dcfda3ad817a 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_flag.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_wait/zpool_wait_trim_flag.ksh @@ -41,10 +41,6 @@ function cleanup [[ -d "$TESTDIR" ]] && log_must rm -r "$TESTDIR" } -if is_freebsd; then - log_unsupported "FreeBSD has no hole punching mechanism for the time being." -fi - typeset trim12_pid trim3_pid typeset -r VDEV1="$TESTDIR/file_vdev1" typeset -r VDEV2="$TESTDIR/file_vdev2" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_002_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_002_pos.ksh index eb032373185f..a2b3464b2bf0 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_002_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_002_pos.ksh @@ -38,7 +38,7 @@ # # STRATEGY: # 1. Set the interval to 1 and count to 4. -# 2. Sleep for 4 seconds. +# 2. Sleep for 5 seconds. # 3. Verify that the output has 4 records. # 4. Set interval to 0.5 and count to 1 to test floating point intervals. @@ -61,11 +61,12 @@ if ! is_global_zone ; then TESTPOOL=${TESTPOOL%%/*} fi -zpool iostat $TESTPOOL 1 4 > $tmpfile 2>&1 & -sleep 4 +log_must eval "zpool iostat $TESTPOOL 1 4 > $tmpfile 2>&1 &" +log_must sleep 5 stat_count=$(grep -c $TESTPOOL $tmpfile) if [[ $stat_count -ne 4 ]]; then + cat $tmpfile log_fail "zpool iostat [pool_name] [interval] [count] failed" fi diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mmp/mmp_on_uberblocks.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mmp/mmp_on_uberblocks.ksh index 54fe2fa35ac7..3e76cd1ff626 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mmp/mmp_on_uberblocks.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mmp/mmp_on_uberblocks.ksh @@ -16,20 +16,17 @@ # # -# Copyright (c) 2017 by Lawrence Livermore National Security, LLC. +# Copyright (c) 2026 by Lawrence Livermore National Security, LLC. # # DESCRIPTION: # Ensure that MMP updates uberblocks with MMP info at expected intervals. # # STRATEGY: -# 1. Set TXG_TIMEOUT to large value -# 2. Create a zpool -# 3. Clear multihost history -# 4. Sleep, then collect count of uberblocks written -# 5. If number of changes seen is less than min threshold, then fail -# 6. If number of changes seen is more than max threshold, then fail -# 7. Sequence number increments when no TXGs are syncing +# 1. Create a zpool +# 2. Clear multihost history +# 3. Sleep for 10s, then collect count of uberblocks written +# 4. Verify the mmp updates are within 20% of the expected target # . $STF_SUITE/include/libtest.shlib @@ -38,51 +35,29 @@ verify_runnable "both" -UBER_CHANGES=0 DURATION=10 -EXPECTED=$((($(echo $DISKS | wc -w) * $DURATION * 1000) / $MMP_INTERVAL_DEFAULT)) -FUDGE=$((EXPECTED * 20 / 100)) -MIN_UB_WRITES=$((EXPECTED - FUDGE)) -MAX_UB_WRITES=$((EXPECTED + FUDGE)) -MIN_SEQ_VALUES=8 +NDISKS=$(echo $DISKS | wc -w) +MMP_INTERVAL=$(get_tunable MULTIHOST_INTERVAL) +TARGET=$((($NDISKS * $DURATION * 1000) / $MMP_INTERVAL)) function cleanup { datasetexists $TESTPOOL && destroy_pool $TESTPOOL - log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_DEFAULT - set_tunable64 TXG_TIMEOUT $TXG_TIMEOUT_DEFAULT log_must mmp_clear_hostid } log_assert "Ensure MMP uberblocks update at the correct interval" log_onexit cleanup -log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_DEFAULT -log_must set_tunable64 TXG_TIMEOUT $TXG_TIMEOUT_LONG log_must mmp_set_hostid $HOSTID1 log_must zpool create -f $TESTPOOL $DISKS log_must zpool set multihost=on $TESTPOOL -clear_mmp_history -UBER_CHANGES=$(count_mmp_writes $TESTPOOL $DURATION) - -log_note "Uberblock changed $UBER_CHANGES times" -if [ $UBER_CHANGES -lt $MIN_UB_WRITES ]; then - log_fail "Fewer uberblock writes occurred than expected ($EXPECTED)" -fi - -if [ $UBER_CHANGES -gt $MAX_UB_WRITES ]; then - log_fail "More uberblock writes occurred than expected ($EXPECTED)" -fi +clear_mmp_history +MMP_WRITES=$(count_mmp_writes $TESTPOOL $DURATION) -log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_MIN -SEQ_BEFORE=$(zdb -luuuu ${DISK[0]} | awk '/mmp_seq/ {if ($NF>max) max=$NF}; END {print max}') -sleep 5 -SEQ_AFTER=$(zdb -luuuu ${DISK[0]} | awk '/mmp_seq/ {if ($NF>max) max=$NF}; END {print max}') -if [ $((SEQ_AFTER - SEQ_BEFORE)) -lt $MIN_SEQ_VALUES ]; then - zdb -luuuu ${DISK[0]} - log_fail "ERROR: mmp_seq did not increase by $MIN_SEQ_VALUES; before $SEQ_BEFORE after $SEQ_AFTER" -fi +log_note "Uberblock changed $MMP_WRITES times" +log_must within_percent $MMP_WRITES $TARGET 80 log_pass "Ensure MMP uberblocks update at the correct interval passed" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/raidz/raidz_zinject.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/raidz/raidz_zinject.ksh new file mode 100755 index 000000000000..e0417afc7755 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/raidz/raidz_zinject.ksh @@ -0,0 +1,94 @@ +#!/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, Klara Inc. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# Inject an io-prefail error on a child of a raidz device, then write +# some data and verify that the pool encountered errors. +# + +function cleanup +{ + log_pos zpool status $TESTPOOL + + log_must zinject -c all + + poolexists "$TESTPOOL" && log_must_busy zpool destroy "$TESTPOOL" + + for i in {1..$devs}; do + log_must rm -f "$TEST_BASE_DIR/dev-$i" + done + +} + +log_onexit cleanup + +typeset -r devs=6 +typeset -r dev_size_mb=128 + +typeset -a disks + +# Disk files which will be used by pool +for i in {1..$devs}; do + device=$TEST_BASE_DIR/dev-$i + log_must truncate -s ${dev_size_mb}M $device + disks[${#disks[*]}+1]=$device +done + +function run_test +{ + log_must zpool create -f -o cachefile=none -O recordsize=16k $TESTPOOL raidz1 ${disks[@]} + + log_must zinject -d $TEST_BASE_DIR/dev-1 -e io-prefail -T write -f 25 $TESTPOOL + + log_must file_write -o create -f /$TESTPOOL/file -b 128k -c 1000 -d R + log_must zpool sync $TESTPOOL + log_pos check_pool_status $TESTPOOL "errors" "No known data errors" || return 1 + log_pos check_pool_status $TESTPOOL "status" "One or more" || return 1 + + log_must zinject -c all + log_must zpool export -f $TESTPOOL + log_must rm $TEST_BASE_DIR/dev-2 + log_must zpool import -d $TEST_BASE_DIR $TESTPOOL + log_must zpool scrub $TESTPOOL + log_must zpool wait -t scrub $TESTPOOL + log_pos check_pool_status $TESTPOOL "errors" "No known data" || return 1 + log_pos check_pool_device $TESTPOOL "dev-1" "ONLINE.* 0$" || return 1 +} + +i=0 +while [[ $i -lt 3 ]]; do + run_test && log_pass "raidz handles partial write failure." + log_must zinject -c all + log_must zpool destroy $TESTPOOL + log_must truncate -s ${dev_size_mb}M $TEST_BASE_DIR/dev-2 + i=$((i + 1)) +done + +log_fail "raidz does not handle partial write failure." 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 53e2efffac2d..91430c0e8fc0 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 } @@ -408,3 +408,77 @@ 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, but the occasional checksum error does occur in +# practice. Until the root cause is identified and resolved, tolerate +# a checksum error when scrubbing after a sequential resilver. +# +# https://github.com/openzfs/zfs/issues/18307 +# https://github.com/openzfs/zfs/issues/18319 +# +# 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 3 ]]; 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 index ae65d3a21290..31444850f76c 100755 --- 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 @@ -89,12 +89,7 @@ function test_sequential_resilver # <pool> <parity> <dir> spare=draid${nparity}-0-0 log_must zpool replace -fsw $pool $dir/dev-$nparity $spare - log_must zpool scrub -w $pool - log_must zpool status $pool - - log_must 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 "sequential" } log_onexit cleanup 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 index 8d102627fdb0..22e1f2dfb310 100755 --- 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 @@ -105,12 +105,7 @@ function test_sequential_resilver # <pool> <parity> <dir> log_must zpool wait -t resilver $pool - log_must zpool scrub -w $pool - log_must zpool status $pool - - log_must 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 "sequential" } log_onexit cleanup 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 0604f7f48c7e..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 @@ -85,9 +85,7 @@ for replace_mode in "healing" "sequential"; do log_must check_hotspare_state $TESTPOOL $spare_vdev "INUSE" # Preserve the 1st faulted vdev for the next test. [[ $i -eq 0 ]] || 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" + log_must verify_draid_pool $TESTPOOL $replace_mode (( i += 1 )) done @@ -98,9 +96,7 @@ for replace_mode in "healing" "sequential"; do # 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_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 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/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare4.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare4.ksh index ffbf664046ec..e4f01bbcf672 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare4.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy_draid_spare4.ksh @@ -102,9 +102,7 @@ for replace_mode in "healing" "sequential"; do log_must zpool detach $TESTPOOL $fault_vdev done - 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 done # Fail remaining drives as long as parity permits. @@ -120,9 +118,7 @@ for replace_mode in "healing" "sequential"; do log_must zpool offline -f $TESTPOOL $fault_vdev log_must check_vdev_state $TESTPOOL $fault_vdev "FAULTED" - 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 (( faults_left > 0 && faults_left-- )) done done @@ -138,9 +134,7 @@ for replace_mode in "healing" "sequential"; do break fi - 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 done log_must is_data_valid $TESTPOOL diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/replacement/resilver_restart_001.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/replacement/resilver_restart_001.ksh index f1e42ff7d849..8827b5398151 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/replacement/resilver_restart_001.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/replacement/resilver_restart_001.ksh @@ -46,6 +46,7 @@ function cleanup { + log_must zpool events log_must set_tunable32 RESILVER_MIN_TIME_MS $ORIG_RESILVER_MIN_TIME log_must set_tunable32 SCAN_SUSPEND_PROGRESS \ $ORIG_SCAN_SUSPEND_PROGRESS @@ -53,11 +54,12 @@ function cleanup $ORIG_RESILVER_DEFER_PERCENT log_must set_tunable32 ZEVENT_LEN_MAX $ORIG_ZFS_ZEVENT_LEN_MAX log_must zinject -c all + log_must zpool events -c destroy_pool $TESTPOOL1 rm -f ${VDEV_FILES[@]} $SPARE_VDEV_FILE } -# count resilver events in zpool and number of deferred rsilvers on vdevs +# count resilver events in zpool and number of deferred resilvers on vdevs function verify_restarts # <msg> <cnt> <defer> { msg=$1 @@ -113,7 +115,7 @@ log_must set_tunable32 ZEVENT_LEN_MAX 512 log_must truncate -s $VDEV_FILE_SIZE ${VDEV_FILES[@]} $SPARE_VDEV_FILE log_must zpool create -f -o feature@resilver_defer=disabled $TESTPOOL1 \ - raidz ${VDEV_FILES[@]} + raidz2 ${VDEV_FILES[@]} # create 4 filesystems for fs in fs{0..3} @@ -157,8 +159,8 @@ do log_must set_tunable32 RESILVER_MIN_TIME_MS 20 # initiate a resilver and suspend the scan as soon as possible - log_must zpool replace $TESTPOOL1 $VDEV_REPLACE log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1 + log_must zpool replace $TESTPOOL1 $VDEV_REPLACE # there should only be 1 resilver start verify_restarts '' "${RESTARTS[0]}" "${VDEVS[0]}" @@ -166,9 +168,12 @@ do # offline then online a vdev to introduce a new DTL range after current # scan, which should restart (or defer) the resilver log_must zpool offline $TESTPOOL1 ${VDEV_FILES[2]} - sync_pool $TESTPOOL1 + log_must wait_vdev_state $TESTPOOL1 ${VDEV_FILES[2]} "OFFLINE" + sync_pool $TESTPOOL1 true + log_must zpool online $TESTPOOL1 ${VDEV_FILES[2]} - sync_pool $TESTPOOL1 + log_must wait_vdev_state $TESTPOOL1 ${VDEV_FILES[2]} "ONLINE" + sync_pool $TESTPOOL1 true # there should now be 2 resilver starts w/o defer, 1 with defer verify_restarts ' after offline/online' "${RESTARTS[1]}" "${VDEVS[1]}" @@ -190,8 +195,8 @@ do log_must is_pool_resilvered $TESTPOOL1 # wait for a few txg's to see if a resilver happens - sync_pool $TESTPOOL1 - sync_pool $TESTPOOL1 + sync_pool $TESTPOOL1 true + sync_pool $TESTPOOL1 true # there should now be 2 resilver starts verify_restarts ' after resilver' "${RESTARTS[3]}" "${VDEVS[3]}" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/snapshot/snapshot_018_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/snapshot/snapshot_018_pos.ksh index db9e268c3c40..cb78cd39d09b 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/snapshot/snapshot_018_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/snapshot/snapshot_018_pos.ksh @@ -91,6 +91,7 @@ log_must eval "[[ $(stat_mtime $tfs_snapdir) == 0 ]]" # Create snapshots for filesystems and check snapshots_changed reports correct time curr_time=$(date '+%s') +log_must sleep 1 log_must zfs snapshot $snap_testpool snap_changed_testpool=$(zfs get -H -o value -p snapshots_changed $TESTPOOL) snap_changed_nsecs_testpool=$(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL) @@ -103,6 +104,7 @@ log_must eval "[[ $list_changed_nsecs_testpool == $snap_changed_nsecs_testpool ] log_must eval "[[ $(stat_mtime $tpool_snapdir) == $snap_changed_testpool ]]" curr_time=$(date '+%s') +log_must sleep 1 log_must zfs snapshot $snap_testfsv1 snap_changed_testfs=$(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS) snap_changed_nsecs_testfs=$(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL/$TESTFS) @@ -121,6 +123,7 @@ log_must eval "[[ $(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL/$TE # Create snapshot while unmounted curr_time=$(date '+%s') +log_must sleep 1 log_must zfs snapshot $snap_testfsv2 snap_changed_testfs=$(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS) snap_changed_nsecs_testfs=$(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL/$TESTFS) @@ -144,6 +147,7 @@ log_must eval "[[ $(stat_mtime $tfs_snapdir) == $snap_changed_testfs ]]" # Destroy the snapshots and check snapshots_changed shows correct time curr_time=$(date '+%s') +log_must sleep 1 log_must zfs destroy $snap_testfsv1 snap_changed_testfs=$(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS) snap_changed_nsecs_testfs=$(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL/$TESTFS) @@ -152,6 +156,7 @@ log_must eval "[[ $((snap_changed_nsecs_testfs / 1000000000)) == $snap_changed_t log_must eval "[[ $(stat_mtime $tfs_snapdir) == $snap_changed_testfs ]]" curr_time=$(date '+%s') +log_must sleep 1 log_must zfs destroy $snap_testpool snap_changed_testpool=$(zfs get -H -o value -p snapshots_changed $TESTPOOL) snap_changed_nsecs_testpool=$(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL) diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/autotrim_config.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/autotrim_config.ksh index a8deedfb8c3c..d67ff8b0ce2a 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/autotrim_config.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/autotrim_config.ksh @@ -40,6 +40,12 @@ verify_runnable "global" +# On FreeBSD, autotrim does not reclaim space on file vdevs stored +# on a ZFS filesystem within the test framework. +if is_freebsd; then + log_unsupported "Autotrim on file vdevs not supported on FreeBSD" +fi + log_assert "Set 'autotrim=on' verify pool disks were trimmed" function cleanup diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/setup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/setup.ksh index 7be2a316a873..483cb3738c72 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/setup.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/setup.ksh @@ -25,7 +25,6 @@ verify_runnable "global" if is_freebsd; then - log_unsupported "FreeBSD has no hole punching mechanism for the time being." diskinfo -v $DISKS | grep -qE 'No.*# TRIM/UNMAP support' && log_unsupported "DISKS do not support discard (TRIM/UNMAP)" else diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/trim.kshlib b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/trim.kshlib index 75d2ee570776..b58e010970f8 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/trim.kshlib +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/trim.kshlib @@ -23,7 +23,7 @@ # function get_size_mb { - du --block-size 1048576 -s "$1" | cut -f1 + du -m -s "$1" | cut -f1 } # diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/trim_config.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/trim_config.ksh index ff569177357b..73496a3d68d6 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/trim_config.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/trim/trim_config.ksh @@ -40,6 +40,12 @@ verify_runnable "global" +# On FreeBSD, manual trim does not reclaim space on file vdevs stored +# on a ZFS filesystem within the test framework. +if is_freebsd; then + log_unsupported "Manual trim on file vdevs not supported on FreeBSD" +fi + log_assert "Run 'zpool trim' verify pool disks were trimmed" function cleanup @@ -68,8 +74,8 @@ log_must set_tunable64 TRIM_TXG_BATCH 8 typeset vdev_min_ms_count=$(get_tunable VDEV_MIN_MS_COUNT) log_must set_tunable64 VDEV_MIN_MS_COUNT 32 -typeset VDEV_MAX_MB=$(( floor(4 * MINVDEVSIZE * 0.75 / 1024 / 1024) )) -typeset VDEV_MIN_MB=$(( floor(4 * MINVDEVSIZE * 0.30 / 1024 / 1024) )) +typeset VDEV_MAX_MB=$(( floor(4 * MINVDEVSIZE * 0.65 / 1024 / 1024) )) +typeset VDEV_MIN_MB=$(( floor(4 * MINVDEVSIZE * 0.40 / 1024 / 1024) )) for type in "" "mirror" "raidz2" "draid"; do @@ -100,7 +106,9 @@ for type in "" "mirror" "raidz2" "draid"; do # Remove the file, issue trim, verify the vdevs are now sparse. log_must rm /$TESTPOOL/file + sync_pool $TESTPOOL log_must timeout 120 zpool trim -w $TESTPOOL + sync_all_pools true verify_vdevs "-le" "$VDEV_MIN_MB" $VDEVS log_must zpool destroy $TESTPOOL diff --git a/sys/modules/zfs/zfs_config.h b/sys/modules/zfs/zfs_config.h index 1cf55ead9587..77c310c268f8 100644 --- a/sys/modules/zfs/zfs_config.h +++ b/sys/modules/zfs/zfs_config.h @@ -911,7 +911,7 @@ /* #undef ZFS_DEVICE_MINOR */ /* Define the project alias string. */ -#define ZFS_META_ALIAS "zfs-2.4.99-522-FreeBSD_g1644e2ffd" +#define ZFS_META_ALIAS "zfs-2.4.99-551-FreeBSD_g84ffe564d" /* Define the project author. */ #define ZFS_META_AUTHOR "OpenZFS" @@ -920,7 +920,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" @@ -941,7 +941,7 @@ #define ZFS_META_NAME "zfs" /* Define the project release. */ -#define ZFS_META_RELEASE "522-FreeBSD_g1644e2ffd" +#define ZFS_META_RELEASE "551-FreeBSD_g84ffe564d" /* Define the project version. */ #define ZFS_META_VERSION "2.4.99" diff --git a/sys/modules/zfs/zfs_gitrev.h b/sys/modules/zfs/zfs_gitrev.h index 9c5cec1628b7..af9caaa07622 100644 --- a/sys/modules/zfs/zfs_gitrev.h +++ b/sys/modules/zfs/zfs_gitrev.h @@ -1 +1 @@ -#define ZFS_META_GITREV "zfs-2.4.99-522-g1644e2ffd" +#define ZFS_META_GITREV "zfs-2.4.99-551-g84ffe564d-dirty" |
