git: 5fe1964fa056 - main - stress2: add two new unionfs test scenarios

From: Jason A. Harmening <jah_at_FreeBSD.org>
Date: Sun, 13 Sep 2026 03:19:35 UTC
The branch main has been updated by jah:

URL: https://cgit.FreeBSD.org/src/commit/?id=5fe1964fa05632cb86459a64debd92f9dca37ed3

commit 5fe1964fa05632cb86459a64debd92f9dca37ed3
Author:     Jason A. Harmening <jah@FreeBSD.org>
AuthorDate: 2026-09-07 17:52:44 +0000
Commit:     Jason A. Harmening <jah@FreeBSD.org>
CommitDate: 2026-09-13 03:19:19 +0000

    stress2: add two new unionfs test scenarios
    
    These exercise lookup traversal from tmpfs into unionfs, which is
    useful because, unlike UFS, tmpfs does not allow recursion on its vnode
    locks by default.
    
    unionfs22.sh exercises these lookups with a normal unionfs mount, while
    unionfs23.sh uses '-o below' for the unionfs mount and reproduces the
    panic described in PR 298201.
    
    Reviewed by:    kib, markj, pho
    Tested by:      pho
    Differential Revision:  https://reviews.freebsd.org/D59494
---
 tools/test/stress2/misc/unionfs22.sh | 77 ++++++++++++++++++++++++++++++++++++
 tools/test/stress2/misc/unionfs23.sh | 77 ++++++++++++++++++++++++++++++++++++
 2 files changed, 154 insertions(+)

diff --git a/tools/test/stress2/misc/unionfs22.sh b/tools/test/stress2/misc/unionfs22.sh
new file mode 100755
index 000000000000..219e55e7690c
--- /dev/null
+++ b/tools/test/stress2/misc/unionfs22.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+#
+# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org>
+# Copyright (c) 2026 Jason Harmening <jah@FreeBSD.org>
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+# unionfs(4) test
+# Variation of unionfs7.sh, but with unionfs lookup
+# traversing a tmpfs mount.
+# No issues seen with this test.
+
+[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
+. ../default.cfg
+
+mp1=/mnt$mdstart
+mp2=/mnt$((mdstart + 1))
+mp3=$mp2/unionfs
+
+mkdir -p $mp1 $mp2
+set -e
+for i in $mp1 $mp2; do
+	mount | grep -q "on $i " && umount -f $i
+done
+
+mount -o size=4g -t tmpfs dummy $mp1
+mount -o size=4g -t tmpfs dummy $mp2
+mkdir -p $mp3
+
+mount -t unionfs -o noatime $mp1 $mp3
+set +e
+export 'INODES=100000'
+
+export CTRLDIR=$mp3/stressX.control
+export INCARNATIONS=10
+export LOAD=80
+export RUNDIR=$mp3/stressX
+export runRUNTIME=5m
+export rwLOAD=80
+export symlinkLOAD=80
+
+export TESTPROGS="
+unionfs/stress2/testcases/lockf2/lockf2
+unionfs/stress2/testcases/symlink/symlink
+unionfs/stress2/testcases/openat/openat
+unionfs/stress2/testcases/rw/rw
+unionfs/stress2/testcases/fts/fts
+unionfs/stress2/testcases/link/link
+unionfs/stress2/testcases/lockf/lockf
+unionfs/stress2/testcases/creat/creat
+unionfs/stress2/testcases/mkdir/mkdir
+unionfs/stress2/testcases/rename/rename
+unionfs/stress2/testcases/mkfifo/mkfifo
+unionfs/stress2/testcases/dirnprename/dirnprename
+unionfs/stress2/testcases/dirrename/dirrename
+unionfs/stress2/testcases/swap/swap
+"
+
+cp -r ../../stress2 $mp3
+export TESTPROGS=`echo $TESTPROGS | sed 's/\n/ /g'`
+
+set +e
+chmod 777 $mp3
+su $testuser -c \
+	"(cd $mp2; ./unionfs/stress2/testcases/run/run $TESTPROGS)"
+
+while mount | grep -Eq "on $mp3 .*unionfs"; do
+	umount $mp3 && break
+	sleep 5
+done
+umount $mp2
+n=`find $mp1/stressX | wc -l`
+[ $n -eq 1 ] && s=0 || { find $mp1/stressX -ls | head -12; s=1; }
+umount $mp1
+exit $s
diff --git a/tools/test/stress2/misc/unionfs23.sh b/tools/test/stress2/misc/unionfs23.sh
new file mode 100755
index 000000000000..1f8b3e8090c0
--- /dev/null
+++ b/tools/test/stress2/misc/unionfs23.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+#
+# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org>
+# Copyright (c) 2026 Jason Harmening <jah@FreeBSD.org>
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+# unionfs(4) test
+# Variation of unionfs22.sh, but with '-o below'
+# Reproduces "lockmgr_xlock_hard: recursing on non recursive lockmgr"
+# panic (PR 298201)
+
+[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
+. ../default.cfg
+
+mp1=/mnt$mdstart
+mp2=/mnt$((mdstart + 1))
+mp3=$mp2/unionfs
+
+mkdir -p $mp1 $mp2
+set -e
+for i in $mp1 $mp2; do
+	mount | grep -q "on $i " && umount -f $i
+done
+
+mount -o size=4g -t tmpfs dummy $mp1
+mount -o size=4g -t tmpfs dummy $mp2
+mkdir -p $mp3
+
+mount -t unionfs -o noatime -o below $mp1 $mp3
+set +e
+export 'INODES=100000'
+
+export CTRLDIR=$mp3/stressX.control
+export INCARNATIONS=10
+export LOAD=80
+export RUNDIR=$mp3/stressX
+export runRUNTIME=5m
+export rwLOAD=80
+export symlinkLOAD=80
+
+export TESTPROGS="
+unionfs/stress2/testcases/lockf2/lockf2
+unionfs/stress2/testcases/symlink/symlink
+unionfs/stress2/testcases/openat/openat
+unionfs/stress2/testcases/rw/rw
+unionfs/stress2/testcases/fts/fts
+unionfs/stress2/testcases/link/link
+unionfs/stress2/testcases/lockf/lockf
+unionfs/stress2/testcases/creat/creat
+unionfs/stress2/testcases/mkdir/mkdir
+unionfs/stress2/testcases/rename/rename
+unionfs/stress2/testcases/mkfifo/mkfifo
+unionfs/stress2/testcases/dirnprename/dirnprename
+unionfs/stress2/testcases/dirrename/dirrename
+unionfs/stress2/testcases/swap/swap
+"
+
+cp -r ../../stress2 $mp3
+export TESTPROGS=`echo $TESTPROGS | sed 's/\n/ /g'`
+
+set +e
+chmod 777 $mp3
+su $testuser -c \
+	"(cd $mp2; ./unionfs/stress2/testcases/run/run $TESTPROGS)"
+
+while mount | grep -Eq "on $mp3 .*unionfs"; do
+	umount $mp3 && break
+	sleep 5
+done
+n=`find $mp3/stressX | wc -l`
+[ $n -eq 1 ] && s=0 || { find $mp3/stressX -ls | head -12; s=1; }
+umount $mp2
+umount $mp1
+exit $s