diff options
Diffstat (limited to 'tools/test/stress2')
458 files changed, 15523 insertions, 666 deletions
diff --git a/tools/test/stress2/default.cfg b/tools/test/stress2/default.cfg index f7748b55fa04..bff7f3f168a9 100644 --- a/tools/test/stress2/default.cfg +++ b/tools/test/stress2/default.cfg @@ -88,6 +88,7 @@ checkfs () { # BMODE=1 ./all.sh -on `grep -lw mycc *.sh` # BMODE=2 STRESS2BIN=/home/pho/stress2/bin.i386.r276368 ./all.sh +BMODE=${BMODE:-0} CC=${CC:-cc} top=`dirname $(pwd)` # cwd for the all.sh script STRESS2BIN=${STRESS2BIN:-$top/bin} diff --git a/tools/test/stress2/lib/resources.c b/tools/test/stress2/lib/resources.c index 935a085a58de..1888d1fba87f 100644 --- a/tools/test/stress2/lib/resources.c +++ b/tools/test/stress2/lib/resources.c @@ -149,7 +149,7 @@ usermem(void) } static void -cleanupdf() +cleanupdf(void) { unlink(dfpath); } diff --git a/tools/test/stress2/misc/1st.sh b/tools/test/stress2/misc/1st.sh index 00602d67e803..59edb7957bfb 100755 --- a/tools/test/stress2/misc/1st.sh +++ b/tools/test/stress2/misc/1st.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/aesni.sh b/tools/test/stress2/misc/aesni.sh index c25694fa002a..0fe7390d2fbd 100755 --- a/tools/test/stress2/misc/aesni.sh +++ b/tools/test/stress2/misc/aesni.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # @@ -29,6 +29,11 @@ # Simple AESNI(4) test. +if [ $(uname -m) != "amd64" -a $(uname -m) != "i386" ]; then + echo "This test requires an x86 system." + exit 0 +fi + kldstat -v | grep -qw aesni || { kldload aesni.ko; loaded=1; } ../misc/geli.sh diff --git a/tools/test/stress2/misc/all.debug.inc b/tools/test/stress2/misc/all.debug.inc index ea0f2d6a5c58..4042ca1f7718 100644 --- a/tools/test/stress2/misc/all.debug.inc +++ b/tools/test/stress2/misc/all.debug.inc @@ -1,5 +1,5 @@ # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # @@ -24,7 +24,6 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # -# $FreeBSD$ # # Example debug include file for misc/all.sh diff --git a/tools/test/stress2/misc/all.exclude b/tools/test/stress2/misc/all.exclude index 029a77b9b094..f8a5ea4a91f1 100644 --- a/tools/test/stress2/misc/all.exclude +++ b/tools/test/stress2/misc/all.exclude @@ -1,40 +1,44 @@ -# List of tests not to run, unless the '-a' option is used with run.sh +# List of tests not to run, unless the '-a' option is used with all.sh # Exclude names must start in column 1 backingstore.sh g_vfs_done():md6a[WRITE(offset=...)]error = 28 20111220 backingstore2.sh panic: 43 vncache entries remaining 20111220 backingstore3.sh g_vfs_done():md6a[WRITE(offset=...)]error = 28 20111230 dd.sh CAM stuck in vmwait 20200116 +force13.sh https://people.freebsd.org/~pho/stress/log/log0376.txt 20221113 +force14.sh Waiting for fix 20230319 +force15.sh Waiting for fix 20230319 force4.sh https://people.freebsd.org/~pho/stress/log/log0082.txt 20210328 force7.sh https://people.freebsd.org/~pho/stress/log/log0266.txt 20220207 +fsck10.sh Waiting for fix 20230319 +fsck11.sh Waiting for fix 20230319 +fsck12.sh Waiting for fix 20230319 fsync.sh panic: Journal overflow 20190208 -fuse.sh Memory corruption seen in log file kostik734.txt 20141114 -fuse2.sh Deadlock seen 20121129 -fuse3.sh Deadlock seen 20141120 +fuse.sh https://people.freebsd.org/~pho/stress/log/log0546.txt 20240828 +fuse2.sh https://people.freebsd.org/~pho/stress/log/log0547.txt 20240828 getrandom.sh Known DoS issue 20201107 getrandom2.sh Known DoS issue 20200302 gjournal.sh panic: Journal overflow 20190626 gjournal2.sh panic: Journal overflow 20180125 gjournal3.sh panic: Bio not on queue 20171225 gjournal4.sh CAM stuck in vmwait 20180517 +gnop10.sh Waiting for fix 20230319 +gnop13.sh https://people.freebsd.org/~pho/stress/log/log0386.txt 20221113 gnop7.sh Waiting for patch commit 20190820 gnop8.sh Waiting for patch commit 20201214 gnop9.sh Waiting for patch commit 20201214 graid1_8.sh Known issue 20170909 graid1_9.sh panic: Bad effnlink 20180212 -gunion.sh Waiting for fix 20220308 -gunion2.sh Waiting for fix 20220308 -ifconfig.sh Bug 253824 20210322 -ifconfig2.sh https://people.freebsd.org/~pho/stress/log/log0051.txt 20210210 lockf5.sh Spinning threads seen 20160718 maxvnodes2.sh https://people.freebsd.org/~pho/stress/log/log0083.txt 20210329 memguard.sh https://people.freebsd.org/~pho/stress/log/log0088.txt 20210402 memguard2.sh Waiting for fix commit memguard3.sh Waiting for fix commit mlockall2.sh Unrecoverable OOM killing seen 20190203 +mlockall6.sh https://people.freebsd.org/~pho/stress/log/log0430.txt 20230403 mlockall7.sh Needs further investigation 20210123 -msetdomain.sh May change policy for random threads to to domainset_fixed 20210104 -newfs4.sh watchdog fired. newbuf 20190225 +msetdomain.sh May change policy for random threads to domainset_fixed 20210104 +newfs4.sh watchdog fired. newbuf (still seen 20240729) 20190225 nfs10.sh Double fault 20151013 nfs13.sh mount_nfs hangs in mntref 20191007 nfs15lockd.sh panic: Assertion td->td_realucred == td->td_ucred failed ... 20210211 @@ -42,53 +46,41 @@ nfs16.sh panic: Failed to register NFS lock locally - error=11 20160608 nullfs28.sh Hang in "mount drain" seen 20220111 oom2.sh Hang in pfault 20180324 overcommit2.sh CAM stuck in vmwait seen 20200112 -pageout.sh panic: handle_written_filepage: not started 20190218 pmc8.sh panic: [pmc,2749] (ri21, rc1) waiting too long for pmc to ... 20210621 -rename14.sh https://people.freebsd.org/~pho/stress/log/log0279.txt 20220415 +rename14.sh https://people.freebsd.org/~pho/stress/log/log0433.txt 20230409 sctp2.sh panic: Queues are not empty when handling SHUTDOWN-COMPLETE 20210211 sctp3.sh panic: Queues are not empty when handling SHUTDOWN-COMPLETE 20210211 -sendfile25.sh WiP 20200611 signal.sh Timing issues. Needs fixing 20171116 snap8.sh https://people.freebsd.org/~pho/stress/log/log0123.txt 20211008 +suj12.sh Waiting for fix 20230319 +suj19.sh https://people.freebsd.org/~pho/stress/log/log0378.txt 20221113 +suj27.sh https://people.freebsd.org/~pho/stress/log/log0387.txt 20221113 +suj36.sh https://people.freebsd.org/~pho/stress/log/log0392.txt 20221114 +swap3.sh https://people.freebsd.org/~pho/stress/log/log0543.txt 20240719 swapoff2.sh swap_pager_force_pagein: read from swap failed 20171223 swapoff3.sh Excessive OOM killing 20220403 swapoff5.sh log0005.txt, known issue 20210111 +swapoff6.sh https://people.freebsd.org/~pho/stress/log/log0540.txt 20240716 systrace.sh WiP 20200227 systrace2.sh WiP 20200227 -syzkaller15.sh WiP 20200712 -syzkaller16.sh WiP 20210722 -syzkaller25.sh WiP 20201116 -syzkaller27.sh watchdogd fires 20220512 -syzkaller28.sh WiP 20201120 -syzkaller50.sh panic: Assertion done != job_total_nbytes failed at ... 20220405 -syzkaller54.sh panic: td 0xfffffe014f7193a0 is not suspended 20220527 -syzkaller55.sh panic: Counter goes negative 20220525 +syzkaller16.sh zonelimit issue 20210722 +syzkaller28.sh panic: About to free ctl:0x... so:0x... and its in 1 20201120 +syzkaller31.sh panic: Bad tailq NEXT(0xfffffe01a0899430->tqh_last) != NULL 20220420 +syzkaller55.sh https://people.freebsd.org/~pho/stress/log/log0533.txt 20240702 syzkaller59.sh Page fault 20220625 +syzkaller65.sh panic: in_pcblookup_hash_locked: invalid local address 20230318 +syzkaller66.sh panic: in_pcbconnect: inp is already connected 20230621 +syzkaller67.sh panic: ASan: Invalid access, 8-byte read at ... 20230621 +quota6.sh https://people.freebsd.org/~pho/stress/log/log0456.txt 20240707 truss3.sh WiP 20200915 -unionfs14.sh WiP 20220111 -unionfs9.sh https://people.freebsd.org/~pho/stress/log/log0226.txt 20220111 # Test not to run for other reasons: -fuzz.sh A know issue marcus3.sh OK, but runs for a long time statfs.sh Not very interesting vunref.sh No problems ever seen vunref2.sh No problems ever seen -# Snapshots has been disabled on SU+J -suj15.sh -suj16.sh -suj19.sh -suj20.sh -suj21.sh -suj22.sh -suj24.sh -suj25.sh -suj26.sh -suj27.sh -suj28.sh - # Exclude NFS loopback tests nfs2.sh panic: wrong diroffset 20140219 nfs5.sh diff --git a/tools/test/stress2/misc/all.sh b/tools/test/stress2/misc/all.sh index 58bf3a630294..86d986099dbb 100755 --- a/tools/test/stress2/misc/all.sh +++ b/tools/test/stress2/misc/all.sh @@ -42,14 +42,15 @@ alloutput=$sdir/output # Output from current test allexcess=$sdir/excessive # Tests with excessive runtime allelapsed=$sdir/elapsed # Test runtime alllocal=$sdir/all.exclude # Local exclude list +exitonerror=0 # -e option loops=0 # Times to run the tests # Get kernel config + revision rev=`uname -a | awk '{print $7}' | sed 's/://'` rev="`uname -a | sed 's#.*/compile/##; s/ .*//'` $rev" -args=`getopt acl:m:no "$@"` +args=`getopt acel:m:no "$@"` [ $? -ne 0 ] && - echo "Usage $0 [-a] [-c] [-l <val>] [-m <min.>] [-n] [-o] [<tests>]" && + echo "Usage $0 [-a] [-c] [-e] [-l <val>] [-m <min.>] [-n] [-o] [<tests>]" && exit 1 set -- $args for i; do @@ -62,6 +63,9 @@ for i; do rm -f $alllist shift ;; + -e) exitonerror=1 + shift + ;; -l) loops=$2 # Number of time to run shift; shift ;; @@ -160,6 +164,7 @@ trap intr INT [ -f all.debug.inc ] && . all.debug.inc s1=`date +%s` +touch $sdir/starttime while true; do exclude=`cat all.exclude $alllocal 2>/dev/null | sed '/^#/d' | grep "^[a-zA-Z].*\.sh" | awk '{print $1}'` @@ -226,6 +231,7 @@ while true; do [ $e -ne 0 ] && echo "FAIL $i exit code $e" ) 2>&1 | tee $alloutput + grep -qw FAIL $alloutput && e=1 || e=0 ts=`date '+%Y%m%d %T'` grep -qw FAIL $alloutput && echo "$ts $rev $i" >> $allfaillog && @@ -237,9 +243,8 @@ while true; do [ -f ../tools/ministat.sh ] && ../tools/ministat.sh $allelapsed $i [ $((`date '+%s'` - start)) -gt 1980 ] && - printf "$ts *** Excessive run time: %s %d min\r\n" $i, \ - $(((`date '+%s'` - start) / 60)) | - tee $console >> $allexcess + printf "$ts $rev $i %d min\n" \ + $(((`date '+%s'` - start) / 60)) >> $allexcess while pgrep -q "^swap$"; do echo "swap still running" sleep 2 @@ -248,6 +253,7 @@ while true; do [ $all_debug ] && post_debug [ $minutes ] && [ $((`date +%s` - s1)) -ge $minutes ] && break 2 + [ $exitonerror -eq 1 -a $e -ne 0 ] && break 2 done [ $((loops -= 1)) -eq 0 ] && break done diff --git a/tools/test/stress2/misc/arp.sh b/tools/test/stress2/misc/arp.sh index ef66ce351e24..5c4d997ba975 100755 --- a/tools/test/stress2/misc/arp.sh +++ b/tools/test/stress2/misc/arp.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/aslr.sh b/tools/test/stress2/misc/aslr.sh index 6261fae4546b..686b2b414030 100755 --- a/tools/test/stress2/misc/aslr.sh +++ b/tools/test/stress2/misc/aslr.sh @@ -1,7 +1,7 @@ #/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/badcode2.sh b/tools/test/stress2/misc/badcode2.sh index 8e47a74a87d1..dbf2cadbc4cd 100755 --- a/tools/test/stress2/misc/badcode2.sh +++ b/tools/test/stress2/misc/badcode2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Peter Holm # diff --git a/tools/test/stress2/misc/badcode3.sh b/tools/test/stress2/misc/badcode3.sh index e0a10d0074a4..da4f811bff6d 100755 --- a/tools/test/stress2/misc/badcode3.sh +++ b/tools/test/stress2/misc/badcode3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Peter Holm # @@ -39,13 +39,18 @@ mdconfig -a -t swap -s 1g -u $mdstart newfs $newfs_flags md$mdstart > /dev/null mount /dev/md$mdstart $mntpoint chmod 777 $mntpoint +export badcodeLOAD=100 +export RUNDIR=$mntpoint/stressX +mkdir -p $RUNDIR +chmod 0777 $RUNDIR here=`pwd` cd $mntpoint (cd $here/../testcases/swap; ./swap -t 5m -i 20) & sleep 2 while pgrep -q swap; do - timeout 1m limits -c 0 $here/../testcases/badcode/badcode -t 1m -i 20 + su $testuser -c \ + "timeout 1m limits -c 0 $here/../testcases/badcode/badcode -t 1m -i 20" done wait cd $here diff --git a/tools/test/stress2/misc/beneath.sh b/tools/test/stress2/misc/beneath.sh index 5f61dbd5e383..29c7ce967197 100755 --- a/tools/test/stress2/misc/beneath.sh +++ b/tools/test/stress2/misc/beneath.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Konstantin Belousov <kib@FreeBSD.org> # diff --git a/tools/test/stress2/misc/beneath2.sh b/tools/test/stress2/misc/beneath2.sh index ad1f5c538258..5cbe3c160e00 100755 --- a/tools/test/stress2/misc/beneath2.sh +++ b/tools/test/stress2/misc/beneath2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/beneath3.sh b/tools/test/stress2/misc/beneath3.sh index 9e7493a2322c..aac7079e284b 100755 --- a/tools/test/stress2/misc/beneath3.sh +++ b/tools/test/stress2/misc/beneath3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/beneath4.sh b/tools/test/stress2/misc/beneath4.sh index 0f51980cb75a..48458f088a96 100755 --- a/tools/test/stress2/misc/beneath4.sh +++ b/tools/test/stress2/misc/beneath4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/buildkernel.sh b/tools/test/stress2/misc/buildkernel.sh index fe8d530dfab7..e0aa85617f9b 100755 --- a/tools/test/stress2/misc/buildkernel.sh +++ b/tools/test/stress2/misc/buildkernel.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # @@ -49,6 +49,7 @@ chmod 0777 $TMPDIR log=$mntpoint/log p=$((`sysctl -n hw.ncpu`+ 1)) +[ $p -gt 32 ] && p=32 # Arbitrary cap p=`jot -r 1 1 $p` echo "make -j $p buildkernel KERNCONF=GENERIC DESTDIR=$mntpoint" \ "TARGET=amd64 TARGET_ARCH=amd64" diff --git a/tools/test/stress2/misc/buildworld.sh b/tools/test/stress2/misc/buildworld.sh index 595b387c90ae..3b362ec7041a 100755 --- a/tools/test/stress2/misc/buildworld.sh +++ b/tools/test/stress2/misc/buildworld.sh @@ -55,6 +55,7 @@ mkdir $TMPDIR chmod 0777 $TMPDIR p=$((`sysctl -n hw.ncpu`+ 1)) +[ $p -gt 32 ] && p=32 # Arbitrary cap timeout 20m make -i -j $p buildworld DESTDIR=$mntpoint TARGET=amd64 \ TARGET_ARCH=amd64 > /dev/null diff --git a/tools/test/stress2/misc/buildworld2.sh b/tools/test/stress2/misc/buildworld2.sh index 9c1eed97b7ea..3653cb1db5b4 100755 --- a/tools/test/stress2/misc/buildworld2.sh +++ b/tools/test/stress2/misc/buildworld2.sh @@ -46,6 +46,7 @@ mkdir $TMPDIR chmod 0777 $TMPDIR p=$((`sysctl -n hw.ncpu`+ 1)) +[ $p -gt 32 ] && p=32 # Arbitrary cap make -j $p buildworld DESTDIR=$mntpoint TARGET=amd64 TARGET_ARCH=amd64 \ > /dev/null & sleep $((20 * 60)) diff --git a/tools/test/stress2/misc/buildworld3.sh b/tools/test/stress2/misc/buildworld3.sh index a5dc642ce876..e3bce2764c0c 100755 --- a/tools/test/stress2/misc/buildworld3.sh +++ b/tools/test/stress2/misc/buildworld3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # @@ -62,6 +62,7 @@ mkdir $TMPDIR $MAKEOBJDIRPREFIX chmod 0777 $TMPDIR $MAKEOBJDIRPREFIX p=$((`sysctl -n hw.ncpu`+ 1)) +[ $p -gt 32 ] && p=32 # Arbitrary cap su $testuser -c \ "make -i -j $p buildworld DESTDIR=$mntpoint TARGET=amd64 \ TARGET_ARCH=amd64 > /dev/null" & diff --git a/tools/test/stress2/misc/buildworld4.sh b/tools/test/stress2/misc/buildworld4.sh index 98d4904ec4bd..d1d162120952 100755 --- a/tools/test/stress2/misc/buildworld4.sh +++ b/tools/test/stress2/misc/buildworld4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # @@ -50,6 +50,7 @@ mkdir $TMPDIR chmod 0777 $TMPDIR p=$((`sysctl -n hw.ncpu`+ 1)) +[ $p -gt 16 ] && p=16 # Arbitrary cap [ `sysctl -n vm.swap_total` -gt 0 ] && p=$((p * 4)) p=`jot -r 1 1 $p` echo "make -i -j $p buildworld DESTDIR=$mntpoint TARGET=amd64 "\ diff --git a/tools/test/stress2/misc/chain.sh b/tools/test/stress2/misc/chain.sh index 46d2f32cd7c4..ebc3f118e1bf 100755 --- a/tools/test/stress2/misc/chain.sh +++ b/tools/test/stress2/misc/chain.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Jeremy <peterj@FreeBSD.org> # diff --git a/tools/test/stress2/misc/chroot.sh b/tools/test/stress2/misc/chroot.sh index 176b249312f0..35e2d2f11e0e 100755 --- a/tools/test/stress2/misc/chroot.sh +++ b/tools/test/stress2/misc/chroot.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/compare.sh b/tools/test/stress2/misc/compare.sh index c983046384b5..9ca6542d1af5 100755 --- a/tools/test/stress2/misc/compare.sh +++ b/tools/test/stress2/misc/compare.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/contigmalloc.sh b/tools/test/stress2/misc/contigmalloc.sh index 92bf6ff40905..abaa2c3cad53 100755 --- a/tools/test/stress2/misc/contigmalloc.sh +++ b/tools/test/stress2/misc/contigmalloc.sh @@ -26,7 +26,7 @@ # SUCH DAMAGE. # -# contigmalloc(9) / contigfree(9) test scenario. +# contigmalloc(9) / free(9) test scenario. # malloc() a random number of buffers with random size and then free them. # A malloc pattern might look like this: @@ -116,7 +116,7 @@ test(int argc, char *argv[]) if (p[i] != NULL) { res = syscall(no, TFREE, &p[i], &size[i]); #if defined(TEST) - fprintf(stderr, "contigfree(%lu pages)\n", + fprintf(stderr, "free(%lu pages)\n", size[i] / ps); #endif p[i] = NULL; @@ -197,10 +197,8 @@ cmalloc(struct thread *td, struct cmalloc_args *uap) switch (uap->a_op) { case TFREE: error = copyin(uap->a_ptr, &p, sizeof(p)); - if (error == 0) { - if (p != NULL) - contigfree(p, size, M_TEMP); - } + if (error == 0) + free(p, M_TEMP); return (error); case TALLOC: diff --git a/tools/test/stress2/misc/contigmalloc2.sh b/tools/test/stress2/misc/contigmalloc2.sh index e3ec5bf3a358..dd4bbd751fd4 100755 --- a/tools/test/stress2/misc/contigmalloc2.sh +++ b/tools/test/stress2/misc/contigmalloc2.sh @@ -26,7 +26,7 @@ # SUCH DAMAGE. # -# contigmalloc(9) / contigfree(9) test scenario. +# contigmalloc(9) / free(9) test scenario. # Regression test for allocations >= 2 GiB. # "panic: vm_page_insert_after: mpred doesn't precede pindex" seen. # Fixed by r284207. @@ -87,8 +87,7 @@ test(int argc, char *argv[]) #endif res = syscall(no, TFREE, &p, &size); #if defined(TEST) - fprintf(stderr, "contigfree(%lu pages)\n", - size); + fprintf(stderr, "free(%lu pages)\n", size); #endif } size /= 2; @@ -165,10 +164,8 @@ cmalloc(struct thread *td, struct cmalloc_args *uap) switch (uap->a_op) { case TFREE: error = copyin(uap->a_ptr, &p, sizeof(p)); - if (error == 0) { - if (p != NULL) - contigfree(p, size, M_TEMP); - } + if (error == 0) + free(p, M_TEMP); return (error); case TALLOC: diff --git a/tools/test/stress2/misc/contigmalloc3.sh b/tools/test/stress2/misc/contigmalloc3.sh index 9baf7c129688..28d5c17e0566 100755 --- a/tools/test/stress2/misc/contigmalloc3.sh +++ b/tools/test/stress2/misc/contigmalloc3.sh @@ -26,7 +26,7 @@ # SUCH DAMAGE. # -# contigmalloc(9) / contigfree(9) test scenario. +# contigmalloc(9) / free(9) test scenario. # Test allocation with 1GB # "panic: Bad link elm 0x6766fbc next->prev != elm" seen: @@ -91,7 +91,7 @@ test(int argc, char *argv[]) res = syscall(no, TFREE, &cp, &size); #if defined(TEST) - fprintf(stderr, "contigfree(%lu pages) %luMB\n", + fprintf(stderr, "free(%lu pages) %luMB\n", size / ps, size / 1024 / 1024); #endif } @@ -166,10 +166,8 @@ cmalloc(struct thread *td, struct cmalloc_args *uap) switch (uap->a_op) { case TFREE: error = copyin(uap->a_ptr, &p, sizeof(p)); - if (error == 0) { - if (p != NULL) - contigfree(p, size, M_TEMP); - } + if (error == 0) + free(p, M_TEMP); return (error); case TALLOC: diff --git a/tools/test/stress2/misc/core5.sh b/tools/test/stress2/misc/core5.sh index 856b01608f2e..c7928a7cf1dc 100755 --- a/tools/test/stress2/misc/core5.sh +++ b/tools/test/stress2/misc/core5.sh @@ -34,7 +34,7 @@ # 20150714 Slowdown seen with core5 waiting in vlruwk. # sysctl vfs.vlru_allow_cache_src=1 used to resolve this. -# For now change MAXVNODES from 1.000 to 4.000. +# For now change MAXVNODES from 1.000 to 5.000. [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg @@ -131,7 +131,7 @@ EOF #include <time.h> #include <unistd.h> -#define MAXVNODES 4000 +#define MAXVNODES 5000 #define NBFILES 10000 #define PARALLEL 4 #define RTIME (10 * 60) diff --git a/tools/test/stress2/misc/cpuset.sh b/tools/test/stress2/misc/cpuset.sh index ad9f8569f386..359974a4bd87 100755 --- a/tools/test/stress2/misc/cpuset.sh +++ b/tools/test/stress2/misc/cpuset.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/creat.sh b/tools/test/stress2/misc/creat.sh new file mode 100755 index 000000000000..1abab774ed7f --- /dev/null +++ b/tools/test/stress2/misc/creat.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Demonstrate incorrect "out of inodes" message with SU enabled. +# No issue seen with SU+J + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +set -eu +prog=$(basename "$0" .sh) +log=/tmp/$prog.log +s=0 +mount | grep -q "on $mntpoint " && umount $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 100m -u $mdstart +[ $# -eq 1 ] && flags="$@" || flags="-Un" +echo "newfs $flags /dev/md$mdstart" +newfs $flags /dev/md$mdstart > /dev/null +[ "$flags" = "" ] && tunefs -n disable md$mdstart +mount /dev/md$mdstart $mntpoint +set +e + +ifree1=`df -i $mntpoint | tail -1 | awk '{print $7}'` +before=`df -i $mntpoint` +n=$(((ifree1 - 5) / 10)) +jot 10 | xargs -I% mkdir $mntpoint/% +start=`date +%s` +while [ $((`date +%s` - start)) -lt 60 ]; do + for j in `jot 10`; do + ( + jot $n | xargs -P0 -I% touch $mntpoint/$j/% + jot $n | xargs -P0 -I% rm $mntpoint/$j/% + ) & + done + wait +done 2>&1 | tee $log | head -5 +[ -s $log ] && s=3 +jot 10 | xargs -I% rmdir $mntpoint/% +umount $mntpoint; mount /dev/md$mdstart $mntpoint + +ifree2=`df -i $mntpoint | tail -1 | awk '{print $7}'` +after=`df -i $mntpoint | tail -1` +if [ $ifree1 -ne $ifree2 ]; then + echo "$before" + echo "$after" + s=1 + ls -alsrt $mntpoint | head -20 +fi + +umount $mntpoint +fsck -fy /dev/md$mdstart > $log 2>&1 +grep -Eq "WAS MODIFIED" $log && { s=2; cat $log; } + +mdconfig -d -u $mdstart +rm -f $log +exit $s diff --git a/tools/test/stress2/misc/crossmp.sh b/tools/test/stress2/misc/crossmp.sh index 0bd07cea2aaf..b61506dcc477 100755 --- a/tools/test/stress2/misc/crossmp.sh +++ b/tools/test/stress2/misc/crossmp.sh @@ -74,7 +74,8 @@ else else # The test: Parallel mount and unmounts - for i in `jot 1024`; do + start=`date +%s` + while [ $((`date +%s`- start)) -lt 300 ]; do m=$1 mount /dev/md${m} ${mntpoint}$m while mount | grep -q "on ${mntpoint}$m "; do diff --git a/tools/test/stress2/misc/crossmp2.sh b/tools/test/stress2/misc/crossmp2.sh index 03cd04e077c1..1f2f1a921e10 100755 --- a/tools/test/stress2/misc/crossmp2.sh +++ b/tools/test/stress2/misc/crossmp2.sh @@ -67,7 +67,8 @@ else else # The test: Parallel mount and unmounts - for i in `jot 128`; do + start=`date +%s` + while [ $((`date +%s`- start)) -lt 300 ]; do m=$1 mount -t nfs -o tcp -o nfsv3 -o retrycnt=3 \ -o intr,soft -o rw $nfs_export ${mntpoint}$m diff --git a/tools/test/stress2/misc/crossmp3.sh b/tools/test/stress2/misc/crossmp3.sh index 5eecb936e900..32c625a1e4ad 100755 --- a/tools/test/stress2/misc/crossmp3.sh +++ b/tools/test/stress2/misc/crossmp3.sh @@ -41,6 +41,7 @@ CONT=/tmp/crossmp3.continue if [ $# -eq 0 ]; then N=`sysctl -n hw.ncpu` + [ $N -gt 32 ] && N=32 # Arbitrary cap usermem=`sysctl -n hw.usermem` [ `sysctl -n vm.swap_total` -eq 0 ] && usermem=$((usermem / 2)) size=$((usermem / 1024 / 1024 / N)) diff --git a/tools/test/stress2/misc/crossmp4.sh b/tools/test/stress2/misc/crossmp4.sh index e22f969b72bb..21d22bee69e5 100755 --- a/tools/test/stress2/misc/crossmp4.sh +++ b/tools/test/stress2/misc/crossmp4.sh @@ -40,6 +40,7 @@ . ../default.cfg N=`sysctl -n hw.ncpu` +[ $N -gt 32 ] && N=32 # Arbitrary cap usermem=`sysctl -n hw.usermem` [ `swapinfo | wc -l` -eq 1 ] && usermem=$((usermem/100*80)) size=$((usermem / 1024 / 1024 - 2)) diff --git a/tools/test/stress2/misc/crossmp5.sh b/tools/test/stress2/misc/crossmp5.sh index b5a8304f2dcb..6e504d9f20ad 100755 --- a/tools/test/stress2/misc/crossmp5.sh +++ b/tools/test/stress2/misc/crossmp5.sh @@ -33,6 +33,7 @@ . ../default.cfg N=`sysctl -n hw.ncpu` +[ $N -gt 32 ] && N=32 # Arbitrary cap usermem=`sysctl -n hw.usermem` [ `swapinfo | wc -l` -eq 1 ] && usermem=$((usermem/100*80)) size=$((usermem / 1024 / 1024 / N)) @@ -74,8 +75,10 @@ else done else # The test: Parallel mount and unmount + i=0 m=$1 - for i in `jot 200`; do + start=`date +%s` + while [ $((`date +%s`- start)) -lt 300 ]; do mount /dev/md${m} ${mntpoint}$m chmod 777 ${mntpoint}$m l=`jot -r 1 65535` @@ -88,6 +91,7 @@ else echo "-f") umount $opt ${mntpoint}$m > /dev/null 2>&1 done + i=$((i + 1)) done rm -f /tmp/crossmp.continue fi diff --git a/tools/test/stress2/misc/crossmp6.sh b/tools/test/stress2/misc/crossmp6.sh index 92ca0abcba27..d5abd27f99f1 100755 --- a/tools/test/stress2/misc/crossmp6.sh +++ b/tools/test/stress2/misc/crossmp6.sh @@ -72,7 +72,8 @@ if [ $# -eq 0 ]; then exit 0 else if [ $1 = find ]; then - for i in `jot 128`; do + start=`date +%s` + while [ $((`date +%s`- start)) -lt 300 ]; do find ${mntpoint}* -maxdepth 1 -type f > \ /dev/null 2>&1 (lockf -t 10 ${mntpoint}$2/$0.$$.$i sleep 1 &) > \ diff --git a/tools/test/stress2/misc/crossmp7.sh b/tools/test/stress2/misc/crossmp7.sh index c2c2752f38e7..f4f12e64c35f 100755 --- a/tools/test/stress2/misc/crossmp7.sh +++ b/tools/test/stress2/misc/crossmp7.sh @@ -91,7 +91,8 @@ else else # The test: Parallel mount and unmounts m=$1 - for i in `jot 1024`; do + start=`date +%s` + while [ $((`date +%s`- start)) -lt 300 ]; do zfs mount stress2_tank/test$m zfs umount -f stress2_tank/test$m done 2>/dev/null diff --git a/tools/test/stress2/misc/crossmp8.sh b/tools/test/stress2/misc/crossmp8.sh index e877dfaf6d1c..eec5ba9bc7c1 100755 --- a/tools/test/stress2/misc/crossmp8.sh +++ b/tools/test/stress2/misc/crossmp8.sh @@ -41,6 +41,7 @@ CONT=/tmp/crossmp8.continue N=`sysctl -n hw.ncpu` +[ $N -gt 32 ] && N=32 # Arbitrary cap usermem=`sysctl -n hw.usermem` [ `swapinfo | wc -l` -eq 1 ] && usermem=$((usermem/100*80)) size=$((usermem / 1024 / 1024 / N)) diff --git a/tools/test/stress2/misc/datagram.sh b/tools/test/stress2/misc/datagram.sh index 5a5715886a88..0eec052823b7 100755 --- a/tools/test/stress2/misc/datagram.sh +++ b/tools/test/stress2/misc/datagram.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/datagram2.sh b/tools/test/stress2/misc/datagram2.sh index 66cfd44711c2..746ea33cb734 100755 --- a/tools/test/stress2/misc/datagram2.sh +++ b/tools/test/stress2/misc/datagram2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/datagram3.sh b/tools/test/stress2/misc/datagram3.sh index ca54377befcc..a5e141702139 100755 --- a/tools/test/stress2/misc/datagram3.sh +++ b/tools/test/stress2/misc/datagram3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/datamove.sh b/tools/test/stress2/misc/datamove.sh index a27a53e5e31b..67de998f3816 100755 --- a/tools/test/stress2/misc/datamove.sh +++ b/tools/test/stress2/misc/datamove.sh @@ -194,7 +194,7 @@ int startIO(int fd,char *buffer) return 0; } -int main(int argc,char *argv[],char *envp[]) +int main(void) { int fdA,fdB,fdDelayA,fdDelayB; diff --git a/tools/test/stress2/misc/datamove2.sh b/tools/test/stress2/misc/datamove2.sh index 1b4c964a1f12..e503edf152a4 100755 --- a/tools/test/stress2/misc/datamove2.sh +++ b/tools/test/stress2/misc/datamove2.sh @@ -194,7 +194,7 @@ startIO(int fd, char *buffer) } int -main(int argc, char *argv[], char *envp[]) +main(void) { int fdA, fdB, fdDelayA, fdDelayB; diff --git a/tools/test/stress2/misc/datamove3.sh b/tools/test/stress2/misc/datamove3.sh index 19beffc00655..0cdd4b5c0c3c 100755 --- a/tools/test/stress2/misc/datamove3.sh +++ b/tools/test/stress2/misc/datamove3.sh @@ -192,7 +192,7 @@ startIO(int fd, char *buffer) } int -main(int argc, char *argv[], char *envp[]) +main(void) { int fdA, fdB, fdDelayA, fdDelayB; diff --git a/tools/test/stress2/misc/datamove6.sh b/tools/test/stress2/misc/datamove6.sh new file mode 100755 index 000000000000..88bfea425bdc --- /dev/null +++ b/tools/test/stress2/misc/datamove6.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Variation of the datamove.sh, using MSDOSFS + +# No problems seen + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +here=`pwd` +prog=$(basename "$0" .sh) +cd /tmp +sed '1,/^EOF/d' < $here/datamove.sh > $prog.c +mycc -o $prog -Wall -Wextra -O2 -g $prog.c +rm -f $prog.c + +set -eu +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 2g -u $mdstart +newfs_msdos -F 32 -b 8192 /dev/md$mdstart 2> /dev/null +#mount -t msdosfs /dev/md$mdstart $mntpoint +mount_msdosfs -m 777 /dev/md$mdstart $mntpoint +set +e + +$here/../testcases/swap/swap -t 5m -i 100 -h & +for i in `jot 5`; do + su $testuser -c "cd $mntpoint; /tmp/$prog" +done +mv /tmp/$prog $mntpoint +for i in `jot 5`; do + mkdir -p $mntpoint/datamove.dir.$i + cd $mntpoint/datamove.dir.$i + $mntpoint/$prog & +done +pkill swap +wait +while mount | grep -q $mntpoint; do + umount -f $mntpoint > /dev/null 2>&1 +done +mdconfig -d -u $mdstart + +exit 0 diff --git a/tools/test/stress2/misc/devfs4.sh b/tools/test/stress2/misc/devfs4.sh index 3ca8f44eb036..03a9f8cc8ca3 100755 --- a/tools/test/stress2/misc/devfs4.sh +++ b/tools/test/stress2/misc/devfs4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/devfs5.sh b/tools/test/stress2/misc/devfs5.sh index b0b1d98fc83e..5a72d7db9efb 100755 --- a/tools/test/stress2/misc/devfs5.sh +++ b/tools/test/stress2/misc/devfs5.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # @@ -30,7 +30,7 @@ [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 # Test scenario for https://reviews.freebsd.org/D20411 -# Add devfs(5) support for VOP_MKDIR(9) and VOP_RMDIR(9) +# Add devfs(4) support for VOP_MKDIR(9) and VOP_RMDIR(9) . ../default.cfg diff --git a/tools/test/stress2/misc/dtrace_fault.sh b/tools/test/stress2/misc/dtrace_fault.sh index 508cfc48cd59..6de6c058a998 100755 --- a/tools/test/stress2/misc/dtrace_fault.sh +++ b/tools/test/stress2/misc/dtrace_fault.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Konstantin Belousov <kib@FreeBSD.org> # diff --git a/tools/test/stress2/misc/dup.sh b/tools/test/stress2/misc/dup.sh index 7223709d09c4..89b4e637a737 100755 --- a/tools/test/stress2/misc/dup.sh +++ b/tools/test/stress2/misc/dup.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/elf.sh b/tools/test/stress2/misc/elf.sh index eb6650c9c088..5d7cbaaf9952 100755 --- a/tools/test/stress2/misc/elf.sh +++ b/tools/test/stress2/misc/elf.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # diff --git a/tools/test/stress2/misc/execpath.sh b/tools/test/stress2/misc/execpath.sh index 22613a948e6b..0e88472ae356 100755 --- a/tools/test/stress2/misc/execpath.sh +++ b/tools/test/stress2/misc/execpath.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/exlock2.sh b/tools/test/stress2/misc/exlock2.sh index 94e3f88f48e3..811fd96f502c 100755 --- a/tools/test/stress2/misc/exlock2.sh +++ b/tools/test/stress2/misc/exlock2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # @@ -68,6 +68,7 @@ EOF #include <unistd.h> static _Atomic(int) *share; +static int debug; /* Set to "1" for debug output */ static int quit; static char file[80]; @@ -101,9 +102,8 @@ test1(void) ; /* wait for test2 to signal "done" */ close(fd); } -#if defined(DEBUG) - fprintf(stderr, "%s: n = %d\n", __func__, n); -#endif + if (debug != 0) + fprintf(stderr, "%s: n = %d\n", __func__, n); _exit(0); } @@ -114,17 +114,15 @@ test2(void) struct flock fl; struct stat st; time_t start; - int e, fd, n; + int e, fd; e = 0; fd = 0; - n = 0; start = time(NULL); while (time(NULL) - start < RUNTIME) { share[SYNC] = 1; if ((fd = open(file, O_RDWR)) == -1) goto out; - n++; memset(&fl, 0, sizeof(fl)); fl.l_start = 0; fl.l_len = 0; @@ -151,12 +149,9 @@ out: share[SYNC] = 0; usleep(100); } -#if defined(DEBUG) - if (e != 0) { - system("ps -Uroot | grep -v grep | grep /tmp/exlock2 | "\ + if (debug != 0 && e != 0) + system("ps -x | grep -v grep | grep /tmp/exlock2 | "\ "awk '{print $1}' | xargs procstat -f"); - } -#endif share[SYNC] = 0; _exit(e); diff --git a/tools/test/stress2/misc/ext2fs.sh b/tools/test/stress2/misc/ext2fs.sh index f4d33116faed..e93da12419b0 100755 --- a/tools/test/stress2/misc/ext2fs.sh +++ b/tools/test/stress2/misc/ext2fs.sh @@ -32,7 +32,7 @@ . ../default.cfg -# Uses mke2fs from sysutils/e2fsprogs +# Uses mke2fs from filesystems/e2fsprogs [ -z "`type mke2fs 2>/dev/null`" ] && echo "Skipping test as mke2fs not installed" && exit 0 diff --git a/tools/test/stress2/misc/ext2fs2.sh b/tools/test/stress2/misc/ext2fs2.sh index 748e45a33ffa..07ff5d5058fb 100755 --- a/tools/test/stress2/misc/ext2fs2.sh +++ b/tools/test/stress2/misc/ext2fs2.sh @@ -33,7 +33,7 @@ . ../default.cfg -# Uses mke2fs from sysutils/e2fsprogs +# Uses mke2fs from filesystems/e2fsprogs [ -x /usr/local/sbin/mke2fs ] || exit 0 mount | grep "$mntpoint" | grep -q md$mdstart && umount -f $mntpoint mdconfig -l | grep -q $mdstart && mdconfig -d -u $mdstart diff --git a/tools/test/stress2/misc/ext2fs3.sh b/tools/test/stress2/misc/ext2fs3.sh index f33b4cc73547..5c904d218a5f 100755 --- a/tools/test/stress2/misc/ext2fs3.sh +++ b/tools/test/stress2/misc/ext2fs3.sh @@ -26,7 +26,7 @@ # SUCH DAMAGE. # -# ext2fs(5) test scenario with a 1k block size +# ext2fs(4) test scenario with a 1k block size # "panic: ext2_reallocblks: alloc mismatch" seen. # "Fatal trap 12: page fault while in kernel mode" seen. @@ -35,7 +35,7 @@ . ../default.cfg -# Uses mke2fs from sysutils/e2fsprogs +# Uses mke2fs from filesystems/e2fsprogs [ -z "`type mke2fs 2>/dev/null`" ] && echo "Skipping test as mke2fs not installed" && exit 0 diff --git a/tools/test/stress2/misc/ext3fs.sh b/tools/test/stress2/misc/ext3fs.sh index 826317857f85..210008ce3942 100755 --- a/tools/test/stress2/misc/ext3fs.sh +++ b/tools/test/stress2/misc/ext3fs.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # @@ -33,7 +33,7 @@ . ../default.cfg -# Uses mke2fs from sysutils/e2fsprogs +# Uses mke2fs from filesystems/e2fsprogs [ -z "`type mke2fs 2>/dev/null`" ] && echo "Skipping test as mke2fs not installed" && exit 0 diff --git a/tools/test/stress2/misc/ext4fs.sh b/tools/test/stress2/misc/ext4fs.sh index 610351352501..2e2ac8d77440 100755 --- a/tools/test/stress2/misc/ext4fs.sh +++ b/tools/test/stress2/misc/ext4fs.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # @@ -36,7 +36,7 @@ . ../default.cfg -# Uses mke2fs from sysutils/e2fsprogs +# Uses mke2fs from filesystems/e2fsprogs [ -z "`type mke2fs 2>/dev/null`" ] && echo "Skipping test as mke2fs not installed" && exit 0 diff --git a/tools/test/stress2/misc/extattr2.sh b/tools/test/stress2/misc/extattr2.sh index 3ce10dfbc894..64cd73dcce47 100755 --- a/tools/test/stress2/misc/extattr2.sh +++ b/tools/test/stress2/misc/extattr2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/extattr3.sh b/tools/test/stress2/misc/extattr3.sh index 84b5e1821473..82d404400b7d 100755 --- a/tools/test/stress2/misc/extattr3.sh +++ b/tools/test/stress2/misc/extattr3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/fcntl.sh b/tools/test/stress2/misc/fcntl.sh index 39f7f87dc005..237cacdf6de8 100755 --- a/tools/test/stress2/misc/fcntl.sh +++ b/tools/test/stress2/misc/fcntl.sh @@ -26,7 +26,7 @@ # SUCH DAMAGE. # -# fcntl(2) locking scenario. No problems seen. +# fcntl(2) locking scenario. . ../default.cfg @@ -45,6 +45,8 @@ rm -f /tmp/fcntl exit $status EOF #include <sys/types.h> +#include <sys/wait.h> + #include <err.h> #include <errno.h> #include <fcntl.h> @@ -52,7 +54,6 @@ EOF #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <sys/wait.h> #include <unistd.h> #define PARALLEL 16 @@ -80,9 +81,10 @@ add(int n, int increment) { struct flock fl; off_t pos; - long val, oval __unused; - int r; + long val, oval; + int debug, r; + debug = 0; /* set to "1" for debug output. */ pos = n * sizeof(val); memset(&fl, 0, sizeof(fl)); fl.l_start = pos; @@ -107,10 +109,9 @@ add(int n, int increment) } oval = val; val = val + increment; -#if defined(DEBUG) - fprintf(stderr, "add(%d, %d) @ pos %ld: %ld = %ld + %d\n", - n, increment, (long)pos, val, oval, increment); -#endif + if (debug != 0) + fprintf(stderr, "add(%d, %d) @ pos %ld: %ld = %ld + %d\n", + n, increment, (long)pos, val, oval, increment); if (lseek(fd, pos, SEEK_SET) == -1) err(1, "lseek"); while ((r = write(fd, &val, sizeof(val)) != sizeof(val))) { @@ -178,9 +179,9 @@ down(void) int main(void) { - int flags, i; - long val, sum; off_t len; + long val, sum; + int flags, i; signal(SIGHUP, handler); signal(SIGALRM, ahandler); diff --git a/tools/test/stress2/misc/fcntl2.sh b/tools/test/stress2/misc/fcntl2.sh index 5f276ae81ccc..acb161fd0523 100755 --- a/tools/test/stress2/misc/fcntl2.sh +++ b/tools/test/stress2/misc/fcntl2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # @@ -150,6 +150,8 @@ test(void) } close(fd); unlink(file); + if (success == 0) + fprintf(stderr, "No calls to fcntl() succeeded.\n"); _exit(0); } diff --git a/tools/test/stress2/misc/fcntl3.sh b/tools/test/stress2/misc/fcntl3.sh index 8892a9d5670b..650619b43762 100755 --- a/tools/test/stress2/misc/fcntl3.sh +++ b/tools/test/stress2/misc/fcntl3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Mark Johnston <markj@freebsd.org> # diff --git a/tools/test/stress2/misc/fexecve.sh b/tools/test/stress2/misc/fexecve.sh index 01ff0b723134..432945061c64 100755 --- a/tools/test/stress2/misc/fexecve.sh +++ b/tools/test/stress2/misc/fexecve.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/fifo2.sh b/tools/test/stress2/misc/fifo2.sh index 9e4a7e632e9d..4a7b986931d9 100755 --- a/tools/test/stress2/misc/fifo2.sh +++ b/tools/test/stress2/misc/fifo2.sh @@ -96,6 +96,7 @@ EOF #include <unistd.h> #define N (128 * 1024 / (int)sizeof(u_int32_t)) +static int debug; /* Set to 1 for debug output */ u_int32_t r[N]; static void @@ -143,11 +144,10 @@ calls(void *arg __unused) arg6 = makearg(); arg7 = makearg(); -#if 0 - fprintf(stderr, "%2d : syscall(%3d, %lx, %lx, %lx, %lx, %lx, %lx, %lx)\n", - i, SYS_open, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + if (debug != 0) + fprintf(stderr, "%2d : syscall(%3d, %lx, %lx, %lx, %lx, %lx, %lx, %lx)\n", + i, SYS_open, arg1, arg2, arg3, arg4, arg5, arg6, arg7); usleep(100000); -#endif alarm(1); syscall(SYS_open, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } diff --git a/tools/test/stress2/misc/fifo4.sh b/tools/test/stress2/misc/fifo4.sh index 7f46f8537dc6..1578b8786d43 100755 --- a/tools/test/stress2/misc/fifo4.sh +++ b/tools/test/stress2/misc/fifo4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # @@ -27,7 +27,7 @@ # SUCH DAMAGE. # -# tmpfs(5) version of fifo2.sh +# tmpfs(4) version of fifo2.sh # No problems seen on HEAD. [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 diff --git a/tools/test/stress2/misc/flock_open_close.sh b/tools/test/stress2/misc/flock_open_close.sh index 01e376319abe..39b894da8a63 100755 --- a/tools/test/stress2/misc/flock_open_close.sh +++ b/tools/test/stress2/misc/flock_open_close.sh @@ -87,6 +87,7 @@ EOF #include <fcntl.h> #include <stdio.h> #include <stdlib.h> +#include <time.h> #include <unistd.h> static void @@ -135,7 +136,8 @@ main(int ac, char **av) { struct stat sb; pid_t pid; - int e, i, status; + time_t start; + int e, status; if (ac < 2) usage(); @@ -150,7 +152,8 @@ main(int ac, char **av) if (pid == 0) child(av[1]); e = 0; - for (i = 0; i < 200000; i++) { + start = time(NULL); + while (time(NULL) - start < 150) { pid = fork(); if (pid < 0) err(1, "vfork"); diff --git a/tools/test/stress2/misc/force.sh b/tools/test/stress2/misc/force.sh index 4c5cd6c255f6..61f15b0d5b8b 100755 --- a/tools/test/stress2/misc/force.sh +++ b/tools/test/stress2/misc/force.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/force10.sh b/tools/test/stress2/misc/force10.sh new file mode 100755 index 000000000000..d0ff36ae2ef9 --- /dev/null +++ b/tools/test/stress2/misc/force10.sh @@ -0,0 +1,92 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# "mdconfig -o force" test scenario. Simplification of force7.sh + +# panic: buf_alloc: BUF_LOCK on free buf 0xfffffe0038652410: 16. +# https://people.freebsd.org/~pho/stress/log/log0270.txt + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +set -u +log=/tmp/force10.sh.log +mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +truncate -s 1g $diskimage +mdconfig -a -t vnode -f $diskimage -s 1g -u $mdstart +flags=$newfs_flags +echo "newfs $flags md$mdstart" +newfs $flags md$mdstart > /dev/null 2>&1 + +#export TESTPROGS=`cd ..; find testcases/ -perm -1 -type f | \ +# egrep -Ev "/run/|/badcode/|/pty/|/shm/|/socket/|sysctl|tcp|thr|udp"` +export TESTPROGS=' +testcases/creat/creat +testcases/swap/swap +' +export runRUNTIME=3m +export RUNDIR=$mntpoint/stressX +s=0 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 300 ]; do + mount /dev/md$mdstart $mntpoint + rm -fr $mntpoint/lost+found + chmod 777 $mntpoint + + su $testuser -c 'cd ..; ./testcases/run/run $TESTPROGS' > \ + /dev/null 2>&1 & + + sleep `jot -r 1 5 9` + while mdconfig -l | grep -q md$mdstart; do + mdconfig -d -u $mdstart -o force || sleep 1 + done + sleep 1 + ../tools/killall.sh + wait + n=0 + while mount | grep $mntpoint | grep -q /dev/md; do + umount $mntpoint || sleep 1 + [ $((n += 1)) -gt 300 ] && { echo FAIL; exit 1; } + done + mdconfig -a -t vnode -f $diskimage -s 1g -u $mdstart + for i in `jot 10`; do + fsck_ffs -fy /dev/md$mdstart > $log 2>&1 + grep -Eq "FILE SYSTEM WAS MODIFIED" $log || break + done + [ $i -gt 2 ] && echo "Ran fsck $i times" + [ $i -eq 10 ] && { s=1; break; } +done +if [ $s -eq 0 ]; then + mdconfig -d -u $mdstart + rm -f $diskimage $log +else + cat $log +fi +exit $s diff --git a/tools/test/stress2/misc/force11.sh b/tools/test/stress2/misc/force11.sh new file mode 100755 index 000000000000..229a83ce69fe --- /dev/null +++ b/tools/test/stress2/misc/force11.sh @@ -0,0 +1,100 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +set -u +backup=`dirname $diskimage`/force11.sh.diskimage.`date +%Y%m%dT%H%M%S` +log=/tmp/force11.sh.log +mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +truncate -s 10g $diskimage +mdconfig -a -t vnode -f $diskimage -u $mdstart +flags=$newfs_flags +[ `jot -r 1 0 1` -eq 1 ] && flags="-j" +echo "newfs $flags md$mdstart" +newfs $flags md$mdstart > /dev/null 2>&1 + +export TESTPROGS=`cd ..; find testcases/ -perm -1 -type f | \ + egrep -Ev "/run/|/badcode/|/pty/|/shm/|/socket/|sysctl|tcp|thr|udp|rename"` +export runRUNTIME=3m +export RUNDIR=$mntpoint/stressX +export CTRLDIR=$mntpoint/stressX.control +start=`date +%s` +while [ $((`date +%s` - start)) -lt $((15 * 60)) ]; do + mount /dev/md$mdstart $mntpoint + rm -fr $mntpoint/lost+found + chmod 777 $mntpoint + + su $testuser -c 'cd ..; ./testcases/run/run $TESTPROGS' > \ + /dev/null 2>&1 & + + sleep `jot -r 1 30 60` + while mdconfig -l | grep -q md$mdstart; do + mdconfig -d -u $mdstart -o force || sleep 1 + done + sleep 1 + ../tools/killall.sh + wait + dd if=$diskimage of=$backup bs=1m conv=sparse,sync status=none + sync; sleep .5; sync; sleep .5; sync + n=0 + while mount | grep $mntpoint | grep -q /dev/md; do + umount $mntpoint || sleep 1 + [ $((n += 1)) -gt 300 ] && { echo FAIL; exit 1; } + done + mdconfig -a -t vnode -f $diskimage -u $mdstart + c=0 + for i in `jot 5`; do + fsck_ffs -fyR /dev/md$mdstart > $log 2>&1; s=$? + grep -q CLEAN $log && grep -q "MODIFIED" $log && c=$((c+=1)) + grep -Eq "FILE SYSTEM WAS MODIFIED" $log || break + done + [ $c -gt 1 ] && + { echo "Note: FS marked clean+modified $c times out of $i fsck runs"; s=101; } + [ $s -ne 0 ] && break + grep -Eq "IS CLEAN|MARKED CLEAN" $log || { s=100; break; } + break # For now, only once +done +if [ $s -eq 0 ]; then + mount /dev/md$mdstart $mntpoint + cp -R /usr/include $mntpoint || s=1 + dd if=/dev/zero of=$mntpoint/big bs=1m count=10 status=none || s=2 + ls -lR $mntpoint > /dev/null || s=3 + find $mntpoint/* -delete || s=4 + umount $mntpoint + [ $s -eq 0 ] && + rm -f $diskimage $log $backup +else + tail -10 $log +fi +mdconfig -d -u $mdstart +[ -f $backup ] && xz -T0 $backup +exit $s diff --git a/tools/test/stress2/misc/force12.sh b/tools/test/stress2/misc/force12.sh new file mode 100755 index 000000000000..c030adb16d86 --- /dev/null +++ b/tools/test/stress2/misc/force12.sh @@ -0,0 +1,83 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# rename() livelock seen with a forced unmount of a FS +# https://people.freebsd.org/~pho/stress/log/log0375.txt + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg +echo "Known issue. Skipping ..."; exit 0 + +set -u +log=/tmp/force12.sh.log +mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 4g -u $mdstart +flags=$newfs_flags +[ `jot -r 1 0 1` -eq 1 ] && flags="-j" +echo "newfs $flags md$mdstart" +newfs $flags md$mdstart > /dev/null 2>&1 + +export TESTPROGS=' +testcases/dirnprename/dirnprename +testcases/dirrename/dirrename +testcases/fts/fts +testcases/mkdir/mkdir +testcases/rename/rename +testcases/rw/rw +testcases/swap/swap +' + +export runRUNTIME=3m +export RUNDIR=$mntpoint/stressX +export CTRLDIR=$mntpoint/stressX.control + +mount /dev/md$mdstart $mntpoint +chmod 777 $mntpoint +export dirnprenameLOAD=100 +export dirrenameLOAD=100 + +su $testuser -c 'cd ..; ./testcases/run/run $TESTPROGS' > \ + /dev/null 2>&1 & + +sleep `jot -r 1 60 180` +while mdconfig -l | grep -q md$mdstart; do + mdconfig -d -u $mdstart -o force || sleep 1 +done +sleep 1 +../tools/killall.sh +wait +n=0 +while mount | grep $mntpoint | grep -q /dev/md; do + umount $mntpoint || sleep 1 + [ $((n += 1)) -gt 30 ] && { echo FAIL; exit 1; } +done +mdconfig -d -u $mdstart > /dev/null 2>&1 +rm -f $log +exit 0 diff --git a/tools/test/stress2/misc/force13.sh b/tools/test/stress2/misc/force13.sh new file mode 100755 index 000000000000..ac32ee90e38c --- /dev/null +++ b/tools/test/stress2/misc/force13.sh @@ -0,0 +1,129 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Snapshot test + +# "panic: flush_pagedep_deps: failed to flush inodedep 0xfff..." seen: +# https://people.freebsd.org/~pho/stress/log/log0376.txt + +# watchdog fired: +# https://people.freebsd.org/~pho/stress/log/log0377.txt + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +set -u +log=/tmp/force13.sh.log +mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +truncate -s 10g $diskimage +mdconfig -a -t vnode -f $diskimage -u $mdstart +flags=$newfs_flags +[ `jot -r 1 0 1` -eq 1 ] && flags="-j" + +echo "newfs $flags md$mdstart" +newfs $flags md$mdstart > /dev/null 2>&1 + +# Exclude rename for now due to log0374.txt +export TESTPROGS=`cd ..; find testcases/ -perm -1 -type f | \ + egrep -Ev "/run/|/badcode/|/pty/|/shm/|/socket/|sysctl|tcp|thr|udp|rename"` +export runRUNTIME=3m +export RUNDIR=$mntpoint/stressX +export CTRLDIR=$mntpoint/stressX.control +start=`date +%s` +while [ $((`date +%s` - start)) -lt $((15 * 60)) ]; do + mount /dev/md$mdstart $mntpoint + rm -fr $mntpoint/lost+found + chmod 777 $mntpoint + + su $testuser -c 'cd ..; ./testcases/run/run $TESTPROGS' > \ + /dev/null 2>&1 & + + t=`jot -r 1 60 180` + start=`date +%s` + mkdir -p $mntpoint/.snap + for i in `jot 10`; do + rm -f $mntpoint/.snap/$i + mksnap_ffs $mntpoint $mntpoint/.snap/$i || + { ../tools/killall.sh; break; } + sleep `jot -r 1 1 5` + [ $((`date +%s` - start)) -ge $t ] && break + done & + sleep `jot -r 1 60 180` + while mdconfig -l | grep -q md$mdstart; do + mdconfig -d -u $mdstart -o force || sleep 1 + done + sleep 1 + ../tools/killall.sh + wait + n=0 + while mount | grep -q "on $mntpoint "; do + umount $mntpoint || sleep 1 + [ $((n += 1)) -gt 300 ] && { echo FAIL; exit 1; } + done + mdconfig -a -t vnode -f $diskimage -u $mdstart + c=0 + # Run fsck minimum two times + for i in `jot 5`; do + fsck_ffs -fy /dev/md$mdstart > $log 2>&1; s=$? + grep -q CLEAN $log && grep -q "MODIFIED" $log && c=$((c+=1)) + grep -Eq "FILE SYSTEM WAS MODIFIED" $log || break + done + [ $c -gt 1 ] && + { echo "Note: FS marked clean+modified $c times out of $i fsck runs"; s=101; } + [ $s -ne 0 ] && break + grep -Eq "IS CLEAN|MARKED CLEAN" $log || { s=102; break; } +done +[ $s -eq 101 ] && s=0 # Ignore CLEANish problem for now +if [ $s -eq 0 ]; then + mount /dev/md$mdstart $mntpoint + cp -R /usr/include $mntpoint + dd if=/dev/zero of=$mntpoint/big bs=1m count=10 status=none + find $mntpoint/* -delete + + # Check the snapshots + for f in $mntpoint/.snap/*; do + c=0 + for i in `jot 5`; do + echo "fsck_ffs -fy $f" + fsck_ffs -fy $f > $log 2>&1; s=$? + grep -q CLEAN $log && grep -q "MODIFIED" $log && c=$((c+=1)) + grep -Eq "FILE SYSTEM WAS MODIFIED" $log || break + done + [ $c -gt 1 ] && + { echo "Note: snapshot $i marked clean+modified $c times out of $i fsck runs"; s=201; } + [ $s -ne 0 ] && break + grep -Eq "IS CLEAN|MARKED CLEAN" $log || + { s=202; tail -10 $log; break; } + done + umount $mntpoint + mdconfig -d -u $mdstart + rm -f $diskimage $log +fi +exit $s diff --git a/tools/test/stress2/misc/force14.sh b/tools/test/stress2/misc/force14.sh new file mode 100755 index 000000000000..eec850c50891 --- /dev/null +++ b/tools/test/stress2/misc/force14.sh @@ -0,0 +1,119 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# SU+J Snapshot test with a 50G file system + +# "panic: handle_jwork: Unknown type jnewblk" seen: +# https://people.freebsd.org/~pho/stress/log/log0422.txt + +# "panic: flush_pagedep_deps: failed to flush inodedep..." seen: +# https://people.freebsd.org/~pho/stress/log/log0423.txt + +# "panic: softdep_deallocate_dependencies: dangling deps" seen: +# https://people.freebsd.org/~pho/stress/log/log0424.txt + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +set -u +log=/tmp/force14.sh.log +mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +truncate -s 50g $diskimage +mdconfig -a -t vnode -f $diskimage -u $mdstart +flags="-j" + +newfs $flags md$mdstart > /dev/null 2>&1 + +# Exclude rename for now due to log0374.txt +export TESTPROGS=`cd ..; find testcases/ -perm -1 -type f | \ + egrep -Ev "/run/|/badcode/|/pty/|/shm/|/socket/|sysctl|tcp|thr|udp|rename"` +export runRUNTIME=3m +export RUNDIR=$mntpoint/stressX +export CTRLDIR=$mntpoint/stressX.control +start=`date +%s` +while [ $((`date +%s` - start)) -lt $((15 * 60)) ]; do + mount /dev/md$mdstart $mntpoint + rm -fr $mntpoint/lost+found + chmod 777 $mntpoint + + su $testuser -c 'cd ..; ./testcases/run/run $TESTPROGS' > \ + /dev/null 2>&1 & + + t=`jot -r 1 60 180` + st=`date +%s` + mkdir -p $mntpoint/.snap + for i in `jot 10`; do + rm -f $mntpoint/.snap/$i + mksnap_ffs $mntpoint $mntpoint/.snap/$i || + { ../tools/killall.sh; break; } + sleep `jot -r 1 1 5` + [ $((`date +%s` - st)) -ge $t ] && break + done & + sleep `jot -r 1 60 180` + while mdconfig -l | grep -q md$mdstart; do + mdconfig -d -u $mdstart -o force || sleep 1 + done + sleep 1 + ../tools/killall.sh + wait + n=0 + while mount | grep -q "on $mntpoint "; do + umount $mntpoint || sleep 1 + [ $((n += 1)) -gt 300 ] && { echo FAIL; exit 1; } + done + mdconfig -a -t vnode -f $diskimage -u $mdstart + c=0 + # Process the journal + fsck_ffs -fy /dev/md$mdstart > $log 2>&1; s=$? + grep 'INTERNAL ERROR: GOT TO reply' $log + for i in `jot 4`; do + [ $i -ne 1 ] && + echo "fsck_ffs -fy /dev/md$mdstart" + fsck_ffs -fy /dev/md$mdstart > $log 2>&1; s=$? + grep 'INTERNAL ERROR: GOT TO reply' $log + grep -q CLEAN $log && c=$((c+=1)) + grep -Eq "WAS MODIFIED" $log || break + done + [ $c -gt 1 ] && + { echo "Note: FS marked clean+modified $c times out of $i fsck runs"; s=101; } + [ $s -ne 0 ] && break + grep -Eq "IS CLEAN|MARKED CLEAN" $log || { s=102; break; } +done +if [ $s -eq 0 ]; then + mount /dev/md$mdstart $mntpoint + cp -R /usr/include $mntpoint + dd if=/dev/zero of=$mntpoint/big bs=1m count=10 status=none + find $mntpoint/* -delete + + umount $mntpoint + mdconfig -d -u $mdstart + rm -f $diskimage $log +fi +exit $s diff --git a/tools/test/stress2/misc/force15.sh b/tools/test/stress2/misc/force15.sh new file mode 100755 index 000000000000..955025cd98c6 --- /dev/null +++ b/tools/test/stress2/misc/force15.sh @@ -0,0 +1,113 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# FFS+SU with snapshots and forced unmounts + +# "panic: flush_pagedep_deps: failed to flush inodedep ..." seen +# https://people.freebsd.org/~pho/stress/log/log0427.txt + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +prog=$(basename "$0" .sh) +diskimage=/tmp/diskimage +log=/tmp/$prog.log +mdstart=10 +mntpoint=/mnt +newfs_flags="-U" + +set -u +mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +dd if=/dev/zero of=$diskimage bs=1m count=1k status=none +mdconfig -a -t vnode -f $diskimage -u $mdstart +flags="-U" + +newfs $flags md$mdstart > /dev/null 2>&1 + +start=`date +%s` +while [ $((`date +%s` - start)) -lt $((5 * 60)) ]; do + mount /dev/md$mdstart $mntpoint + rm -fr $mntpoint/lost+found + + jot 10 | xargs -I% mkdir -p $mntpoint/% + n=5000 + for j in `jot 10`; do + ( + jot $n | xargs -P0 -I% touch $mntpoint/$j/% + jot $n | xargs -P0 -I% rm $mntpoint/$j/% + ) > /dev/null 2>&1 & + done + + sleep `jot -r 1 5 20` + t=`jot -r 1 60 180` + st=`date +%s` + mkdir -p $mntpoint/.snap + for i in `jot 10`; do + rm -f $mntpoint/.snap/$i + mksnap_ffs $mntpoint $mntpoint/.snap/$i > /dev/null 2>&1 || break + sleep `jot -r 1 1 5` + [ $((`date +%s` - st)) -ge $t ] && break + done & + sleep `jot -r 1 2 5` + while mdconfig -l | grep -q md$mdstart; do + mdconfig -d -u $mdstart -o force || sleep 1 + done + sleep 1 + wait + n=0 + while mount | grep -q "on $mntpoint "; do + umount $mntpoint || sleep 1 + [ $((n += 1)) -gt 300 ] && { echo FAIL; exit 1; } + done + mdconfig -a -t vnode -f $diskimage -u $mdstart + c=0 + for i in `jot 5`; do + [ $i -ne 1 ] && + echo "$i: fsck_ffs -fy /dev/md$mdstart" + fsck_ffs -fy /dev/md$mdstart > $log 2>&1; s=$? + grep 'INTERNAL ERROR: GOT TO reply' $log + grep -q CLEAN $log && grep -q MODIFIED && c=$((c+=1)) + grep -Eq "WAS MODIFIED" $log || break + done + [ $c -gt 1 ] && + { echo "Note: FS marked clean+modified $c times out of $i fsck runs"; s=101; } + [ $s -ne 0 ] && break + grep -Eq "IS CLEAN|MARKED CLEAN" $log || { s=102; break; } +done +if [ $s -eq 0 ]; then + mount /dev/md$mdstart $mntpoint + cp -R /usr/include $mntpoint + dd if=/dev/zero of=$mntpoint/big bs=1m count=10 status=none + find $mntpoint/* -delete + + umount $mntpoint + mdconfig -d -u $mdstart + rm -f $diskimage $log +fi +exit $s diff --git a/tools/test/stress2/misc/force2.sh b/tools/test/stress2/misc/force2.sh index 35e448afbbba..cd947ef7d13d 100755 --- a/tools/test/stress2/misc/force2.sh +++ b/tools/test/stress2/misc/force2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/force3.sh b/tools/test/stress2/misc/force3.sh index 4bfb0011cbef..2fc947bb0af6 100755 --- a/tools/test/stress2/misc/force3.sh +++ b/tools/test/stress2/misc/force3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/force4.sh b/tools/test/stress2/misc/force4.sh index 72932aec1fe6..69bbb7f4c978 100755 --- a/tools/test/stress2/misc/force4.sh +++ b/tools/test/stress2/misc/force4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/force5.sh b/tools/test/stress2/misc/force5.sh index c0aa6436fc1f..263761211148 100755 --- a/tools/test/stress2/misc/force5.sh +++ b/tools/test/stress2/misc/force5.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/force6.sh b/tools/test/stress2/misc/force6.sh index 5c7d508241ec..22b362d51573 100755 --- a/tools/test/stress2/misc/force6.sh +++ b/tools/test/stress2/misc/force6.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/force7.sh b/tools/test/stress2/misc/force7.sh index 0f2e6e9a0e9e..e828b0090f7b 100755 --- a/tools/test/stress2/misc/force7.sh +++ b/tools/test/stress2/misc/force7.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/force8.sh b/tools/test/stress2/misc/force8.sh index 77a8e6fd97bf..26361890f02f 100755 --- a/tools/test/stress2/misc/force8.sh +++ b/tools/test/stress2/misc/force8.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # diff --git a/tools/test/stress2/misc/force9.sh b/tools/test/stress2/misc/force9.sh index a62e00242a67..54a17f20e036 100755 --- a/tools/test/stress2/misc/force9.sh +++ b/tools/test/stress2/misc/force9.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # @@ -34,9 +34,12 @@ # "panic: softdep_update_inodeblock inconsistent ip ..." seen: # https://people.freebsd.org/~pho/stress/log/log0184.txt +# Watchdog fired: https://people.freebsd.org/~pho/stress/log/log0374.txt + [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg +set -u log=/tmp/force7.sh.log mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart @@ -46,22 +49,22 @@ flags=$newfs_flags echo "newfs $flags md$mdstart" newfs $flags md$mdstart > /dev/null 2>&1 +# Exclude rename for now due to log0374.txt export TESTPROGS=`cd ..; find testcases/ -perm -1 -type f | \ - egrep -Ev "/run/|/badcode/|/pty/|/shm/|/socket/|sysctl|tcp|thr|udp"` + egrep -Ev "/run/|/badcode/|/pty/|/shm/|/socket/|sysctl|tcp|thr|udp|rename"` export runRUNTIME=3m export RUNDIR=$mntpoint/stressX +export CTRLDIR=$mntpoint/stressX.control start=`date +%s` while [ $((`date +%s` - start)) -lt $((15 * 60)) ]; do mount /dev/md$mdstart $mntpoint rm -fr $mntpoint/lost+found chmod 777 $mntpoint - echo "Start tests" su $testuser -c 'cd ..; ./testcases/run/run $TESTPROGS' > \ /dev/null 2>&1 & sleep `jot -r 1 60 180` - echo "Force destroy MD disk" while mdconfig -l | grep -q md$mdstart; do mdconfig -d -u $mdstart -o force || sleep 1 done @@ -74,9 +77,17 @@ while [ $((`date +%s` - start)) -lt $((15 * 60)) ]; do [ $((n += 1)) -gt 300 ] && { echo FAIL; exit 1; } done mdconfig -a -t vnode -f $diskimage -u $mdstart - fsck_ffs -fyR /dev/md$mdstart > $log 2>&1; s=$? + c=0 + # Run fsck minimum two times + for i in `jot 5`; do + fsck_ffs -fy /dev/md$mdstart > $log 2>&1; s=$? + grep -q CLEAN $log && grep -q "MODIFIED" $log && c=$((c+=1)) + grep -Eq "FILE SYSTEM WAS MODIFIED" $log || break + done + [ $c -gt 1 ] && + { echo "Note: FS marked clean+modified $c times out of $i fsck runs"; s=101; } [ $s -ne 0 ] && break - grep -Eq "IS CLEAN|MARKED CLEAN" $log || { s=100; break; } + grep -Eq "IS CLEAN|MARKED CLEAN" $log || { s=102; break; } done if [ $s -eq 0 ]; then mount /dev/md$mdstart $mntpoint @@ -87,6 +98,6 @@ if [ $s -eq 0 ]; then mdconfig -d -u $mdstart rm -f $diskimage $log else - cat $log + tail -10 $log fi exit $s diff --git a/tools/test/stress2/misc/fork2.sh b/tools/test/stress2/misc/fork2.sh new file mode 100755 index 000000000000..4dbe2de3f6d1 --- /dev/null +++ b/tools/test/stress2/misc/fork2.sh @@ -0,0 +1,134 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Regression test for D36069 +# thread_create(): call cpu_copy_thread() after td_pflags is zeroed + +# Seen before fix: +# cc: error: unable to execute command: Segmentation fault (core dumped) +# cc: error: linker command failed due to signal (use -v to see invocation) +# Aug 9 18:27:47 freebsd-vm kernel: pid 32094 (ld.lld), jid 0, uid 0: exited on signal 11 (core dumped) + +. ../default.cfg +[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 + +dir=/tmp +odir=`pwd` +cd $dir +sed '1,/^EOF/d' < $odir/$0 > $dir/fork2.c +mycc -o fork2 -Wall -Wextra -O0 -g fork2.c || exit 1 +cd $odir + +set -e +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 2g -u $mdstart +newfs $newfs_flags md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +set +e + +cd $mntpoint +$dir/fork2 +s=$? +pkill fork2 +[ -f fork2.core -a $s -eq 0 ] && + { ls -l fork2.core; mv fork2.core $dir; s=1; } +cd $odir + +for i in `jot 6`; do + mount | grep -q "on $mntpoint " || break + umount $mntpoint && break || sleep 10 + [ $i -eq 6 ] && + { echo FATAL; fstat -mf $mntpoint; exit 1; } +done +mdconfig -d -u $mdstart +cd $dir +mycc -o $dir/fork2 -Wall -Wextra -O0 -g $dir/fork2.c; s=$? +rm -rf $dir/fork2 $dir/fork2.c +exit $s + +EOF +#include <sys/param.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <machine/atomic.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +static volatile u_int *share; + +#define MX 5000 +#define RUNTIME (1 * 60) +#define SYNC 0 + +int +main(void) +{ + pid_t pid; + size_t len; + time_t start; + int n; + + len = PAGE_SIZE; + if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) + err(1, "mmap"); + + n = 0; + signal(SIGCHLD, SIG_IGN); + start = time(NULL); + while ((time(NULL) - start) < RUNTIME) { + while ((atomic_load_int(&share[SYNC])) > MX) + usleep(100); + n++; + pid = fork(); + if (pid == -1) + err(1, "fork)"); + if (pid == 0) { + atomic_add_int(&share[SYNC], 1); + while (atomic_load_int(&share[SYNC]) <= MX) + usleep(10000); + usleep(arc4random() % 1000); + atomic_add_int(&share[SYNC], -1); + raise(SIGHUP); + _exit(0); + } + } + atomic_add_int(&share[SYNC], MX * 2); + fprintf(stderr, "%d fork() calls\n", n); +} diff --git a/tools/test/stress2/misc/forkbomb.sh b/tools/test/stress2/misc/forkbomb.sh index 73a3c5f37fe2..caaaa27db281 100755 --- a/tools/test/stress2/misc/forkbomb.sh +++ b/tools/test/stress2/misc/forkbomb.sh @@ -81,7 +81,7 @@ volatile u_int *share; #define R4 4 /* fork failed */ //#define DEBUG -#define MXFAIL 100 +#define MXFAIL 2 #define MAXPROC 40000 /* Arbitrary cap */ #define PARALLEL 200 @@ -93,7 +93,7 @@ test(void) alarm(1200); atomic_add_int(&share[R1], 1); while (share[R1] != PARALLEL) - ; + usleep(100); atomic_add_int(&share[R2], 1); for (;;) { @@ -103,6 +103,7 @@ test(void) if ((r = fork()) == -1) { atomic_add_int(&share[R4], 1); atomic_add_int(&share[R2], -1); + usleep(arc4random() % 100000); break; } } diff --git a/tools/test/stress2/misc/fsck.sh b/tools/test/stress2/misc/fsck.sh index 826c31f733c3..4af41df037e9 100755 --- a/tools/test/stress2/misc/fsck.sh +++ b/tools/test/stress2/misc/fsck.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # @@ -49,9 +49,12 @@ u2=$((mdstart + 1)) mp1=${mntpoint}$u1 mp2=${mntpoint}$u2 mkdir -p $mp1 $mp2 -log=$mp1/fsck.sh.log -diskimage=$mp1/fsck.sh.diskimage + backup=/tmp/fsck.sh.diskimage.`date +%Y%m%dT%H%M%S`.gz +core=/tmp/fsck.sh.core.`date +%Y%m%dT%H%M%S` +diskimage=$mp1/fsck.sh.diskimage +log=$mp1/fsck.sh.log + asbs=0 cleans=0 reruns=0 @@ -71,6 +74,7 @@ mount /dev/md$u1 $mp1 [ -c /dev/md$u2 ] && mdconfig -d -u $u2 dd if=/dev/zero of=$diskimage bs=$max count=1 status=none mdconfig -a -t vnode -f $diskimage -u $u2 +[ "$newfs_flags" = "-U" ] && [ `jot -r 1 0 1` -eq 1 ] && newfs_flags="-j" backups=`newfs -N $newfs_flags md$u2 | grep -A1 "super-block backups" | \ tail -1 | sed 's/,//g'` newfs $newfs_flags md$u2 > /dev/null @@ -86,13 +90,13 @@ chk() { waccess=0 fsck_ffs -fy $1 > $log 2>&1 r=$? - if grep -qE "Cannot find file system superblock|Superblock check-hash failed" $log; then + if grep -qiE "super-?block.*failed" $log; then for b in $backups; do echo "Using alternate SB $b" asbs=$((asbs + 1)) fsck_ffs -b $b -fy $1 > $log 2>&1 r=$? - grep -qE "Cannot find file system superblock|Superblock check-hash failed" $log || + grep -qiE "super-?block.*failed" $log || break done usedasb=1 @@ -144,7 +148,8 @@ while [ $((`date +%s` - start)) -lt 60 ]; do break done mount | grep -q "on $mp2 " && umount $mp2 -mdconfig -d -u $u2 || exit 1 +mdconfig -l | grep -q "md$u2" && + mdconfig -d -u $u2 echo "$cleans cleans, $reruns reruns, $asbs alternate SBs." if [ $clean -ne 1 ]; then @@ -153,8 +158,9 @@ if [ $clean -ne 1 ]; then cp -v $log /tmp [ $s -eq 0 ] && s=106 fi -echo * | grep -q core && { ls -l *.core; cp $log /tmp; exit 106; } || - rm -f $backup +[ -f fsck_ffs.core ] && + mv fsck_ffs.core $core +[ $s -eq 0 ] && rm -f $backup cd /tmp umount $mp1 mdconfig -d -u $u1 diff --git a/tools/test/stress2/misc/fsck10.sh b/tools/test/stress2/misc/fsck10.sh new file mode 100755 index 000000000000..33ad35f65f11 --- /dev/null +++ b/tools/test/stress2/misc/fsck10.sh @@ -0,0 +1,172 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Variation of fsck9.sh with smaller disk size and newfs options '', 'U' and 'O1' +# fsck_ffs core dump seen + +. ../default.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +cc -o /tmp/flip -Wall -Wextra -O2 ../tools/flip.c || exit 1 + +set -e +prog=$(basename "$0" .sh) +u1=$mdstart +u2=$((mdstart + 1)) +mp1=${mntpoint}$u1 +mp2=${mntpoint}$u2 +mkdir -p $mp1 $mp2 +log=$mp1/$prog.sh.log +diskimage=$mp1/$prog.sh.diskimage +backup=/tmp/$prog.sh.diskimage.`date +%Y%m%dT%H%M%S`.gz +cleans=0 +reruns=0 + +# Pick a random newfs flag +newfs_flags=$(echo "" "-U" "-O1" | awk -v N=`jot -r 1 1 3` '{print $N}') +[ $# -eq 1 ] && newfs_flags="$1" # or use script argument +max=$((512 * 1024)) + +mount | grep "on $mp1 " | grep -q /dev/md && umount -f $mp1 +[ -c /dev/md$u1 ] && mdconfig -d -u $u1 +mdconfig -a -t swap -s 1g -u $u1 +newfs $newfs_flags -n /dev/md$u1 > /dev/null +mount /dev/md$u1 $mp1 + +[ -c /dev/md$u2 ] && mdconfig -d -u $u2 +dd if=/dev/zero of=$diskimage bs=$max count=1 status=none +mdconfig -a -t vnode -f $diskimage -u $u2 +backups=`newfs -N $newfs_flags md$u2 | grep -A1 "super-block backups" | \ + tail -1 | sed 's/,//g'` +echo "newfs $newfs_flags -n md$u2" +newfs $newfs_flags -n md$u2 > /dev/null +[ "$newfs_flags" = "" ] && tunefs -n disable md$u2 +set +e + +chk() { + local i + + clean=0 + rerun=0 + fsck_ffs -fy $1 > $log 2>&1 + r=$? + if grep -qiE "super-?block.*failed" $log; then + for b in $backups; do + echo "fsck_ffs -b $b -fy $1" + fsck_ffs -b $b -fy $1 > $log 2>&1 + r=$? + grep -qiE "super-?block.*failed" $log || + break + echo "Checking next SB" + done + usedasb=1 + else + usedasb=0 + fi + LANG=C egrep -q "[A-Z][A-Z]" $log && clean=0 + grep -Eq "IS CLEAN|MARKED CLEAN" $log && clean=1 + grep -q RERUN $log && rerun=1 + [ $r -ne 0 -a $clean -eq 1 ] && echo "Exit code $r w/ clean == 1" +} + +cd $mp1 +clean=0 +errors=0 +s=0 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 300 ]; do + mount /dev/md$u2 $mp2 || break + if ! ls -lR $mp2 > /dev/null; then + s=102 + echo "ls failed"; grep "core dumped" /var/log/messages | tail -1 + break + fi + rm -f $mp2/???????? + touch $mp2/`jot -rc 8 a z | tr -d '\n'` + mkdir -p $mp2/dir/dir/dir/dir + echo "abc" > $mp2/dir/dir/dir/dir/f + while mount | grep -q "on $mp2 "; do umount $mp2; done + echo * | grep -q core && break + mdconfig -d -u $u2 + + # Introduce 5 random single bit errors to the file system image + /tmp/flip -n 5 $diskimage + + sync; sleep .1 + if [ `stat -f%z $diskimage` -gt $max ]; then + ls -lh $diskimage + truncate -s $max $diskimage + else + gzip < $diskimage > $backup + fi + fsync $backup + sync; sleep .1 + + for i in `jot 5`; do + [ $i -gt 2 ] && echo "fsck run #$i" + chk $diskimage + [ $rerun -eq 1 ] && { reruns=$((reruns + 1)); continue; } + [ $clean -eq 1 ] && { cleans=$((cleans + 1)); break; } + if [ -f fsck_ffs.core ]; then + tstamp=`date +%Y%m%dT%H%M%S` + gzip < $backup > /tmp/fsck_ffs.core.diskimage.$tstamp + gzip < fsck_ffs.core > /tmp/fsck_ffs.core.$tstamp + break 2 + fi + done + if [ $clean -eq 1 ]; then + fsck_ffs -fy $diskimage > $log 2>&1 + if grep -q MODIFIED $log; then + echo "*** fsck of \"clean\" FS found more issues:" + cat $log + errors=$((errors + 1)) + s=1 + break + fi + fi + [ $clean -ne 1 ] && break + mdconfig -a -t vnode -f $diskimage -u $u2 +done +for i in `jot 5`; do + mount | grep -q "on $mp2 " || break + umount $mp2 && break + sleep 2 +done +mdconfig -l | grep -q $u2 && mdconfig -d -u $u2 + +[ $s -eq 0 ] && rm -f $backup || echo "Preserved $backup due to status code $s" +cd /tmp +for i in `jot 5`; do + umount $mp1 && break + sleep 2 +done +mdconfig -d -u $u1 +rm -f /tmp/flip +exit $s diff --git a/tools/test/stress2/misc/fsck11.sh b/tools/test/stress2/misc/fsck11.sh new file mode 100755 index 000000000000..de4cf2536dad --- /dev/null +++ b/tools/test/stress2/misc/fsck11.sh @@ -0,0 +1,171 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Demonstrate how the "CLEAN" message and the exit code can be misleading + +# "panic: softdep_update_inodeblock inconsistent ip ..." seen: +# https://people.freebsd.org/~pho/stress/log/log0421.txt +# https://people.freebsd.org/~pho/fsck11.sh.diskimage.20230228T064402.gz + +. ../default.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +cc -o /tmp/flip -Wall -Wextra -O2 ../tools/flip.c || exit 1 + +set -e +prog=$(basename "$0" .sh) +u1=$mdstart +u2=$((mdstart + 1)) +mp1=${mntpoint}$u1 +mp2=${mntpoint}$u2 +mkdir -p $mp1 $mp2 +log=$mp1/$prog.sh.log +diskimage=$mp1/$prog.sh.diskimage +backup=/tmp/$prog.sh.diskimage.`date +%Y%m%dT%H%M%S`.gz +cleans=0 +reruns=0 + +# Pick a random newfs flag +newfs_flags=$(echo "" "-U" "-O1" | awk -v N=`jot -r 1 1 3` '{print $N}') +[ $# -eq 1 ] && newfs_flags="$1" # or use script argument +max=$((2 * 1024 * 1024)) +[ "$newfs_flags" = "-j" ] && max=$((20 * 1024 * 1024)) # Make room for the journal file + +mount | grep "on $mp1 " | grep -q /dev/md && umount -f $mp1 +[ -c /dev/md$u1 ] && mdconfig -d -u $u1 +mdconfig -a -t swap -s 1g -u $u1 +newfs $newfs_flags -n /dev/md$u1 > /dev/null +mount /dev/md$u1 $mp1 + +[ -c /dev/md$u2 ] && mdconfig -d -u $u2 +dd if=/dev/zero of=$diskimage bs=$max count=1 status=none +mdconfig -a -t vnode -f $diskimage -u $u2 +backups=`newfs -N $newfs_flags md$u2 | grep -A1 "super-block backups" | \ + tail -1 | sed 's/,//g'` +echo "newfs $newfs_flags -n md$u2" +newfs $newfs_flags -n md$u2 > /dev/null +[ "$newfs_flags" = "" ] && tunefs -n disable md$u2 +set +e + +chk() { + local i + + clean=0 + rerun=0 + fsck_ffs -fy $1 > $log 2>&1 + r=$? + if grep -qiE "super-?block.*failed" $log; then + for b in $backups; do + echo "fsck_ffs -b $b -fy $1" + fsck_ffs -b $b -fy $1 > $log 2>&1 + r=$? + grep -qiE "super-?block.*failed" $log || + break + echo "Checking next SB" + done + usedasb=1 + else + usedasb=0 + fi + LANG=C egrep -q "[A-Z][A-Z]" $log && clean=0 + grep -Eq "IS CLEAN|MARKED CLEAN" $log && clean=1 + grep -q RERUN $log && rerun=1 + [ $r -ne 0 -a $clean -eq 1 ] && echo "Exit code $r w/ clean == 1" +} + +cd $mp1 +clean=0 +errors=0 +s=0 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 300 ]; do + mount /dev/md$u2 $mp2 || break + if ! ls -lR $mp2 > /dev/null; then + s=102 + echo "ls failed"; grep "core dumped" /var/log/messages | tail -1 + break + fi + + find $mp2 -type f | xargs cat > /dev/null + for j in `jot 9`; do + rm -rf $mp2/$j + mkdir $mp2/$j + jot 10 | xargs -P0 -I% cp /etc/group $mp2/$j/% + done 2>/dev/null + + while mount | grep -q "on $mp2 "; do umount $mp2; done + echo * | grep -q core && break + mdconfig -d -u $u2 + + # Introduce 5 random single bit errors to the file system image + /tmp/flip -n 5 $diskimage + + if [ `stat -f%z $diskimage` -gt $max ]; then + ls -lh $diskimage + truncate -s $max $diskimage + else + gzip < $diskimage > $backup + fi + fsync $backup + sync; sleep 1 + + [ "$newfs_flags" = "-j" ] && + fsck -fy $diskimage > $log 2>&1 # process the journal file + for i in `jot 5`; do + [ $i -gt 2 ] && echo "fsck run #$i" + chk $diskimage + [ $rerun -eq 1 ] && { reruns=$((reruns + 1)); continue; } + [ $clean -eq 1 ] && { cleans=$((cleans + 1)); break; } + if [ -f fsck_ffs.core ]; then + tstamp=`date +%Y%m%dT%H%M%S` + gzip < $backup > /tmp/fsck_ffs.core.diskimage.$tstamp + gzip < fsck_ffs.core > /tmp/fsck_ffs.core.$tstamp + break 2 + fi + done + [ $clean -ne 1 ] && { s=99; break; } # broken image? + mdconfig -a -t vnode -f $diskimage -u $u2 +done +for i in `jot 5`; do + mount | grep -q "on $mp2 " || break + umount $mp2 && break + sleep 2 +done +mdconfig -l | grep -q $u2 && mdconfig -d -u $u2 + +[ $s -eq 0 ] && rm -f $backup || echo "Preserved $backup due to status code $s" +cd /tmp +for i in `jot 5`; do + umount $mp1 && break + sleep 2 +done +mdconfig -d -u $u1 +rm -f /tmp/flip +exit $s diff --git a/tools/test/stress2/misc/fsck12.sh b/tools/test/stress2/misc/fsck12.sh new file mode 100755 index 000000000000..da4629991705 --- /dev/null +++ b/tools/test/stress2/misc/fsck12.sh @@ -0,0 +1,175 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# "panic: ffs_copyonwrite: bad copy block" seen: +# Hunt for fsck_ffs's INTERNAL ERROR message + +# https://people.freebsd.org/~pho/stress/log/log0426.txt + +. ../default.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +cc -o /tmp/flip -Wall -Wextra -O2 ../tools/flip.c || exit 1 + +set -e +prog=$(basename "$0" .sh) +u1=$mdstart +u2=$((mdstart + 1)) +mp1=${mntpoint}$u1 +mp2=${mntpoint}$u2 +mkdir -p $mp1 $mp2 +log=$mp1/$prog.sh.log +diskimage=$mp1/$prog.sh.diskimage +backup=/tmp/$prog.sh.diskimage.`date +%Y%m%dT%H%M%S`.gz +cleans=0 +reruns=0 + +mount | grep "on $mp1 " | grep -q /dev/md && umount -f $mp1 +[ -c /dev/md$u1 ] && mdconfig -d -u $u1 +mdconfig -a -t swap -s 1g -u $u1 +newfs $newfs_flags -n /dev/md$u1 > /dev/null +mount /dev/md$u1 $mp1 + +newfs_flags='-j' +[ $# -eq 1 ] && newfs_flags="$1" # or use script argument +max=$((2 * 1024 * 1024)) +[ "$newfs_flags" = "-j" ] && max=$((20 * 1024 * 1024)) # Make room for the journal file + +[ -c /dev/md$u2 ] && mdconfig -d -u $u2 +dd if=/dev/zero of=$diskimage bs=$max count=1 status=none +mdconfig -a -t vnode -f $diskimage -u $u2 +backups=`newfs -N $newfs_flags md$u2 | grep -A1 "super-block backups" | \ + tail -1 | sed 's/,//g'` +echo "newfs $newfs_flags md$u2" +newfs $newfs_flags md$u2 > /dev/null +set +e + +chk() { + local i + + clean=0 + rerun=0 + fsck_ffs -fy $1 > $log 2>&1 + r=$? + grep "GOT TO reply" $log && exit 1 + if grep -qiE "super-?block.*failed" $log; then + for b in $backups; do + echo "fsck_ffs -b $b -fy $1" + fsck_ffs -b $b -fy $1 > $log 2>&1 + r=$? + grep "GOT TO reply" $log && exit 1 + grep -qiE "super-?block.*failed" $log || + break + echo "Checking next SB" + done + usedasb=1 + else + usedasb=0 + fi + LANG=C egrep -q "[A-Z][A-Z]" $log && clean=0 + grep -Eq "IS CLEAN|MARKED CLEAN" $log && clean=1 + grep -q RERUN $log && rerun=1 + [ $r -ne 0 -a $clean -eq 1 ] && echo "Exit code $r w/ clean == 1" +} + +cd $mp1 +clean=0 +errors=0 +s=0 +sno=0 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 300 ]; do + mount /dev/md$u2 $mp2 || break + if ! ls -lR $mp2 > /dev/null; then + s=102 + echo "ls failed"; grep "core dumped" /var/log/messages | tail -1 + break + fi + mkdir -p $mp2/d/d/d/d/d + cp /etc/group $mp2/d/d/d/d/d/f + for i in `jot 20`; do + cp -r $mp2/d $i + done + + rm -f $mp2/.snap/$sno + mksnap_ffs $mp2 $mp2/.snap/$sno & + sno=$(((sno + 1) % 10)) + + sleep 1 + rm -rf $mp/? + wait + while mount | grep -q "on $mp2 "; do umount $mp2; done + echo * | grep -q core && break + mdconfig -d -u $u2 + + # Introduce 5 random single bit errors to the file system image + /tmp/flip -n 5 $diskimage + + if [ `stat -f%z $diskimage` -gt $max ]; then + ls -lh $diskimage + truncate -s $max $diskimage + else + gzip < $diskimage > $backup + fi + fsync $backup + sync; sleep 1 + + [ $newfs_flags = "-j" ] && + fsck -fy $diskimage > $log 2>&1 # process the journal file + for i in `jot 5`; do + [ $i -gt 2 ] && echo "fsck run #$i" + chk $diskimage + [ $rerun -eq 1 ] && { reruns=$((reruns + 1)); continue; } + grep -q "MODIFIED" $log && continue # For now, do not trust CLEAN + [ $clean -eq 1 ] && { cleans=$((cleans + 1)); break; } + if [ -f fsck_ffs.core ]; then + s=1 + break 2 + fi + done + [ $clean -ne 1 ] && { s=99; break; } # broken image? + mdconfig -a -t vnode -f $diskimage -u $u2 +done +for i in `jot 5`; do + mount | grep -q "on $mp2 " || break + umount $mp2 && break + sleep 2 +done +mdconfig -l | grep -q $u2 && mdconfig -d -u $u2 + +[ $s -eq 0 ] && rm -f $backup || echo "Preserved $backup due to status code $s" +cd /tmp +for i in `jot 5`; do + umount $mp1 && break + sleep 2 +done +mdconfig -d -u $u1 +rm -f /tmp/flip +exit $s diff --git a/tools/test/stress2/misc/fsck13.sh b/tools/test/stress2/misc/fsck13.sh new file mode 100755 index 000000000000..3b8dc64d12b9 --- /dev/null +++ b/tools/test/stress2/misc/fsck13.sh @@ -0,0 +1,153 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# fsck_ffs(8) disk image fuzz test. +# Test without mount(8) and umount(8) + +. ../default.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +cc -o /tmp/flip -Wall -Wextra -O2 ../tools/flip.c || exit 1 + +# Disable the calls to sync(2) in fsck_ffs(8) to speed up the test +echo 'int sync(void) { return (0); }' > /tmp/fsck_preload.c +mycc -o /tmp/fsck_preload.so -shared -fpic /tmp/fsck_preload.c || exit 1 +rm /tmp/fsck_preload.c + +set -eu +u1=$mdstart +u2=$((mdstart + 1)) +mp1=${mntpoint}$u1 +prog=$(basename "$0" .sh) +mkdir -p $mp1 + +max=$((2 * 1024 * 1024)) # Two alternate super blocks @ 192 and 2240 +i=`jot -r 1 1 3` +[ $i -eq 1 ] && flags="-O2" +[ $i -eq 2 ] && flags="-U" +[ $i -eq 3 ] && { flags="-j"; max=$((8 * 1024 * 1024)); } + +backup=$mp1/$prog.diskimage.$flags.`date +%Y%m%dT%H%M%S` +core=/tmp/$prog.core.`date +%Y%m%dT%H%M%S` +diskimage=$mp1/$prog.diskimage +log=$mp1/$prog.log + +asbs=0 +cleans=0 +reruns=0 +waccess=0 + +set +e +mount | grep "on $mp1 " | grep -q /dev/md && umount -f $mp1 +[ -c /dev/md$u1 ] && mdconfig -d -u $u1 +mdconfig -a -t swap -s 10g -u $u1 +newfs $newfs_flags /dev/md$u1 > /dev/null +mount /dev/md$u1 $mp1 + +[ -c /dev/md$u2 ] && mdconfig -d -u $u2 +dd if=/dev/zero of=$diskimage bs=$max count=1 status=none +mdconfig -a -t vnode -f $diskimage -u $u2 +backups=`newfs -N $flags md$u2 | grep -A1 "super-block backups" | \ + tail -1 | sed 's/,//g'` +echo "newfs $flags /dev/md$u2" +newfs $flags md$u2 > /dev/null +[ "$newfs_flags" = "" ] && tunefs -n disable md$u2 +mdconfig -d -u $u2 + +chk() { + local i + + clean=0 + rerun=0 + waccess=0 + LD_PRELOAD=/tmp/fsck_preload.so \ + timeout 2m fsck_ffs -fy $1 > $log 2>&1 + r=$? + if grep -qiE "super-?block.*failed" $log; then + for b in $backups; do + asbs=$((asbs + 1)) + LD_PRELOAD=/tmp/fsck_preload.so \ + timeout 2m fsck_ffs -b $b -fy $1 > $log 2>&1 + r=$? + grep -qiE "super-?block.*failed" $log || + break + done + usedasb=1 + else + usedasb=0 + fi + LANG=C egrep -q "[A-Z][A-Z]" $log && clean=0 + grep -Eq "IS CLEAN|MARKED CLEAN" $log && clean=1 + # For now regard a "was modified" as a cause for a rerun, + # disregarding "clean" claim. + grep -Eq "WAS MODIFIED" $log && rerun=1 + grep -q RERUN $log && rerun=1 + grep -q "NO WRITE ACCESS" $log && waccess=1 + [ $r -ne 0 -a $clean -eq 1 ] && echo "Exit code $r w/ clean == 1" +} + +cd $mp1 +s=0 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 60 ]; do + /tmp/flip -n 50 $diskimage + + cp $diskimage $backup + + for i in `jot 10`; do + chk $diskimage + [ $i -eq 1 -a "$flags" = "-j" ] && continue # First run processes the journal + [ $rerun -eq 1 ] && { reruns=$((reruns + 1)); continue; } + [ $clean -eq 1 ] && { cleans=$((cleans + 1)); break; } + [ -f fsck_ffs.core ] && { s=1; break 2; } + [ $r -eq 124 ] && { s=2; break 2; } # timeout + done + [ $clean -ne 1 ] && break + [ $r -ne 0 -a $clean -eq 1 ] && + { echo "CLEAN && non zero exit code"; break; } + [ $clean -eq 1 ] && continue + [ $usedasb -eq 1 ] && { echo "Alt. SB failed"; s=104; } + [ $waccess -eq 1 ] && { echo "No write access"; s=105; } + break +done + +echo "$cleans cleans, $reruns reruns, $asbs alternate SBs." +if [ $clean -ne 1 ]; then + echo "FS still not clean. Last fsck_ffs exit code was $r." + [ $s -eq 0 ] && s=106 +fi +grep -q "Superblock check-hash failed" $log && s=0 # Ignore for now +grep -q "is not a file system superblock" $log && s=0 # Ignore for now +[ $s -ne 0 ] && { gzip $backup; cp -v $backup.gz /tmp; } +cd /tmp +umount $mp1 +mdconfig -d -u $u1 +rm -f /tmp/flip /tmp/fsck_preload.so +exit $s diff --git a/tools/test/stress2/misc/fsck14.sh b/tools/test/stress2/misc/fsck14.sh new file mode 100755 index 000000000000..ddeb45a83e96 --- /dev/null +++ b/tools/test/stress2/misc/fsck14.sh @@ -0,0 +1,119 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# fsck -B test scenario with SUJ. -B implies "preen mode". + +# 'panic: ffs_blkfree_cg: bad size' seen: +# https://people.freebsd.org/~pho/stress/log/log0465.txt +# Fixed by: 220427da0e9b - Set UFS/FFS file type to snapshot before changing +# its block pointers. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg +mycc -o /tmp/flip -Wall -Wextra ../tools/flip.c || exit 2 + +set -e +md=/dev/md$mdstart +prog=$(basename "$0" .sh) +backup=/tmp/$prog.sh.diskimage.`date +%Y%m%dT%H%M%S`.gz +log=/tmp/$prog.sh.log +[ -c $md ] && mdconfig -d -u $mdstart +dd if=/dev/zero of=$diskimage bs=128m count=1 status=none +mdconfig -a -t vnode -f $diskimage -u $mdstart +backups=`newfs -N $j $md | grep -A1 "super-block backups" | \ + tail -1 | sed 's/,//g'` +newfs -j $md > /dev/null 2>&1 +mount $md $mntpoint +set +e + +jot 5000 | xargs -P0 -I% touch $mntpoint/a% +while ! umount $mntpoint; do :; done +/tmp/flip -n 10 $diskimage +gzip < $diskimage > $backup +fsync $diskimage $backup + +mount -f $md $mntpoint + +if ! fsck_ffs -B $md > $log 2>&1; then + grep MANUALLY $log + umount $mntpoint + fsck_ffs -fy $md > $log 2>&1; s=$? + grep -Eq "IS CLEAN|MARKED CLEAN" $log || { + cat $log + echo "fsck_ffs -f failed with exit code $s" + umount $mntpoint; mdconfig -d -u $mdstart + rm -f $log /tmp/flip $diskimage $backup + exit 1 + } + mount $md $mntpoint +fi + +jot 5000 | xargs -P0 -I% rm $mntpoint/a% +jot 5000 | xargs -P0 -I% touch $mntpoint/b% + +ls -lR $mntpoint > /dev/null || { + echo "ls -lR $mntpoint failed after fsck -B" + umount $mntpoint; mdconfig -d -u $mdstart + rm -f $log /tmp/flip $diskimage $backup + exit 0 # For now, ignore non fatal errors +} + +jot 5000 | xargs -P0 -I% rm $mntpoint/b% || { + echo "clean failed" + umount $mntpoint; mdconfig -d -u $mdstart + rm -f $log /tmp/flip $diskimage $backup + exit 0 # For now, ignore non fatal errors +} +umount $mntpoint + +r=0 +for i in `jot 4`; do + fsck_ffs -fy $diskimage > $log 2>&1; r=$? + if grep -qiE "super-?block.*failed" $log; then + for b in $backups; do + echo "fsck_ffs -b $b -fy $diskimage" + fsck_ffs -b $b -fy $diskimage > $log 2>&1 + r=$? + grep -qiE "super-?block.*failed" $log || + break + echo "Checking next SB" + done + fi + [ $r -ne 0 ] && continue + grep -Eq "WAS MODIFIED" $log && continue + grep -Eq "CLEAN" $log && break +done +mount $md $mntpoint || exit 3 +ls -lR $mntpoint > /dev/null || { umount $mntpoint; mdconfig -d -u mdstart; echo "exit 4"; exit 4; } +umount $mntpoint +fsck_ffs -fy $md > $log 2>&1 +grep -Eq 'IS CLEAN|MARKED CLEAN' $log && s=0 || { s=1; cat $log; } +mdconfig -d -u $mdstart +rm -f $log /tmp/flip $diskimage $backup +exit $s diff --git a/tools/test/stress2/misc/fsck2.sh b/tools/test/stress2/misc/fsck2.sh index 313efec490d1..3287e240d338 100755 --- a/tools/test/stress2/misc/fsck2.sh +++ b/tools/test/stress2/misc/fsck2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/fsck3.sh b/tools/test/stress2/misc/fsck3.sh index f9bd29017e35..39ebd112fccf 100755 --- a/tools/test/stress2/misc/fsck3.sh +++ b/tools/test/stress2/misc/fsck3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/fsck4.sh b/tools/test/stress2/misc/fsck4.sh index 3e97f7b54340..feb955ac3231 100755 --- a/tools/test/stress2/misc/fsck4.sh +++ b/tools/test/stress2/misc/fsck4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/fsck5.sh b/tools/test/stress2/misc/fsck5.sh index 35381c8c55e7..5ffded87d95e 100755 --- a/tools/test/stress2/misc/fsck5.sh +++ b/tools/test/stress2/misc/fsck5.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/fsck6.sh b/tools/test/stress2/misc/fsck6.sh index e1c5a4f36559..5d86b9d59ed2 100755 --- a/tools/test/stress2/misc/fsck6.sh +++ b/tools/test/stress2/misc/fsck6.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/fsck7.sh b/tools/test/stress2/misc/fsck7.sh index ab83f6ad0166..9662393e1df6 100755 --- a/tools/test/stress2/misc/fsck7.sh +++ b/tools/test/stress2/misc/fsck7.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/fsck8.sh b/tools/test/stress2/misc/fsck8.sh new file mode 100755 index 000000000000..9613fe72173e --- /dev/null +++ b/tools/test/stress2/misc/fsck8.sh @@ -0,0 +1,179 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# fsck_ffs(8) disk image fuzz test. SB focus. + +# panic: wrong length 4098 for sectorsize 512 +# FreeBSD 14.0-CURRENT #0 main-n255602-51adf913e8815: Fri May 13 07:55:32 CEST 2022 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO + +. ../default.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +cc -o /tmp/flip -Wall -Wextra -O2 ../tools/flip.c || exit 1 + +set -e +u1=$mdstart +u2=$((mdstart + 1)) +mp1=${mntpoint}$u1 +mp2=${mntpoint}$u2 +mkdir -p $mp1 $mp2 +log=$mp1/fsck8.sh.log +diskimage=$mp1/fsck8.sh.diskimage +backup=/tmp/fsck8.sh.diskimage.`date +%Y%m%dT%H%M%S`.gz +asbs=0 +cleans=0 +reruns=0 +waccess=0 + +max=$((10 * 1024 * 1024)) +# UFS1 or UFS2 SU: +[ `jot -r 1 0 1` -eq 0 ] && newfs_flags='-O 1' || newfs_flags='-O 2 -U' + +mount | grep "on $mp1 " | grep -q /dev/md && umount -f $mp1 +[ -c /dev/md$u1 ] && mdconfig -d -u $u1 +mdconfig -a -t swap -s 1g -u $u1 +newfs $newfs_flags -n /dev/md$u1 > /dev/null +mount /dev/md$u1 $mp1 + +[ -c /dev/md$u2 ] && mdconfig -d -u $u2 +dd if=/dev/zero of=$diskimage bs=$max count=1 status=none +mdconfig -a -t vnode -f $diskimage -u $u2 +backups=`newfs -N $newfs_flags md$u2 | grep -A1 "super-block backups" | \ + tail -1 | sed 's/,//g'` +newfs $newfs_flags -n md$u2 > /dev/null +mount /dev/md$u2 $mp2 +[ -d /usr/include/sys ] && cp -r /usr/include/sys $mp2 +umount $mp2 +set +e + +chk() { + local i + + clean=0 + rerun=0 + waccess=0 + timeout 5m fsck_ffs -fy $1 > $log 2>&1 + r=$? + if grep -qiE "super-?block.*failed" $log; then + for b in $backups; do + echo "Using alternate SB $b" + asbs=$((asbs + 1)) + fsck_ffs -b $b -fy $1 > $log 2>&1 + r=$? + grep -qiE "super-?block.*failed" $log || + break + done + usedasb=1 + else + usedasb=0 + fi + LANG=C egrep -q "[A-Z][A-Z]" $log && clean=0 + grep -Eq "IS CLEAN|MARKED CLEAN" $log && clean=1 + # For now regard a "was modified" as a cause for a rerun, + # disregarding the "clean" claim. + grep -Eq "WAS MODIFIED" $log && rerun=1 + grep -q RERUN $log && rerun=1 + grep -q "NO WRITE ACCESS" $log && waccess=1 + [ $r -ne 0 -a $clean -eq 1 ] && echo "Exit code $r w/ clean == 1" +} + +cd $mp1 +clean=0 +s=0 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 300 ]; do + mount /dev/md$u2 $mp2 || break + ls -lR $mp2 > /dev/null || { s=102; echo "ls failed"; break; } + touch $mp2/`jot -rc 8 a z | tr -d '\n'` + while mount | grep -q "on $mp2 "; do umount $mp2; done + echo * | grep -q core && break + sync + mdconfig -d -u $u2 + # SBLOCK = 64k, SBLOCKSIZE = 8k + /tmp/flip -n 5 -s $(((64 + 8) * 1024)) $diskimage + + sync + if [ `stat -f%z $diskimage` -gt $max ]; then + ls -lh $diskimage + truncate -s $max $diskimage + else + gzip < $diskimage > $backup + fi + fsync $backup + sync + + for i in `jot 5`; do + [ $i -gt 2 ] && echo "fsck run #$i" + chk $diskimage + [ $rerun -eq 1 ] && { reruns=$((reruns + 1)); continue; } + [ $clean -eq 1 ] && { cleans=$((cleans + 1)); break; } + [ -f fsck_ffs.core ] && + { cp -v $diskimage \ + /tmp/fsck_ffs.core.diskimage.`date +%Y%m%dT%H%M%S`; break 2; } + done + [ $clean -ne 1 ] && break + mdconfig -a -t vnode -f $diskimage -u $u2 + [ $r -ne 0 -a $clean -eq 1 ] && + { echo "CLEAN && non zero exit code"; break; } + [ $clean -eq 1 ] && continue + [ $usedasb -eq 1 ] && { echo "Alt. SB failed"; s=104; } + [ $waccess -eq 1 ] && { echo "No write access"; s=105; } + break +done +sleep 2 # Wait for /dev to catch up +[ -c /dev/md$u2 ] && r1=1 || r1=0 +for i in `jot 5`; do + mount | grep -q "on $mp2 " || break + umount $mp2 && break + sleep 2 +done +mdconfig -d -u $u2 2>/dev/null # XXX when mount fails + +echo "$cleans cleans, $reruns reruns, $asbs alternate SBs." +if [ $clean -ne 1 ]; then + echo "FS still not clean. Last fsck_ffs exit code was $r." + echo ================= + cat $log + echo ================= + cp -v $log /tmp + [ $s -eq 0 ] && s=106 +fi +echo * | grep -q core && { ls -l *.core; cp -v $log /tmp; exit 106; } || + rm -f $backup +[ $s -eq 101 ] && rm -f $backup # mount error breakout +cd /tmp +for i in `jot 5`; do + umount $mp1 && break + sleep 2 +done +mdconfig -d -u $u1 +rm -f /tmp/flip +exit $s diff --git a/tools/test/stress2/misc/fsck9.sh b/tools/test/stress2/misc/fsck9.sh new file mode 100755 index 000000000000..bbb10609ea67 --- /dev/null +++ b/tools/test/stress2/misc/fsck9.sh @@ -0,0 +1,168 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# fsck_ffs(8) false CLEAN claim scenario + +# https://people.freebsd.org/~pho/fsck9.sh.diskimage.20220716T150359.txt +# https://people.freebsd.org/~pho/fsck9.sh.diskimage.20220716T150359.gz + +# https://people.freebsd.org/~pho/fsck9.sh.diskimage.20220716T172428.txt +# https://people.freebsd.org/~pho/fsck9.sh.diskimage.20220716T172428.gz + +. ../default.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +cc -o /tmp/flip -Wall -Wextra -O2 ../tools/flip.c || exit 1 + +set -e +u1=$mdstart +u2=$((mdstart + 1)) +mp1=${mntpoint}$u1 +mp2=${mntpoint}$u2 +mkdir -p $mp1 $mp2 +log=$mp1/fsck9.sh.log +diskimage=$mp1/fsck9.sh.diskimage +backup=/tmp/fsck9.sh.diskimage.`date +%Y%m%dT%H%M%S`.gz +cleans=0 +reruns=0 + +max=$((10 * 1024 * 1024)) +newfs_flags='-U' + +mount | grep "on $mp1 " | grep -q /dev/md && umount -f $mp1 +[ -c /dev/md$u1 ] && mdconfig -d -u $u1 +mdconfig -a -t swap -s 1g -u $u1 +newfs $newfs_flags -n /dev/md$u1 > /dev/null +mount /dev/md$u1 $mp1 + +[ -c /dev/md$u2 ] && mdconfig -d -u $u2 +dd if=/dev/zero of=$diskimage bs=$max count=1 status=none +mdconfig -a -t vnode -f $diskimage -u $u2 +backups=`newfs -N $newfs_flags md$u2 | grep -A1 "super-block backups" | \ + tail -1 | sed 's/,//g'` +newfs $newfs_flags -n md$u2 > /dev/null +mount /dev/md$u2 $mp2 +[ -d /usr/include/sys ] && cp -r /usr/include/sys $mp2 +umount $mp2 +set +e + +chk() { + local i + + clean=0 + rerun=0 + fsck_ffs -fy $1 > $log 2>&1 + r=$? + if grep -qiE "super-?block.*failed" $log; then + for b in $backups; do + echo "fsck_ffs -b $b -fy $1" + fsck_ffs -b $b -fy $1 > $log 2>&1 + r=$? + grep -qiE "super-?block.*failed" $log || + break + echo "Checking next SB" + done + usedasb=1 + else + usedasb=0 + fi + LANG=C egrep -q "[A-Z][A-Z]" $log && clean=0 + grep -Eq "IS CLEAN|MARKED CLEAN" $log && clean=1 + grep -q RERUN $log && rerun=1 + [ $r -ne 0 -a $clean -eq 1 ] && echo "Exit code $r w/ clean == 1" +} + +cd $mp1 +clean=0 +s=0 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 300 ]; do + mount /dev/md$u2 $mp2 || break + if ! ls -lR $mp2 > /dev/null; then + s=102 + echo "ls failed"; grep "core dumped" /var/log/messages | tail -1 + break + fi + touch $mp2/`jot -rc 8 a z | tr -d '\n'` + while mount | grep -q "on $mp2 "; do umount $mp2; done + echo * | grep -q core && break + sync + mdconfig -d -u $u2 + /tmp/flip -n 5 $diskimage + + sync + if [ `stat -f%z $diskimage` -gt $max ]; then + ls -lh $diskimage + truncate -s $max $diskimage + else + gzip < $diskimage > $backup + fi + fsync $backup + sync + + for i in `jot 5`; do + [ $i -gt 2 ] && echo "fsck run #$i" + chk $diskimage + [ $rerun -eq 1 ] && { reruns=$((reruns + 1)); continue; } + [ $clean -eq 1 ] && { cleans=$((cleans + 1)); break; } + [ -f fsck_ffs.core ] && + { cp -v $diskimage \ + /tmp/fsck_ffs.core.diskimage.`date +%Y%m%dT%H%M%S`; break 2; } + done + if [ $clean -eq 1 ]; then + fsck_ffs -fy $diskimage > $log 2>&1 + if grep -q MODIFIED $log; then + echo "*** fsck of \"clean\" FS found more issues:" + cat $log + s=1 + break + fi + fi + [ $clean -ne 1 ] && break + mdconfig -a -t vnode -f $diskimage -u $u2 +done +sleep 2 # Wait for /dev to catch up +[ -c /dev/md$u2 ] && r1=1 || r1=0 +for i in `jot 5`; do + mount | grep -q "on $mp2 " || break + umount $mp2 && break + sleep 2 +done +mdconfig -d -u $u2 2>/dev/null # XXX when mount fails + +[ $s -eq 0 ] && rm -f $backup || echo "Preserved $backup due to status code $s" +cd /tmp +for i in `jot 5`; do + umount $mp1 && break + sleep 2 +done +mdconfig -d -u $u1 +rm -f /tmp/flip +exit $s diff --git a/tools/test/stress2/misc/fstat.sh b/tools/test/stress2/misc/fstat.sh index 441065f8e769..72e90d631e6d 100755 --- a/tools/test/stress2/misc/fstat.sh +++ b/tools/test/stress2/misc/fstat.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/fsync2.sh b/tools/test/stress2/misc/fsync2.sh index f2e846c4aa20..009fe9542f07 100755 --- a/tools/test/stress2/misc/fsync2.sh +++ b/tools/test/stress2/misc/fsync2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/fsync3.sh b/tools/test/stress2/misc/fsync3.sh new file mode 100755 index 000000000000..f220d19b8c24 --- /dev/null +++ b/tools/test/stress2/misc/fsync3.sh @@ -0,0 +1,156 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Regression test for D37997: ffs_syncvnode(): avoid a LoR for SU +# https://people.freebsd.org/~pho/stress/log/log0402.txt +# Fixed by 6e1eabadcb1d - main - ffs_syncvnode(): avoid a LoR for SU + +# Test scenario based on report by jkim + +. ../default.cfg +[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 + +dir=/tmp +odir=`pwd` +prog=$(basename "$0" .sh) +cd $dir +sed '1,/^EOF/d' < $odir/$0 > $dir/$prog.c +mycc -o $prog -Wall -Wextra -O0 -g $prog.c -lpthread || exit 1 +rm -f $prog.c +cd $odir + +set -eu +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 1g -u $mdstart +newfs -U md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +set +e + +cd $odir +../testcases/swap/swap -t 1m -i 20 -l 100 > /dev/null & +sleep .5 +cd $mntpoint +mkdir -p d1/d2/d3/d4/d5 +for i in `jot 8`; do + $dir/$prog $i & +done +cd $odir +wait + +for i in `jot 6`; do + mount | grep -q "on $mntpoint " || break + umount $mntpoint && break || sleep 10 + [ $i -eq 6 ] && + { echo FATAL; fstat -mf $mntpoint; exit 1; } +done +mdconfig -d -u $mdstart +rm -rf $dir/$prog +exit 0 +EOF +#include <sys/types.h> +#include <sys/stat.h> + +#include <err.h> +#include <fcntl.h> +#include <pthread.h> +#include <pthread_np.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define RUNTIME 60 + +static time_t start; +static volatile int fd, n; +static char buf[4096]; + +static void * +t1(void *data __unused) +{ + char *path = "d1/d2/d3/d4/d5"; + char d1[1024], d2[1024], file[1024]; + + pthread_set_name_np(pthread_self(), __func__); + snprintf(d1, sizeof(d1), "%s/dir.%d", path, getpid()); + snprintf(d2, sizeof(d2), "%s/new.%d", path, getpid()); + snprintf(file, sizeof(file), "%s/../file.%d", path, getpid()); + while (time(NULL) - start < RUNTIME) { + if (mkdir(d1, 0740) == -1) + err(1, "mkdir(%s)", d1); + if (rename(d1, d2) == -1) + err(1, "rename(%s, %s)", d1, d2); + if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) == -1) + err(1, "open%s()", file); + if (write(fd, buf, sizeof(buf)) != sizeof(buf)) + err(1, "write()"); + close(fd); + if (rename(d2, d1) == -1) + err(1, "rename(%s, %s)", d2, d1); + if (rmdir(d1) == -1) + err(1, "rmdir(%s)", d1); + } + + return (NULL); +} + +static void * +t2(void *data __unused) +{ + pthread_set_name_np(pthread_self(), __func__); + while (time(NULL) - start < RUNTIME) { + fsync(fd); + usleep(arc4random() % 500); + } + + return (NULL); +} + +int +main(int argc __unused, char *argv[]) +{ + pthread_t tid[2]; + int r; + + n = atoi(argv[1]); + start = time(NULL); + if ((r = pthread_create(&tid[0], NULL, t1, NULL)) != 0) + errc(1, r, "pthread_create"); + if ((r = pthread_create(&tid[1], NULL, t2, NULL)) != 0) + errc(1, r, "pthread_create"); + + if ((r = pthread_join(tid[0], NULL)) != 0) + errc(1, r, "pthread_join"); + if ((r = pthread_join(tid[1], NULL)) != 0) + errc(1, r, "pthread_join"); + + return (0); +} diff --git a/tools/test/stress2/misc/fsync4.sh b/tools/test/stress2/misc/fsync4.sh new file mode 100755 index 000000000000..ac08dd6dff49 --- /dev/null +++ b/tools/test/stress2/misc/fsync4.sh @@ -0,0 +1,146 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Regression test for D38114: Handle ERELOOKUP from VOP_FSYNC() + +# "fsync4: msync(0x82d3cc000), file d1/d2/d3/d4/d5/../file.92660: +# Input/output error" seen + +# Fixed by: 6189672e6008 - main - Handle ERELOOKUP from VOP_FSYNC() in +# several other places + +. ../default.cfg +[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 + +dir=/tmp +odir=`pwd` +pids="" +prog=$(basename "$0" .sh) +s=0 +cd $dir +sed '1,/^EOF/d' < $odir/$0 > $dir/$prog.c +mycc -o $prog -Wall -Wextra -O0 -g $prog.c || exit 1 +rm -f $prog.c +cd $odir + +set -eu +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 1g -u $mdstart +newfs -U md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +set +e + +cd $odir +../testcases/swap/swap -t 1m -i 20 -l 100 > /dev/null & +sleep .5 +cd $mntpoint +mkdir -p d1/d2/d3/d4/d5 +for i in `jot 8`; do + $dir/$prog $i & + pids="$pids $!" +done +cd $odir +for pid in $pids; do + wait $pid + [ $? -ne 0 ] && s=1 +done + +for i in `jot 6`; do + mount | grep -q "on $mntpoint " || break + umount $mntpoint && break || sleep 10 + [ $i -eq 6 ] && + { echo FATAL; fstat -mf $mntpoint; exit 1; } +done +mdconfig -d -u $mdstart +rm -rf $dir/$prog +exit $s +EOF +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/param.h> +#include <sys/stat.h> + + +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define RUNTIME 60 +#define SIZ (1024 * 1024) + +static time_t start; + +int +main(void) +{ + size_t len; + int fd, i, ps; + char *cp; + char *path = "d1/d2/d3/d4/d5"; + char d1[1024], d2[1024], file[1024]; + + snprintf(d1, sizeof(d1), "%s/dir.%d", path, getpid()); + snprintf(d2, sizeof(d2), "%s/new.%d", path, getpid()); + snprintf(file, sizeof(file), "%s/../file.%d", path, getpid()); + + start = time(NULL); + while (time(NULL) - start < RUNTIME) { + if (mkdir(d1, 0740) == -1) + err(1, "mkdir(%s)", d1); + if (rename(d1, d2) == -1) + err(1, "rename(%s, %s)", d1, d2); + if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) == -1) + err(1, "open%s()", file); + len = SIZ; + if (ftruncate(fd, len) == -1) + err(1, "ftruncate"); + cp = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + if (cp == MAP_FAILED) + err(1, "mmap()"); + ps = getpagesize(); + for (i = 0; i < SIZ; i += ps) + cp[i] = 1; + if (msync(cp, 0, MS_SYNC) == -1) + err(1, "msync(%p), file %s", cp, file); + if (munmap(cp, len) == -1) + err(1, "unmap()"); + close(fd); + if (rename(d2, d1) == -1) + err(1, "rename(%s, %s)", d2, d1); + if (rmdir(d1) == -1) + err(1, "rmdir(%s)", d1); + } + + return (0); +} diff --git a/tools/test/stress2/misc/ftruncate3.sh b/tools/test/stress2/misc/ftruncate3.sh new file mode 100755 index 000000000000..7373ae8d22a8 --- /dev/null +++ b/tools/test/stress2/misc/ftruncate3.sh @@ -0,0 +1,96 @@ +#!/bin/sh + +# Test scenario from Bug 64816: [nfs] [patch] mmap and/or ftruncate does not work correctly on nfs mounted file systems + +. ../default.cfg + +set -u +grep -q $mntpoint /etc/exports || + { echo "$mntpoint missing from /etc/exports"; exit 0; } +rpcinfo 2>/dev/null | grep -q mountd || exit 0 + +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +void error(char *msg) +{ + fprintf(stderr, "Error: %s\nSystem error %d: %s\n", msg, errno, strerror(errno)); + exit(-1); +} + +#define SZ 1024 // Less than page size + +int main(int argn, char *argv[]) +{ + int fd, s; + char buffer[SZ]; + char *map; + + if (argn!=2) + { + fprintf(stderr, "Usage:\n %s [filename]\n", argv[0]); + _exit(-1); + } + + memset(buffer, 0, SZ); + s = 0; + + fd=open(argv[1], O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); + if (fd==-1) + error("Could not create file"); + + if (write(fd, buffer, SZ)!=SZ) + error("Could not write buffer"); + + map=mmap(NULL, SZ, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (map==MAP_FAILED) + error("Map failed"); + map[SZ-1]=1; + + if (ftruncate(fd, SZ+1)!=0) + error("Could not truncate file"); + + if (map[SZ-1]==1) + printf("Test passed\n"); + else { + printf("Test failed\n"); + s = 1; + } + + exit(s); +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 -g /tmp/$prog.c || exit 1 + +mount | grep -q "on $mntpoint " && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -s 1g -u $mdstart +newfs -n $newfs_flags /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint + +mp2=${mntpoint}2 +mkdir -p $mp2 +mount | grep -q "on $mp2 " && umount -f $mp2 +mount -t nfs -o retrycnt=3 127.0.0.1:$mntpoint $mp2 || exit 1 +sleep .2 +mount | grep $mntpoint + +cd $mp2 +/tmp/$prog $prog.data; s=$? +ls -ls $mp2/$prog.data +cd - + +umount $mp2 +umount $mntpoint +mdconfig -d -u $mdstart +rm -f /tmp/$prog /tmp/$prog.c +exit $s diff --git a/tools/test/stress2/misc/geomleak2.sh b/tools/test/stress2/misc/geomleak2.sh index 19b6f03d6333..1fc2405da66b 100755 --- a/tools/test/stress2/misc/geomleak2.sh +++ b/tools/test/stress2/misc/geomleak2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/getrandom.sh b/tools/test/stress2/misc/getrandom.sh index 3b2de3ec2a7a..402ff8a40544 100755 --- a/tools/test/stress2/misc/getrandom.sh +++ b/tools/test/stress2/misc/getrandom.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/getrandom2.sh b/tools/test/stress2/misc/getrandom2.sh index 941ffb737a6d..23eaa5aedb8e 100755 --- a/tools/test/stress2/misc/getrandom2.sh +++ b/tools/test/stress2/misc/getrandom2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/gnop10.sh b/tools/test/stress2/misc/gnop10.sh index 012104cbf9ed..5ab05280279c 100755 --- a/tools/test/stress2/misc/gnop10.sh +++ b/tools/test/stress2/misc/gnop10.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # @@ -32,6 +32,10 @@ # Copy of gnop9.sh. Uses SU instead of SUJ. +# https://people.freebsd.org/~pho/stress/log/log0269.txt +# https://people.freebsd.org/~pho/stress/log/log0370.txt +# https://people.freebsd.org/~pho/stress/log/log0396.txt + [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg diff --git a/tools/test/stress2/misc/gnop11.sh b/tools/test/stress2/misc/gnop11.sh index 4d4f936bd8c6..48da18f1c425 100755 --- a/tools/test/stress2/misc/gnop11.sh +++ b/tools/test/stress2/misc/gnop11.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Kirk McKusick <mckusick@mckusick.com> # diff --git a/tools/test/stress2/misc/gnop12.sh b/tools/test/stress2/misc/gnop12.sh index d22a82b35a7e..1b5d311d7723 100755 --- a/tools/test/stress2/misc/gnop12.sh +++ b/tools/test/stress2/misc/gnop12.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/gnop13.sh b/tools/test/stress2/misc/gnop13.sh new file mode 100755 index 000000000000..45668b9d8e82 --- /dev/null +++ b/tools/test/stress2/misc/gnop13.sh @@ -0,0 +1,138 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Snapshot test +# Variation of force13.sh, but uses "gnop -f destroy" + +# Seen: +# UFS: forcibly unmounting /dev/md10.nop from /mnt +# panic: flush_pagedep_deps: failed to flush inodedep + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +set -u +log=/tmp/gnop13.sh.log +mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +truncate -s 10g $diskimage +mdconfig -a -t vnode -f $diskimage -u $mdstart +flags=$newfs_flags +[ `jot -r 1 0 1` -eq 1 ] && flags="-j" + +echo "newfs $flags md$mdstart" +newfs $flags md$mdstart > /dev/null 2>&1 + +# Exclude rename for now due to log0374.txt +export TESTPROGS=`cd ..; find testcases/ -perm -1 -type f | \ + egrep -Ev "/run/|/badcode/|/pty/|/shm/|/socket/|sysctl|tcp|thr|udp|rename"` +export runRUNTIME=3m +export RUNDIR=$mntpoint/stressX +export CTRLDIR=$mntpoint/stressX.control +start=`date +%s` +while [ $((`date +%s` - start)) -lt $((15 * 60)) ]; do + gnop create /dev/md$mdstart || exit 1 + mount /dev/md$mdstart.nop $mntpoint || exit 1 + rm -fr $mntpoint/lost+found + chmod 777 $mntpoint + + su $testuser -c 'cd ..; ./testcases/run/run $TESTPROGS' > \ + /dev/null 2>&1 & + + t=`jot -r 1 60 120` + st=`date +%s` + for i in `jot 10`; do + [ -d $mntpoint/.snap ] || break + rm -f $mntpoint/.snap/$i + echo "mksnap_ffs $mntpoint $mntpoint/.snap/$i" + mksnap_ffs $mntpoint $mntpoint/.snap/$i + sleep `jot -r 1 1 5` + [ $((`date +%s` - st)) -ge $t ] && break + done & + sleep `jot -r 1 60 120` + while [ -c /dev/md$mdstart.nop ]; do + echo "gnop destroy -f /dev/md$mdstart.nop" + gnop destroy -f /dev/md$mdstart.nop || sleep 1 + done + n=0 + st=`date +%s` + while mount | grep -q "on $mntpoint "; do + [ $n -eq 0 ] && /bin/echo -n "Waiting for $mntpoint to force umount ..." + n=$((n + 1)) + sleep 2 + if [ $((`date +%s` - st)) -ge 180 ]; then + echo "Giving up on waiting for umount of $mntpoint" + umount $mntpoint || umount -f $mntpoint + break + fi + done + [ $n -ne 0 ] && echo + + ../tools/killall.sh + wait + mount | grep -q "on $mntpoint " && umount -f $mntpoint + c=0 + # Run fsck minimum two times + for i in `jot 5`; do + fsck_ffs -fy /dev/md$mdstart > $log 2>&1; s=$? + grep -q CLEAN $log && grep -q "MODIFIED" $log && c=$((c+=1)) + grep -Eq "FILE SYSTEM WAS MODIFIED" $log || break + done + [ $c -gt 1 ] && + { echo "Note: FS marked clean+modified $c times out of $i fsck runs"; s=101; } + [ $s -ne 0 ] && break + grep -Eq "IS CLEAN|MARKED CLEAN" $log || { s=102; break; } +done +[ $s -eq 101 ] && s=0 # Ignore CLEANish problem for now +if [ $s -eq 0 ]; then + mount /dev/md$mdstart.nop $mntpoint + cp -R /usr/include $mntpoint + dd if=/dev/zero of=$mntpoint/big bs=1m count=10 status=none + find $mntpoint/* -delete + + # Check the RO snapshots + for f in $mntpoint/.snap/*; do + c=0 + for i in `jot 5`; do + echo "fsck_ffs -fy $f" + fsck_ffs -fy $f > $log 2>&1; s=$? + grep -q CLEAN $log && grep -q "MODIFIED" $log && c=$((c+=1)) + grep -Eq "FILE SYSTEM WAS MODIFIED" $log || break + done + [ $c -gt 1 ] && + { echo "Note: snapshot $i marked clean+modified $c times out of $i fsck runs"; s=201; } + [ $s -ne 0 ] && break + grep -Eq "IS CLEAN|MARKED CLEAN" $log || + { s=202; tail -10 $log; break; } + done + umount $mntpoint + mdconfig -d -u $mdstart + rm -f $diskimage $log +fi +exit $s diff --git a/tools/test/stress2/misc/gnop2.sh b/tools/test/stress2/misc/gnop2.sh index d38754d58456..0a6b830ce749 100755 --- a/tools/test/stress2/misc/gnop2.sh +++ b/tools/test/stress2/misc/gnop2.sh @@ -71,8 +71,10 @@ test() { gnop status || exit 1 +start=`date +%s` for i in 1k 2k 4k 8k; do test $i + [ $((`date +%s` - start)) -gt 1200 ] && break done [ $notloaded ] && gnop unload diff --git a/tools/test/stress2/misc/gnop4.sh b/tools/test/stress2/misc/gnop4.sh index f938dd3b790b..1b4da74266f6 100755 --- a/tools/test/stress2/misc/gnop4.sh +++ b/tools/test/stress2/misc/gnop4.sh @@ -34,6 +34,8 @@ # https://people.freebsd.org/~pho/stress/log/kostik1017.txt # Fixed by r322175 +# Seen with p=513: Threads stuck in "ffsrca" + . ../default.cfg gigs=9 @@ -62,6 +64,7 @@ cd $mntpoint/src export MAKEOBJDIRPREFIX=$mntpoint/obj p=$((`sysctl -n hw.ncpu`+ 1)) +[ $p -gt 32 ] && p=32 # Temporary work around timeout 10m \ make -i -j $p buildworld DESTDIR=$mntpoint TARGET=amd64 \ TARGET_ARCH=amd64 > /dev/null diff --git a/tools/test/stress2/misc/gnop6.sh b/tools/test/stress2/misc/gnop6.sh index 63301d8fe841..4d32f584662e 100755 --- a/tools/test/stress2/misc/gnop6.sh +++ b/tools/test/stress2/misc/gnop6.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/gnop7.sh b/tools/test/stress2/misc/gnop7.sh index 3f3118ff0fab..76008aabe925 100755 --- a/tools/test/stress2/misc/gnop7.sh +++ b/tools/test/stress2/misc/gnop7.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/gnop8.sh b/tools/test/stress2/misc/gnop8.sh index 6916c14e41f4..e9067c8c8066 100755 --- a/tools/test/stress2/misc/gnop8.sh +++ b/tools/test/stress2/misc/gnop8.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Kirk McKusick <mckusick@mckusick.com> # diff --git a/tools/test/stress2/misc/gnop9.sh b/tools/test/stress2/misc/gnop9.sh index 0389391398f3..12c6fff0a3bf 100755 --- a/tools/test/stress2/misc/gnop9.sh +++ b/tools/test/stress2/misc/gnop9.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/gpt.sh b/tools/test/stress2/misc/gpt.sh index 51b4ba39afda..5c1818921321 100755 --- a/tools/test/stress2/misc/gpt.sh +++ b/tools/test/stress2/misc/gpt.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/growfs2.sh b/tools/test/stress2/misc/growfs2.sh new file mode 100755 index 000000000000..0990f71423a3 --- /dev/null +++ b/tools/test/stress2/misc/growfs2.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# growfs(8) test with output to FS to be grown. +# A regression test for D37896 ufs/suspend: deny suspension if calling +# process has file from mp opened for write +# Before D37896 this would result in growfs(8) hanging. + +. ../default.cfg +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +log=/tmp/growfs2.sh.log +s=0 +set -eu +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 32g -u $mdstart +/sbin/gpart create -s GPT md$mdstart > /dev/null +/sbin/gpart add -t freebsd-ufs -s 2g -a 4k md$mdstart > /dev/null +set +e + +newfs $newfs_flags md${mdstart}p1 > /dev/null +mount /dev/md${mdstart}p1 $mntpoint +cp -r /usr/include $mntpoint/inc1 + +gpart resize -i 1 -s 31g -a 4k md$mdstart +echo "Expect: growfs: UFSSUSPEND: Resource deadlock avoided" +growfs -y md${mdstart}p1 > $mntpoint/log && s=1 || s=0 + +cp -r /usr/include $mntpoint/inc2 +umount $mntpoint +fsck -fy /dev/md${mdstart}p1 > $log 2>&1 +grep -q "WAS MODIFIED" $log && s=2 +grep -q CLEAN $log || s=3 +[ $s -ne 0 ] && cat $log + +mdconfig -d -u $mdstart +rm -f $log +exit $s diff --git a/tools/test/stress2/misc/growfs3.sh b/tools/test/stress2/misc/growfs3.sh new file mode 100755 index 000000000000..33e8327cdbbc --- /dev/null +++ b/tools/test/stress2/misc/growfs3.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +. ../default.cfg +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +set -eu +prog=$(basename "$0" .sh) +log=/tmp/$prog.log +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 32g -u $mdstart +/sbin/gpart create -s GPT md$mdstart > /dev/null +/sbin/gpart add -t freebsd-ufs -s 2g -a 4k md$mdstart > /dev/null +set +e + +newfs_flags=$(echo "-O1" "-O2" "-U" "-j" | awk -v N=`jot -r 1 1 4` '{print $N}') +echo "newfs $newfs_flags md${mdstart}p1" +newfs $newfs_flags md${mdstart}p1 > /dev/null +[ "$newfs_flags" = "-O2" ] && + tunefs -n disable md${mdstart}p1 > /dev/null 2>&1 +mount /dev/md${mdstart}p1 $mntpoint +cp -r /usr/include $mntpoint/inc1 +umount $mntpoint + +gpart resize -i 1 -s 31g -a 4k md$mdstart +growfs -y md${mdstart}p1 > /dev/null + +mount /dev/md${mdstart}p1 $mntpoint +cp -r /usr/include $mntpoint/inc2 +umount $mntpoint +fsck -fy /dev/md${mdstart}p1 > $log 2>&1; s=$? +grep -q "WAS MODIFIED" $log && { cat $log; s=1; } +rm -f $log +mdconfig -d -u $mdstart +exit $s diff --git a/tools/test/stress2/misc/gunion.sh b/tools/test/stress2/misc/gunion.sh index c7d376e5409e..ceecc55b2f13 100755 --- a/tools/test/stress2/misc/gunion.sh +++ b/tools/test/stress2/misc/gunion.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # @@ -50,7 +50,10 @@ cp -r ../../stress2 $mp1 umount $mp1 mdconfig -a -t swap -s 5g -u $md2 -gunion create -v /dev/md$md2 /dev/md$md1 +set +e +gunion create -v /dev/md$md2 /dev/md$md1; s=$? +[ $s -ne 0 ] && echo "gunion create returned $s" +set -e mount /dev/md$md2-md$md1.union $mntpoint export RUNDIR=$mntpoint/stressX @@ -71,7 +74,7 @@ for i in `jot 6`; do done fsck_ffs -fyR /dev/md$md2-md$md1.union > $log 2>&1 grep -Eq "IS CLEAN|MARKED CLEAN" $log || { s=2; cat $log; } -set +e +set -e gunion commit /dev/md$md2-md$md1.union gunion list | egrep Block\|Current | egrep -v 0 && s=3 gunion destroy /dev/md$md2-md$md1.union diff --git a/tools/test/stress2/misc/gunion2.sh b/tools/test/stress2/misc/gunion2.sh index a8fe180c48af..0d14c17b24eb 100755 --- a/tools/test/stress2/misc/gunion2.sh +++ b/tools/test/stress2/misc/gunion2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # @@ -50,7 +50,10 @@ cp -r ../../stress2 $mp1 umount $mp1 mdconfig -a -t swap -s 5g -u $md2 -gunion create -v /dev/md$md2 /dev/md$md1 +set +e +gunion create -v /dev/md$md2 /dev/md$md1; s=$? +[ $s -ne 0 ] && echo "gunion create returned $s" +set -e mount /dev/md$md2-md$md1.union $mntpoint export CTRLDIR=$mntpoint/stressX.control @@ -79,7 +82,7 @@ testcases/swap/swap " export TESTPROGS=`echo $TESTPROGS | sed 's/\n/ /g'` -set +e +set -e chmod 777 $mntpoint su $testuser -c \ "(cd $mntpoint/stress2; ./testcases/run/run $TESTPROGS)" diff --git a/tools/test/stress2/misc/holdcnt05.sh b/tools/test/stress2/misc/holdcnt05.sh index efafa984bdd8..fa6c7b4bd628 100755 --- a/tools/test/stress2/misc/holdcnt05.sh +++ b/tools/test/stress2/misc/holdcnt05.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/ifconfig.sh b/tools/test/stress2/misc/ifconfig.sh index 7b3c7e317ec3..0fe768d8c53c 100755 --- a/tools/test/stress2/misc/ifconfig.sh +++ b/tools/test/stress2/misc/ifconfig.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/ifconfig2.sh b/tools/test/stress2/misc/ifconfig2.sh index 273db43a329d..77b0d4860647 100755 --- a/tools/test/stress2/misc/ifconfig2.sh +++ b/tools/test/stress2/misc/ifconfig2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/indir.sh b/tools/test/stress2/misc/indir.sh index d2d28cd650ab..1f0b873833ee 100755 --- a/tools/test/stress2/misc/indir.sh +++ b/tools/test/stress2/misc/indir.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/indir_trunc.sh b/tools/test/stress2/misc/indir_trunc.sh index 64c11f3570ee..e7f1b7cb4fe6 100755 --- a/tools/test/stress2/misc/indir_trunc.sh +++ b/tools/test/stress2/misc/indir_trunc.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/jexec.sh b/tools/test/stress2/misc/jexec.sh index c5c2ab605e08..00fb17a27a92 100755 --- a/tools/test/stress2/misc/jexec.sh +++ b/tools/test/stress2/misc/jexec.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/jumbo.sh b/tools/test/stress2/misc/jumbo.sh index 8dcc5aa7aca3..a2d09bafaa82 100755 --- a/tools/test/stress2/misc/jumbo.sh +++ b/tools/test/stress2/misc/jumbo.sh @@ -131,7 +131,7 @@ reader(void) { if ((buf = malloc(MX)) == NULL) err(1, "malloc(%d), %s:%d", MX, __FILE__, __LINE__); setproctitle("reader"); - for (i = 4096; i < MX; i += 1024) { + for (i = sysconf(_SC_PAGESIZE); i < MX; i += 1024) { alarm(TIMEOUT); if ((n = recvfrom(msgsock, buf, i, MSG_WAITALL, NULL, NULL)) < 0) { diff --git a/tools/test/stress2/misc/kcmp.sh b/tools/test/stress2/misc/kcmp.sh new file mode 100755 index 000000000000..7c571dd8e8a1 --- /dev/null +++ b/tools/test/stress2/misc/kcmp.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Seen: +# UID PID PPID C PRI NI VSZ RSS MWCHAN STAT TT TIME COMMAND +# 0 3730 3668 11 20 0 13596 2904 exithold DE+ 0 1:59.68 ./kcmp + +# Fixed by: 5b3e5c6ce3e5 + +. ../default.cfg + +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +#include <sys/types.h> + +#include <err.h> +#include <fcntl.h> +#include <pthread.h> +#include <signal.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +static void * +t1(void *data __unused) +{ + for (;;) + pause(); + + return (NULL); +} + +int +main(void) +{ + pid_t p1, p2; + pthread_t tid[2]; + time_t start; + uintptr_t idx1, idx2; + int r; + + if ((r = pthread_create(&tid[0], NULL, t1, NULL)) != 0) + errc(1, r, "pthread_create"); + if ((r = pthread_create(&tid[1], NULL, t1, NULL)) != 0) + errc(1, r, "pthread_create"); + + start = time(NULL); + while (time(NULL) - start < 60) { + idx1 = idx2 = 0; + p1 = arc4random() % 1000000; + p2 = arc4random() % 1000000; + kcmp(p1, p2, KCMP_VM, idx1, idx2); + } +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +/tmp/$prog + +rm /tmp/$prog.c /tmp/$prog +exit 0 diff --git a/tools/test/stress2/misc/kern_umtx_inf_loop.sh b/tools/test/stress2/misc/kern_umtx_inf_loop.sh index b8088814d7b2..2c4d99149480 100755 --- a/tools/test/stress2/misc/kern_umtx_inf_loop.sh +++ b/tools/test/stress2/misc/kern_umtx_inf_loop.sh @@ -46,7 +46,6 @@ EOF * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <sys/types.h> #include <machine/cpufunc.h> diff --git a/tools/test/stress2/misc/kevent10.sh b/tools/test/stress2/misc/kevent10.sh index 6efdedfc28cd..b7f74f487cec 100755 --- a/tools/test/stress2/misc/kevent10.sh +++ b/tools/test/stress2/misc/kevent10.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/kevent12.sh b/tools/test/stress2/misc/kevent12.sh index 3ae0085f1e5d..1a022e2d1b47 100755 --- a/tools/test/stress2/misc/kevent12.sh +++ b/tools/test/stress2/misc/kevent12.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/kevent13.sh b/tools/test/stress2/misc/kevent13.sh index 82a7a10b983c..0e2f8982f4ab 100755 --- a/tools/test/stress2/misc/kevent13.sh +++ b/tools/test/stress2/misc/kevent13.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/kevent14.sh b/tools/test/stress2/misc/kevent14.sh index 2531b15caecf..3cf88fd87ba7 100755 --- a/tools/test/stress2/misc/kevent14.sh +++ b/tools/test/stress2/misc/kevent14.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/kevent15.sh b/tools/test/stress2/misc/kevent15.sh index 52925365c865..56a3bc4fbd0a 100755 --- a/tools/test/stress2/misc/kevent15.sh +++ b/tools/test/stress2/misc/kevent15.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/killpg2.sh b/tools/test/stress2/misc/killpg2.sh new file mode 100755 index 000000000000..5e986f059637 --- /dev/null +++ b/tools/test/stress2/misc/killpg2.sh @@ -0,0 +1,197 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# killpg(2) version of reaper.sh. No problems seen. + +. ../default.cfg + +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +#include <sys/param.h> +#include <sys/mman.h> +#include <sys/wait.h> + +#include <err.h> +#include <errno.h> +#include <pwd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +static volatile u_int *share; + +#define CONT 0 +#define GID 1 +#define SYNC 2 +#define MAXP 10000 + +static void +hand(int i __unused) { + _exit(0); +} + +static void +looper(void) +{ + struct sigaction sa; + time_t start; + struct passwd *pw; + pid_t pids[MAXP]; + int i, parallel; + + setproctitle("looper"); + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGUSR1, &sa, NULL) == -1) + err(1, "sigaction"); + + if ((pw = getpwnam("TUSER")) == NULL) + err(1, "no such user: TUSER"); + + if (setgroups(1, &pw->pw_gid) || + setegid(pw->pw_gid) || setgid(pw->pw_gid) || + seteuid(pw->pw_uid) || setuid(pw->pw_uid)) + err(1, "Can't drop privileges to \"TUSER\""); + endpwent(); + setpgrp(0, 0); + share[GID] = getpgrp(); + share[SYNC] = 1; + start = time(NULL); + while (time(NULL) - start < 120) { + parallel = arc4random() % MAXP + 1; + for (i = 0; i < parallel; i++) { + if ((pids[i] = fork()) == 0) { + sa.sa_handler = hand; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGUSR1, &sa, NULL) == -1) + err(1, "sigaction"); + setproctitle("child"); + for (;;) + pause(); + _exit(0); /* never reached */ + } + if (pids[i] == -1) + err(1, "fork()"); + } + for (i = 0; i < parallel; i++) { + if (waitpid(pids[i], NULL, 0) != pids[i]) + err(1, "waitpid(%d) in looper", pids[i]); + } + } + _exit(0); +} + +static void +killer(void) +{ + int e, gid; + + while (share[SYNC] == 0) + ; + gid = share[GID]; + while (share[CONT] == 1) { + usleep(arc4random() % 50000); + gid = share[GID]; + if (gid != 0) { + e = 0; + while (e == 0) { + if (killpg(gid, SIGUSR1) == -1) { + e = 1; + if (errno != ESRCH) + err(1, "pgkill(%d)", gid); + } + usleep(5000 + arc4random() % 5000); + } + } + } + _exit(0); +} + +int +main(void) +{ + size_t len; + time_t start; + int lpid, kpid, s1, s2; + + len = PAGE_SIZE; + if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) + err(1, "mmap"); + + start = time(NULL); + while (time(NULL) - start < 120) { + share[CONT] = 1; + share[GID] = 0; + share[SYNC] = 0; + if ((lpid = fork()) == 0) + looper(); + usleep(arc4random() % 100000); + if ((kpid = fork()) == 0) + killer(); + + if (waitpid(lpid, &s1, 0) != lpid) + err(1, "waitpid looper"); + usleep(arc4random() % 1000); + share[CONT] = 0; + waitpid(kpid, &s2, 0); + } + + return (0); +} +EOF +sed -i '' "s#TUSER#$testuser#" /tmp/$prog.c +cc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1 +rm /tmp/$prog.c + +n=1 +start=`date +%s` +while true; do + /tmp/$prog + for i in `jot 50`; do + pgrep -q $prog || break + sleep .5 + done + if pgrep -q $prog; then + e=$((`date +%s` - start)) + echo "Failed in loop #$n after $e seconds." + pgrep "$prog|timeout" | xargs ps -jp + pkill $prog + rm -f /tmp/$prog + exit 1 + fi + [ $((`date +%s` - start)) -ge 600 ] && break + n=$((n + 1)) +done +rm /tmp/$prog +exit 0 diff --git a/tools/test/stress2/misc/killpg3.sh b/tools/test/stress2/misc/killpg3.sh new file mode 100755 index 000000000000..304b3e320f2f --- /dev/null +++ b/tools/test/stress2/misc/killpg3.sh @@ -0,0 +1,192 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# killpg(2) version of reaper.sh. No problems seen. + +. ../default.cfg + +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +#include <sys/param.h> +#include <sys/mman.h> +#include <sys/wait.h> + + +#include <err.h> +#include <errno.h> +#include <pwd.h> +#include <signal.h> +#include <stdatomic.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +static _Atomic(int) *share; + +#define GID 0 +#define PARALLEL 10 +#define RDY 1 +#define MAXP 7000 + +static void +hand(int i __unused) { + _exit(0); +} + +static void +innerloop(int parallel) +{ + pid_t pids[MAXP]; + struct sigaction sa; + int i; + + usleep(1000); + for (i = 0; i < parallel; i++) { + if ((pids[i] = fork()) == 0) { + sa.sa_handler = hand; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGUSR1, &sa, NULL) == -1) + err(1, "sigaction"); + atomic_fetch_add(&share[RDY], 1); + setproctitle("child"); + for (;;) + pause(); + _exit(0); /* never reached */ + } + if (pids[i] == -1) + err(1, "fork()"); + } + for (i = 0; i < parallel; i++) { + if (waitpid(pids[i], NULL, 0) != pids[i]) + err(1, "waitpid(%d) in looper", pids[i]); + } + _exit(0); +} + +static void +looper(void) +{ + struct sigaction sa; + struct passwd *pw; + pid_t pids[MAXP]; + int i, parallel; + + setproctitle("looper"); + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction(SIGUSR1, &sa, NULL) == -1) + err(1, "sigaction"); + + if ((pw = getpwnam("TUSER")) == NULL) + err(1, "no such user: TUSER"); + + if (setgroups(1, &pw->pw_gid) || + setegid(pw->pw_gid) || setgid(pw->pw_gid) || + seteuid(pw->pw_uid) || setuid(pw->pw_uid)) + err(1, "Can't drop privileges to \"TUSER\""); + endpwent(); + setpgrp(0, 0); + share[GID] = getpgrp(); + parallel = arc4random() % MAXP + 1; + parallel = parallel / PARALLEL * PARALLEL; + for (i = 0; i < PARALLEL; i++) { + if ((pids[i] = fork()) == 0) + innerloop(parallel / PARALLEL); + } + while (atomic_load(&share[RDY]) != parallel) + usleep(10000); + if (killpg(share[GID], SIGUSR1) == -1) + err(1, "pgkill(%d)", share[GID]); + for (i = 0; i < 4; i++) { + if (waitpid(pids[i], NULL, 0) != pids[i]) + err(1, "waitpid(%d) in looper", pids[i]); + } + _exit(0); +} + +int +main(void) +{ + size_t len; + time_t start; + int lpid, s1; + + len = PAGE_SIZE; + if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) + err(1, "mmap"); + + start = time(NULL); + while (time(NULL) - start < 120) { + share[GID] = 0; + share[RDY] = 0; + if ((lpid = fork()) == 0) + looper(); + if (waitpid(lpid, &s1, 0) != lpid) + err(1, "waitpid looper"); + } + + return (0); +} +EOF +sed -i '' "s#TUSER#$testuser#" /tmp/$prog.c +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1 +rm /tmp/$prog.c + +export MAXSWAPPCT=70 +n=1 +start=`date +%s` +while true; do + ../testcases/swap/swap -t 2m -i 20 > /dev/null & + /tmp/$prog & pid=$! + st=`date +%s` + while kill -0 $pid > /dev/null 2>&1; do + e=$((`date +%s` - st)) + if [ $e -ge 120 ]; then + while pgrep -q swap; do pkill swap; done + fi + if [ $e -ge 600 ]; then + echo "Failed in loop #$n after $e seconds." + ps -jU$testuser | head -20 + kill $pid + pkill -U$testuser + wait + rm -f /tmp/$prog + exit 1 + fi + done + wait + [ $((`date +%s` - start)) -ge 300 ] && break + n=$((n + 1)) +done +rm /tmp/$prog +exit 0 diff --git a/tools/test/stress2/misc/killpg4.sh b/tools/test/stress2/misc/killpg4.sh new file mode 100755 index 000000000000..448a7f60dd4b --- /dev/null +++ b/tools/test/stress2/misc/killpg4.sh @@ -0,0 +1,114 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Another killpg(2) test scenario. No problems seen. + +. ../default.cfg +export prog=$(basename "$0" .sh) +set -u + +cat > /tmp/$prog.c <<EOF +#include <sys/wait.h> +#include <err.h> +#include <time.h> +#include <stdlib.h> +#include <unistd.h> +#define PARALLEL 2 + +int +test(void) +{ + pid_t pid; + time_t start; + + start = time(NULL); + while (time(NULL) - start < 300) { + if ((pid = fork()) == -1) + err(1, "fork()"); + if (pid == 0) { + if (arc4random() % 100 < 20) + usleep(arc4random() % 5000); + _exit(0); /* Not reached */ + } + if (waitpid(pid, NULL, 0) != pid) + err(1, "waitpid()"); + } + _exit(0); +} + +int +main(void) +{ + pid_t pids[PARALLEL]; + int i; + + for (i = 0; i < PARALLEL; i++) { + test(); + } + for (i = 0; i < PARALLEL; i++) { + if (waitpid(pids[i], NULL, 0) != pids[i]) + err(1, "waotpid() main"); + } + +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O2 /tmp/$prog.c || exit 1 + +export MAXSWAPPCT=80 +../testcases/swap/swap -t 2m -i 5 > /dev/null 2>&1 & +sleep .5 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 120 ]; do + for i in `jot 200 100`; do + ( + sl=$prog.$i + sleep=/tmp/$sl + cp /tmp/$prog $sleep + su $testuser -c "$sleep & $sleep & $sleep &" & pid=$! + for j in `jot 10`; do + pgrep -q "$sl" && break + sleep .5 + done + pgrep -q "$sl" || { echo "No start"; exit 1; } + pgid=`pgrep "$sl" | xargs ps -jp | sed 1d | \ + tail -1 | awk '{print $4}'` + [ -z "$pgid" ] && { echo "Zero pgid:$pgid"; ps aj | \ + sed -n "1p;/$sl/p"; exit 1; } + sleep 1.`jot -r 1 2 9` + kill -- -$pgid || { echo "kill -$pgid failed"; exit 1; } + wait $pid + rm -f $sleep + ) & + done + while [ `ps -U$testuser | wc -l` -gt 1 ] ; do sleep 2; done +done +while pkill swap; do :; done +wait +rm /tmp/$prog /tmp/$prog.c +exit 0 diff --git a/tools/test/stress2/misc/kpti.sh b/tools/test/stress2/misc/kpti.sh index c5ca254a48d6..fdd516197482 100755 --- a/tools/test/stress2/misc/kpti.sh +++ b/tools/test/stress2/misc/kpti.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/largepage.sh b/tools/test/stress2/misc/largepage.sh index 7e492de748fa..6e7baeca0bfc 100755 --- a/tools/test/stress2/misc/largepage.sh +++ b/tools/test/stress2/misc/largepage.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/ldt.sh b/tools/test/stress2/misc/ldt.sh index 21c7055d76fe..7b23548c9eea 100755 --- a/tools/test/stress2/misc/ldt.sh +++ b/tools/test/stress2/misc/ldt.sh @@ -284,7 +284,6 @@ EOF cat > fault.c <<EOF /* \$Id: fault.c,v 1.5 2008/10/28 17:39:16 kostik Exp \$ */ -#include <sys/cdefs.h> #include <sys/types.h> #include <sys/ucontext.h> #include <errno.h> diff --git a/tools/test/stress2/misc/linux.sh b/tools/test/stress2/misc/linux.sh index 1cbbfb8b27a1..9f5a14d8324f 100755 --- a/tools/test/stress2/misc/linux.sh +++ b/tools/test/stress2/misc/linux.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/mapwrite.sh b/tools/test/stress2/misc/mapwrite.sh new file mode 100755 index 000000000000..1fef81942b64 --- /dev/null +++ b/tools/test/stress2/misc/mapwrite.sh @@ -0,0 +1,189 @@ +#!/bin/sh + +# File corruption scenario + +# Test program by Rob Norris <rob norris klarasystems com> +# Test program obtained from: https://gist.github.com/robn/9804c60cd0275086d26893d73e7af35c +# https://github.com/openzfs/zfs/issues/15654 + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +/* + * Some kind of clone-related crasher. Not sure if legit or just outdated + * assertion. + * + * Creates clone, maps it, writes from map back into itself. + * + * Compile a recent (2.2+) ZFS with --enable-debug. + * + * cc -o mapwrite mapwrite.c + * + * echo 1 > /sys/modules/zfs/parameters/zfs_bclone_enabled + * zpool create tank ... + * cd /tank + * mapwrite + * + * [ 7.666305] VERIFY(arc_released(db->db_buf)) failed + * [ 7.666443] PANIC at dbuf.c:2150:dbuf_redirty() + * [ 7.666489] Showing stack for process 608 + * [ 7.666534] CPU: 1 PID: 608 Comm: mapwrite Tainted: P O 5.10.170 #3 + * [ 7.666610] Call Trace: + * [ 7.666646] dump_stack+0x57/0x6e + * [ 7.666717] spl_panic+0xd3/0xfb [spl] + * [ 7.667113] ? zfs_btree_find+0x16a/0x300 [zfs] + * [ 7.667278] ? range_tree_find_impl+0x55/0xa0 [zfs] + * [ 7.667333] ? _cond_resched+0x1a/0x50 + * [ 7.667371] ? __kmalloc_node+0x14a/0x2b0 + * [ 7.667415] ? spl_kmem_alloc_impl+0xb0/0xd0 [spl] + * [ 7.667555] ? __list_add+0x12/0x30 [zfs] + * [ 7.667681] spl_assert+0x17/0x20 [zfs] + * [ 7.667807] dbuf_redirty+0xad/0xb0 [zfs] + * [ 7.667963] dbuf_dirty+0xe76/0x1310 [zfs] + * [ 7.668011] ? mutex_lock+0xe/0x30 + * [ 7.668133] ? dbuf_noread+0x112/0x240 [zfs] + * [ 7.668271] dmu_write_uio_dnode+0x101/0x1b0 [zfs] + * [ 7.668411] dmu_write_uio_dbuf+0x4a/0x70 [zfs] + * [ 7.668555] zfs_write+0x500/0xc80 [zfs] + * [ 7.668610] ? page_add_file_rmap+0xe/0xb0 + * [ 7.668740] zpl_iter_write+0xe4/0x130 [zfs] + * [ 7.668803] new_sync_write+0x119/0x1b0 + * [ 7.668843] vfs_write+0x1ce/0x260 + * [ 7.668880] __x64_sys_pwrite64+0x91/0xc0 + * [ 7.668918] do_syscall_64+0x30/0x40 + * [ 7.668957] entry_SYSCALL_64_after_hwframe+0x61/0xc6 + */ + +#define _GNU_SOURCE + +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/mman.h> + +#define DATASIZE (1024*1024) +char data[DATASIZE]; + +#define NDATA (512) + +#define FILE_NAME "file" +#define CLONE_NAME "clone" + +static int +_create_file(void) +{ + memset(data, 0x5a, DATASIZE); + + int fd; + if ((fd = open(FILE_NAME, O_RDWR | O_CREAT | O_APPEND, + S_IRUSR | S_IWUSR)) < 0) { + perror("open '" FILE_NAME "'"); + abort(); + } + + for (int i = 0; i < NDATA; i++) { + int nwr = write(fd, data, DATASIZE); + if (nwr < 0) { + perror("write"); + abort(); + } + if (nwr < DATASIZE) { + fprintf(stderr, "short write\n"); + abort(); + } + } + + if (lseek(fd, 0, SEEK_SET) < 0) { + perror("lseek"); + abort(); + } + + sync(); + + return (fd); +} + +static int +_clone_file(int sfd) +{ + int dfd; + if ((dfd = open(CLONE_NAME, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { + perror("open '" CLONE_NAME "'"); + abort(); + } + + if (copy_file_range(sfd, 0, dfd, 0, DATASIZE * NDATA, 0) < 0) { + perror("copy_file_range"); + abort(); + } + + return (dfd); +} + +static void * +_map_file(int fd) +{ + void *p = mmap(NULL, DATASIZE*NDATA, PROT_READ, MAP_SHARED, fd, 0); + if (p == MAP_FAILED) { + perror("mmap"); + abort(); + } + + return (p); +} + +static void +_map_write(void *p, int fd) +{ + if (pwrite(fd, p, DATASIZE, 0) < 0) { + perror("pwrite"); + abort(); + } +} + +int +main(void) +{ + int sfd = _create_file(); + int dfd = _clone_file(sfd); + void *p = _map_file(dfd); + _map_write(p, dfd); + return (0); +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O2 /tmp/$prog.c || exit 1 + +mount | grep -q "on $mntpoint " && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -s 5g -u $mdstart + +newfs -n $newfs_flags /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint + +mycc -o /tmp/swap -Wall -Wextra -O0 ../tools/swap.c || exit 1 +timeout -k 90 60 /tmp/swap -d 100 & +for i in `jot 10`; do + capacity=`swapinfo | tail -1 | sed 's/.* //; s/%//'` + [ $capacity -gt 1 ] && break + sleep 2 # Wait for swapping +done + +cd $mntpoint +/tmp/$prog; s=$? +pkill swap +wait +cmp $mntpoint/file $mntpoint/clone || { echo Fail; s=1; } +cd - + +umount $mntpoint +mdconfig -d -u $mdstart +rm /tmp/$prog /tmp/$prog.c +exit $s diff --git a/tools/test/stress2/misc/marcus6.sh b/tools/test/stress2/misc/marcus6.sh index 1a209b2256ee..e541a552233e 100755 --- a/tools/test/stress2/misc/marcus6.sh +++ b/tools/test/stress2/misc/marcus6.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/marcus7.sh b/tools/test/stress2/misc/marcus7.sh index e196a1e60269..ac34c5419a14 100755 --- a/tools/test/stress2/misc/marcus7.sh +++ b/tools/test/stress2/misc/marcus7.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/marcus8.sh b/tools/test/stress2/misc/marcus8.sh new file mode 100755 index 000000000000..0c6110c8ec4c --- /dev/null +++ b/tools/test/stress2/misc/marcus8.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +# Run with marcus.cfg on a 5g swap backed MD with UFS non SU fs. +# Check for non empty file system after test. + +. ../default.cfg + +set -u +mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 4g -u $mdstart +newfs_flags="" # With SU this test runs out of disk space +newfs $newfs_flags md$mdstart > /dev/null +tunefs -n disable md$mdstart # Remove the default SU flag +mount /dev/md$mdstart $mntpoint +chmod 777 $mntpoint + +export runRUNTIME=5m +export CTRLDIR=$mntpoint/stressX.control +export RUNDIR=$mntpoint/stressX + +su $testuser -c 'cd ..; ./run.sh marcus.cfg' + +nb=`find $RUNDIR | wc -l` +[ $nb -gt 1 ] && { find $RUNDIR -ls | head -12; s=1; } || s=0 +n=0 +while mount | grep $mntpoint | grep -q /dev/md; do + umount $mntpoint || sleep 1 + [ $((n += 1)) -gt 300 ] && { echo FAIL; exit 1; } +done +checkfs /dev/md$mdstart; s2=$? +mdconfig -d -u $mdstart +exit $((s + s2)) diff --git a/tools/test/stress2/misc/mdconfig3.sh b/tools/test/stress2/misc/mdconfig3.sh index 7fbdcbc1a5ff..5c145e34cc6d 100755 --- a/tools/test/stress2/misc/mdconfig3.sh +++ b/tools/test/stress2/misc/mdconfig3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/mdconfig4.sh b/tools/test/stress2/misc/mdconfig4.sh index c8e0530741c0..284ce1b08045 100755 --- a/tools/test/stress2/misc/mdconfig4.sh +++ b/tools/test/stress2/misc/mdconfig4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/mdconfig5.sh b/tools/test/stress2/misc/mdconfig5.sh index b0b25cc5d64b..b3ecd913bc4b 100755 --- a/tools/test/stress2/misc/mdconfig5.sh +++ b/tools/test/stress2/misc/mdconfig5.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm # diff --git a/tools/test/stress2/misc/midi.sh b/tools/test/stress2/misc/midi.sh index 47594734b4e0..de9161e262ca 100755 --- a/tools/test/stress2/misc/midi.sh +++ b/tools/test/stress2/misc/midi.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Mark Johnston <markj@freebsd.org> # diff --git a/tools/test/stress2/misc/midi2.sh b/tools/test/stress2/misc/midi2.sh index 91f15aa3cc3b..80a485437dbb 100755 --- a/tools/test/stress2/misc/midi2.sh +++ b/tools/test/stress2/misc/midi2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/mincore.sh b/tools/test/stress2/misc/mincore.sh index 85c09cc0ceaf..8f42971144a7 100755 --- a/tools/test/stress2/misc/mincore.sh +++ b/tools/test/stress2/misc/mincore.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/minherit.sh b/tools/test/stress2/misc/minherit.sh index facb018a0337..ba5b0d9d1aeb 100755 --- a/tools/test/stress2/misc/minherit.sh +++ b/tools/test/stress2/misc/minherit.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Peter Holm # diff --git a/tools/test/stress2/misc/mkdir.sh b/tools/test/stress2/misc/mkdir.sh new file mode 100755 index 000000000000..734b8994ad4e --- /dev/null +++ b/tools/test/stress2/misc/mkdir.sh @@ -0,0 +1,81 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Demonstrate incorrect "out of inodes" message with SU enabled. +# No issue seen with SU+J + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +set -eu +prog=$(basename "$0" .sh) +log=/tmp/$prog.log +s=0 +mount | grep -q "on $mntpoint " && umount $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 100m -u $mdstart +[ $# -eq 1 ] && flags="$@" || flags="-Un" +echo "newfs $flags /dev/md$mdstart" +newfs $flags /dev/md$mdstart > /dev/null +[ "$flags" = "" ] && tunefs -n disable md$mdstart +mount /dev/md$mdstart $mntpoint +set +e + +ifree1=`df -i $mntpoint | tail -1 | awk '{print $7}'` +before=`df -i $mntpoint` +n=$(((ifree1 - 5) / 10)) +jot 10 | xargs -I% mkdir $mntpoint/% +start=`date +%s` +while [ $((`date +%s` - start)) -lt 180 ]; do + for j in `jot 10`; do + jot $n | xargs -P0 -I% mkdir $mntpoint/$j/% + jot $n | xargs -P0 -I% rmdir $mntpoint/$j/% + done +done 2>&1 | tee $log | head -5 +[ -s $log ] && s=3 +jot 10 | xargs -I% rmdir $mntpoint/% +umount $mntpoint; mount /dev/md$mdstart $mntpoint + +ifree2=`df -i $mntpoint | tail -1 | awk '{print $7}'` +after=`df -i $mntpoint | tail -1` +if [ $ifree1 -ne $ifree2 ]; then + echo "$before" + echo "$after" + s=1 + ls -alsrt $mntpoint | head -20 +fi + +umount $mntpoint +fsck -fy /dev/md$mdstart > $log 2>&1 +grep -Eq "WAS MODIFIED" $log && { s=2; cat $log; } + +mdconfig -d -u $mdstart +rm -f $log +exit $s diff --git a/tools/test/stress2/misc/mkfifo5.sh b/tools/test/stress2/misc/mkfifo5.sh index c0355cef2db0..96d30e5fe024 100755 --- a/tools/test/stress2/misc/mkfifo5.sh +++ b/tools/test/stress2/misc/mkfifo5.sh @@ -26,7 +26,7 @@ # SUCH DAMAGE. # -# mkfifo(2), select(2) with tmpfs(5) scenario. +# mkfifo(2), select(2) with tmpfs(4) scenario. . ../default.cfg [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 diff --git a/tools/test/stress2/misc/mkfifo6.sh b/tools/test/stress2/misc/mkfifo6.sh index 5647bf9493d6..13a62b5e0286 100755 --- a/tools/test/stress2/misc/mkfifo6.sh +++ b/tools/test/stress2/misc/mkfifo6.sh @@ -26,7 +26,7 @@ # SUCH DAMAGE. # -# mkfifo(2), select(2) with tmpfs(5) scenario. +# mkfifo(2), select(2) with tmpfs(4) scenario. . ../default.cfg [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 diff --git a/tools/test/stress2/misc/mkfifo7.sh b/tools/test/stress2/misc/mkfifo7.sh index b17e84536bed..c1af3374526e 100755 --- a/tools/test/stress2/misc/mkfifo7.sh +++ b/tools/test/stress2/misc/mkfifo7.sh @@ -26,7 +26,7 @@ # SUCH DAMAGE. # -# mkfifo(2), poll(2) with tmpfs(5) scenario. +# mkfifo(2), poll(2) with tmpfs(4) scenario. . ../default.cfg [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 diff --git a/tools/test/stress2/misc/mkfifo8.sh b/tools/test/stress2/misc/mkfifo8.sh index 6227070f016e..eeed86bd98ec 100755 --- a/tools/test/stress2/misc/mkfifo8.sh +++ b/tools/test/stress2/misc/mkfifo8.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/mlockall4.sh b/tools/test/stress2/misc/mlockall4.sh index 778256fa8976..66ae05fa4ae1 100755 --- a/tools/test/stress2/misc/mlockall4.sh +++ b/tools/test/stress2/misc/mlockall4.sh @@ -26,7 +26,7 @@ # SUCH DAMAGE. # -# mlockall(2) / nullfs(5) scenario causes: +# mlockall(2) / nullfs(4) scenario causes: # http://people.freebsd.org/~pho/stress/log/kostik619.txt # kern/182661, fixed in r256211. diff --git a/tools/test/stress2/misc/mlockall6.sh b/tools/test/stress2/misc/mlockall6.sh index 33b20ce3137a..b47f9be9bb1e 100755 --- a/tools/test/stress2/misc/mlockall6.sh +++ b/tools/test/stress2/misc/mlockall6.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # @@ -30,6 +30,9 @@ # "panic: Lock (rw) vm object not locked @ vm/vm_page.c:1013" seen: # https://people.freebsd.org/~pho/stress/log/mlockall6-2.txt +# "panic: vm_page_unwire: wire count underflow for page..." seen: +# https://people.freebsd.org/~pho/stress/log/log0430.txt + . ../default.cfg [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 diff --git a/tools/test/stress2/misc/mmap10.sh b/tools/test/stress2/misc/mmap10.sh index a29768c36691..0bb7845f4d15 100755 --- a/tools/test/stress2/misc/mmap10.sh +++ b/tools/test/stress2/misc/mmap10.sh @@ -40,18 +40,22 @@ sed '1,/^EOF/d' < $here/$0 > mmap10.c mycc -o mmap10 -Wall -Wextra -O2 -g mmap10.c -lpthread || exit 1 rm -f mmap10.c -daemon sh -c "(cd $here/../testcases/swap; ./swap -t 2m -i 20 -k)" +daemon sh -c "(cd $here/../testcases/swap; ./swap -t 2m -i 20 -k > /dev/null)" +ulimit -c 0 sleep `jot -r 1 0 9` for i in `jot 2`; do - /tmp/mmap10 & + su $testuser -c /tmp/mmap10 & done -sleep 300 +start=`date +%s` while pgrep -q mmap10; do - pkill -9 mmap10 + [ $((`date +%s` - start)) -ge 300 ] && break + sleep 2 +done +while pgrep -q 'mmap10|swap'; do + pkill -9 mmap10 swap sleep 2 done wait -killall -q swap rm -f /tmp/mmap10 /tmp/mmap10.core exit 0 @@ -76,6 +80,7 @@ EOF #define N (128 * 1024 / (int)sizeof(u_int32_t)) #define PARALLEL 50 +static int debug = 0; /* set to "1" for debug output */ void *p; u_int32_t r[N]; @@ -169,7 +174,7 @@ tmlock(void *arg __unused) if (munlock(makeptr(), len) == 0) n++; } - if (n < 10) + if (debug == 1 && n < 10) fprintf(stderr, "Note: tmlock() only succeeded %d times.\n", n); @@ -193,7 +198,7 @@ tmprotect(void *arg __unused) n++; usleep(1000); } - if (n < 10) + if (debug == 1 && n < 10) fprintf(stderr, "Note: tmprotect() only succeeded %d times.\n", n); @@ -215,7 +220,7 @@ tmlockall(void *arg __unused) munlockall(); usleep(1000); } - if (n < 10) + if (debug == 1 && n < 10) fprintf(stderr, "Note: tmlockall() only succeeded %d times.\n", n); diff --git a/tools/test/stress2/misc/mmap18.sh b/tools/test/stress2/misc/mmap18.sh index 065b5bb7df6c..f2b19c07fe60 100755 --- a/tools/test/stress2/misc/mmap18.sh +++ b/tools/test/stress2/misc/mmap18.sh @@ -89,6 +89,7 @@ EOF static u_int32_t r[N]; static void *p; +static int debug; /* set to 1 for debug output */ static unsigned long makearg(void) @@ -176,11 +177,9 @@ tmlock(void *arg __unused) if (munlock(makeptr(), len) == 0) n++; } -#if defined(DEBUG) - if (n < 10) + if (debug != 0 && n < 10) fprintf(stderr, "Note: tmlock() only succeeded %d " "times.\n", n); -#endif return (NULL); } @@ -202,11 +201,9 @@ tmprotect(void *arg __unused) n++; usleep(1000); } -#if defined(DEBUG) - if (n < 10) + if (debug != 0 && n < 10) fprintf(stderr, "Note: tmprotect() only succeeded %d " "times.\n", n); -#endif return (NULL); } @@ -226,11 +223,9 @@ tmlockall(void *arg __unused) munlockall(); usleep(1000); } -#if defined(DEBUG) - if (n < 10) + if (debug != 0 && n < 10) fprintf(stderr, "Note: tmlockall() only succeeded %d " "times.\n", n); -#endif return (NULL); } diff --git a/tools/test/stress2/misc/mmap32.sh b/tools/test/stress2/misc/mmap32.sh index a775b756084e..334327a85989 100755 --- a/tools/test/stress2/misc/mmap32.sh +++ b/tools/test/stress2/misc/mmap32.sh @@ -62,6 +62,7 @@ EOF #include <unistd.h> #define N 4096 +static int debug; /* set to 1 for debug output */ static uint32_t r[N]; static unsigned long @@ -133,10 +134,8 @@ fuzz(int arg, void *addr, size_t len, int prot, int flags, int fd, n++; } } -#if defined(DEBUG) - if (n == 0 && arg != 5) + if (debug != 0 &&n == 0 && arg != 5) fprintf(stderr, "%s(%d) failed\n", __func__, arg); -#endif exit(0); } diff --git a/tools/test/stress2/misc/mmap33.sh b/tools/test/stress2/misc/mmap33.sh index de7262c1bf1f..8ecd9e22180b 100755 --- a/tools/test/stress2/misc/mmap33.sh +++ b/tools/test/stress2/misc/mmap33.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/mmap34.sh b/tools/test/stress2/misc/mmap34.sh index 02bd193421b9..f1bf09200d8a 100755 --- a/tools/test/stress2/misc/mmap34.sh +++ b/tools/test/stress2/misc/mmap34.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/mmap35.sh b/tools/test/stress2/misc/mmap35.sh index 6e76434e77ec..f613b7006a89 100755 --- a/tools/test/stress2/misc/mmap35.sh +++ b/tools/test/stress2/misc/mmap35.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/mmap36.sh b/tools/test/stress2/misc/mmap36.sh index 89fc6721fbeb..4a38d5073344 100755 --- a/tools/test/stress2/misc/mmap36.sh +++ b/tools/test/stress2/misc/mmap36.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/mmap37.sh b/tools/test/stress2/misc/mmap37.sh index f5e25a282927..9d5f9d74c1c7 100755 --- a/tools/test/stress2/misc/mmap37.sh +++ b/tools/test/stress2/misc/mmap37.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/mmap38.sh b/tools/test/stress2/misc/mmap38.sh index b4cf60afe25b..06ff8770f36f 100755 --- a/tools/test/stress2/misc/mmap38.sh +++ b/tools/test/stress2/misc/mmap38.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/mmap39.sh b/tools/test/stress2/misc/mmap39.sh index f4b97717624b..d94b40593a10 100755 --- a/tools/test/stress2/misc/mmap39.sh +++ b/tools/test/stress2/misc/mmap39.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/mmap40.sh b/tools/test/stress2/misc/mmap40.sh index 4bf60fc8f44d..2314596e2f5d 100755 --- a/tools/test/stress2/misc/mmap40.sh +++ b/tools/test/stress2/misc/mmap40.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # @@ -53,13 +53,14 @@ mount /dev/md$mdstart $mntpoint set +e u1=`swapinfo | tail -1 | awk '{print $3}'` -(nice $odir/../testcases/swap/swap -t 10m -i 30 -h -l 100) & -while [ $((`swapinfo | tail -1 | awk '{print $3}'` - $u1)) -le 100 ]; do +(nice $odir/../testcases/swap/swap -t 10m -i 30 -h -l 100) > /dev/null & +for i in `jot 120`; do + u2=`swapinfo | tail -1 | awk '{print $3}'` + [ $u2 -lt $u1 ] && u1=$u2 + [ $((u2 - $u1)) -gt 100 ] && break sleep 1 done - -$dir/mmap40 -s=0 +/usr/bin/timeout 10m $dir/mmap40; s=$? while pkill swap; do :; done wait [ -f mmap40.core -a $s -eq 0 ] && diff --git a/tools/test/stress2/misc/mmap41.sh b/tools/test/stress2/misc/mmap41.sh new file mode 100755 index 000000000000..5051681aaf31 --- /dev/null +++ b/tools/test/stress2/misc/mmap41.sh @@ -0,0 +1,160 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Based on code from https://syzkaller.appspot.com/text?tag=ReproC&x=15d9baada80000 +# No problems seen + +. ../default.cfg + +prog=$(basename "$0" .sh) +odir=`pwd` +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > $prog.c +mycc -o $prog -Wall -Wextra -O0 $prog.c -lpthread || exit 1 +rm -f $prog.c + +set -e +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 2g -u $mdstart +newfs $newfs_flags md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +set +e + +$odir/../testcases/swap/swap -t 2m -i 10 > /dev/null & +cd $mntpoint +/tmp/$prog +cd $odir +while pkill swap; do :; done +wait + +for i in `jot 6`; do + mount | grep -q "on $mntpoint " || break + umount $mntpoint && break || sleep 10 + [ $i -eq 6 ] && + { echo FATAL; fstat -mf $mntpoint; exit 1; } +done +mdconfig -d -u $mdstart +rm -f /tmp/$prog +exit 0 + +EOF +#include <sys/param.h> +#include <sys/mman.h> +#include <sys/uio.h> +#include <sys/wait.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define DEBUG 0 /* 1 to enable */ +#define THREADS 2 + +static volatile int go; +static int fd; +static char *p, path[128]; + +#define ADDR (void *) 0x20000000ul +#define LEN 0x1000000ul + +void * +thr(void *arg) +{ + struct iovec iov; + long n, w; + char *p1; + + if (*(int *)arg == 0) { + while (go == 0) + usleep(100); + while (go == 1) { + if ((p1 = mmap(ADDR, LEN, PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0)) == MAP_FAILED) + err(1, "mmap() in %s", __func__); + usleep(arc4random() % 50); + if ((p1 = mmap(ADDR, LEN, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0)) == MAP_FAILED) + err(1, "mmap() in %s", __func__); + usleep(arc4random() % 10000); + } + } else { + while (go == 0) + usleep(100); + n = w = 0; + while (go == 1) { + iov.iov_base = p; + iov.iov_len = 0x100000; + if (pwritev(fd, &iov, 1, 0) != -1) + w++; + n++; + } + if (DEBUG == 1) + fprintf(stderr, "%ld out of %ld writes (%ld%%)\n", w, n, w * 100 / n); + } + + + return (0); +} + +void +test(void) +{ + pthread_t threads[THREADS]; + int nr[THREADS]; + int i, r; + + sprintf(path, "mmap.%06d", getpid()); + if ((fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0622)) == -1) + err(1,"open()"); + + + if ((p = mmap(ADDR, LEN, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0)) == MAP_FAILED) + err(1, "mmap() in %s", __func__); + + go = 0; + for (i = 0; i < THREADS; i++) { + nr[i] = i; + if ((r = pthread_create(&threads[i], NULL, thr, + (void *)&nr[i])) != 0) + errc(1, r, "pthread_create()"); + } + + go = 1; + sleep(60); + go = 2; + + for (i = 0; i < THREADS; i++) { + if ((r = pthread_join(threads[i], NULL)) != 0) + errc(1, r, "pthread_join(%d)", i); + } + close(fd); + if (DEBUG == 0) { + if (unlink(path) == -1) + err(1, "unlink(%s)", path); + } + + _exit(0); +} + +int +main(void) +{ + pid_t pid; + int i; + + for (i = 0; i < 2; i++) { + if ((pid = fork()) == 0) + test(); + if (waitpid(pid, NULL, 0) != pid) + err(1, "waitpid()"); + } +} diff --git a/tools/test/stress2/misc/mmap42.sh b/tools/test/stress2/misc/mmap42.sh new file mode 100755 index 000000000000..11235e581e73 --- /dev/null +++ b/tools/test/stress2/misc/mmap42.sh @@ -0,0 +1,101 @@ +#!/bin/sh + +# Test scenario by: kib@ +# Test program obtained from Kyle Evans <kevans@FreeBSD.org> + +# Demonstrate UFS SU file corruption: +# ffs: on write into a buffer without content + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +set -u +prog=$(basename "$0" .sh) +s=0 +cat > /tmp/$prog.c <<EOF +#include <sys/mman.h> +#include <sys/stat.h> + +#include <assert.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> + +#define FILE "file" + +int +main(void) +{ + struct stat sb; + ssize_t wsz; + size_t bufsz; + void *buf, *obuf; + int mfd, fd; + int done = 0; + + mfd = open(FILE, O_RDONLY); + assert(mfd >= 0); + + assert(fstat(mfd, &sb) == 0); + bufsz = sb.st_size; + buf = obuf = mmap(NULL, bufsz, PROT_READ, MAP_SHARED, mfd, 0); + assert(buf != MAP_FAILED); + + /* O_RDWR */ + fd = open(FILE, O_RDWR); + if (fd < 0) + err(1, "open"); + assert(fd >= 0); + +again: + while (bufsz > 0) { + wsz = write(fd, buf, bufsz); + if (wsz < 0) + err(1, "write"); + else if (wsz == 0) + fprintf(stderr, "Huh?\n"); + bufsz -= wsz; + buf += wsz; + } + + bufsz = sb.st_size; + buf = obuf; + + if (++done < 2) + goto again; + + close(fd); + munmap(obuf, sb.st_size); + close(mfd); + return (0); +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1 + +mount | grep -q "on $mntpoint " && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -s 32m -u $mdstart + +pagesize=$(sysctl -n hw.pagesize) +newfs -Un -b $pagesize /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +dd if=/dev/random of=/mnt/file.orig bs=${pagesize} count=1 status=none +cp $mntpoint/file.orig $mntpoint/file +cat $mntpoint/file $mntpoint/file > $mntpoint/file.post +umount $mntpoint + +mount /dev/md$mdstart $mntpoint +(cd $mntpoint; /tmp/$prog) + +if ! cmp $mntpoint/file $mntpoint/file.post; then + echo "Files differ" + ls -l $mntpoint/file $mntpoint/file.post + s=1 +fi + +umount $mntpoint +mdconfig -d -u $mdstart +rm /tmp/$prog /tmp/$prog.c +exit $s diff --git a/tools/test/stress2/misc/mmap43.sh b/tools/test/stress2/misc/mmap43.sh new file mode 100755 index 000000000000..98f1de174d54 --- /dev/null +++ b/tools/test/stress2/misc/mmap43.sh @@ -0,0 +1,182 @@ +#!/bin/sh + +# Test program obtained from Kyle Evans <kevans@FreeBSD.org> + +# Demonstrate UFS SU file corruption + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +set -u +prog=$(basename "$0" .sh) +log=/tmp/$prog.log +rm -f $log +cat > /tmp/$prog.c <<EOF +#include <sys/mman.h> +#include <sys/stat.h> + +#include <assert.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> + +#define FILE "file" + +int +main(void) +{ + struct stat sb; + ssize_t wsz; + size_t bufsz; + void *buf, *obuf; + int mfd, fd; + int done = 0; + + mfd = open(FILE, O_RDONLY); + assert(mfd >= 0); + + assert(fstat(mfd, &sb) == 0); + bufsz = sb.st_size; + buf = obuf = mmap(NULL, bufsz, PROT_READ, MAP_SHARED, mfd, 0); + assert(buf != MAP_FAILED); + + /* O_RDWR */ + fd = open(FILE, O_RDWR); + if (fd < 0) + err(1, "open"); + assert(fd >= 0); + +again: + while (bufsz > 0) { + wsz = write(fd, buf, bufsz); + if (wsz < 0) + err(1, "write"); + else if (wsz == 0) + fprintf(stderr, "Huh?\n"); + bufsz -= wsz; + buf += wsz; + } + + bufsz = sb.st_size; + buf = obuf; + + if (++done < 2) + goto again; + + close(fd); + munmap(obuf, sb.st_size); + close(mfd); + return (0); +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1 + +cat > /tmp/$prog.serial.c <<EOF +/* Fill a file with sequential numbers */ +#include <sys/param.h> +#include <sys/mman.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int +main(int argc, char *argv[]) +{ + size_t i, size; + long ix, *lp; + int fd; + char *file; + + if (argc != 3) { + fprintf(stderr, "Usage: %s <file> <file length in bytes>\n", argv[0]); + exit(1); + } + file = argv[1]; + size = atol(argv[2]); + + if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) + err(1, "%s", file); + + if (lseek(fd, size - 1, SEEK_SET) == -1) + err(1, "lseek error"); + + /* write a dummy byte at the last location */ + if (write(fd, "\0", 1) != 1) + err(1, "write error"); + + if ((lp = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) + err(1, "mmap()"); + + for (i = 0, ix = 0; i < size; i += sizeof(long), ix++) + lp[ix] = ix; + + if (munmap(lp, size) == -1) + err(1, "munmap"); + close(fd); +} +EOF +mycc -o /tmp/$prog.serial -Wall -Wextra -O0 /tmp/$prog.serial.c || exit 1 + +mount | grep -q "on $mntpoint " && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -s 5g -u $mdstart + +newfs -n $newfs_flags /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint + +here=`pwd` +cd $mntpoint + +size=875998990 +pagesize=`sysctl -n hw.pagesize` +tail=$((size % pagesize)) +/tmp/$prog.serial file $size + +cat file file > file.post +mv file file.orig +md5=`md5 < file.post` + +cp /usr/bin/sort /tmp/$prog.sort +counter=1 +n=$((`sysctl -n hw.ncpu`)) +[ $n -gt 10 ] && n=10 +s=0 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 300 ]; do + st=`date +%s` + cp file.orig file + for i in `jot $n`; do + timeout -k 70s 1m /tmp/$prog.sort /dev/zero & + done + sleep $n + /tmp/$prog + while pkill $prog.sort; do sleep .2; done + wait + m=`md5 < file` + if [ $md5 != $m ]; then + echo "Failed @ iteration $counter" + ls -l + od -t x8 file > /var/tmp/$prog.file1 + od -t x8 file.post > /var/tmp/$prog.file2 + diff /var/tmp/$prog.file1 /var/tmp/$prog.file2 > $log + head -10 $log + rm /var/tmp/$prog.file1 /var/tmp/$prog.file2 + s=1 + break + fi + echo "`date +%T` Loop #$counter, elapsed $((`date +%s` - st)) seconds." + counter=$((counter + 1)) +done +cd $here + +umount $mntpoint +mdconfig -d -u $mdstart +rm /tmp/$prog /tmp/$prog.c /tmp/$prog.sort +[ $s -eq 0 ] && + printf "OK File size is %9d, tail is %4d bytes. (%3d loops)\n" $size $tail $counter || + printf "FAIL File size is %9d, tail is %4d bytes. (%3d loops)\n" $size $tail $counter +exit $s diff --git a/tools/test/stress2/misc/mmap44.sh b/tools/test/stress2/misc/mmap44.sh new file mode 100755 index 000000000000..f5999ac62536 --- /dev/null +++ b/tools/test/stress2/misc/mmap44.sh @@ -0,0 +1,255 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Demonstrate issue described in: +# [Bug 276002] nfscl: data corruption using both copy_file_range and mmap'd I/O + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +log=/tmp/$prog.log +grep -q $mntpoint /etc/exports || + { echo "$mntpoint missing from /etc/exports"; exit 0; } + +cat > /tmp/$prog.c <<EOF +#include <sys/mman.h> +#include <sys/stat.h> + +#include <err.h> +#include <fcntl.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static off_t siz; +static pthread_mutex_t write_mutex; +static int fd, go; +static char *cp; + +static void * +memread(void *arg __unused) +{ + int i; + char c; + + while (go == 1) { + i = arc4random() % siz; + c = cp[i]; + if (c != 0x77) /* No unused vars here */ + usleep(arc4random() % 400); + } + return (0); +} + +static void * +memwrite(void *arg __unused) +{ + int i; + char c; + + while (go == 1) { + i = arc4random() % siz; + pthread_mutex_lock(&write_mutex); + c = cp[i]; + cp[i] = 0xee; /* This value seems to linger with NFS */ + cp[i] = c; + pthread_mutex_unlock(&write_mutex); + usleep(arc4random() % 400); + } + return (0); +} + +static void * +wr(void *arg __unused) +{ + off_t pos; + int r, s; + char buf[1024]; + + while (go == 1) { + s = arc4random() % sizeof(buf) + 1; + pos = arc4random() % (siz - s); + pthread_mutex_lock(&write_mutex); + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "lseek(%d)", (int)pos); + if ((r = read(fd, buf, s)) != s) { + fprintf(stderr, "r = %d, s = %d, pos = %d\n", r, s, (int)pos); + err(1, "read():2"); + } + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "lseek(%d)", (int)pos); + if (write(fd, buf, s) != s) + err(1, "write()"); + pthread_mutex_unlock(&write_mutex); + usleep(arc4random() % 400); + } + return (0); +} + +static void * +s1(void *arg __unused) +{ + + while (go == 1) { + if (fdatasync(fd) == -1) + err(1, "fdatasync()"); + usleep(arc4random() % 1000); + } + return (0); +} + +static void * +s2(void *arg __unused) +{ + + while (go == 1) { + if (fsync(fd) == -1) + err(1, "fdatasync()"); + usleep(arc4random() % 1000); + } + return (0); +} + +static void * +tr(void *arg __unused) +{ + int i, s; + char buf[1024]; + + memset(buf, 0x5a, sizeof(buf)); + while (go == 1) { + pthread_mutex_lock(&write_mutex); + if (lseek(fd, arc4random() % siz, SEEK_END) == -1) + err(1, "lseek() END"); + s = sizeof(buf); + for (i = 0; i < 50; i++) { + if (write(fd, buf, s) != s) + warn("write()"); + } + if (ftruncate(fd, siz) == -1) + err(1, "truncate()"); + pthread_mutex_unlock(&write_mutex); + usleep(arc4random() % 400); + } + return (0); +} + +int +main(int argc, char *argv[]) +{ + struct stat st; + pthread_t tp[6]; + int e, i; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <file>\n", argv[0]); + exit(1); + } + if ((fd = open(argv[1], O_RDWR)) == -1) + err(1, "open(%s)", argv[1]); + if (fstat(fd, &st) == -1) + err(1, "stat(%s)", argv[1]); + siz = st.st_size; + cp = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (cp == MAP_FAILED) + err(1, "mmap()"); + + go = 1; + pthread_mutex_init(&write_mutex, NULL); + if ((e = pthread_create(&tp[0], NULL, memwrite, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[1], NULL, memread, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[2], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[3], NULL, s1, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[4], NULL, s2, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[5], NULL, tr, NULL)) != 0) + errc(1, e, "pthread_create"); + + sleep(60); + go = 0; + for (i = 0; i < (int)(sizeof(tp) / sizeof(tp[0])); i++) + pthread_join(tp[i], NULL); + if (munmap(cp, siz) == -1) + err(1, "munmap()"); + close(fd); +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +mycc -o /tmp/serial -Wall -Wextra -O2 ../tools/serial.c || exit 1 +mount | grep -q "on $mntpoint " && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -s 5g -u $mdstart +newfs -n $newfs_flags /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint + +mp2=${mntpoint}2 +mkdir -p $mp2 +mount | grep -q "on $mp2 " && umount -f $mp2 +mount -t nfs -o retrycnt=3 127.0.0.1:$mntpoint $mp2 || exit 1 +sleep .2 + +here=`pwd` +mount | grep $mntpoint +cd $mp2 +$here/../testcases/swap/swap -t 5m -i 20 > /dev/null & +sleep 2 + +size=262144 +/tmp/serial file $size +cp file file.orig + +s=0 +/tmp/$prog file || s=1 + +while pgrep -q swap; do pkill swap; done +wait +if ! cmp -s file.orig file; then + od -t x1 file.orig > /var/tmp/$prog.file1 + od -t x1 file > /var/tmp/$prog.file2 + diff /var/tmp/$prog.file1 /var/tmp/$prog.file2 > $log + head -20 $log + rm /var/tmp/$prog.file1 /var/tmp/$prog.file2 + ls -ls file.orig file + s=2 +fi + +cd $here +umount $mp2 +umount $mntpoint +mdconfig -d -u $mdstart +rm -f /tmp/serial /tmp/$prog /tmp/$prog.c $log +exit $s diff --git a/tools/test/stress2/misc/mmap45.sh b/tools/test/stress2/misc/mmap45.sh new file mode 100755 index 000000000000..59450b41bb5e --- /dev/null +++ b/tools/test/stress2/misc/mmap45.sh @@ -0,0 +1,230 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Demonstrate issue described in: +# [Bug 276002] nfscl: data corruption using both copy_file_range and mmap'd I/O + +# Issue seen: +# +# 8994c8994 +# < 0431020 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f +# --- +# > 0431020 10 11 ee 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f +# 256 -rw------- 1 root wheel 262144 Feb 28 19:44 file +# 256 -rw------- 1 root wheel 262144 Feb 28 19:43 file.orig +# 19:44:34, elapsed 0 days, 00:13.59 +# Failed with exit code 2 after 13 loops. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +log=/tmp/$prog.log +serial=/tmp/$prog.serial +grep -q $mntpoint /etc/exports || + { echo "$mntpoint missing from /etc/exports"; exit 0; } +rpcinfo 2>/dev/null | grep -q mountd || exit 0 + +cat > /tmp/$prog.c <<EOF +#include <sys/mman.h> +#include <sys/stat.h> + +#include <err.h> +#include <fcntl.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static off_t siz; +static pthread_mutex_t write_mutex; +static int fd, go; +static char *cp; + +static void * +memread(void *arg __unused) +{ + int i; + char c; + + while (go == 1) { + i = arc4random() % siz; + c = cp[i]; + if (c != 0x77) /* No unused vars here */ + usleep(arc4random() % 400); + } + return (0); +} + +static void * +memwrite(void *arg __unused) +{ + int i; + char c; + + while (go == 1) { + i = arc4random() % siz; + pthread_mutex_lock(&write_mutex); + c = cp[i]; + cp[i] = 0xee; /* This value seems to linger with NFS */ + cp[i] = c; + pthread_mutex_unlock(&write_mutex); + usleep(arc4random() % 400); + } + return (0); +} + +static void * +wr(void *arg __unused) +{ + off_t pos; + int r, s; + char buf[1024]; + + while (go == 1) { + s = arc4random() % sizeof(buf) + 1; + pos = arc4random() % (siz - s); + pthread_mutex_lock(&write_mutex); + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "lseek(%d)", (int)pos); + if ((r = read(fd, buf, s)) != s) { + fprintf(stderr, "r = %d, s = %d, pos = %d\n", r, s, (int)pos); + err(1, "read():2"); + } + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "lseek(%d)", (int)pos); + if (write(fd, buf, s) != s) + err(1, "write()"); + pthread_mutex_unlock(&write_mutex); + usleep(arc4random() % 400); + } + return (0); +} + +static void * +s1(void *arg __unused) +{ + + while (go == 1) { + if (fdatasync(fd) == -1) + err(1, "fdatasync()"); + usleep(arc4random() % 1000); + } + return (0); +} + +static void * +s2(void *arg __unused) +{ + + while (go == 1) { + if (fsync(fd) == -1) + err(1, "fdatasync()"); + usleep(arc4random() % 1000); + } + return (0); +} + +int +main(int argc, char *argv[]) +{ + struct stat st; + pthread_t tp[10]; + int e, i; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <file>\n", argv[0]); + exit(1); + } + if ((fd = open(argv[1], O_RDWR)) == -1) + err(1, "open(%s)", argv[1]); + if (fstat(fd, &st) == -1) + err(1, "stat(%s)", argv[1]); + siz = st.st_size; + cp = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (cp == MAP_FAILED) + err(1, "mmap()"); + + go = 1; + pthread_mutex_init(&write_mutex, NULL); + if ((e = pthread_create(&tp[0], NULL, memwrite, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[1], NULL, memwrite, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[2], NULL, memread, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[3], NULL, memread, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[4], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[5], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[6], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[7], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[8], NULL, s1, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[9], NULL, s2, NULL)) != 0) + errc(1, e, "pthread_create"); + + sleep(60); + go = 0; + for (i = 0; i < (int)(sizeof(tp) / sizeof(tp[0])); i++) + pthread_join(tp[i], NULL); + if (munmap(cp, siz) == -1) + err(1, "munmap()"); + close(fd); +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +mycc -o $serial -Wall -Wextra -O2 ../tools/serial.c || exit 1 +mount | grep -q "on $mntpoint " && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -s 5g -u $mdstart +newfs -n $newfs_flags /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint + +mp2=${mntpoint}2 +mkdir -p $mp2 +mount | grep -q "on $mp2 " && umount -f $mp2 +mount -t nfs -o retrycnt=3 127.0.0.1:$mntpoint $mp2 || exit 1 +sleep .2 + +here=`pwd` +cd $mp2 +$here/../testcases/swap/swap -t 5m -i 20 > /dev/null & +sleep 2 + +size=262144 +$serial file $size +cp file file.orig + +s=0 +/tmp/$prog file || s=1 + +while pgrep -q swap; do pkill swap; done +wait +if ! cmp -s file.orig file; then + od -t x1 file.orig > /var/tmp/$prog.file1 + od -t x1 file > /var/tmp/$prog.file2 + diff /var/tmp/$prog.file1 /var/tmp/$prog.file2 > $log + head -20 $log + rm /var/tmp/$prog.file1 /var/tmp/$prog.file2 + ls -ls file.orig file + s=2 +fi + +cd $here +umount $mp2 +umount $mntpoint +mdconfig -d -u $mdstart +rm -f $serial /tmp/$prog /tmp/$prog.c $log +exit $s diff --git a/tools/test/stress2/misc/mmap46.sh b/tools/test/stress2/misc/mmap46.sh new file mode 100755 index 000000000000..a739f36f3f9e --- /dev/null +++ b/tools/test/stress2/misc/mmap46.sh @@ -0,0 +1,233 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Demonstrate issue described in: +# [Bug 276002] nfscl: data corruption using both copy_file_range and mmap'd I/O + +# Issue seen: +# +# 8994c8994 +# < 0431020 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f +# --- +# > 0431020 10 11 ee 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f +# 256 -rw------- 1 root wheel 262144 Feb 28 19:44 file +# 256 -rw------- 1 root wheel 262144 Feb 28 19:43 file.orig +# 19:44:34, elapsed 0 days, 00:13.59 +# Failed with exit code 2 after 13 loops. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +log=/tmp/$prog.log +serial=/tmp/$prog.serial +grep -q $mntpoint /etc/exports || + { echo "$mntpoint missing from /etc/exports"; exit 0; } +rpcinfo 2>/dev/null | grep -q mountd || exit 0 + +cat > /tmp/$prog.c <<EOF +#include <sys/mman.h> +#include <sys/stat.h> + +#include <err.h> +#include <fcntl.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static off_t siz; +static pthread_mutex_t write_mutex; +static int fd, go; +static char *cp; + +static void * +memread(void *arg __unused) +{ + int i; + char c; + + while (go == -1) + usleep(50); + while (go == 1) { + i = arc4random() % siz; + c = cp[i]; + if (c != 0x77) /* No unused vars here */ + usleep(arc4random() % 200); + } + return (0); +} + +static void * +memwrite(void *arg __unused) +{ + int i; + char c; + + while (go == -1) + usleep(50); + while (go == 1) { + i = arc4random() % siz; + pthread_mutex_lock(&write_mutex); + c = cp[i]; + cp[i] = 0xee; /* This value seems to linger with NFS */ + cp[i] = c; + pthread_mutex_unlock(&write_mutex); + usleep(arc4random() % 200); + } + return (0); +} + +static void * +wr(void *arg __unused) +{ + off_t pos; + int r, s; + char buf[1024]; + + while (go == -1) + usleep(50); + while (go == 1) { + s = arc4random() % sizeof(buf) + 1; + pos = arc4random() % (siz - s); + pthread_mutex_lock(&write_mutex); + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "lseek(%d)", (int)pos); + if ((r = read(fd, buf, s)) != s) { + fprintf(stderr, "r = %d, s = %d, pos = %d\n", r, s, (int)pos); + err(1, "read():2"); + } + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "lseek(%d)", (int)pos); + if (write(fd, buf, s) != s) + err(1, "write()"); + pthread_mutex_unlock(&write_mutex); + usleep(arc4random() % 200); + } + return (0); +} + +static void * +tr(void *arg __unused) +{ + while (go == -1) + usleep(50); + while (go == 1) { + if (ftruncate(fd, siz) == -1) /* No size change */ + err(1, "truncate)"); + usleep(arc4random() % 1000); + } + return (0); +} + +int +main(int argc, char *argv[]) +{ + struct stat st; + pthread_t tp[13]; + int e, i; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <file>\n", argv[0]); + exit(1); + } + if ((fd = open(argv[1], O_RDWR)) == -1) + err(1, "open(%s)", argv[1]); + if (fstat(fd, &st) == -1) + err(1, "stat(%s)", argv[1]); + siz = st.st_size; + cp = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (cp == MAP_FAILED) + err(1, "mmap()"); + + go = -1; + pthread_mutex_init(&write_mutex, NULL); + if ((e = pthread_create(&tp[0], NULL, memwrite, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[1], NULL, memwrite, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[2], NULL, memread, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[3], NULL, memread, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[4], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[5], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[6], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[7], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[8], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[9], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[10], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[11], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + if ((e = pthread_create(&tp[12], NULL, tr, NULL)) != 0) + errc(1, e, "pthread_create"); + + sleep(1); + go = 1; + sleep(60); + go = 0; + for (i = 0; i < (int)(sizeof(tp) / sizeof(tp[0])); i++) + pthread_join(tp[i], NULL); + if (munmap(cp, siz) == -1) + err(1, "munmap()"); + close(fd); +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +mycc -o $serial -Wall -Wextra -O2 ../tools/serial.c || exit 1 +mount | grep -q "on $mntpoint " && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -s 5g -u $mdstart +newfs -n $newfs_flags /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint + +mp2=${mntpoint}2 +mkdir -p $mp2 +mount | grep -q "on $mp2 " && umount -f $mp2 +mount -t nfs -o retrycnt=3 127.0.0.1:$mntpoint $mp2 || exit 1 +sleep .2 + +here=`pwd` +cd $mp2 +$here/../testcases/swap/swap -t 5m -i 20 > /dev/null & +sleep 2 + +size=262144 +$serial file $size +cp file file.orig + +s=0 +/tmp/$prog file || s=1 + +while pgrep -q swap; do pkill swap; done +wait +if ! cmp -s file.orig file; then + od -t x1 file.orig > /var/tmp/$prog.file1 + od -t x1 file > /var/tmp/$prog.file2 + diff /var/tmp/$prog.file1 /var/tmp/$prog.file2 > $log + head -20 $log + rm /var/tmp/$prog.file1 /var/tmp/$prog.file2 + ls -ls file.orig file + s=2 +fi + +cd $here +umount $mp2 +umount $mntpoint +mdconfig -d -u $mdstart +rm -f $serial /tmp/$prog /tmp/$prog.c $log +exit $s diff --git a/tools/test/stress2/misc/mmap47.sh b/tools/test/stress2/misc/mmap47.sh new file mode 100755 index 000000000000..43778a193202 --- /dev/null +++ b/tools/test/stress2/misc/mmap47.sh @@ -0,0 +1,237 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Demonstrate issue described in: +# [Bug 276002] nfscl: data corruption using both copy_file_range and mmap'd I/O + +# This version only uses mapped read/write, read(2)/write(2) and ftruncate(2) + +# Issue seen: + +# 19:50:53 Start test of mmap47.sh +# 19:51:56, elapsed 0 days, 00:01.03 +# 19:53:01, elapsed 0 days, 00:02.08 +# 19:54:06, elapsed 0 days, 00:03.13 +# 19:55:40, elapsed 0 days, 00:04.47 +# 617c617 +# < 0023200 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f +# --- +# > 0023200 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e ee +# 256 -rw------- 1 root wheel 262144 Mar 1 19:56 file +# 256 -rw------- 1 root wheel 262144 Mar 1 19:55 file.orig +# 19:56:44, elapsed 0 days, 00:05.51 +# Failed with exit code 2 after 5 loops of mmap47.sh. +# 19:56 /usr/src/tools/test/stress2/misc $ + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +log=/tmp/$prog.log +serial=/tmp/$prog.serial +grep -q $mntpoint /etc/exports || + { echo "$mntpoint missing from /etc/exports"; exit 0; } +rpcinfo 2>/dev/null | grep -q mountd || exit 0 + +cat > /tmp/$prog.c <<EOF +#include <sys/mman.h> +#include <sys/stat.h> + +#include <err.h> +#include <fcntl.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static off_t siz; +static pthread_mutex_t write_mutex; +static int fd, go; +static char *cp; + +static void * +memread(void *arg __unused) +{ + int i; + char c; + + while (go == -1) + usleep(50); + while (go == 1) { + i = arc4random() % siz; + c = cp[i]; + if (c != 0x77) /* No unused vars here */ + usleep(arc4random() % 200); + } + return (0); +} + +static void * +memwrite(void *arg __unused) +{ + int i; + char c; + + while (go == -1) + usleep(50); + while (go == 1) { + i = arc4random() % siz; + pthread_mutex_lock(&write_mutex); + c = cp[i]; + cp[i] = 0xee; /* This value seems to linger with NFS */ + cp[i] = c; + pthread_mutex_unlock(&write_mutex); + usleep(arc4random() % 200); + } + return (0); +} + +static void * +wr(void *arg __unused) +{ + off_t pos; + int r, s; + char buf[1024]; + + while (go == -1) + usleep(50); + while (go == 1) { + s = arc4random() % sizeof(buf) + 1; + pos = arc4random() % (siz - s); + pthread_mutex_lock(&write_mutex); + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "lseek(%d)", (int)pos); + if ((r = read(fd, buf, s)) != s) { + fprintf(stderr, "r = %d, s = %d, pos = %d\n", r, s, (int)pos); + err(1, "read():2"); + } + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "lseek(%d)", (int)pos); + if (write(fd, buf, s) != s) + err(1, "write()"); + pthread_mutex_unlock(&write_mutex); + usleep(arc4random() % 200); + } + return (0); +} + +/* Both ftruncate() and fdatasync() triggers the problem */ + +static void * +tr(void *arg __unused) +{ + while (go == -1) + usleep(50); + while (go == 1) { +#if 0 + if (ftruncate(fd, siz) == -1) /* No size change */ + err(1, "truncate)"); +#else + if (fdatasync(fd) == -1) + err(1, "fdatasync()"); +#endif + usleep(arc4random() % 1000); + } + return (0); +} + +int +main(int argc, char *argv[]) +{ + struct stat st; + pthread_t tp[31]; + int e, i, idx; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <file>\n", argv[0]); + exit(1); + } + if ((fd = open(argv[1], O_RDWR)) == -1) + err(1, "open(%s)", argv[1]); + if (fstat(fd, &st) == -1) + err(1, "stat(%s)", argv[1]); + siz = st.st_size; + cp = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (cp == MAP_FAILED) + err(1, "mmap()"); + + go = -1; + pthread_mutex_init(&write_mutex, NULL); + idx = 0; + for (i = 0; i < (int)(arc4random() % 10 + 1); i++) { + if ((e = pthread_create(&tp[idx++], NULL, memread, NULL)) != 0) + errc(1, e, "pthread_create"); + } + for (i = 0; i < (int)(arc4random() % 10 + 1); i++) { + if ((e = pthread_create(&tp[idx++], NULL, memwrite, NULL)) != 0) + errc(1, e, "pthread_create"); + } + for (i = 0; i < (int)(arc4random() % 10 + 1); i++) { + if ((e = pthread_create(&tp[idx++], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + } + if ((e = pthread_create(&tp[idx++], NULL, tr, NULL)) != 0) + errc(1, e, "pthread_create"); + + sleep(1); + go = 1; + sleep(60); + go = 0; + for (i = 0; i < idx; i++) + pthread_join(tp[i], NULL); + if (munmap(cp, siz) == -1) + err(1, "munmap()"); + close(fd); +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +mycc -o $serial -Wall -Wextra -O2 ../tools/serial.c || exit 1 +mount | grep -q "on $mntpoint " && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -s 5g -u $mdstart +newfs -n $newfs_flags /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint + +mp2=${mntpoint}2 +mkdir -p $mp2 +mount | grep -q "on $mp2 " && umount -f $mp2 +mount -t nfs -o retrycnt=3 127.0.0.1:$mntpoint $mp2 || exit 1 +sleep .2 + +here=`pwd` +cd $mp2 +$here/../testcases/swap/swap -t 5m -i 20 > /dev/null & +sleep 2 + +size=262144 +$serial file $size +cp file file.orig + +s=0 +/tmp/$prog file || s=1 + +while pgrep -q swap; do pkill swap; done +wait +if ! cmp -s file.orig file; then + od -t x1 file.orig > /var/tmp/$prog.file1 + od -t x1 file > /var/tmp/$prog.file2 + diff /var/tmp/$prog.file1 /var/tmp/$prog.file2 > $log + head -20 $log + rm /var/tmp/$prog.file1 /var/tmp/$prog.file2 + ls -ls file.orig file + s=2 +fi + +cd $here +umount $mp2 +umount $mntpoint +mdconfig -d -u $mdstart +rm -f $serial /tmp/$prog /tmp/$prog.c $log +exit $s diff --git a/tools/test/stress2/misc/mmap48.sh b/tools/test/stress2/misc/mmap48.sh new file mode 100755 index 000000000000..35da78a98c26 --- /dev/null +++ b/tools/test/stress2/misc/mmap48.sh @@ -0,0 +1,289 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Demonstrate issue described in: +# [Bug 276002] nfscl: data corruption using both copy_file_range and mmap'd I/O + +# This version only uses mapped read/write, read(2)/write(2), fstat(2) and ftruncate(2) + +# Issue seen: +# 20241003 10:04:24 all: mmap48.sh +# 5257c5257 +# < 0244200 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f +# --- +# > 0244200 80 81 82 83 84 85 86 87 88 ee 8a 8b 8c 8d 8e 8f +# 256 -rw------- 1 root wheel 262144 Oct 3 10:05 file +# 256 -rw------- 1 root wheel 262144 Oct 3 10:04 file.orig +# FAIL mmap48.sh exit code 2 + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +log=/tmp/$prog.log +serial=/tmp/$prog.serial +grep -q $mntpoint /etc/exports || + { echo "$mntpoint missing from /etc/exports"; exit 0; } +rpcinfo 2>/dev/null | grep -q mountd || exit 0 + +cat > /tmp/$prog.c <<EOF +#include <sys/mman.h> +#include <sys/stat.h> + +#include <assert.h> +#include <err.h> +#include <fcntl.h> +#include <pthread.h> +#include <pthread_np.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static off_t siz; +static pthread_mutex_t write_mutex; +static int fd, go; +static char *cp; + +#define THREADS 100 + +static void * +memread(void *arg __unused) +{ + int i; + char c; + + if (arc4random() % 100 < 10) + return (0); + pthread_set_name_np(pthread_self(), __func__); + while (go == -1) + usleep(50); + while (go == 1) { + i = arc4random() % siz; + c = cp[i]; + if (c != 0x77) /* No unused vars here */ + usleep(arc4random() % 400); + } + return (NULL); +} + +static void * +memwrite(void *arg __unused) +{ + int i; + char c; + + if (arc4random() % 100 < 10) + return (0); + pthread_set_name_np(pthread_self(), __func__); + while (go == -1) + usleep(50); + while (go == 1) { + i = arc4random() % siz; + pthread_mutex_lock(&write_mutex); + c = cp[i]; + cp[i] = 0xee; /* This value seems to linger with NFS */ + cp[i] = c; + pthread_mutex_unlock(&write_mutex); + usleep(arc4random() % 400); + } + return (NULL); +} + +static void * +wr(void *arg __unused) +{ + off_t pos; + int r, s; + char buf[1024]; + + if (arc4random() % 100 < 10) + return (0); + pthread_set_name_np(pthread_self(), __func__); + while (go == -1) + usleep(50); + while (go == 1) { + s = arc4random() % sizeof(buf) + 1; + pos = arc4random() % (siz - s); + pthread_mutex_lock(&write_mutex); + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "lseek(%d)", (int)pos); + if ((r = read(fd, buf, s)) != s) { + fprintf(stderr, "r = %d, s = %d, pos = %d\n", r, s, (int)pos); + err(1, "read():2"); + } + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "lseek(%d)", (int)pos); + if (write(fd, buf, s) != s) + err(1, "write()"); + pthread_mutex_unlock(&write_mutex); + usleep(arc4random() % 200); + } + return (NULL); +} + +/* Both ftruncate() and fdatasync() triggers the problem */ + +static void * +sy(void *arg __unused) +{ + + if (arc4random() % 100 < 10) + return (0); + pthread_set_name_np(pthread_self(), __func__); + while (go == -1) + usleep(50); + while (go == 1) { + if (fdatasync(fd) == -1) + err(1, "fdatasync()"); + usleep(arc4random() % 1000); + } + return (NULL); +} + +static void * +tr(void *arg __unused) +{ + + if (arc4random() % 100 < 10) + return (0); + pthread_set_name_np(pthread_self(), __func__); + while (go == -1) + usleep(50); + while (go == 1) { + if (ftruncate(fd, siz) == -1) /* No size change */ + err(1, "truncate)"); + usleep(arc4random() % 1000); + } + return (NULL); +} + +static void * +fs(void *arg __unused) +{ + struct stat st; + + if (arc4random() % 100 < 10) + return (0); + pthread_set_name_np(pthread_self(), __func__); + while (go == -1) + usleep(50); + while (go == 1) { + if (fstat(fd, &st) == -1) + err(1, "stat()"); + usleep(arc4random() % 1000); + } + return (NULL); +} + +int +main(int argc, char *argv[]) +{ + struct stat st; + pthread_t tp[THREADS]; + int e, i, idx; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <file>\n", argv[0]); + exit(1); + } + if ((fd = open(argv[1], O_RDWR)) == -1) + err(1, "open(%s)", argv[1]); + if (fstat(fd, &st) == -1) + err(1, "stat(%s)", argv[1]); + siz = st.st_size; + cp = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (cp == MAP_FAILED) + err(1, "mmap()"); + + go = -1; + pthread_mutex_init(&write_mutex, NULL); + idx = 0; + for (i = 0; i < (int)(arc4random() % 3 + 1); i++) { + if ((e = pthread_create(&tp[idx++], NULL, memread, NULL)) != 0) + errc(1, e, "pthread_create"); + } + for (i = 0; i < (int)(arc4random() % 3 + 1); i++) { + if ((e = pthread_create(&tp[idx++], NULL, memwrite, NULL)) != 0) + errc(1, e, "pthread_create"); + } + for (i = 0; i < (int)(arc4random() % 3 + 1); i++) { + if ((e = pthread_create(&tp[idx++], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create"); + } + for (i = 0; i < (int)(arc4random() % 3 + 1); i++) { + if ((e = pthread_create(&tp[idx++], NULL, fs, NULL)) != 0) + errc(1, e, "pthread_create"); + } + for (i = 0; i < (int)(arc4random() % 3 + 1); i++) { + if ((e = pthread_create(&tp[idx++], NULL, tr, NULL)) != 0) + errc(1, e, "pthread_create"); + } + for (i = 0; i < (int)(arc4random() % 3 + 1); i++) { + if ((e = pthread_create(&tp[idx++], NULL, sy, NULL)) != 0) + errc(1, e, "pthread_create"); + } + assert(idx <= THREADS); + + sleep(1); + go = 1; + sleep(60); + go = 0; + for (i = 0; i < idx; i++) + pthread_join(tp[i], NULL); + if (munmap(cp, siz) == -1) + err(1, "munmap()"); + close(fd); +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +mycc -o $serial -Wall -Wextra -O2 ../tools/serial.c || exit 1 +mount | grep -q "on $mntpoint " && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -s 5g -u $mdstart +newfs -n $newfs_flags /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint + +mp2=${mntpoint}2 +mkdir -p $mp2 +mount | grep -q "on $mp2 " && umount -f $mp2 +mount -t nfs -o retrycnt=3 127.0.0.1:$mntpoint $mp2 || exit 1 +sleep .2 + +here=`pwd` +cd $mp2 +#$here/../testcases/swap/swap -t 5m -i 20 > /dev/null & +sleep 2 + +size=262144 +$serial file $size +cp file file.orig + +s=0 +#ktrace -id -f $here/ktrace.out /tmp/$prog file || s=1 +/tmp/$prog file || s=1 + +while pgrep -q swap; do pkill swap; done +wait +if ! cmp -s file.orig file; then + od -t x1 file.orig > /var/tmp/$prog.file1 + od -t x1 file > /var/tmp/$prog.file2 + diff /var/tmp/$prog.file1 /var/tmp/$prog.file2 > $log + head -20 $log + rm /var/tmp/$prog.file1 /var/tmp/$prog.file2 + ls -ls file.orig file + s=2 +fi + +cd $here +umount $mp2 +umount $mntpoint +mdconfig -d -u $mdstart +rm -f $serial /tmp/$prog /tmp/$prog.c $log +exit $s diff --git a/tools/test/stress2/misc/mmap5.sh b/tools/test/stress2/misc/mmap5.sh index e6dee6d551de..c7369118e0e2 100755 --- a/tools/test/stress2/misc/mmap5.sh +++ b/tools/test/stress2/misc/mmap5.sh @@ -52,15 +52,16 @@ rm -f /tmp/mmap5 /tmp/mmap5.inputfile exit EOF -#include <err.h> -#include <errno.h> -#include <stdlib.h> +#include <sys/param.h> #include <sys/fcntl.h> #include <sys/mman.h> -#include <sys/param.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> +#include <err.h> +#include <errno.h> +#include <stdlib.h> +#include <time.h> #include <unistd.h> const char *file; @@ -113,13 +114,14 @@ test(void) int main(int argc, char *argv[]) { - int i; + time_t start; if (argc != 2) errx(1, "Usage: %s <file>", argv[0]); file = argv[1]; - for (i = 0; i < 30000; i++) { + start = time(NULL); + while (time(NULL) - start < 120) { if (fork() == 0) test(); wait(NULL); diff --git a/tools/test/stress2/misc/vmstat2.sh b/tools/test/stress2/misc/mount7.sh index db3cb1a697e2..2489421c544d 100755 --- a/tools/test/stress2/misc/vmstat2.sh +++ b/tools/test/stress2/misc/mount7.sh @@ -1,9 +1,8 @@ #!/bin/sh - # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # -# Copyright (c) 2019 Dell EMC Isilon +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -27,15 +26,40 @@ # SUCH DAMAGE. # -# "0xFFFFFFFFFFFFFFFF in vmstat output" seen. +# Another parallel mount(8) test scenario + +# Seen: +# UID PID PPID C PRI NI VSZ RSS MWCHAN STAT TT TIME COMMAND +# 0 37225 99871 1 32 0 13280 3116 sdstart D+ 0 0:00.04 mount /dev/md21 /mnt21 +# 0 37236 99550 9 68 0 13280 3112 sdstart D+ 0 0:00.04 mount /dev/md19 /mnt19 + +# https://people.freebsd.org/~pho/stress/log/log0549.txt +# Fixed by kib@ in 4b273a7fb9e6 + +. ../default.cfg -(cd ../testcases/swap; ./swap -t 2m -i 20 -h -l 100 &) -sleep .5 -s=0 -while pgrep -q swap; do - vmstat -z | awk '{if (length($4) > 11) { print $0; exit 1}}' || - { pkill swap; s=1; } - sleep 2 +mounts=15 + +../testcases/swap/swap -t 2m -i 20 & +for i in `jot $mounts $mdstart`; do + mdconfig -a -s 50m -u $i + newfs -U /dev/md$i > /dev/null + mkdir -p $mntpoint$i + start=`date +%s` + while [ $((`date +%s` - start)) -lt 120 ]; do + mount /dev/md$i $mntpoint$i && cp /etc/passwd $mntpoint$i + while mount | grep -q " on $mntpoint$i "; do + umount $mntpoint$i > /dev/null 2>&1 + done + done & + while [ $((`date +%s` - start)) -lt 120 ]; do + find $mntpoint$i -ls > /dev/null 2>&1 + done & done wait + +for i in `jot $mounts $mdstart`; do + mdconfig -d -u $i + rmdir $mntpoint$i +done exit $s diff --git a/tools/test/stress2/misc/mountro4.sh b/tools/test/stress2/misc/mountro4.sh index eddc345c85af..906639d9dc3a 100755 --- a/tools/test/stress2/misc/mountro4.sh +++ b/tools/test/stress2/misc/mountro4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/mountro5.sh b/tools/test/stress2/misc/mountro5.sh index 67663df54145..bcc77694b6d0 100755 --- a/tools/test/stress2/misc/mountro5.sh +++ b/tools/test/stress2/misc/mountro5.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/mountro6.sh b/tools/test/stress2/misc/mountro6.sh index 398cbeed4fea..d19a73d76c4c 100755 --- a/tools/test/stress2/misc/mountro6.sh +++ b/tools/test/stress2/misc/mountro6.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/mountu.sh b/tools/test/stress2/misc/mountu.sh index 838850ef3e96..abd3c744d160 100755 --- a/tools/test/stress2/misc/mountu.sh +++ b/tools/test/stress2/misc/mountu.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2012 Peter Holm <pho@FreeBSD.org> # Copyright (c) 2019 Dell EMC Isilon diff --git a/tools/test/stress2/misc/mprotect.sh b/tools/test/stress2/misc/mprotect.sh index e3e6e765c331..cdb3b2cccd13 100755 --- a/tools/test/stress2/misc/mprotect.sh +++ b/tools/test/stress2/misc/mprotect.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Mark Johnston <markj@freebsd.org> # diff --git a/tools/test/stress2/misc/mprotect2.sh b/tools/test/stress2/misc/mprotect2.sh index c5cdc44a0f39..6f8d0c3ce6fd 100755 --- a/tools/test/stress2/misc/mprotect2.sh +++ b/tools/test/stress2/misc/mprotect2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/mprotect3.sh b/tools/test/stress2/misc/mprotect3.sh new file mode 100755 index 000000000000..9bd4a6f9be79 --- /dev/null +++ b/tools/test/stress2/misc/mprotect3.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +# Test scenario from: +# Bug 272585 - calling mprotect in an mmap-ed stack can affect non-target pages +# Test scenario by: John F. Carr <jfc mit edu> + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +/* Test program from: + Bug 272585 - calling mprotect in an mmap-ed stack can affect non-target pages + */ +#include <err.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <sys/mman.h> +#include <sysexits.h> +#include <unistd.h> + +#ifndef MAP_GROWSDOWN +#define MAP_GROWSDOWN 0 +#endif +#ifndef MAP_STACK +#define MAP_STACK 0 +#endif + +int main(void) +{ + long pagesize; + char *addr, *guard; + size_t alloc_size; + + pagesize = sysconf(_SC_PAGESIZE); + if (pagesize < 0) + err(EX_OSERR, "getPAGESIZE"); + + alloc_size = 0x200000 + pagesize; + + addr = mmap(0, alloc_size, PROT_READ|PROT_WRITE, + MAP_GROWSDOWN|MAP_STACK|MAP_PRIVATE|MAP_ANONYMOUS, + -1, 0); + if (addr == MAP_FAILED) { + err(EX_OSERR, "mmap"); + } + + /* Only 0x20 causes a failure. */ + guard = addr + alloc_size - 0x20 * pagesize; + + if (mprotect(guard, pagesize, PROT_NONE)) { + err(EX_OSERR, "mprotect"); + } + + printf("mapped %p..%p, guard at %p\n", addr, addr + alloc_size, guard); + fflush(stdout); + + ((volatile char *)guard)[-1]; + + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 0 + +cd /tmp +./$prog; s=$? +cd - + +rm -f /tmp/$prog /tmp/$prog.c /tmp/$prog.core +exit $s diff --git a/tools/test/stress2/misc/mprotect4.sh b/tools/test/stress2/misc/mprotect4.sh new file mode 100755 index 000000000000..c233d20852a2 --- /dev/null +++ b/tools/test/stress2/misc/mprotect4.sh @@ -0,0 +1,109 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +/* N readers and 1 writer threaded test scenario */ + +#include <sys/types.h> +#include <sys/mman.h> + +#include <assert.h> +#include <err.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +static int go, n, ps; +static char *cp; +static volatile char v; + +void * +rd(void *arg __unused) +{ + int i; + + while (go == 0) + usleep(100); + while (go == 1) { + for (i = 0; i < n; i += ps) { + v = cp[i]; + } + pthread_yield(); + } + return(NULL); +} + +void +usage(char *prog) { + fprintf(stderr, "Usage: %s <number of threads>\n", prog); + _exit(1); +} + +int +main(int argc, char *argv[]) +{ + pthread_t *tid; + time_t start; + int e, i, nb; + + if (argc != 2) + usage(argv[0]); + if (sscanf(argv[1], "%d", &n) != 1) + usage(argv[0]); + if (n > 1) + n--; + if ((tid = calloc(n, sizeof(pthread_t *))) == NULL) + err(1, "calloc()"); + + ps = getpagesize(); + cp = mmap(NULL, n * ps, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); + go = 0; + for (i = 0; i < n; i++) { + if ((e = pthread_create(&tid[i], NULL, rd, NULL)) != 0) + errc(1, e, "pthread_create()"); + } + go = 1; + + nb = 0; + start = time(NULL); + while (time(NULL) - start < 120) { + for (i = 0; i < n; i += ps) { + if (mprotect(&cp[i], ps, PROT_READ|PROT_WRITE) == -1) + err(1, "mprotect(PROT_READ)"); + cp[i] = 1; + if (mprotect(&cp[i], ps, PROT_READ) == -1) + err(1, "mprotect(PROT_READ)"); + nb++; + } + } + go = 0; + for (i = 0; i < n; i++) { + if ((e = pthread_join(tid[i], NULL)) != 0) + errc(1, e, "pthread_join() in loop %d", i); + } + if (nb >= 0) { +#if defined(DEBUG) + fprintf(stderr, "%d loops\n", nb); +#endif + ; + } +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +/tmp/$prog `sysctl -n hw.ncpu`; s=$? + +rm -d /tmp/$prog /tmp/$prog.c +exit $s diff --git a/tools/test/stress2/misc/mprotect5.sh b/tools/test/stress2/misc/mprotect5.sh new file mode 100755 index 000000000000..ab4d2eeee118 --- /dev/null +++ b/tools/test/stress2/misc/mprotect5.sh @@ -0,0 +1,118 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +/* N writers threaded test scenario */ + +#include <sys/types.h> +#include <sys/mman.h> + +#include <assert.h> +#include <err.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +static pthread_mutex_t write_mutex; +static int go, n, ps; +static char *cp, *wp; + +void * +wr(void *arg __unused) +{ + while (go == 0) + usleep(100); + while (go == 1) { + pthread_mutex_lock(&write_mutex); + if (wp != NULL) + *wp += 1; + pthread_mutex_unlock(&write_mutex); + } + return(NULL); +} + +void +usage(char *prog) { + fprintf(stderr, "Usage: %s <number of threads>\n", prog); + _exit(1); +} + +int +main(int argc, char *argv[]) +{ + pthread_t *tid; + time_t start; + int e, i, nb; + + if (argc != 2) + usage(argv[0]); + if (sscanf(argv[1], "%d", &n) != 1) + usage(argv[0]); + if (n > 1) + n--; + if ((tid = calloc(n, sizeof(pthread_t *))) == NULL) + err(1, "calloc()"); + + ps = getpagesize(); + cp = mmap(NULL, n * ps, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); + pthread_mutex_init(&write_mutex, NULL); + pthread_mutex_lock(&write_mutex); + go = 0; + for (i = 0; i < n; i++) { + if ((e = pthread_create(&tid[i], NULL, wr, NULL)) != 0) + errc(1, e, "pthread_create()"); + } + go = 1; + + nb = 0; + start = time(NULL); + while (time(NULL) - start < 120) { + for (i = 0; i < n; i += ps) { + pthread_mutex_lock(&write_mutex); + if (mprotect(&cp[i], ps, PROT_READ|PROT_WRITE) == -1) + err(1, "mprotect(PROT_READ)"); + cp[i] = 0; + wp = &cp[i]; + pthread_mutex_unlock(&write_mutex); + + usleep(100); + + pthread_mutex_lock(&write_mutex); + if (mprotect(&cp[i], ps, PROT_READ) == -1) + err(1, "mprotect(PROT_READ)"); + wp = NULL; + pthread_mutex_unlock(&write_mutex); + nb++; + } + } + go = 0; + for (i = 0; i < n; i++) { + if ((e = pthread_join(tid[i], NULL)) != 0) + errc(1, e, "pthread_join() in loop %d", i); + } + if (nb >= 0) { +#if defined(DEBUG) + fprintf(stderr, "%d loops\n", nb); +#endif + ; + } +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +/tmp/$prog `sysctl -n hw.ncpu`; s=$? + +rm -d /tmp/$prog /tmp/$prog.c +exit $s diff --git a/tools/test/stress2/misc/mprotect6.sh b/tools/test/stress2/misc/mprotect6.sh new file mode 100755 index 000000000000..ef1443c216d3 --- /dev/null +++ b/tools/test/stress2/misc/mprotect6.sh @@ -0,0 +1,146 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +#include <sys/types.h> +#include <sys/mman.h> + +#include <assert.h> +#include <err.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +static pthread_mutex_t write_mutex; +static volatile int done; +static int go, n, *once, *p, ps; + +static void * +wr(void *arg) +{ + int idx; + + alarm(180); + idx = *(int *)arg; + while (go == 0) + usleep(100); + while (go == 1) { + while (go == 1 && once[idx] == 0) + usleep(100); + if (go == 0) + break; + p[idx]++; + once[idx] = 0; + pthread_mutex_lock(&write_mutex); + done++; + pthread_mutex_unlock(&write_mutex); + } + return(NULL); +} + +static void +setonce(int val) +{ + int i; + + for (i = 0; i < n; i++) + once[i] = val; +} + +static void +usage(char *prog) { + fprintf(stderr, "Usage: %s <number of threads>\n", prog); + _exit(1); +} + +int +main(int argc, char *argv[]) +{ + pthread_t *tid; + time_t start; + int *arg; + int e, i, nb, r; + + if (argc != 2) + usage(argv[0]); + if (sscanf(argv[1], "%d", &n) != 1) + usage(argv[0]); + if (n > 1) + n--; + if ((tid = calloc(n, sizeof(pthread_t *))) == NULL) + err(1, "calloc()"); + if ((once = calloc(n, sizeof(int *))) == NULL) + err(1, "calloc()"); + setonce(0); + + ps = getpagesize(); + p = mmap(NULL, n * ps, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); + go = 0; + pthread_mutex_init(&write_mutex, NULL); + for (i = 0; i < n; i++) { + arg = malloc(sizeof(int)); + *arg = i; + if ((e = pthread_create(&tid[i], NULL, wr, (void *)arg)) != 0) + errc(1, e, "pthread_create()"); + } + go = 1; + + nb = 0; + start = time(NULL); + while (time(NULL) - start < 120) { + if (mprotect(p, n * ps, PROT_READ|PROT_WRITE) == -1) + err(1, "mprotect(PROT_READ)"); + done = 0; + setonce(1); + while (done != n) + usleep(100); + if (mprotect(p, n * ps, PROT_READ) == -1) + err(1, "mprotect(PROT_READ)"); + nb++; + usleep(100); + } + go = 0; + for (i = 0; i < n; i++) { + if ((e = pthread_join(tid[i], NULL)) != 0) + errc(1, e, "pthread_join() in loop %d", i); + } + r = 0; + for (i = 1; i < n; i++) { + if (p[0] != p[i]) + r++; + } + if (r != 0) { + fprintf(stderr, "%d loops.\n", nb); + for (i = 0; i < n; i++) + fprintf(stderr, "p[%3d] = %d\n", i, p[i]); + } + + return (r); +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 -g /tmp/$prog.c -lpthread || exit 1 + +n=`sysctl -n hw.ncpu` +if [ $# -eq 1 ]; then + echo $1 | grep -Eq '^[0-9]+$' && n=$1 +fi +../testcases/swap/swap -t 2m > /dev/null & +sleep 10 +/tmp/$prog $n; s=$? +pkill -9 swap +wait + +rm -d /tmp/$prog /tmp/$prog.c +exit $s diff --git a/tools/test/stress2/misc/msdos11.sh b/tools/test/stress2/misc/msdos11.sh index c14ef55f1f7c..023a16af08c7 100755 --- a/tools/test/stress2/misc/msdos11.sh +++ b/tools/test/stress2/misc/msdos11.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # diff --git a/tools/test/stress2/misc/msdos12.sh b/tools/test/stress2/misc/msdos12.sh index da5c8104c3a6..8e3984305cd7 100755 --- a/tools/test/stress2/misc/msdos12.sh +++ b/tools/test/stress2/misc/msdos12.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # diff --git a/tools/test/stress2/misc/msdos13.sh b/tools/test/stress2/misc/msdos13.sh index 52c3d9ece686..2f714ba120a8 100755 --- a/tools/test/stress2/misc/msdos13.sh +++ b/tools/test/stress2/misc/msdos13.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # diff --git a/tools/test/stress2/misc/msdos14.sh b/tools/test/stress2/misc/msdos14.sh index 0f5b5b9ab736..aaa95144c14e 100755 --- a/tools/test/stress2/misc/msdos14.sh +++ b/tools/test/stress2/misc/msdos14.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # @@ -27,7 +27,7 @@ # SUCH DAMAGE. # -# Rename(2) test with msdosfs(5) +# Rename(2) test with msdosfs(4) # Test scenario by kib@ . ../default.cfg diff --git a/tools/test/stress2/misc/msdos15.sh b/tools/test/stress2/misc/msdos15.sh index 79e60972e34b..b07defd677af 100755 --- a/tools/test/stress2/misc/msdos15.sh +++ b/tools/test/stress2/misc/msdos15.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/msdos16.sh b/tools/test/stress2/misc/msdos16.sh index e188795e1851..965be8233881 100755 --- a/tools/test/stress2/misc/msdos16.sh +++ b/tools/test/stress2/misc/msdos16.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/msdos17.sh b/tools/test/stress2/misc/msdos17.sh new file mode 100755 index 000000000000..392a9a622b9a --- /dev/null +++ b/tools/test/stress2/misc/msdos17.sh @@ -0,0 +1,144 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# No problems observed + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +set -u +prog=$(basename "$0" .sh) +mount | grep -q "on $mntpoint " && umount $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 1g -u $mdstart +gpart create -s bsd md$mdstart > /dev/null +gpart add -t freebsd-ufs md$mdstart > /dev/null +part=a +newfs_msdos -F 32 -b 8192 /dev/md${mdstart}$part > /dev/null || exit 1 +mount -t msdosfs /dev/md${mdstart}$part $mntpoint + +here=`pwd` +cd /tmp +cat > $prog.c <<EOF +#include <sys/param.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <machine/atomic.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static volatile u_int *share; +static char file1[80], file2[80]; + +#define SYNC 0 +#define STOP 1 + +static void +test0(void) +{ + struct stat sb; + + while (share[STOP] == 0) { + while (share[SYNC] != 0) + usleep(100); + if (rename(file1, file2) == -1) + err(1, "rename(%s, %s)", file1, file2); + if (stat(file1, &sb) == 0) + err(1, "stat(%s)", file1); + atomic_add_int(&share[SYNC], 1); + } + + _exit(0); +} + +static void +test1(void) +{ + struct stat sb; + + while (share[STOP] == 0) { + while (share[SYNC] != 1) + usleep(100); + if (rename(file2, file1) == -1) + err(1, "rename(%s, %s)", file2, file1); + if (stat(file2, &sb) == 0) + err(1, "stat(%s)", file2); + atomic_add_int(&share[SYNC], -1); + } + + _exit(0); +} + +int +main(void) +{ + pid_t pids[2]; + size_t len; + int fd; + char cwd[80]; + + len = PAGE_SIZE; + if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) + err(1, "mmap"); + + if (getcwd(cwd, sizeof(cwd)) == NULL) + err(1, "getcwd()"); + snprintf(file1, sizeof(file1), "%s/a.%06d", cwd, getpid()); + snprintf(file2, sizeof(file2), "%s/b.%06d", cwd, getpid()); + if ((fd = open(file1, O_CREAT, 0640)) == -1) + err(1, "open(%s)", file1); + close(fd); + + if ((pids[0] = fork()) == 0) + test0(); + if ((pids[1] = fork()) == 0) + test1(); + + sleep(120); + share[STOP] = 1; + + if (waitpid(pids[0], NULL, 0) == -1) + err(1, "waitpid(%d)", pids[0]); + if (waitpid(pids[1], NULL, 0) == -1) + err(1, "waitpid(%d)", pids[1]); + unlink(file1); + unlink(file2); +} +EOF +mycc -o $prog -Wall $prog.c || exit 1 +rm -f $prog.c +cd $here + +(cd ../testcases/swap; ./swap -t 5m -i 20 -l 100) & +cd $mntpoint +pids="" +for i in `jot 30`; do + /tmp/$prog & + pids="$pids $!" +done +for pid in $pids; do + wait $pid +done +cd $here +while pkill swap; do :; done +wait + +umount $mntpoint +mdconfig -d -u $mdstart +rm -f /tmp/$prog +exit 0 diff --git a/tools/test/stress2/misc/msdos18.sh b/tools/test/stress2/misc/msdos18.sh new file mode 100755 index 000000000000..faeed9dca944 --- /dev/null +++ b/tools/test/stress2/misc/msdos18.sh @@ -0,0 +1,250 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# D38549: msdosfs deextend: validate pages of the partial buffer + +# https://people.freebsd.org/~pho/stress/log/log0420.txt + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +set -eu +prog=$(basename "$0" .sh) +mkdir -p $mntpoint +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 1g -u $mdstart +newfs_msdos /dev/md$mdstart > /dev/null 2>&1 +mount -t msdosfs /dev/md$mdstart $mntpoint +mount | grep $mntpoint +set +e + +odir=`pwd` + +cd /tmp +sed '1,/^EOF/d' < $odir/$0 > $prog.c +cc -o $prog -Wall -O0 $prog.c -pthread || exit 1 +rm -f $prog.c +cd $mntpoint + +in=inputFile +out=outputFile + +/tmp/$prog $in $out 12345 +ls -al + +cd $odir +umount $mntpoint +mdconfig -d -u $mdstart +rm -f /tmp/$prog +exit +EOF +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <err.h> +#include <fcntl.h> +#include <netdb.h> +#include <netinet/in.h> +#include <pthread.h> +#include <pthread_np.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +int fd, port; +volatile int go; +char *inputFile; +char *outputFile; + +#define FSIZE 936374 +char buf[FSIZE]; + +static void +reader(void) { + struct sockaddr_in inetaddr, inetpeer; + socklen_t len; + int on, n, tcpsock, msgsock; + + on = 1; + if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + err(1, "socket(), %s:%d", __FILE__, __LINE__); + + if (setsockopt(tcpsock, + SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) + err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); + + inetaddr.sin_family = AF_INET; + inetaddr.sin_addr.s_addr = INADDR_ANY; + inetaddr.sin_port = htons(port); + inetaddr.sin_len = sizeof(inetaddr); + + if (bind(tcpsock, + (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) + err(1, "bind(), %s:%d", __FILE__, __LINE__); + + if (listen(tcpsock, 5) < 0) + err(1, "listen(), %s:%d", __FILE__, __LINE__); + + len = sizeof(inetpeer); + if ((msgsock = accept(tcpsock, + (struct sockaddr *)&inetpeer, &len)) < 0) + err(1, "accept(), %s:%d", __FILE__, __LINE__); + + if ((fd = open(outputFile, O_RDWR | O_CREAT | O_TRUNC, 0640)) == -1) + err(1, "open(%s)", outputFile); + + usleep(arc4random() % 1000); + for (;;) { + if ((n = read(msgsock, buf, FSIZE)) < 0) + err(1, "read(), %s:%d", __FILE__, __LINE__); + if (n == 0) + break; + + } + close(msgsock); + close(tcpsock); + close(fd); + return; +} + +static void * +thr(void *data __unused) +{ + pthread_set_name_np(pthread_self(), __func__); + go = 1; + while (go == 1) { + ftruncate(fd, FSIZE / 2); + ftruncate(fd, FSIZE); + } + + return (NULL); +} + +static void +writer(void) { + struct hostent *hostent; + struct sockaddr_in inetaddr; + pthread_t tid; + off_t off = 0; + size_t size; + int i, on, r, tcpsock; + + on = 1; + for (i = 1; i < 5; i++) { + if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + err(1, "socket(), %s:%d", __FILE__, __LINE__); + + if (setsockopt(tcpsock, + SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) + err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); + + size = getpagesize(); + if (setsockopt(tcpsock, SOL_SOCKET, SO_SNDBUF, (void *)&size, + sizeof(size)) < 0) + err(1, "setsockopt(SO_SNDBUF), %s:%d", + __FILE__, __LINE__); + + hostent = gethostbyname ("localhost"); + memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr, + sizeof (struct in_addr)); + + inetaddr.sin_family = AF_INET; + inetaddr.sin_port = htons(port); + inetaddr.sin_len = sizeof(inetaddr); + + r = connect(tcpsock, (struct sockaddr *) &inetaddr, + sizeof(inetaddr)); + if (r == 0) + break; + sleep(1); + close(tcpsock); + } + if (r < 0) + err(1, "connect(), %s:%d", __FILE__, __LINE__); + + if ((fd = open(inputFile, O_RDWR | O_CREAT | O_TRUNC, 0640)) == -1) + err(1, "open(%s)", inputFile); + + if (write(fd, buf, sizeof(buf)) != sizeof(buf)) + err(1, "write()"); + + r = pthread_create(&tid, NULL, thr, NULL); + if (r) + errc(1, r, "pthread_create"); + + usleep(5000); + if (sendfile(fd, tcpsock, 0, FSIZE, NULL, &off, 0) == -1) + err(1, "sendfile"); + + usleep(arc4random() % 20000); + go = 0; + if ((r = pthread_join(tid, NULL)) != 0) + errc(1, r, "pthread_join"); + + _exit(0); +} + +int +main(int argc, char **argv) +{ + pid_t pid; + time_t start; + + if (argc != 4) { + fprintf(stderr, "Usage: %s <inputFile outputFile portNumber\n", + argv[0]); + return (1); + } + inputFile = argv[1]; + outputFile = argv[2]; + port = atoi(argv[3]); + pthread_set_name_np(pthread_self(), __func__); + + start = time(NULL); + while (time(NULL) - start < 120) { + if ((pid = fork()) == 0) { + writer(); + } else if (pid > 0) { + reader(); + kill(pid, SIGINT); + if (waitpid(pid, NULL, 0) != pid) + err(1, "waitpid()"); + } else + err(1, "fork(), %s:%d", __FILE__, __LINE__); + } + + return (0); +} diff --git a/tools/test/stress2/misc/msdos20.sh b/tools/test/stress2/misc/msdos20.sh new file mode 100755 index 000000000000..96c224a629f3 --- /dev/null +++ b/tools/test/stress2/misc/msdos20.sh @@ -0,0 +1,87 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# msdosfs disk image fuzz test. +# No problems seen + +. ../default.cfg + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +cc -o /tmp/flip -Wall -Wextra -O2 ../tools/flip.c || exit 1 + +set -eu +u1=$mdstart +u2=$((mdstart + 1)) +mp1=${mntpoint}$u1 +mp2=${mntpoint}$u2 +mkdir -p $mp1 $mp2 +prog=$(basename "$0" .sh) +backup=/tmp/$prog.sh.diskimage.`date +%Y%m%dT%H%M%S` +cap=$((32 * 1024)) # Only fuzz the first 32k +log=$mp1/$prog.sh.log +diskimage=$mp1/msdos20.sh.diskimage + +set +e +mount | grep "on $mp2 " | grep -q /dev/md && umount -f $mp2 +mount | grep "on $mp1 " | grep -q /dev/md && umount -f $mp1 +[ -c /dev/md$u2 ] && mdconfig -d -u $u2 +[ -c /dev/md$u1 ] && mdconfig -d -u $u1 +mdconfig -a -t swap -s 2g -u $u1 +newfs -U /dev/md$u1 > /dev/null +mount /dev/md$u1 $mp1 + +size=32m +type=`jot -r 1 1 3` +[ $type -eq 3 ] && size=260m +[ -c /dev/md$u2 ] && mdconfig -d -u $u2 +dd if=/dev/zero of=$diskimage bs=$size count=1 status=none +mdconfig -a -t vnode -f $diskimage -u $u2 +[ $type -eq 1 ] && newfs_msdos -F 12 /dev/md$u2 > /dev/null 2>&1 +[ $type -eq 2 ] && newfs_msdos -F 16 /dev/md$u2 > /dev/null 2>&1 +[ $type -eq 3 ] && newfs_msdos -F 32 -b 4096 /dev/md$u2 > /dev/null 2>&1 + +mount -t msdosfs /dev/md$u2 $mp2 || { echo "Initial mount of type $type failed"; exit 1; } +if [ -d /usr/include/sys ]; then + mkdir $mp2/sys + cp /usr/include/sys/elf_common.h $mp2/sys + cp /usr/include/sys/soundcard.h $mp2/sys + cp /usr/include/sys/sysproto.h $mp2/sys +fi +umount $mp2 + +cd $mp1 +start=`date +%s` +nn=0 +s=0 +while [ $((`date +%s` - start)) -lt 240 ]; do + mount -t msdosfs /dev/md$u2 $mp2 2>/dev/null || { s=1; break; } + ls -lR $mp2 > /dev/null 2>&1 || { s=2; break; } + rm -rf $mp2/* > /dev/null 2>&1 || { s=3; break; } + touch $mp2/`jot -rc 8 a z | tr -d '\n'` || { s=4; break; } + while mount | grep -q "on $mp2 "; do umount $mp2; done + echo * | grep -q core && { s=5; break; } + sync + mdconfig -d -u $u2 + /tmp/flip -n 10 -s $cap $diskimage + cp $diskimage $backup + fsync $backup + sync + mdconfig -a -t vnode -f $diskimage -u $u2 + nn=$((nn + 1)) +done +#echo "Exit after $nn loops on a type $type MSDOS FS with code $s" +mount | grep -q "on $mp2 " && umount $mp2 +mdconfig -d -u $u2 || exit 1 + +echo * | grep -q core && { ls -l *.core; cp $log /tmp; exit 106; } || +cd /tmp +umount $mp1 +mdconfig -d -u $u1 +rm -f /tmp/flip $backup +exit 0 diff --git a/tools/test/stress2/misc/msdos21.sh b/tools/test/stress2/misc/msdos21.sh new file mode 100755 index 000000000000..68ea94eab105 --- /dev/null +++ b/tools/test/stress2/misc/msdos21.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +# Test scenario from https://reviews.freebsd.org/D43951 "Fix MSDOSFS rename (in case target exists)" +# Test scenario by se@ + +# Triggered a panic with a WiP kernel patch. + +set -u +[ -f "`which rsync`" ] || exit 0 +[ -d /usr/src/lib ] || exit 0 + +MDUNIT=10 +FS=/mnt/test +mdconfig -u $MDUNIT -t malloc -s 512m +newfs_msdos -c 8 -F 32 /dev/md$MDUNIT > /dev/null 2>&1 +mkdir -p $FS +mount -t msdos /dev/md$MDUNIT $FS +rsync -r /usr/src/lib/libsysdecode $FS +rsync -r /usr/src/lib/libsysdecode $FS +rsync -r /usr/src/lib/libsysdecode $FS +umount $FS +fsck_msdosfs -y /dev/md$MDUNIT; s=$? +mdconfig -d -u $MDUNIT + +exit $s diff --git a/tools/test/stress2/misc/namecache2.sh b/tools/test/stress2/misc/namecache2.sh index 9fcfe5e0226c..b32d41974468 100755 --- a/tools/test/stress2/misc/namecache2.sh +++ b/tools/test/stress2/misc/namecache2.sh @@ -26,7 +26,7 @@ # SUCH DAMAGE. # -# UFS cache inconsistancy for rename(2) demonstrated +# UFS cache inconsistency for rename(2) demonstrated # Fails with: # ls -ali /mnt # ls: tfa1022: No such file or directory diff --git a/tools/test/stress2/misc/newfs.sh b/tools/test/stress2/misc/newfs.sh index 44c76f78b599..252629c04b90 100755 --- a/tools/test/stress2/misc/newfs.sh +++ b/tools/test/stress2/misc/newfs.sh @@ -78,8 +78,8 @@ for opt in -O1 -O2 -U -j; do done blocksize=$((blocksize * 2)) done - if [ $((`date '+%s'` - start)) -gt 1200 ]; then - echo "Timed out" + if [ $((`date '+%s'` - start)) -gt 1800 ]; then + echo "Timed out in $opt" s=4 break fi diff --git a/tools/test/stress2/misc/md4.sh b/tools/test/stress2/misc/newfs6.sh index 0d760b99b058..cf481569ee9c 100755 --- a/tools/test/stress2/misc/md4.sh +++ b/tools/test/stress2/misc/newfs6.sh @@ -1,8 +1,9 @@ #!/bin/sh # -# Copyright (c) 2013 Peter Holm <pho@FreeBSD.org> -# All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -26,19 +27,38 @@ # SUCH DAMAGE. # -# Demonstrate data corruption on the swap-backed md. -# Test scenario by Nigel Williams <njwilliams swin edu au>. -# Fixed in r250966. +# A fast version of newfs.sh [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 -[ -z "`which bsdlabel`" ] && exit 0 -status=0 -MD_DEV=`mdconfig -an -t swap -s 1m -x 63 -y 16` -fdisk -I md$MD_DEV > /dev/null 2>&1 -bsdlabel -w -B md${MD_DEV}s1 || exit 1 -dd if=/dev/md$MD_DEV of=/dev/null bs=64k status=none -bsdlabel md${MD_DEV}s1 > /dev/null || - { echo FAIL; status=1; } -mdconfig -d -u $MD_DEV -exit $status +. ../default.cfg + +mount | grep "on $mntpoint " | grep -q md$mdstart && + umount $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 1g -u $mdstart || exit 1 + +log=/tmp/newfs6.sh.log +s=0 +for opt in -O1 -O2 -U -j; do + bs=4096 + while [ $bs -le 65536 ]; do + for i in 8 4 2 1; do + fragsize=$((bs / i)) + echo "newfs $opt -b $bs -f $fragsize md$mdstart " + newfs $opt -b $bs -f $fragsize \ + md$mdstart > /dev/null || { s=1; continue; } + mount /dev/md$mdstart $mntpoint || s=2 && + umount $mntpoint + fsck -fy /dev/md$mdstart > $log 2>&1 + grep -q "WAS MODIFIED" $log && { + s=3 + cat $log + } + done + bs=$((bs * 2)) + done +done +mdconfig -d -u $mdstart +rm -f $log +exit $s diff --git a/tools/test/stress2/misc/gbde.sh b/tools/test/stress2/misc/newfs7.sh index f47d8e9e15bf..1456d1360bc1 100755 --- a/tools/test/stress2/misc/gbde.sh +++ b/tools/test/stress2/misc/newfs7.sh @@ -1,8 +1,9 @@ #!/bin/sh # -# Copyright (c) 2012 Peter Holm <pho@FreeBSD.org> -# All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -26,30 +27,27 @@ # SUCH DAMAGE. # -# "panic: bio_driver1 used by the consumer (geom ffs.md5.bde)" seen -# http://people.freebsd.org/~pho/stress/log/gbde.txt - [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 - . ../default.cfg -mdconfig -l | grep -q $mdstart && mdconfig -d -u $mdstart -mdconfig -a -t swap -s 1g -u $mdstart - -gbde init /dev/md$mdstart -P pass-phrase || exit -gbde attach md$mdstart -p pass-phrase || exit - -newfs $newfs_flags /dev/md$mdstart.bde > /dev/null -mount /dev/md$mdstart.bde $mntpoint -chmod 777 $mntpoint - -export runRUNTIME=20m -export RUNDIR=$mntpoint/stressX - -su $testuser -c 'cd ..; ./run.sh marcus.cfg' - -while mount | grep $mntpoint | grep -q bde; do - umount $mntpoint || sleep 1 -done -gbde detach md$mdstart +# "mount: /dev/md10: Invalid fstype: Invalid argument" seen. +# Reported by: soralx@cydem.org +# Fixed by: 017367c1146a + +set -eu +prog=`basename ${0%.sh}` +log=/tmp/$prog.log +s=0 +mdconfig -a -t swap -s 32T -u $mdstart +newfs -L tst0 -U -b 65536 -f 8192 -d 1048576 -g 131072 -h 16 -i 1048576 \ + /dev/md$mdstart > /dev/null || s=1 +set +e +mount /dev/md$mdstart $mntpoint && umount $mntpoint || s=$((s | 2)) +fsck_ffs -fy md$mdstart > $log 2>&1 || s=$((s | 4)) +grep -Eq "IS CLEAN|MARKED CLEAN" $log || s=$((s | 8)) +grep -Eq "WAS MODIFIED" $log && s=$((s | 16)) +[ $s -ne 0 ] && tail -10 $log mdconfig -d -u $mdstart +rm -f $log + +exit $s diff --git a/tools/test/stress2/misc/newfs8.sh b/tools/test/stress2/misc/newfs8.sh new file mode 100755 index 000000000000..56ee07cba9b1 --- /dev/null +++ b/tools/test/stress2/misc/newfs8.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Variation of newfs.sh with VM pressure added + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +set -u +mount | grep "$mntpoint" | grep md$mdstart > /dev/null && + umount $mntpoint +mdconfig -l | grep md$mdstart > /dev/null && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 20g -u $mdstart + +log=/tmp/newfs.sh.log +s=0 +export RUNDIR=$mntpoint/stressX +export runRUNTIME=2m +export RUNTIME=$runRUNTIME +export CTRLDIR=$mntpoint/stressX.control +start=`date '+%s'` +for opt in -O2 -U -j; do + blocksize=4096 + while [ $blocksize -le 65536 ]; do + for i in 8 4 2 1; do + fragsize=$((blocksize / i)) + echo "`date +%T` newfs $opt -b $blocksize -f $fragsize"\ + "md$mdstart" + newfs $opt -b $blocksize -f $fragsize \ + md$mdstart > /dev/null || { s=1; continue; } + [ "$opt" = "-O2" ] && tunefs -n disable md$mdstart > /dev/null 2>&1 + mount /dev/md$mdstart $mntpoint || { s=2; continue; } + chmod 777 $mntpoint + su $testuser -c \ + "(cd ..; ./run.sh io.cfg > /dev/null 2>&1)" & + sleep 30 + while pkill swap; do :; done + while pkill -U $testuser; do :; done + ../tools/killall.sh || { echo "Failed at $opt -b $blocksize -f $fragsize$"; \ + exit 3; } + wait + while mount | grep "$mntpoint" | \ + grep -q md$mdstart; do + umount $mntpoint > /dev/null 2>&1 || sleep 1 + done + fsck -fy /dev/md$mdstart > $log 2>&1 + grep -q "WAS MODIFIED" $log && { + s=4 + cat $log + } + done + blocksize=$((blocksize * 2)) + done + if [ $((`date '+%s'` - start)) -gt 3600 ]; then + echo "Timed out in $opt -b $blocksize -f $fragsize$" + s=5 + break + fi +done +mdconfig -d -u $mdstart +rm -f $log +exit $s diff --git a/tools/test/stress2/misc/nfs17.sh b/tools/test/stress2/misc/nfs17.sh index 2a012e476e55..86f045a34bdf 100755 --- a/tools/test/stress2/misc/nfs17.sh +++ b/tools/test/stress2/misc/nfs17.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/nfs18.sh b/tools/test/stress2/misc/nfs18.sh index 46330a0290a1..b1432dd355d2 100755 --- a/tools/test/stress2/misc/nfs18.sh +++ b/tools/test/stress2/misc/nfs18.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # diff --git a/tools/test/stress2/misc/nfs_halfpage.sh b/tools/test/stress2/misc/nfs_halfpage.sh index b665e84d7ddf..8d02ca8ebbcf 100755 --- a/tools/test/stress2/misc/nfs_halfpage.sh +++ b/tools/test/stress2/misc/nfs_halfpage.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2017 Konstantin Belousov <kib@FreeBSD.org> # diff --git a/tools/test/stress2/misc/nfs_halfpage2.sh b/tools/test/stress2/misc/nfs_halfpage2.sh index 15895da2da21..b916531c7a9d 100755 --- a/tools/test/stress2/misc/nfs_halfpage2.sh +++ b/tools/test/stress2/misc/nfs_halfpage2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2017 Konstantin Belousov <kib@FreeBSD.org> # diff --git a/tools/test/stress2/misc/nfsrename.sh b/tools/test/stress2/misc/nfsrename.sh index b6513fba1553..864c64aed8ac 100755 --- a/tools/test/stress2/misc/nfsrename.sh +++ b/tools/test/stress2/misc/nfsrename.sh @@ -137,7 +137,7 @@ write_file(void) unlink(path); } - fprintf(fp, "blah blah blah garbage %ld\n", random()); + fprintf(fp, "blah blah blah garbage %ld\n", (long)arc4random()); fclose(fp); if (rename(path, filename) < 0) { warn("rename"); @@ -150,7 +150,7 @@ random_sleep(int base, int slop) { long val; - val = random() % slop; + val = arc4random() % slop; usleep(base + val); } diff --git a/tools/test/stress2/misc/nlink.sh b/tools/test/stress2/misc/nlink.sh index 1d3bde8c7d42..f06752290ac3 100755 --- a/tools/test/stress2/misc/nlink.sh +++ b/tools/test/stress2/misc/nlink.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/nlink2.sh b/tools/test/stress2/misc/nlink2.sh index 41cdaa676fc9..559ad5cfa417 100755 --- a/tools/test/stress2/misc/nlink2.sh +++ b/tools/test/stress2/misc/nlink2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/nlink3.sh b/tools/test/stress2/misc/nlink3.sh index 2484e8569928..55557124c9c2 100755 --- a/tools/test/stress2/misc/nlink3.sh +++ b/tools/test/stress2/misc/nlink3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # @@ -52,7 +52,7 @@ main (void) { err(1, "creat(%s)", file); close(fd); - mx = UFS_LINK_MAX - 1; /* UFS_LINK_MAX = 32767 */ + mx = UFS_LINK_MAX - 1; for (i = 0; i < mx; i++) { snprintf(file, sizeof(file), "%d", i); if (link("f", file) == -1) diff --git a/tools/test/stress2/misc/nlink4.sh b/tools/test/stress2/misc/nlink4.sh index 12412666b182..cce8bb06985a 100755 --- a/tools/test/stress2/misc/nlink4.sh +++ b/tools/test/stress2/misc/nlink4.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # @@ -51,7 +51,7 @@ main (void) { err(1, "creat(%s)", file); close(fd); - mx = UFS_LINK_MAX - 1; /* UFS_LINK_MAX = 32767 */ + mx = UFS_LINK_MAX - 1; for (i = 0; i < mx; i++) { snprintf(file, sizeof(file), "%d", i); if (link("f", file) == -1) diff --git a/tools/test/stress2/misc/nlink5.sh b/tools/test/stress2/misc/nlink5.sh index c90f43b35dd5..0738bc7548bf 100755 --- a/tools/test/stress2/misc/nlink5.sh +++ b/tools/test/stress2/misc/nlink5.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # @@ -33,6 +33,9 @@ . ../default.cfg +UFS_LINK_MAX=`grep UFS_LINK_MAX /usr/include/ufs/ufs/dinode.h 2>/dev/null` +[ -z "$UFS_LINK_MAX" ] && exit 0 +UFS_LINK_MAX=`echo $UFS_LINK_MAX | awk '{print $3}'` cat > /tmp/nlink5.c <<EOF #include <sys/stat.h> #include <ufs/ufs/dinode.h> @@ -46,7 +49,7 @@ main (void) { int i, mx; char dir[100]; - mx = UFS_LINK_MAX - 2; /* UFS_LINK_MAX = 32767 */ + mx = UFS_LINK_MAX - 2; for (i = 0; i < mx; i++) { snprintf(dir, sizeof(dir), "%d", i); if (mkdir(dir, 0700) == -1) @@ -111,7 +114,7 @@ set +e cd $mntpoint /tmp/nlink5; s=$? n=`find . -type d -maxdepth 1 | wc -l` -[ $n -ne 32766 ] && s=2 +[ $n -ne $((UFS_LINK_MAX - 1)) ] && s=2 cd $here umount $mntpoint diff --git a/tools/test/stress2/misc/nullfs18.sh b/tools/test/stress2/misc/nullfs18.sh index 0ee0a1c2ef6b..3936ea64c6a3 100755 --- a/tools/test/stress2/misc/nullfs18.sh +++ b/tools/test/stress2/misc/nullfs18.sh @@ -28,7 +28,7 @@ [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 -# Demonstate nullfs(5) inode leak. +# Demonstate nullfs(4) inode leak. # Fixed by r295717. . ../default.cfg @@ -41,6 +41,7 @@ mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart mdconfig -a -t swap -s 2g -u $mdstart || exit 1 newfs -n md$mdstart > /dev/null +tunefs -n disable md$mdstart 2>/dev/null mount /dev/md$mdstart $mntpoint chmod 777 $mntpoint diff --git a/tools/test/stress2/misc/nullfs25.sh b/tools/test/stress2/misc/nullfs25.sh index 57f63c6d2330..b98d4599a7ad 100755 --- a/tools/test/stress2/misc/nullfs25.sh +++ b/tools/test/stress2/misc/nullfs25.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/nullfs26.sh b/tools/test/stress2/misc/nullfs26.sh index 720021e9e199..ae3dfa23dc2b 100755 --- a/tools/test/stress2/misc/nullfs26.sh +++ b/tools/test/stress2/misc/nullfs26.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/nullfs27.sh b/tools/test/stress2/misc/nullfs27.sh index 907e9de14253..bf7b2a5fea61 100755 --- a/tools/test/stress2/misc/nullfs27.sh +++ b/tools/test/stress2/misc/nullfs27.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/nullfs28.sh b/tools/test/stress2/misc/nullfs28.sh index 3e313de6f64c..6ebb47974ffe 100755 --- a/tools/test/stress2/misc/nullfs28.sh +++ b/tools/test/stress2/misc/nullfs28.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/nullfs30.sh b/tools/test/stress2/misc/nullfs30.sh new file mode 100755 index 000000000000..8b8f35aed4c0 --- /dev/null +++ b/tools/test/stress2/misc/nullfs30.sh @@ -0,0 +1,112 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Parallel mount and umount test of file mounts, +# mounting over non-directories + +# panic: free: address 0xffffffff80b229b4 ... has not been allocated +# https://people.freebsd.org/~pho/stress/log/log0454.txt + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +cont=/tmp/nullfs30.continue +mounts=3 # Number of parallel scripts + +set -eu +md1=$mdstart +md2=$((md1 + 1)) +mp1=$mntpoint$md1 +mp2=$mntpoint$md2 +mkdir -p $mp1 $mp2 + +mdconfig -a -t swap -s 256m -u $md1 +newfs $newfs_flags -n md$md1 > /dev/null +mount /dev/md$md1 $mp1 +mdconfig -a -t swap -s 256m -u $md2 +newfs $newfs_flags -n md$md2 > /dev/null +mount /dev/md$md2 $mp2 + +for i in `jot $mounts`; do + cp /etc/group $mp1/f$i + touch $mp2/m$i +done +set +e + +mount -t nullfs $mp1/f1 $mp2/m1 || { + umount $mp2 + umount $mp1 + mdconfig -d -u $md2 + mdconfig -d -u $md1 + echo "File mount not implemented" + exit 0 +} + +(cd ../testcases/swap; ./swap -t 5m -i 20 > /dev/null) & + +# Start the parallel tests +touch $cont +while [ -f $cont ]; do + while mount | grep -q "on $mp2/m1 "; do umount $mp2/m1; done 2> /dev/null + mount -t nullfs $mp1/f1 $mp2/m1 +done & +while [ -f $cont ]; do + while mount | grep -q "on $mp2/m2 "; do umount $mp2/m2; done 2> /dev/null + mount -t nullfs $mp1/f2 $mp2/m2 +done & +while [ -f $cont ]; do + while mount | grep -q "on $mp2/m3 "; do umount $mp2/m3; done 2> /dev/null + mount -t nullfs $mp1/f3 $mp2/m3 +done & + +start=`date +%s` +while [ $((`date +%s` - start)) -lt 300 ]; do + cat $mp2/m1 $mp2/m2 $mp2/m3 > /dev/null +done +rm -f $cont +while pgrep -q swap; do pkill swap; done +wait + +for i in 1 2 3; do + while mount | grep -q "on $mp2/m$i "; do umount $mp2/m$i; done 2> /dev/null +done + +# Check error handling +mount -t nullfs $mp1/f1 $mp2/m1 +mount -t nullfs $mp1/f1 $mp2/m1 2>/dev/null && s=1 || s=0 +while mount | grep -q "on $mp2/m1 "; do umount $mp2/m1; done 2> /dev/null + +mkdir $mp2/dir +mount -t nullfs $mp1/f1 $mp2/dir 2>/dev/null && s=2 + +umount $mp2 +umount $mp1 +mdconfig -d -u $md2 +mdconfig -d -u $md1 +exit $s diff --git a/tools/test/stress2/misc/nullfs31.sh b/tools/test/stress2/misc/nullfs31.sh new file mode 100755 index 000000000000..381ec6bf041c --- /dev/null +++ b/tools/test/stress2/misc/nullfs31.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Variation of nullfs25.sh, using cp(1) (copy_file_range()) + +# Page fault in vn_copy_file_range() seen: +# https://people.freebsd.org/~pho/stress/log/log0497.txt +# Fixed by: 23210f538a00 + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +set -u +mounts=4 # Number of parallel scripts +: ${nullfs_srcdir:=$mntpoint} +: ${nullfs_dstdir:=$mntpoint} +prog=$(basename "$0" .sh) +CONT=/tmp/$prog.continue + +mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 1g -u $mdstart +newfs $newfs_flags md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +chmod 777 $mntpoint +(cd $mntpoint; jot 500 | xargs touch) +(cd ../testcases/swap; ./swap -t 5m -i 20 > /dev/null) & + +for i in `jot $mounts $mdstart`; do + [ ! -d ${nullfs_dstdir}$i ] && mkdir ${nullfs_dstdir}$i + mount | grep -q " ${nullfs_dstdir}$i " && + umount ${nullfs_dstdir}$i +done + +# Start the parallel tests +touch $CONT +for i in `jot $mounts $mdstart`; do + while [ -f $CONT ]; do + cp /etc/group ${nullfs_dstdir}$i > \ + /dev/null 2>&1 + done & + # The test: Parallel mount and unmount + start=`date +%s` + ( + while [ $((`date +%s` - start)) -lt 300 ]; do + mount_nullfs $nullfs_srcdir ${nullfs_dstdir}$i > \ + /dev/null 2>&1 + opt=$([ `jot -r 1 0 1` -eq 0 ] && echo "-f") + while mount | grep -q ${nullfs_dstdir}$i; do + umount $opt ${nullfs_dstdir}$i > \ + /dev/null 2>&1 + done + done + rm -f $CONT + ) & +done +while [ -f $CONT ] ; do sleep 1; done +while pgrep -q swap; do pkill swap; done +wait + +for i in `jot $mounts`; do + umount ${nullfs_dstdir}$i > /dev/null 2>&1 +done +n=0 +while mount | grep $mntpoint | grep -q /dev/md; do + umount $mntpoint || sleep 1 + [ $((n += 1)) -gt 300 ] && { echo FAIL; exit 1; } +done +mdconfig -d -u $mdstart +exit 0 diff --git a/tools/test/stress2/misc/nullfs32.sh b/tools/test/stress2/misc/nullfs32.sh new file mode 100755 index 000000000000..567a40d4d373 --- /dev/null +++ b/tools/test/stress2/misc/nullfs32.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +# Test scenario from: +# Bug 254210 - jail: nullfs: deleted files does not free up space +# Fixed by: 1a0cb938f7b4 + +# Test scenario idea by: ronald@FreeBSD.org + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +set -u +prog=$(basename "$0" .sh) +log=/tmp/$prog.log +df -h | grep "$mntpoint" +mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 2g -u $mdstart +newfs $newfs_flags -n md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint + +cd $mntpoint +mkdir storage test1 test2 +mount_nullfs -o rw,noatime ./storage ./test1 +mount_nullfs -o rw,noatime ./storage ./test2 + +dd if=/dev/random of=./test1/random.dd bs=1M count=1024 status=none + +rm ./test2/random.dd +df -h | grep "$mntpoint" > $log +grep -E "${mntpoint}$" $log | grep -q '16K 1.8G 0%' && s=0 || s=1 +if [ $s -eq 1 ]; then + echo "Leaking:" + cat $log + find $mntpoint -type f -ls +fi +cd - +umount $mntpoint/test1 +umount $mntpoint/test2 +umount $mntpoint +mdconfig -d -u $mdstart +rm -f rm -f $log +exit $s diff --git a/tools/test/stress2/misc/numa.sh b/tools/test/stress2/misc/numa.sh index 048eb1201714..afa153ec1ed1 100755 --- a/tools/test/stress2/misc/numa.sh +++ b/tools/test/stress2/misc/numa.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/open2.sh b/tools/test/stress2/misc/open2.sh index 7c0994bfd4e4..fc3f7c9b05eb 100755 --- a/tools/test/stress2/misc/open2.sh +++ b/tools/test/stress2/misc/open2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/overflow3.sh b/tools/test/stress2/misc/overflow3.sh index a5a29721a30b..d09794e57bca 100755 --- a/tools/test/stress2/misc/overflow3.sh +++ b/tools/test/stress2/misc/overflow3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Mark Johnston <markj@FreeBSD.org> # diff --git a/tools/test/stress2/misc/pageout.sh b/tools/test/stress2/misc/pageout.sh index eafeb22d3417..92eb899880ac 100755 --- a/tools/test/stress2/misc/pageout.sh +++ b/tools/test/stress2/misc/pageout.sh @@ -33,6 +33,10 @@ # "panic: handle_written_filepage: not started" seen: # https://people.freebsd.org/~pho/stress/log/pageout-2.txt +# "panic: ffs_geom_strategy: bad I/O" seen: +# https://people.freebsd.org/~pho/stress/log/log0434.txt +# Fixed by: 7aeea73e3078 + [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg @@ -49,6 +53,8 @@ mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart mdconfig -a -t swap -s 2g -u $mdstart || exit 1 +[ "$newfs_flags" = "-U" ] && [ `jot -r 1 0 1` -eq 1 ] && newfs_flags="-j" +[ $# -eq 1 ] && newfs_flags="$1" # or use script argument newfs $newfs_flags md$mdstart > /dev/null mount /dev/md$mdstart $mntpoint @@ -61,8 +67,8 @@ daemon sh -c "(cd ../testcases/swap; ./swap -t 5m -i 20 -l 100 -h)" > /dev/null (cd /tmp; /tmp/pageout $f1) & sleep .2 while kill -0 $! 2> /dev/null; do - mksnap_ffs $mntpoint $mntpoint/.snap/stress2 && - rm -f $mntpoint/.snap/stress2 + rm -f $mntpoint/.snap/stress2 + mksnap_ffs $mntpoint $mntpoint/.snap/stress2 done while pgrep -q swap; do pkill swap diff --git a/tools/test/stress2/misc/pager_read_error.sh b/tools/test/stress2/misc/pager_read_error.sh new file mode 100755 index 000000000000..9a2f3c7cc380 --- /dev/null +++ b/tools/test/stress2/misc/pager_read_error.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Hunt for "vm_fault: pager read error, pid 32939 (mmap)" + +# "panic: namei: unexpected flags: 0x10000000" seen: +# https://people.freebsd.org/~pho/stress/log/log0585.txt +# Fixed by: 58b2bd33aff7 + +. ../default.cfg + +md=$mdstart +mp=$mntpoint +mdconfig -l | grep -q md$md && mdconfig -d -u $md +mount | grep -q "on $mp " && umount -f $mp + +mdconfig -a -t swap -s 1g -u $md +newfs -U /dev/md$md > /dev/null +mount /dev/md$md $mp + +export RUNDIR=$mp/stressX +../testcases/swap/swap -t 5m -i 20 -l 100 > /dev/null & +sleep 5 +../testcases/mmap/mmap -t 5m -i 20 -l 100 > /dev/null 2>&1 & +sleep 5 +umount -f $mp +pkill swap mmap +wait + +mdconfig -d -u $md +exit 0 diff --git a/tools/test/stress2/misc/perf.sh b/tools/test/stress2/misc/perf.sh index 89e9dd8d371c..de6c20028c59 100755 --- a/tools/test/stress2/misc/perf.sh +++ b/tools/test/stress2/misc/perf.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # @@ -84,6 +84,7 @@ tst() { s=0 for i in "" "-U" "-j"; do newfs $i /dev/md$mdstart > /dev/null 2>&1 + [ "$i" = "" ] && tunefs -n disable md$mdstart mount /dev/md$mdstart $mntpoint t1=`date +%s` diff --git a/tools/test/stress2/misc/ping.sh b/tools/test/stress2/misc/ping.sh index 2594c6d5e43c..29ed6dec955f 100755 --- a/tools/test/stress2/misc/ping.sh +++ b/tools/test/stress2/misc/ping.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/pipe3.sh b/tools/test/stress2/misc/pipe3.sh index 6208e1a52f90..654b94e3caaf 100755 --- a/tools/test/stress2/misc/pipe3.sh +++ b/tools/test/stress2/misc/pipe3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Peter Holm # diff --git a/tools/test/stress2/misc/pipe_enomem.sh b/tools/test/stress2/misc/pipe_enomem.sh index 92558b164336..9a00aac5cb6b 100755 --- a/tools/test/stress2/misc/pipe_enomem.sh +++ b/tools/test/stress2/misc/pipe_enomem.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Konstantin Belousov # diff --git a/tools/test/stress2/misc/pkru.sh b/tools/test/stress2/misc/pkru.sh index 9ac0a5000daf..047b7f8f8745 100755 --- a/tools/test/stress2/misc/pkru.sh +++ b/tools/test/stress2/misc/pkru.sh @@ -1,6 +1,6 @@ #/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Konstantin Belousov <kib@FreeBSD.org> # diff --git a/tools/test/stress2/misc/pmc6.sh b/tools/test/stress2/misc/pmc6.sh index 4cbdf278125f..f0869333b0ff 100755 --- a/tools/test/stress2/misc/pmc6.sh +++ b/tools/test/stress2/misc/pmc6.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/poll2.sh b/tools/test/stress2/misc/poll2.sh index 13db2d0d22d3..aa5ad5f995dd 100755 --- a/tools/test/stress2/misc/poll2.sh +++ b/tools/test/stress2/misc/poll2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # @@ -136,11 +136,11 @@ static void * pl(void *data __unused) { struct pollfd pfd; - int i, r; + int r; pfd.fd = fds[0]; pfd.events = POLLIN; - for (i = 0; done == 0; i++) { + while (done == 0) { pfd.fd = fds[0]; pfd.events = POLLIN; pthread_set_name_np(pthread_self(), "pl-idle"); diff --git a/tools/test/stress2/misc/pread.sh b/tools/test/stress2/misc/pread.sh index 1bf3b874e6af..24ee2efb696a 100755 --- a/tools/test/stress2/misc/pread.sh +++ b/tools/test/stress2/misc/pread.sh @@ -46,13 +46,13 @@ mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart mount -t tmpfs tmpfs $mntpoint cp -a /usr/include $mntpoint -echo "Testing tmpfs(5)" +echo "Testing tmpfs(4)" /tmp/pread $mntpoint while mount | grep -q "on $mntpoint "; do umount $mntpoint || sleep 1 done -echo "Testing fdescfs(5)" +echo "Testing fdescfs(4)" mount -t fdescfs null /dev/fd for i in `jot 100`; do /tmp/pread /dev/fd @@ -62,7 +62,7 @@ while mount | grep -q "on /dev/fd "; do umount /dev/fd || sleep 1 done -echo "Testing procfs(5)" +echo "Testing procfs(4)" mount -t procfs procfs $mntpoint /tmp/pread $mntpoint while mount | grep -q "on $mntpoint "; do @@ -81,13 +81,13 @@ done mdconfig -d -u $mdstart mount -t nullfs /bin $mntpoint -echo "Testing nullfs(5)" +echo "Testing nullfs(4)" /tmp/pread $mntpoint while mount | grep -q "on $mntpoint "; do umount $mntpoint || sleep 1 done -echo "Testing procfs(5)" +echo "Testing procfs(4)" mount -t procfs procfs $mntpoint /tmp/pread $mntpoint while mount | grep -q "on $mntpoint "; do diff --git a/tools/test/stress2/misc/proccontrol.sh b/tools/test/stress2/misc/proccontrol.sh index 52f7cc824372..cea8c0dc0f0a 100755 --- a/tools/test/stress2/misc/proccontrol.sh +++ b/tools/test/stress2/misc/proccontrol.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/procfs.sh b/tools/test/stress2/misc/procfs.sh index 6b445b0d7e48..a59235c6d521 100755 --- a/tools/test/stress2/misc/procfs.sh +++ b/tools/test/stress2/misc/procfs.sh @@ -56,7 +56,8 @@ else else # The test: Parallel mount and unmounts - for i in `jot 128`; do + start=`date +%s` + while [ $((`date +%s`- start)) -lt 300 ]; do m=$1 mount -t procfs proc ${mntpoint}$m while mount | grep -qw $mntpoint$m; do diff --git a/tools/test/stress2/misc/procfs3.sh b/tools/test/stress2/misc/procfs3.sh index c9c4820adbff..30bcc8b3cd62 100755 --- a/tools/test/stress2/misc/procfs3.sh +++ b/tools/test/stress2/misc/procfs3.sh @@ -26,7 +26,7 @@ # SUCH DAMAGE. # -# procfs(5) test scenario. +# procfs(4) test scenario. # "panic: wchan 0xc10a4f68 has no wmesg" seen [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 diff --git a/tools/test/stress2/misc/procfs4.sh b/tools/test/stress2/misc/procfs4.sh index ffa812a7f73d..18e5c0a6f803 100755 --- a/tools/test/stress2/misc/procfs4.sh +++ b/tools/test/stress2/misc/procfs4.sh @@ -68,6 +68,7 @@ EOF #define MAXRUN 1200 #define PARALLEL 10 +static int debug; /* Set to 1 for debug output */ char *files[] = { "cmdline", "ctl", @@ -116,10 +117,8 @@ test(void) close(fd); } kill(p, SIGHUP); -#if 0 - if (opens < 1) - fprintf(stderr, "Warn %d open(s) for pid %d\n", opens, getpid()); -#endif + if (debug != 0 && opens == 0) + fprintf(stderr, "No ioctl() calls succeeded.\n"); } for (i = 0; i < 64; i++) diff --git a/tools/test/stress2/misc/procfs6.sh b/tools/test/stress2/misc/procfs6.sh index b4cc4c1eb4c0..24ea6ae47588 100755 --- a/tools/test/stress2/misc/procfs6.sh +++ b/tools/test/stress2/misc/procfs6.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/procstat.sh b/tools/test/stress2/misc/procstat.sh index 91a846ba91ee..c760583c8bbd 100755 --- a/tools/test/stress2/misc/procstat.sh +++ b/tools/test/stress2/misc/procstat.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/procstat2.sh b/tools/test/stress2/misc/procstat2.sh index 712f53c11b3b..758b684dbf0a 100755 --- a/tools/test/stress2/misc/procstat2.sh +++ b/tools/test/stress2/misc/procstat2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/pthread10.sh b/tools/test/stress2/misc/pthread10.sh new file mode 100755 index 000000000000..ddeab0f9bb57 --- /dev/null +++ b/tools/test/stress2/misc/pthread10.sh @@ -0,0 +1,106 @@ +#!/bin/sh + +# Original test scenario by nabijaczleweli@nabijaczleweli.xyz: +# Bug 283101 - pthread_cancel() doesn't cancel a thread that's currently in pause() +# Fixed by: 9f78c837d94f check_cancel: when in_sigsuspend, send SIGCANCEL unconditionally + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static void * +thread(void *arg __unused) +{ + for(;;) { + pause(); + printf("woke up from pause\n"); + } +} + +static void +thread_cancel_and_join(pthread_t ptid) +{ + void *status = NULL; + + if (pthread_cancel(ptid)) { + printf("pthread_cancel() failed\n"); + exit(1); + } + + (void) pthread_join(ptid, &status); + int error = (int)(uintptr_t)status; + + if (error) { + if (status == PTHREAD_CANCELED) { + printf("pthread_cancel() succeeded\n"); + } else { + printf("pthread_join() error (not PTHREAD_CANCELED)\n"); + exit(1); + } + } +} + +int +main(void) +{ + // Empirically, I've noticed that either the hang occurs somewhere between + // 10 and 500 iterations, or it runs infinitely without ever hanging. + // Therefore, stopping at 500th iteration, and looping from a shell script. + + // For quick results (usually under 10 minutes), invoke "./run" from a dozen + // consoles or GNU screen windows in parallel. + + pid_t pid = getpid(); + + for (uint64_t iteration = 1; iteration <= 500; ++iteration) { + printf("PID %d, iteration %lu...", pid, iteration); + + pthread_t ptid; + int err; + + err = pthread_create(&ptid, NULL, thread, NULL); + + if (err) { + printf("pthread_create() failed with error: %d\n", err); + return 1; + } + + thread_cancel_and_join(ptid); + + printf("OK\n"); + + // Tiny sleep + usleep(20000); + } +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O2 /tmp/$prog.c -lpthread || exit 1 +(cd ../testcases/swap; ./swap -t 3m -i 20 > /dev/null) & +sleep 5 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 180 ]; do + /tmp/$prog > /dev/null & pid=$! + t1=`date +%s` + while kill -0 $pid 2> /dev/null; do + if [ $((`date +%s` - t1)) -gt 180 ]; then + ps -lH $pid +# exit 1 # For DEBUG + kill -9 $pid; s=1 + echo fail + break 2 + else + sleep 1 + fi + done + wait $pid; s=$? + [ $s -ne 0 ] && break +done +while pkill swap; do :; done +wait +rm -f /tmp/$prog /tmp/$prog.c +exit $s diff --git a/tools/test/stress2/misc/ptrace10.sh b/tools/test/stress2/misc/ptrace10.sh index c2dec736a240..205efe2cc27a 100755 --- a/tools/test/stress2/misc/ptrace10.sh +++ b/tools/test/stress2/misc/ptrace10.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Mark Johnston <markj@FreeBSD.org> # diff --git a/tools/test/stress2/misc/ptrace11.sh b/tools/test/stress2/misc/ptrace11.sh index 9fbd44481624..f5231bc1850f 100755 --- a/tools/test/stress2/misc/ptrace11.sh +++ b/tools/test/stress2/misc/ptrace11.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/ptrace12.sh b/tools/test/stress2/misc/ptrace12.sh index b7381c4937e1..b80ba69b1327 100755 --- a/tools/test/stress2/misc/ptrace12.sh +++ b/tools/test/stress2/misc/ptrace12.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/ptrace9.sh b/tools/test/stress2/misc/ptrace9.sh index ac1329fd1a2a..ffd5fce0d646 100755 --- a/tools/test/stress2/misc/ptrace9.sh +++ b/tools/test/stress2/misc/ptrace9.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2016 Mark Johnston <markj@FreeBSD.org> # diff --git a/tools/test/stress2/misc/pts2.sh b/tools/test/stress2/misc/pts2.sh index 84f7bbd78255..32adb98f2cfe 100755 --- a/tools/test/stress2/misc/pts2.sh +++ b/tools/test/stress2/misc/pts2.sh @@ -40,11 +40,11 @@ sed '1,/^EOF/d' < $here/$0 > pts2.c mycc -o pts2 -Wall -Wextra -O2 pts2.c || exit 1 rm -f pts2.c -pts=`vmstat -m | grep pts | awk '{print $2}'` +pts=`vmstat -m | awk '/ pts / {print $2}'` for i in `jot 10`; do /tmp/pts2 done -new=`vmstat -m | grep pts | awk '{print $2}'` +new=`vmstat -m | awk '/ pts / {print $2}'` s=0 [ $((new - pts)) -gt 1 ] && { s=1; echo "Leaked $((new - pts)) pts."; } diff --git a/tools/test/stress2/misc/pts3.sh b/tools/test/stress2/misc/pts3.sh index b398e92916af..ebd854b82bf7 100755 --- a/tools/test/stress2/misc/pts3.sh +++ b/tools/test/stress2/misc/pts3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/quota12.sh b/tools/test/stress2/misc/quota12.sh index 2b2094f22460..cd0855b07584 100755 --- a/tools/test/stress2/misc/quota12.sh +++ b/tools/test/stress2/misc/quota12.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/quota5.sh b/tools/test/stress2/misc/quota5.sh index 050ea4a822d9..ee69dac4be01 100755 --- a/tools/test/stress2/misc/quota5.sh +++ b/tools/test/stress2/misc/quota5.sh @@ -39,6 +39,6 @@ edquota -g -f /tmp -e /tmp:1500000:1400000:200000:180000 $testuser quotaon /tmp su $testuser -c "export runRUNTIME=60m; cd ../testcases/mkdir; \ - ./mkdir -t 30m -i 200 -v -v" + ./mkdir -t 10m -i 200 -v -v" quotaoff /tmp diff --git a/tools/test/stress2/misc/r335171.sh b/tools/test/stress2/misc/r335171.sh index 2d2e9ad72fee..09a11f304198 100755 --- a/tools/test/stress2/misc/r335171.sh +++ b/tools/test/stress2/misc/r335171.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/radix.sh b/tools/test/stress2/misc/radix.sh index fa85512c79c5..b102c09aca92 100755 --- a/tools/test/stress2/misc/radix.sh +++ b/tools/test/stress2/misc/radix.sh @@ -46,14 +46,14 @@ mycc -o radix -Wall -Wextra radix.c || exit 1 rm -f radix.c cd $odir -set -e +set -u trap "rm -f rendezvous" EXIT INT parallel=1 usermem=`sysctl hw.usermem | sed 's/.* //'` pagesize=`pagesize` start=`date +%s` while true; do - timeout 2m /tmp/radix $parallel > $log; s=$? + timeout 20m /tmp/radix $parallel > $log; s=$? [ $s -eq 124 ] && { echo "Timed out"; break; } [ $s -ne 0 ] && cat $log used=`awk '{print $4}' < $log` @@ -63,7 +63,7 @@ while true; do [ $parallel -eq 1 ] && parallel=$((usermem / pagesize / used)) parallel=$((parallel + 1)) - echo "`date +%T` parallel=$parallel" # XXX + [ $parallel -gt 10 ] && parallel=10 done cat /tmp/radix.log diff --git a/tools/test/stress2/misc/random.sh b/tools/test/stress2/misc/random.sh index 04a0075d0c2c..100d9d9b88d0 100755 --- a/tools/test/stress2/misc/random.sh +++ b/tools/test/stress2/misc/random.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/rangelocks.sh b/tools/test/stress2/misc/rangelocks.sh new file mode 100755 index 000000000000..fa855359d72b --- /dev/null +++ b/tools/test/stress2/misc/rangelocks.sh @@ -0,0 +1,194 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Range lock test scenario suggestion by kib@ + +. ../default.cfg + +set -u +prog=$(basename "$0" .sh) +dir=/tmp +odir=`pwd` +cd $dir +sed '1,/^EOF/d' < $odir/$0 > $dir/$prog.c +mycc -o $prog -Wall -Wextra -O2 -g $prog.c || exit 1 +rm -f $prog.c +cd $odir + +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +set -e +mdconfig -a -t swap -s 6g -u $mdstart +newfs $newfs_flags -n /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +set +e +wd="$mntpoint/$prog.dir" +mkdir -p $wd +dd if=/dev/zero of=$wd/file bs=1m count=5k status=none + +[ `jot -r 1 1 100` -le 25 ] && + ../testcases/swap/swap -t 10m -i 20 > /dev/null 2>&1 & +cd $wd +/tmp/$prog $wd/file; s=$? +cd $odir +while pkill swap; do :; done +wait + +umount $mntpoint +mdconfig -d -u $mdstart +rm -rf /tmp/$prog $wd +exit $s + +EOF +#include <sys/param.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <machine/atomic.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <sched.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +#define DONE 1 +#define MAXBLK 10240 +//#define MAXPROC 32 +#define MAXPROC 1024 +#define MAXSIZ (5LL * 1024 * 1024 *1024) +#define RUNTIME (5 * 60) +#define SYNC 0 + +static volatile u_int *share; +static int parallel; + +static char *file; + +static off_t +newpos(int lng) +{ + off_t p; + + do { + arc4random_buf(&p, sizeof(p)); + p = p & 0xfffffff; + } while (p + lng > MAXSIZ); + return (p); +} + +static void +test(int indx, int num) +{ + off_t pos; + ssize_t i, l, r; + time_t start; + int fd, n; + char *buf; + + atomic_add_int(&share[SYNC], 1); + while (share[SYNC] != (unsigned int)parallel) + sched_yield(); + + if ((buf = malloc(MAXBLK)) == NULL) + err(1, "malloc"); + n = 0; + start = time(NULL); + while (share[DONE] != (unsigned int)parallel) { + setproctitle("test(%d) num %d, n %d", indx, num, n); + if ((fd = open(file, O_RDWR)) == -1) + err(1, "open(%s)", file); + + for (i = 0; i < arc4random() % 512; i++) { + if (arc4random() % 100 < 50) { + l = arc4random() % MAXBLK + 1; + pos = newpos(l); + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "lseek"); + if ((r = read(fd, buf, l)) != l) { + warn("read %jd @ %jd returned %zd\n", (intmax_t)l, (intmax_t)pos, r); + goto done; + } + } + + l = arc4random() % MAXBLK + 1; + pos = newpos(l); + if (lseek(fd, pos, SEEK_SET) == -1) + err(1, "lseek"); + if ((r = write(fd, buf, l)) != l) { + warn("write returned %zd\n", r); + goto done; + } + } + + close(fd); + if (n++ == 0) + atomic_add_int(&share[DONE], 1); + if (time(NULL) - start >= RUNTIME * 4) { + fprintf(stderr, "test(%d), %d Timed out\n", indx, num); + break; + } + } +done: + if (n++ == 0) + atomic_add_int(&share[DONE], 1); + + _exit(0); +} + +void +setup(void) +{ + + parallel = arc4random() % MAXPROC + 1; +} + +int +main(int argc, char *argv[]) +{ + size_t len; + time_t start; + int e, i, n, *pids, status; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <file>\n", argv[0]); + _exit(1); + } + e = 0; + file = argv[1]; + len = PAGE_SIZE; + if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) + err(1, "mmap"); + + n = 0; + start = time(NULL); + while ((time(NULL) - start) < RUNTIME && e == 0) { + setup(); + + pids = malloc(sizeof(pid_t) * parallel); + share[SYNC] = share[DONE] = 0; + for (i = 0; i < parallel; i++) { + if ((pids[i] = fork()) == 0) + test(i, n); + } + for (i = 0; i < parallel; i++) { + if (waitpid(pids[i], &status, 0) != pids[i]) + err(1, "waitpid %d", pids[i]); + e += status == 0 ? 0 : 1; + } + n++; + n = n % 10; + free(pids); + } + + return (e); +} diff --git a/tools/test/stress2/misc/rangelocks2.sh b/tools/test/stress2/misc/rangelocks2.sh new file mode 100755 index 000000000000..2df4cf346bc8 --- /dev/null +++ b/tools/test/stress2/misc/rangelocks2.sh @@ -0,0 +1,178 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +. ../default.cfg + +set -u +prog=$(basename "$0" .sh) +dir=/tmp +odir=`pwd` +cd $dir +sed '1,/^EOF/d' < $odir/$0 > $dir/$prog.c +mycc -o $prog -Wall -Wextra -O2 -g $prog.c || exit 1 +rm -f $prog.c +cd $odir + +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +set -e +mdconfig -a -t swap -s 6g -u $mdstart +newfs $newfs_flags -n /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +set +e +wd="$mntpoint/$prog.dir" +mkdir -p $wd +dd if=/dev/zero of=$wd/file bs=1m count=5k status=none + +[ `jot -r 1 1 100` -le 25 ] && + ../testcases/swap/swap -t 10m -i 20 > /dev/null 2>&1 & +cd $wd +touch $wd/out +/tmp/$prog $wd/file $wd/out; s=$? +cd $odir +while pkill swap; do :; done +wait + +umount $mntpoint +mdconfig -d -u $mdstart +rm -rf /tmp/$prog $wd +exit $s + +EOF +#include <sys/param.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <machine/atomic.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <sched.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +#define DONE 1 +#define MAXBLK (100 * 1024 * 1024) +#define MAXPROC 32 +#define MAXSIZ (5LL * 1024 * 1024 *1024) +#define RUNTIME (5 * 60) +#define SYNC 0 + +static volatile u_int *share; +static int parallel; + +static char *file, *file2; + +static off_t +newpos(int lng) +{ + off_t p; + + do { + arc4random_buf(&p, sizeof(p)); + p = p & 0xfffffff; + } while (p + lng > MAXSIZ); + return (p); +} + +static void +test(int indx, int num) +{ + off_t pos, pos2; + ssize_t i, l; + time_t start; + int fd, fd2, n; + + atomic_add_int(&share[SYNC], 1); + while (share[SYNC] != (unsigned int)parallel) + sched_yield(); + + n = 0; + start = time(NULL); + while (share[DONE] != (unsigned int)parallel) { + setproctitle("test(%d) num %d, n %d", indx, num, n); + if ((fd = open(file, O_RDWR)) == -1) + err(1, "open(%s)", file); + if ((fd2 = open(file2, O_RDWR)) == -1) + err(1, "open(%s)", file2); + + for (i = 0; i < arc4random() % 512; i++) { + l = arc4random() % MAXBLK + 1; + pos = newpos(l); + pos2 = newpos(l); + if (copy_file_range(fd, &pos, fd2, &pos2, l, 0) == -1) + err(1, "copy_file_range()"); + } + + close(fd2); + close(fd); + if (n++ == 0) + atomic_add_int(&share[DONE], 1); + if (time(NULL) - start >= RUNTIME * 4) { + fprintf(stderr, "test(%d), %d Timed out\n", indx, num); + break; + } + } + if (n++ == 0) + atomic_add_int(&share[DONE], 1); + + _exit(0); +} + +void +setup(void) +{ + + parallel = arc4random() % MAXPROC + 1; +} + +int +main(int argc, char *argv[]) +{ + size_t len; + time_t start; + int e, i, n, *pids, status; + + if (argc != 3) { + fprintf(stderr, "Usage: %s <in file> <out file>\n", argv[0]); + _exit(1); + } + e = 0; + file = argv[1]; + file2 = argv[2]; + len = PAGE_SIZE; + if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) + err(1, "mmap"); + + n = 0; + start = time(NULL); + while ((time(NULL) - start) < RUNTIME && e == 0) { + setup(); + + pids = malloc(sizeof(pid_t) * parallel); + share[SYNC] = share[DONE] = 0; + for (i = 0; i < parallel; i++) { + if ((pids[i] = fork()) == 0) + test(i, n); + } + for (i = 0; i < parallel; i++) { + if (waitpid(pids[i], &status, 0) != pids[i]) + err(1, "waitpid %d", pids[i]); + e += status == 0 ? 0 : 1; + } + n++; + n = n % 10; + free(pids); + } + + return (e); +} diff --git a/tools/test/stress2/misc/rdgsbase.sh b/tools/test/stress2/misc/rdgsbase.sh index 66a44592d419..3c5597e3f9c2 100755 --- a/tools/test/stress2/misc/rdgsbase.sh +++ b/tools/test/stress2/misc/rdgsbase.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2017 Konstantin Belousov <kib@FreeBSD.org> # diff --git a/tools/test/stress2/misc/rdwr.sh b/tools/test/stress2/misc/rdwr.sh index c77c955dc210..893056558560 100755 --- a/tools/test/stress2/misc/rdwr.sh +++ b/tools/test/stress2/misc/rdwr.sh @@ -28,6 +28,11 @@ # Test with read/write length of INT_MAX (i386) or INT_MAX+1 (amd64) +# Seen: +# rdwr: readv(). Expected 2147483648 (80000000), got -2147483648 (ffffffff80000000) bytes: No error: 0 +# rdwr: writev(). Expected 2147483648 (80000000), got -2147483648 (ffffffff80000000) bytes: No error: 0 +# Fixed by: 78101d437a92 + . ../default.cfg [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 @@ -61,11 +66,22 @@ EOF #include <fcntl.h> #include <unistd.h> +static int s; + +static void +er(char * syscall, size_t len, ssize_t ret) +{ + warn("%8s. Expected %zu (%zx), got %zd (%zx) bytes", + syscall, len, len, ret, ret); + s=1; +} + int main(int argc, char **argv) { int fd1, fd2; size_t len; + ssize_t r; void *p; struct iovec iov; @@ -85,34 +101,34 @@ main(int argc, char **argv) MAP_FAILED) err(1, "mmap"); - if (read(fd2, p, len) != len) - err(1, "read"); + if ((r = read(fd2, p, len)) != len) + er("read()", len, r); - if (write(fd1, p, len) != len) - err(1, "write"); + if ((r = write(fd1, p, len)) != len) + er("write()", len, r); - if (pread(fd2, p, len, 0) != len) - err(1, "pread"); + if ((r = pread(fd2, p, len, 0)) != len) + er("pread()", len, r); - if (pwrite(fd1, p, len, 0) != len) - err(1, "pwrite"); + if ((r = pwrite(fd1, p, len, 0)) != len) + er("pwrite()", len, r); iov.iov_base = p; iov.iov_len = len; - if (readv(fd2, &iov, 1) != len) - err(1, "readv"); + if ((r = readv(fd2, &iov, 1)) != len) + er("readv()", len, r); - if (writev(fd1, &iov, 1) != len) - err(1, "writev"); + if ((r = writev(fd1, &iov, 1)) != len) + er("writev()", len, r); - if (preadv(fd2, &iov, 1, 0) != len) - err(1, "preadv"); + if ((r = preadv(fd2, &iov, 1, 0)) != len) + er("preadv()", len, r); - if (pwritev(fd1, &iov, 1, 0) != len) - err(1, "pwritev"); + if ((r = pwritev(fd1, &iov, 1, 0)) != len) + er("pwritev()", len, r); close(fd1); close(fd2); - return (0); + return (s); } diff --git a/tools/test/stress2/misc/readdir.sh b/tools/test/stress2/misc/readdir.sh index 8616a8a40206..425295631181 100755 --- a/tools/test/stress2/misc/readdir.sh +++ b/tools/test/stress2/misc/readdir.sh @@ -45,19 +45,19 @@ mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart mount -t tmpfs tmpfs $mntpoint -echo "Testing tmpfs(5)" +echo "Testing tmpfs(4)" cp -a /usr/include $mntpoint /tmp/readdir $mntpoint umount $mntpoint -echo "Testing fdescfs(5)" +echo "Testing fdescfs(4)" kldstat -v | grep -q fdescfs || { kldload fdescfs.ko; loaded=1; } mount -t fdescfs null /dev/fd /tmp/readdir /dev/fd umount /dev/fd [ $unload ] && kldunload fdescfs.ko -echo "Testing procfs(5)" +echo "Testing procfs(4)" mount -t procfs procfs $mntpoint /tmp/readdir $mntpoint umount $mntpoint @@ -89,7 +89,7 @@ umount $mntpoint mdconfig -d -u $mdstart mount -t nullfs /bin $mntpoint -echo "Testing nullfs(5)" +echo "Testing nullfs(4)" /tmp/readdir $mntpoint umount $mntpoint diff --git a/tools/test/stress2/misc/reaper.sh b/tools/test/stress2/misc/reaper.sh index 1d2d5ade8c6e..5ad19a55d60b 100755 --- a/tools/test/stress2/misc/reaper.sh +++ b/tools/test/stress2/misc/reaper.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/reaper2.sh b/tools/test/stress2/misc/reaper2.sh index 8290e38d34e4..ee9cf927f1d9 100755 --- a/tools/test/stress2/misc/reaper2.sh +++ b/tools/test/stress2/misc/reaper2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # @@ -65,8 +65,9 @@ test(void) { struct procctl_reaper_kill killemall; pid_t pid; time_t start; - int data[20], e, n, m; + int data[20], debug, e, n, m; + debug = 0; /* set to 1 for debug output */ n = m = 0; if (procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == -1) err(EXIT_FAILURE, "Fail to acquire the reaper"); @@ -94,9 +95,8 @@ test(void) { if (waitpid(pid, NULL, 0) != pid) err(1, "waitpid()"); } -#if defined(DEBUG) - fprintf(stderr, "n = %d out of %d\n", n, m); -#endif + if (debug == 1) + fprintf(stderr, "n = %d out of %d\n", n, m); _exit(0); } diff --git a/tools/test/stress2/misc/reaper3.sh b/tools/test/stress2/misc/reaper3.sh index fdf715fa7b0b..59012d2c45ca 100755 --- a/tools/test/stress2/misc/reaper3.sh +++ b/tools/test/stress2/misc/reaper3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # @@ -59,14 +59,13 @@ flip(void *ap, size_t len) { unsigned char *cp; int byte; - unsigned char bit, buf, mask, old __unused; + unsigned char bit, buf, mask; cp = (unsigned char *)ap; byte = random_long(0, len); bit = random_long(0,7); mask = ~(1 << bit); buf = cp[byte]; - old = cp[byte]; buf = (buf & mask) | (~buf & ~mask); cp[byte] = buf; } @@ -86,8 +85,9 @@ test(void) { struct procctl_reaper_kill killemall; pid_t pid; time_t start; - int data[20], e, n, m; + int data[20], debug, e, n, m; + debug = 0; /* set to 1 for debug output */ n = m = 0; if (procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == -1) err(EXIT_FAILURE, "Fail to acquire the reaper"); @@ -118,9 +118,8 @@ test(void) { if (waitpid(pid, NULL, 0) != pid) err(1, "waitpid()"); } -#if defined(DEBUG) - fprintf(stderr, "n = %d out of %d\n", n, m); -#endif + if (debug == 1) + fprintf(stderr, "n = %d out of %d\n", n, m); _exit(0); } diff --git a/tools/test/stress2/misc/reaper4.sh b/tools/test/stress2/misc/reaper4.sh index bf400e396e63..0fdb3f75ccff 100755 --- a/tools/test/stress2/misc/reaper4.sh +++ b/tools/test/stress2/misc/reaper4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # @@ -59,14 +59,13 @@ flip(void *ap, size_t len) { unsigned char *cp; int byte; - unsigned char bit, buf, mask, old __unused; + unsigned char bit, buf, mask; cp = (unsigned char *)ap; byte = random_long(0, len); bit = random_long(0,7); mask = ~(1 << bit); buf = cp[byte]; - old = cp[byte]; buf = (buf & mask) | (~buf & ~mask); cp[byte] = buf; } @@ -85,8 +84,9 @@ test(void) { struct procctl_reaper_kill killemall; pid_t pid; time_t start; - int data[20], e, n, m; + int data[20], debug, e, n, m; + debug = 0; /* set to 1 for debug output */ n = m = 0; if (procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == -1) err(EXIT_FAILURE, "Fail to acquire the reaper"); @@ -117,9 +117,8 @@ test(void) { if (waitpid(pid, NULL, 0) != pid) err(1, "waitpid()"); } -#if defined(DEBUG) - fprintf(stderr, "n = %d out of %d\n", n, m); -#endif + if (debug == 1) + fprintf(stderr, "n = %d out of %d\n", n, m); _exit(0); } diff --git a/tools/test/stress2/misc/reaper5.sh b/tools/test/stress2/misc/reaper5.sh index eec58c36713a..944475479e2c 100755 --- a/tools/test/stress2/misc/reaper5.sh +++ b/tools/test/stress2/misc/reaper5.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/rename14.sh b/tools/test/stress2/misc/rename14.sh index 83612a2632df..cf7f5f6d8148 100755 --- a/tools/test/stress2/misc/rename14.sh +++ b/tools/test/stress2/misc/rename14.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # @@ -33,6 +33,9 @@ # Based on a syzkaller scenario reported by tuexen@freebsd.org +# "panic: journal_jremref: Lost inodedep": +# https://people.freebsd.org/~pho/stress/log/log0279.txt + . ../default.cfg [ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 diff --git a/tools/test/stress2/misc/rename15.sh b/tools/test/stress2/misc/rename15.sh index aa884e045010..0831343101e5 100755 --- a/tools/test/stress2/misc/rename15.sh +++ b/tools/test/stress2/misc/rename15.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/rename16.sh b/tools/test/stress2/misc/rename16.sh new file mode 100755 index 000000000000..09e796299794 --- /dev/null +++ b/tools/test/stress2/misc/rename16.sh @@ -0,0 +1,261 @@ +#!/bin/sh + +# Copy of suj30.sh but with SU instead of SUJ + +# Rename test scenario by Andrey Zonov <zont@FreeBSD.org> + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +set -u +prog=$(basename "$0" .sh) +here=`pwd` +log=/tmp/$prog.sh.log +cd /tmp +sed '1,/^EOF/d' < $here/$0 > $prog.c +mycc -o $prog -Wall -Wextra -O2 $prog.c -lpthread +rm -f $prog.c + +mount | grep "on $mntpoint " | grep -q md$mdstart && umount $mntpoint +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart + +mdconfig -a -t swap -s 8g -u $mdstart +newfs -U md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +chmod 777 $mntpoint + +t=`date +%s` +/tmp/$prog $mntpoint/test-0 100000 +t=$((`date +%s` - t)) +[ $t -gt 60 ] && n=20000 || n=100000 + +for i in `jot 10`; do + /tmp/$prog $mntpoint/test-$i $n & +done +wait + +while mount | grep -q $mntpoint; do + umount $mntpoint || sleep 1 +done +fsck -fy /dev/md$mdstart > $log +grep -q "WAS MODIFIED" $log && s=1 || s=0 +mdconfig -d -u $mdstart +rm -f /tmp/$prog $log +exit $s +EOF +/* + * Andrey Zonov (c) 2012 + * + * compile as `cc -o rename rename.c -lpthread' + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/queue.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#ifdef __FreeBSD__ +#include <pthread_np.h> +#define __NP__ +#endif +#include <sched.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#define LOCK(x) pthread_mutex_lock(&x.mtx) +#define UNLOCK(x) pthread_mutex_unlock(&x.mtx) +#define SIGNAL(x) pthread_cond_signal(&x.wait) +#define WAIT(x) pthread_cond_wait(&x.wait, &x.mtx) + +int max; +int exited; +char *dirname1; +char *dirname2; + +struct file { + char *name; + STAILQ_ENTRY(file) next; +}; + +struct files { + pthread_mutex_t mtx; + pthread_cond_t wait; + STAILQ_HEAD(, file) list; +}; + +static struct files newfiles; +static struct files renamedfiles; + +void *loop_create(void *arg __unused); +void *loop_rename(void *arg __unused); +void *loop_unlink(void *arg __unused); + +int +main(int argc, char **argv) +{ + int i; + int rc; + pthread_t tid[3]; + + if (argc != 3) + errx(1, "usage: pthread_count <dirname> <max>"); + + asprintf(&dirname1, "%s.1", argv[1]); + asprintf(&dirname2, "%s.2", argv[1]); + if (mkdir(dirname1, 0755) == -1) + err(1, "mkdir(%s)", dirname1); + if (mkdir(dirname2, 0755) == -1) + err(1, "mkdir(%s)", dirname2); + max = atoi(argv[2]); + + STAILQ_INIT(&newfiles.list); + STAILQ_INIT(&renamedfiles.list); + + rc = pthread_mutex_init(&newfiles.mtx, NULL); + if (rc != 0) + errc(1, rc, "pthread_mutex_init()"); + rc = pthread_cond_init(&newfiles.wait, NULL); + if (rc != 0) + errc(1, rc, "pthread_cond_init()"); + rc = pthread_mutex_init(&renamedfiles.mtx, NULL); + if (rc != 0) + errc(1, rc, "pthread_mutex_init()"); + rc = pthread_cond_init(&renamedfiles.wait, NULL); + if (rc != 0) + errc(1, rc, "pthread_cond_init()"); + + rc = pthread_create(&tid[0], NULL, loop_create, NULL); + if (rc != 0) + errc(1, rc, "pthread_create()"); + rc = pthread_create(&tid[1], NULL, loop_rename, NULL); + if (rc != 0) + errc(1, rc, "pthread_create()"); + rc = pthread_create(&tid[2], NULL, loop_unlink, NULL); + if (rc != 0) + errc(1, rc, "pthread_create()"); + + for (i = 0; i < 3; i++) { + rc = pthread_join(tid[i], NULL); + if (rc != 0) + errc(1, rc, "pthread_join(%d)", i); + } + + rc = pthread_mutex_destroy(&newfiles.mtx); + if (rc != 0) + errc(1, rc, "pthread_mutex_destroy(newfiles)"); + rc = pthread_cond_destroy(&newfiles.wait); + if (rc != 0) + errc(1, rc, "pthread_cond_destroy(newfiles)"); + rc = pthread_mutex_destroy(&renamedfiles.mtx); + if (rc != 0) + errc(1, rc, "pthread_mutex_destroy(renamedfiles)"); + rc = pthread_cond_destroy(&renamedfiles.wait); + if (rc != 0) + errc(1, rc, "pthread_cond_destroy(renamedfiles)"); + rmdir(dirname1); + rmdir(dirname2); + free(dirname1); + free(dirname2); + + exit(0); +} + +void * +loop_create(void *arg __unused) +{ + int i; + struct file *file; + +#ifdef __NP__ + pthread_set_name_np(pthread_self(), __func__); +#endif + + for (i = 0; i < max; i++) { + file = malloc(sizeof(*file)); + asprintf(&file->name, "%s/filename_too-long:%d", dirname1, i); + if (mkdir(file->name, 0666) == -1) { + warn("mkdir(%s)", file->name); + free(file->name); + free(file); + break; + } + LOCK(newfiles); + STAILQ_INSERT_TAIL(&newfiles.list, file, next); + UNLOCK(newfiles); + SIGNAL(newfiles); + } + exited = 1; + SIGNAL(newfiles); + pthread_exit(NULL); +} + +void * +loop_rename(void *arg __unused) +{ + char *filename, *newname; + struct file *file; + +#ifdef __NP__ + pthread_set_name_np(pthread_self(), __func__); +#endif + + for ( ;; ) { + LOCK(newfiles); + while (STAILQ_EMPTY(&newfiles.list) && exited < 1) + WAIT(newfiles); + if (STAILQ_EMPTY(&newfiles.list) && exited == 1) { + UNLOCK(newfiles); + break; + } + file = STAILQ_FIRST(&newfiles.list); + STAILQ_REMOVE_HEAD(&newfiles.list, next); + UNLOCK(newfiles); + filename = strrchr(file->name, '/'); + asprintf(&newname, "%s/%s", dirname2, filename); + if (rename(file->name, newname) == -1) + err(1, "rename(%s, %s)", file->name, newname); + free(file->name); + file->name = newname; + LOCK(renamedfiles); + STAILQ_INSERT_TAIL(&renamedfiles.list, file, next); + UNLOCK(renamedfiles); + SIGNAL(renamedfiles); + } + exited = 2; + SIGNAL(renamedfiles); + pthread_exit(NULL); +} + +void * +loop_unlink(void *arg __unused) +{ + struct file *file; + +#ifdef __NP__ + pthread_set_name_np(pthread_self(), __func__); +#endif + + for ( ;; ) { + LOCK(renamedfiles); + while (STAILQ_EMPTY(&renamedfiles.list) && exited < 2) + WAIT(renamedfiles); + if (STAILQ_EMPTY(&renamedfiles.list) && exited == 2) { + UNLOCK(renamedfiles); + break; + } + file = STAILQ_FIRST(&renamedfiles.list); + STAILQ_REMOVE_HEAD(&renamedfiles.list, next); + UNLOCK(renamedfiles); + rmdir(file->name); + free(file->name); + free(file); + } + pthread_exit(NULL); +} diff --git a/tools/test/stress2/misc/rename3.sh b/tools/test/stress2/misc/rename3.sh index c7ce91f0d359..aa4a3754bfab 100755 --- a/tools/test/stress2/misc/rename3.sh +++ b/tools/test/stress2/misc/rename3.sh @@ -36,7 +36,8 @@ # Test scenario by Tor Egge root=/tmp -for i in `jot 10000`; do +start=`date +%s` +while [ $((`date +%s` - start)) -lt 60 ]; do rm -rf $root/a mkdir -p $root/a/b/c/d/e/f/g mkdir -p $root/a/b/c/d/e/f/z diff --git a/tools/test/stress2/misc/rename7.sh b/tools/test/stress2/misc/rename7.sh index 9f6954916411..fdaa8f575117 100755 --- a/tools/test/stress2/misc/rename7.sh +++ b/tools/test/stress2/misc/rename7.sh @@ -122,7 +122,8 @@ int main(void) { pid_t wpid, spid; - int e, fd, i, status; + time_t start; + int e, fd, status; if ((wpid = fork()) == 0) r1(); @@ -132,7 +133,8 @@ main(void) setproctitle("main"); e = 0; - for (i = 0; i < 800000; i++) { + start = time(NULL); + while (time(NULL) - start < 60) { if ((fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) warn("creat(%s)", logfile); close(fd); diff --git a/tools/test/stress2/misc/rmdir.sh b/tools/test/stress2/misc/rmdir.sh new file mode 100755 index 000000000000..2df62a5576a8 --- /dev/null +++ b/tools/test/stress2/misc/rmdir.sh @@ -0,0 +1,119 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Based on msdos11.sh + +. ../default.cfg + +set -u +prog=$(basename "$0" .sh) +log=/tmp/$prog.log + +cat > /tmp/$prog.c <<EOF +#include <sys/param.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/wait.h> + + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdatomic.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +static _Atomic(int) *share; + +#define PARALLEL 3 +#define RUNTIME (2 * 60) +#define SYNC 0 + +static void +test(void) +{ + time_t start; + + atomic_fetch_add(&share[SYNC], 1); + while (share[SYNC] != PARALLEL) + ; + start = time(NULL); + while ((time(NULL) - start) < 30) { + mkdir("a", 0755); + rename("a", "b"); + rmdir("b"); + } + + _exit(0); +} + +int +main(void) +{ + pid_t pids[PARALLEL]; + size_t len; + time_t start; + int e, i, status; + + e = 0; + len = PAGE_SIZE; + if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) + err(1, "mmap"); + + start = time(NULL); + while ((time(NULL) - start) < RUNTIME && e == 0) { + share[SYNC] = 0; + for (i = 0; i < PARALLEL; i++) { + if ((pids[i] = fork()) == 0) + test(); + if (pids[i] == -1) + err(1, "fork()"); + } + for (i = 0; i < PARALLEL; i++) { + if (waitpid(pids[i], &status, 0) == -1) + err(1, "waitpid(%d)", pids[i]); + if (status != 0) { + if (WIFSIGNALED(status)) + fprintf(stderr, + "pid %d exit signal %d\n", + pids[i], WTERMSIG(status)); + } + e += status == 0 ? 0 : 1; + } + } + + return (e); +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1 + +set -e +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 512m -u $mdstart +newfs $newfs_flags md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +set +e + +here=`pwd` +(cd $here/../testcases/swap; ./swap -t 2m -i 20 -l 100 > /dev/null) & +sleep .5 + +cd $mntpoint +/tmp/$prog; s=$? +cd - +wait +umount $mntpoint +fsck_ffs /dev/md$mdstart > $log 2>&1 +grep -Eq "WAS MODIFIED" $log && { cat $log; s=32; } +mdconfig -d -u $mdstart +rm -f /tmp/$prog /tmp/$prog.c $log +exit $s diff --git a/tools/test/stress2/misc/rsync.sh b/tools/test/stress2/misc/rsync.sh new file mode 100755 index 000000000000..fa52f98c6f02 --- /dev/null +++ b/tools/test/stress2/misc/rsync.sh @@ -0,0 +1,49 @@ +#/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +[ -f "`which rsync`" ] || exit 0 +[ -d /usr/src/sys ] || exit 0 + +set -eu +prog=$(basename "$0" .sh) +log=/tmp/$prog.log +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 15g -u $mdstart +newfs $newfs_flags md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +set +e + +mkdir -p $mntpoint/usr/src +rsync -avrq /usr/src/sys $mntpoint/usr/src; s=$? +if [ $s -eq 0 ]; then + (cd $mntpoint; umount $mntpoint > /dev/null 2>&1) # sync + rsync -avrq /usr/src/sys $mntpoint/usr/src; s=$? +fi + +if [ $s -eq 0 ]; then + diff -rq /usr/src/sys $mntpoint/usr/src/sys > $log; s=$? + [ $s -ne 0 ] && + { echo "/usr/src $mntpoint/usr/src differ!"; head -10 $log; } +fi + +while mount | grep -q "on $mntpoint "; do + umount $mntpoint || break + sleep 1 +done +if [ $s -eq 0 ]; then + fsck_ffs -fy /dev/md$mdstart > $log 2>&1; s=$? + grep -Eq "WAS MODIFIED" $log && { cat $log; s=1; } +fi +mdconfig -d -u $mdstart +rm -f $log +exit $s diff --git a/tools/test/stress2/misc/rsync2.sh b/tools/test/stress2/misc/rsync2.sh new file mode 100755 index 000000000000..882753fe596f --- /dev/null +++ b/tools/test/stress2/misc/rsync2.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# Test scenario by se@ from https://reviews.freebsd.org/D43951 + +set -u +MDUNIT=10 +FS=/mnt/test +mdconfig -u $MDUNIT -t malloc -s 512m +newfs_msdos -c 8 -F 32 /dev/md$MDUNIT +mkdir -p $FS +mount -t msdos /dev/md$MDUNIT $FS +rsync -r /usr/src/lib/libsysdecode $FS +rsync -r /usr/src/lib/libsysdecode $FS +rsync -r /usr/src/lib/libsysdecode $FS +umount $FS +fsck_msdosfs -y /dev/md$MDUNIT; s=$? +exit $s diff --git a/tools/test/stress2/misc/rsync3.sh b/tools/test/stress2/misc/rsync3.sh new file mode 100755 index 000000000000..1d77bdfbcaa5 --- /dev/null +++ b/tools/test/stress2/misc/rsync3.sh @@ -0,0 +1,43 @@ +#/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# tmpfs version of rsync.sh + +[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +[ -f "`which rsync`" ] || exit 0 +[ -d /usr/src/sys ] || exit 0 + +set -eu +prog=$(basename "$0" .sh) +log=/tmp/$prog.log +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +mount -t tmpfs dummy $mntpoint +set +e + +mkdir -p $mntpoint/usr/src +rsync -avrq /usr/src/sys $mntpoint/usr/src; s=$? +if [ $s -eq 0 ]; then + rsync -avrq /usr/src/sys $mntpoint/usr/src; s=$? +fi + +if [ $s -eq 0 ]; then + diff -rq /usr/src/sys $mntpoint/usr/src/sys > $log; s=$? + [ $s -ne 0 ] && + { echo "/usr/src $mntpoint/usr/src differ!"; head -10 $log; } +fi + +while mount | grep -q "on $mntpoint "; do + umount $mntpoint || break + sleep 1 +done +rm -f $log +exit $s diff --git a/tools/test/stress2/misc/seekhole.sh b/tools/test/stress2/misc/seekhole.sh new file mode 100755 index 000000000000..40c397b04521 --- /dev/null +++ b/tools/test/stress2/misc/seekhole.sh @@ -0,0 +1,77 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# A SEEK_HOLE / SEEK_DATA test scenario + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +prog=$(basename "$0" .sh) +exp=/tmp/$prog.exp +here=`pwd` +log=/tmp/$prog.log + +cc -o /tmp/lsholes -Wall -Wextra -O2 $here/../tools/lsholes.c | exit 1 +cat > $exp <<EXP +Min hole size is 32768, file size is 524288000. +data #1 @ 0, size=32768) +hole #2 @ 32768, size=32768 +data #3 @ 65536, size=32768) +hole #4 @ 98304, size=32768 +data #5 @ 131072, size=32768) +hole #6 @ 163840, size=524091392 +data #7 @ 524255232, size=32768) +hole #8 @ 524288000, size=0 +EXP + +set -eu +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +mdconfig -s 2g -u $mdstart +newfs -U /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +set +e + +file=$mntpoint/file +truncate -s 500m $file +bs=`getconf MIN_HOLE_SIZE $file` +printf "\001" | dd of=$file seek=$((0*bs)) bs=1 count=1 conv=notrunc status=none +printf "\002" | dd of=$file seek=$((2*bs)) bs=1 count=1 conv=notrunc status=none +printf "\003" | dd of=$file seek=$((4*bs)) bs=1 count=1 conv=notrunc status=none +s1=0 +s2=0 +/tmp/lsholes $file > $log 2>&1; s1=$? + +cat $log +cmp -s $exp $log || s2=1 + +umount $mntpoint +mdconfig -d -u $mdstart +rm -f /tmp/lsholes $exp $log +exit $((s1 + s2)) diff --git a/tools/test/stress2/misc/seekhole2.sh b/tools/test/stress2/misc/seekhole2.sh new file mode 100755 index 000000000000..e3f08779061d --- /dev/null +++ b/tools/test/stress2/misc/seekhole2.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +# +# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# A SEEK_HOLE / SEEK_DATA test scenario, FFS version + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +prog=$(basename "$0" .sh) +exp=/tmp/$prog.exp +here=`pwd` +log=/tmp/$prog.log + +cc -o /tmp/lsholes -Wall -Wextra -O2 $here/../tools/lsholes.c | exit 1 +cat > $exp <<EXP +Min hole size is 32768, file size is 524288000. +data #1 @ 0, size=32768) +hole #2 @ 32768, size=32768 +data #3 @ 65536, size=32768) +hole #4 @ 98304, size=32768 +data #5 @ 131072, size=32768) +hole #6 @ 163840, size=524091392 +data #7 @ 524255232, size=32768) +hole #8 @ 524288000, size=0 +EXP + +set -eu +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 2g -u $mdstart +newfs $newfs_flags md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +set +e + +file=$mntpoint/file +copy=$mntpoint/copy +truncate -s 500m $file +bs=`getconf MIN_HOLE_SIZE $file` +printf "\001" | dd of=$file seek=$((0*bs)) bs=1 count=1 conv=notrunc status=none +printf "\002" | dd of=$file seek=$((2*bs)) bs=1 count=1 conv=notrunc status=none +printf "\003" | dd of=$file seek=$((4*bs)) bs=1 count=1 conv=notrunc status=none +s1=0 +s2=0 +s3=0 +/tmp/lsholes $file > $log 2>&1; s1=$? + +sdiff -s $exp $log || s2=1 + +$here/../testcases/swap/swap -t 2m -i 20 -h > /dev/null & +sleep 10 +cp $file $copy +while pkill swap; do :; done +wait +cmp $file $copy || { echo "copy error"; s3=1; } + +umount $mntpoint +mdconfig -d -u $mdstart +rm -f /tmp/lsholes $exp $log +exit $((s1 + s2 + s3)) diff --git a/tools/test/stress2/misc/segnp.sh b/tools/test/stress2/misc/segnp.sh index 3dbe91e04550..96f163070db7 100755 --- a/tools/test/stress2/misc/segnp.sh +++ b/tools/test/stress2/misc/segnp.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2017 Konstantin Belousov <kib@FreeBSD.org> # diff --git a/tools/test/stress2/misc/segregs.sh b/tools/test/stress2/misc/segregs.sh index 0ecc3565546a..63aa3abb5354 100755 --- a/tools/test/stress2/misc/segregs.sh +++ b/tools/test/stress2/misc/segregs.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2017 Konstantin Belousov <kib@FreeBSD.org> # diff --git a/tools/test/stress2/misc/sem_post.sh b/tools/test/stress2/misc/sem_post.sh index 2f1d7c4c004f..7fc2ffdd8778 100755 --- a/tools/test/stress2/misc/sem_post.sh +++ b/tools/test/stress2/misc/sem_post.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/sem_timedwait.sh b/tools/test/stress2/misc/sem_timedwait.sh index 33e5c1933f37..86c33f7e2ac3 100755 --- a/tools/test/stress2/misc/sem_timedwait.sh +++ b/tools/test/stress2/misc/sem_timedwait.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/sem_wait.sh b/tools/test/stress2/misc/sem_wait.sh index 6d8bc49c9199..2a4474eff4d5 100755 --- a/tools/test/stress2/misc/sem_wait.sh +++ b/tools/test/stress2/misc/sem_wait.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/sendfile15.sh b/tools/test/stress2/misc/sendfile15.sh index 90cbdd86ada6..c5f46d72c280 100755 --- a/tools/test/stress2/misc/sendfile15.sh +++ b/tools/test/stress2/misc/sendfile15.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/sendfile17.sh b/tools/test/stress2/misc/sendfile17.sh index 560cb6b83081..3ebd992fcd8e 100755 --- a/tools/test/stress2/misc/sendfile17.sh +++ b/tools/test/stress2/misc/sendfile17.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/sendfile18.sh b/tools/test/stress2/misc/sendfile18.sh index 3b13292932f1..f8bb111e2986 100755 --- a/tools/test/stress2/misc/sendfile18.sh +++ b/tools/test/stress2/misc/sendfile18.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Mark Johnston <markj@FreeBSD.org> # diff --git a/tools/test/stress2/misc/sendfile19.sh b/tools/test/stress2/misc/sendfile19.sh index 0254a495d5cf..faf08ca87d85 100755 --- a/tools/test/stress2/misc/sendfile19.sh +++ b/tools/test/stress2/misc/sendfile19.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/sendfile20.sh b/tools/test/stress2/misc/sendfile20.sh index 88c0a344a926..aefbb58eeb6c 100755 --- a/tools/test/stress2/misc/sendfile20.sh +++ b/tools/test/stress2/misc/sendfile20.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/sendfile21.sh b/tools/test/stress2/misc/sendfile21.sh index c50c0f0ccdab..88b59c018c81 100755 --- a/tools/test/stress2/misc/sendfile21.sh +++ b/tools/test/stress2/misc/sendfile21.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/sendfile22.sh b/tools/test/stress2/misc/sendfile22.sh index d948d8c001b6..a9bff35d8662 100755 --- a/tools/test/stress2/misc/sendfile22.sh +++ b/tools/test/stress2/misc/sendfile22.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/sendfile23.sh b/tools/test/stress2/misc/sendfile23.sh index 02c354cdf48e..f7079eabc5f2 100755 --- a/tools/test/stress2/misc/sendfile23.sh +++ b/tools/test/stress2/misc/sendfile23.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/sendfile24.sh b/tools/test/stress2/misc/sendfile24.sh index b9f7d7ac89c2..363008f69cb3 100755 --- a/tools/test/stress2/misc/sendfile24.sh +++ b/tools/test/stress2/misc/sendfile24.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/sendfile25.sh b/tools/test/stress2/misc/sendfile25.sh index dba0378d547a..ae755bf1d4df 100755 --- a/tools/test/stress2/misc/sendfile25.sh +++ b/tools/test/stress2/misc/sendfile25.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # @@ -105,7 +105,7 @@ reader(void) { int on; socklen_t len; struct sockaddr_in inetaddr, inetpeer; - int n, t, *buf, fd; + int n, *buf, fd; on = 1; if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) @@ -132,7 +132,6 @@ reader(void) { (struct sockaddr *)&inetpeer, &len)) < 0) err(1, "accept(), %s:%d", __FILE__, __LINE__); - t = 0; if ((buf = malloc(bufsize)) == NULL) err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__); @@ -142,7 +141,6 @@ reader(void) { for (;;) { if ((n = read(msgsock, buf, bufsize)) < 0) err(1, "read(), %s:%d", __FILE__, __LINE__); - t += n; if (n == 0) break; diff --git a/tools/test/stress2/misc/sendfile26.sh b/tools/test/stress2/misc/sendfile26.sh index da9aa52d5f3c..cecf2547a182 100755 --- a/tools/test/stress2/misc/sendfile26.sh +++ b/tools/test/stress2/misc/sendfile26.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Jean-Sébastien Pédron <dumbbell@FreeBSD.org> # diff --git a/tools/test/stress2/misc/sendfile5.sh b/tools/test/stress2/misc/sendfile5.sh index c81515003a13..933e4f94a73c 100755 --- a/tools/test/stress2/misc/sendfile5.sh +++ b/tools/test/stress2/misc/sendfile5.sh @@ -52,7 +52,7 @@ mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart kldstat | grep -q tmpfs.ko || loaded=1 mount -t tmpfs tmpfs $mntpoint -echo "Testing tmpfs(5)" +echo "Testing tmpfs(4)" cp $diskimage $mntpoint /tmp/sendfile5 $mntpoint/$file umount $mntpoint @@ -68,7 +68,7 @@ umount $mntpoint mdconfig -d -u $mdstart mount -t nullfs $dir $mntpoint -echo "Testing nullfs(5)" +echo "Testing nullfs(4)" /tmp/sendfile5 $mntpoint/$file umount $mntpoint diff --git a/tools/test/stress2/misc/setrlimit.sh b/tools/test/stress2/misc/setrlimit.sh new file mode 100755 index 000000000000..ca7a2d7f5364 --- /dev/null +++ b/tools/test/stress2/misc/setrlimit.sh @@ -0,0 +1,193 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +# Test setrlimit() max file size and ftruncate() + +# Problem seen: +# Testing UFS -O1 +# setrlimit: ftruncate(5413) did not fail. limit = 2791 +# Testing FFS -U +# setrlimit: ftruncate(9956) did not fail. limit = 7880 +# Testing msdosfs +# setrlimit: ftruncate(9033) did not fail. limit = 5884 +# Testing tmpfs +# setrlimit: ftruncate(123) did not fail. limit = 86 + +. ../default.cfg + +cat > /tmp/setrlimit.c <<EOF +#include <sys/types.h> +#include <sys/resource.h> +#include <sys/stat.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static int signals; + +static void +handler(int sig __unused) +{ +#if defined(DEBUG) + fprintf(stderr, "Got signal SIGXFSZ\n"); +#endif + signals++; +} + +void +test(int argc, char *argv[]) +{ + struct rlimit rlim; + rlim_t limit, sz; + struct sigaction act; + long pos; + int e, expected, fd; + char file[] = "setrlimit.file"; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <FS size>\n", argv[0]); + exit(1); + } + expected = signals = 0; + sz = atol(argv[1]); + arc4random_buf(&limit, sizeof(limit)); + if (limit < 0) + limit = -limit; + limit = limit % sz + 1; + rlim.rlim_cur = rlim.rlim_max = limit; + if (setrlimit(RLIMIT_FSIZE, &rlim) == -1) + err(1, "setrlimit(%ld)", limit); + + act.sa_handler = handler; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + if (sigaction(SIGXFSZ, &act, NULL) != 0) + err(1, "sigaction"); + + if ((fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, DEFFILEMODE)) == -1) + err(1, "open(%s)", file); + + e = 0; + arc4random_buf(&pos, sizeof(pos)); + if (pos < 0) + pos = -pos; + pos = pos % (limit * 2); + if (pos > limit) + expected = 1; + if (ftruncate(fd, pos) == -1) { + e = errno; + if (pos <= limit) + errc(1, e, "ftruncate(%ld), limit = %ld", pos, limit); + } else { + if (pos > limit) + errx(1, "ftruncate(%ld) did not fail. limit = %ld", pos, limit); + } + + if (lseek(fd, limit - 1, SEEK_SET) == -1) + err(1, "lseek(limit - 1)"); + if (write(fd, "a", 1) != 1) + err(1, "write() at limit - 1. limit = %ld", limit); + + if (write(fd, "b", 1) != -1) + err(1, "write() at limit. limit = %ld", limit); + expected++; + + /* Partial write test. No signal is expected */ + if (lseek(fd, limit - 1, SEEK_SET) == -1) + err(1, "lseek(limit - 1)"); + if (write(fd, "12", 2) != 1) + err(1, "write() at limit - 1. limit = %ld", limit); + + if (signals != expected) + errx(1, "Expected %d signals, got %d", expected, signals); + + close(fd); + unlink(file); +} + +int +main(int argc, char *argv[]) +{ + int i; + + for (i = 0; i < 100; i++) + test(argc, argv); + +} +EOF + +here=`pwd` +s=0 +cc -o /tmp/setrlimit -Wall -Wextra -O0 -g /tmp/setrlimit.c || exit 1 + +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart + +echo "Testing UFS -O1" +mdconfig -t swap -s 1g -u $mdstart +newfs -O1 /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +cd $mntpoint; /tmp/setrlimit 10000 || s=1 +cd $here +umount $mntpoint +mdconfig -d -u $mdstart + +echo "Testing FFS -U" +mdconfig -t swap -s 1g -u $mdstart +newfs -U /dev/md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +cd $mntpoint; /tmp/setrlimit 10000 || s=$((s + 2)) +cd $here +umount $mntpoint +mdconfig -d -u $mdstart + +echo "Testing msdosfs" +mdconfig -t swap -s 1g -u $mdstart +newfs_msdos -F 32 -b 8192 /dev/md$mdstart > /dev/null 2>&1 +mount -t msdosfs /dev/md$mdstart $mntpoint +cd $mntpoint; /tmp/setrlimit 10000 || s=$((s + 4)) +cd $here +umount $mntpoint +mdconfig -d -u $mdstart + +echo "Testing tmpfs" +mount -o size=20000 -t tmpfs dummy $mntpoint +cd $mntpoint; /tmp/setrlimit 10000 || s=$((s + 8)) +cd $here +umount $mntpoint + +rm -f /tmp/setrlimit /tmp/setrlimit.c +exit $s diff --git a/tools/test/stress2/misc/setrlimit2.sh b/tools/test/stress2/misc/setrlimit2.sh new file mode 100755 index 000000000000..4eea25ef3ee4 --- /dev/null +++ b/tools/test/stress2/misc/setrlimit2.sh @@ -0,0 +1,118 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Demonstrate that a mapped SHARED file can be updated past LIMIT_FSIZE + +# Kostik wrote: +# This one should be reproducible when you +# - have file larger than e.g. RLIMIT_FSIZE +# - mmaped it without closing the file descriptor +# - dirty its pages beyond the limit +# - then unmap +# - then close the file descriptor. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +cat > /tmp/setrlimit2.c <<EOF +#include <sys/param.h> +#include <sys/mman.h> +#include <sys/resource.h> +#include <sys/stat.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static int signals; + +static void +handler(int sig __unused) +{ + signals++; +} + +int +main(int argc, char *argv[]) +{ + struct rlimit rlim; + struct sigaction act; + struct stat st; + size_t len; + int error, fd, ps; + char *file, *p; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <data file>\n", argv[0]); + exit(1); + } + act.sa_handler = handler; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + if (sigaction(SIGXFSZ, &act, NULL) != 0) + err(1, "sigaction"); + + file = argv[1]; + ps = getpagesize(); + if ((fd = open(file, O_RDWR)) == -1) + err(1, "open(%s)", file); + if ((error = fstat(fd, &st)) == -1) + err(1, "stat(%s)", file); + len = round_page(st.st_size); + if ((p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) + err(1, "mmap"); + rlim.rlim_cur = rlim.rlim_max = len / 2;; + if (setrlimit(RLIMIT_FSIZE, &rlim) == -1) + err(1, "setrlimit(%ld)", len / 2); + + p[len / 2 + ps] = 'a'; + + if (munmap(p, len) == -1) + err(1, "unmap()"); + close(fd); + +} +EOF +here=`pwd` +cd /tmp +mycc -o setrlimit2 -Wall -Wextra -O0 -g setrlimit2.c || exit 1 +data=/tmp/setrlimit2.data +dd if=/dev/zero of=$data bs=1m count=1 status=none +h1=`md5 < $data` + +./setrlimit2 $data + +h2=`md5 < $data` +rm -f /tmp/setrlimit2 /tmp/setrlimit2.c +[ $h1 = $h2 ] && exit 1 || exit 0 diff --git a/tools/test/stress2/misc/setsockopt.sh b/tools/test/stress2/misc/setsockopt.sh index 969c7b23069b..439b1984cb3c 100755 --- a/tools/test/stress2/misc/setsockopt.sh +++ b/tools/test/stress2/misc/setsockopt.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/setsockopt2.sh b/tools/test/stress2/misc/setsockopt2.sh index d032c68f77c4..13cc3175cce3 100755 --- a/tools/test/stress2/misc/setsockopt2.sh +++ b/tools/test/stress2/misc/setsockopt2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # @@ -86,6 +86,7 @@ EOF #include <time.h> #include <unistd.h> +static int debug; /* set to 1 for debug output */ static volatile u_int *share; #define PARALLEL 128 @@ -165,6 +166,8 @@ bad: if (waitpid(pid, NULL, 0) != pid) err(1, "waitpid(%d)", pid); } + if (debug != 0 && success == 0) + fprintf(stderr, "No calls to connect() succeded.\n"); _exit(0); } diff --git a/tools/test/stress2/misc/shm2.sh b/tools/test/stress2/misc/shm2.sh index 55d63b19f462..e45f9f45ac4f 100755 --- a/tools/test/stress2/misc/shm2.sh +++ b/tools/test/stress2/misc/shm2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/shm_super.sh b/tools/test/stress2/misc/shm_super.sh index 8437eb5be92f..59d142002264 100755 --- a/tools/test/stress2/misc/shm_super.sh +++ b/tools/test/stress2/misc/shm_super.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Konstantin Belousov <kib@FreeBSD.org> # diff --git a/tools/test/stress2/misc/sigfastblock.sh b/tools/test/stress2/misc/sigfastblock.sh index 403dbde31553..ce655a611e6d 100755 --- a/tools/test/stress2/misc/sigfastblock.sh +++ b/tools/test/stress2/misc/sigfastblock.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Konstantin Belousov # diff --git a/tools/test/stress2/misc/sigfastblock2.sh b/tools/test/stress2/misc/sigfastblock2.sh index 8354307f6f7a..c8474333cbca 100755 --- a/tools/test/stress2/misc/sigfastblock2.sh +++ b/tools/test/stress2/misc/sigfastblock2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 corydoras@ridiculousfish.com # diff --git a/tools/test/stress2/misc/signal2.sh b/tools/test/stress2/misc/signal2.sh new file mode 100755 index 000000000000..2cb0589f1dce --- /dev/null +++ b/tools/test/stress2/misc/signal2.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +# Test scenario from: +# Bug 265889 - sys.kern.basic_signal.trap_signal_test crashes bhyve in i386 VM +# Test scenario by: Li-Wen Hsu <lwhsu@FreeBSD.org> + +cat > /tmp/signal2.c <<EOF +#include <stdio.h> +#include <signal.h> + +#include <machine/psl.h> +#define SET_TRACE_FLAG(ucp) (ucp)->uc_mcontext.mc_eflags |= PSL_T +#define CLR_TRACE_FLAG(ucp) (ucp)->uc_mcontext.mc_eflags &= ~PSL_T + +static volatile sig_atomic_t trap_signal_fired = 0; + +static void +trap_sig_handler(int signo __unused, siginfo_t *info __unused, void *_ucp) +{ + ucontext_t *ucp = _ucp; + + if (trap_signal_fired < 9) { + SET_TRACE_FLAG(ucp); + } else { + CLR_TRACE_FLAG(ucp); + } + trap_signal_fired++; +} + +int main() { + struct sigaction sa = { + .sa_sigaction = trap_sig_handler, + .sa_flags = SA_SIGINFO, + }; + + sigemptyset(&sa.sa_mask); + sigaction(SIGTRAP, &sa, NULL); + + raise(SIGTRAP); + + printf("test\n"); +} +EOF +cc -o /tmp/signal2 -Wall -Wextra -O0 -m32 /tmp/signal2.c || exit 1 + +/tmp/signal2; s=$? +for i in `jot 30`; do + /tmp/signal2 & +done > /dev/null +wait + +rm -f /tmp/signal2 /tmp/signal2.c +exit $s diff --git a/tools/test/stress2/misc/sigreturn2.sh b/tools/test/stress2/misc/sigreturn2.sh new file mode 100755 index 000000000000..8960b9b3958c --- /dev/null +++ b/tools/test/stress2/misc/sigreturn2.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# A sigreturn(2) syscall fuzzer + +# panic: vm_fault_lookup: fault on nofault entry, addr: 0 +# cpuid = 0 +# time = 1661248103 +# KDB: stack backtrace: +# db_trace_self_wrapper(e,27e1dae0,27e1dae2,ffc07db8,c1f0490,...) at db_trace_self_wrapper+0x28/frame 0xffc07d24 +# vpanic(150b260,ffc07d60,ffc07d60,ffc07e20,12cb565,...) at vpanic+0xf4/frame 0xffc07d40 +# panic(150b260,14ec2f3,0,149349d,1430,...) at panic+0x14/frame 0xffc07d54 +# vm_fault(1e37000,0,4,0,0) at vm_fault+0x1725/frame 0xffc07e20 +# vm_fault_trap(1e37000,3b,4,0,0,0) at vm_fault_trap+0x52/frame 0xffc07e48 +# trap_pfault(3b,0,0) at trap_pfault+0x176/frame 0xffc07e94 +# trap(ffc07f6c,8,28,28,1915b000,...) at trap+0x2d9/frame 0xffc07f60 +# calltrap() at 0xffc031ef/frame 0xffc07f60 +# --- trap 0xc, eip = 0x3b, esp = 0xffc07fac, ebp = 0xffc0340c --- +# (null)() at 0x3b/frame 0xffc0340c +# KDB: enter: panic +# [ thread pid 26126 tid 120029 ] +# Stopped at kdb_enter+0x34: movl $0,kdb_why +# db> x/s version +# version: FreeBSD 14.0-CURRENT #0 ast-n257558-eb20af97a66-dirty: Mon Aug 22 17:53:22 CEST 2022 +# pho@mercat1.netperf.freebsd.org:/media/obj/var/tmp/deviant3/i386.i386/sys/PHO +# db> + +inc=/usr/include/sys/syscall.h +[ -f $inc ] || exit 0 +num=`awk '/SYS_sigreturn/ {print $NF}' < $inc` +old=`grep -E 'sigreturn \*' < $inc | \ + sed 's/.* \([0-9]\{1,3\}\) .*/\1/' | tr '\n' ' '` +num="$num $old" + +start=`date +%s` +while [ $((`date +%s` - start)) -lt 180 ]; do + for i in $num; do + echo "noswap=1 ./syscall4.sh $i" + noswap=1 ./syscall4.sh $i + done +done + +exit 0 diff --git a/tools/test/stress2/misc/sigreturn3.sh b/tools/test/stress2/misc/sigreturn3.sh new file mode 100755 index 000000000000..271ade287e9a --- /dev/null +++ b/tools/test/stress2/misc/sigreturn3.sh @@ -0,0 +1,181 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Fatal trap -4186856: UNKNOWN while in kernel mode +# cpuid = 1; apic id = 01 +# error code = 0xfbafcf8c +# instruction pointer = 0x79e4:0x4 +# stack pointer = 0x28:0xffc0aff0 +# frame pointer = 0x28:0x204620d4 +# code segment = base 0x0, limit 0x0, type 0x0 +# = DPL 0, pres 0, def32 0, gran 0 +# processor eflags = trace trap, at 0x3b/frame 0xffc0340c +# KDB: enter: panic +# [ thread pid 15631 tid 114622 ] +# Stopped at kdb_enter+0x34: movl $0,kdb_why +# db> + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +prog=sigreturn3 + +cat > /tmp/$prog.c <<EOF +#include <sys/types.h> +#include <sys/resource.h> +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/wait.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <libutil.h> +#include <pthread.h> +#include <pthread_np.h> +#include <pwd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define N 4096 +#define RUNTIME 120 +#define THREADS 1 + +static uint32_t r[N]; + +static void +hand(int i __unused) { /* handler */ + exit(1); +} + +static void * +churn(void *arg __unused) +{ + time_t start; + + pthread_set_name_np(pthread_self(), __func__); + start = time(NULL); + while (time(NULL) - start < 10) { + arc4random_buf(r, sizeof(r)); + usleep(100); + } + return(NULL); +} + +static void * +calls(void *arg __unused) +{ + time_t start; + + start = time(NULL); + while (time(NULL) - start < 10) { + arc4random_buf(r, sizeof(r)); + alarm(1); + syscall(SYS_sigreturn, r); + } + + return (NULL); +} + +int +main(int argc, char **argv) +{ + struct passwd *pw; + struct rlimit limit; + pid_t pid; + pthread_t rp, cp[THREADS]; + time_t start; + int e, j; + + if ((pw = getpwnam("nobody")) == NULL) + err(1, "failed to resolve nobody"); + + if (getenv("USE_ROOT") && argc == 2) + fprintf(stderr, "Running syscall4 as root for %s.\n", + argv[1]); + else { + if (setgroups(1, &pw->pw_gid) || + setegid(pw->pw_gid) || setgid(pw->pw_gid) || + seteuid(pw->pw_uid) || setuid(pw->pw_uid)) + err(1, "Can't drop privileges to \"nobody\""); + endpwent(); + } + + limit.rlim_cur = limit.rlim_max = 1000; +#if defined(RLIMIT_NPTS) + if (setrlimit(RLIMIT_NPTS, &limit) < 0) + err(1, "setrlimit"); +#endif + + signal(SIGALRM, hand); + signal(SIGILL, hand); + signal(SIGFPE, hand); + signal(SIGSEGV, hand); + signal(SIGBUS, hand); + signal(SIGURG, hand); + signal(SIGSYS, hand); + signal(SIGTRAP, hand); + + if (daemon(1, 1) == -1) + err(1, "daemon()"); + + start = time(NULL); + while ((time(NULL) - start) < RUNTIME) { + if ((pid = fork()) == 0) { + if ((e = pthread_create(&rp, NULL, churn, NULL)) != 0) + errc(1, e, "pthread_create"); + for (j = 0; j < THREADS; j++) + if ((e = pthread_create(&cp[j], NULL, calls, + NULL)) != 0) + errc(1, e, "pthread_create"); + for (j = 0; j < THREADS; j++) + pthread_join(cp[j], NULL); + + if ((e = pthread_kill(rp, SIGINT)) != 0) + errc(1, e, "pthread_kill"); + if ((e = pthread_join(rp, NULL)) != 0) + errc(1, e, "pthread_join"); + _exit(0); + } + waitpid(pid, NULL, 0); + } + + return (0); +} +EOF + +cd /tmp +cc -o $prog -Wall -Wextra -O0 $prog.c -lpthread || exit 1 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 300 ]; do + ./$prog > /dev/null 2>&1 +done +rm -f /tmp/$prog /tmp/$ptog.c /tmp/$prog.core +exit 0 diff --git a/tools/test/stress2/misc/sigreturn4.sh b/tools/test/stress2/misc/sigreturn4.sh new file mode 100755 index 000000000000..9e2a6a32715c --- /dev/null +++ b/tools/test/stress2/misc/sigreturn4.sh @@ -0,0 +1,207 @@ +#!/bin/sh + +# panic: vm_fault_lookup: fault on nofault entry, addr: 0 +# cpuid = 2 +# time = 1661698922 +# KDB: stack backtrace: +# db_trace_self_wrapper(b,2931e740,2931e742,ffc0ddb8,190431,...) at db_trace_self_wrapper+0x28/frame 0xffc0dd24 +# vpanic(150acba,ffc0dd60,ffc0dd60,ffc0de20,12cc155,...) at vpanic+0xf4/frame 0xffc0dd40 +# panic(150acba,14ec1ab,0,146253d,1430,...) at panic+0x14/frame 0xffc0dd54 +# vm_fault(1e360c8,0,4,0,0) at vm_fault+0x1725/frame 0xffc0de20 +# vm_fault_trap(1e360c8,3b,4,0,0,0) at vm_fault_trap+0x52/frame 0xffc0de48 +# trap_pfault(3b,0,0) at trap_pfault+0x176/frame 0xffc0de94 +# trap(ffc0df6c,8,28,28,19156000,...) at trap+0x2d9/frame 0xffc0df60 +# calltrap() at 0xffc031ef/frame 0xffc0df60 +# --- trap 0xc, eip = 0x3b, esp = 0xffc0dfac, ebp = 0xffc0340c --- +# (null)() at 0x3b/frame 0xffc0340c +# KDB: enter: panic +# [ thread pid 54680 tid 102765 ] +# Stopped at kdb_enter+0x34: movl $0,kdb_why +# db> x/s version +# version: FreeBSD 14.0-CURRENT #0 main-n257606-9ea2716b775-dirty: Thu Aug 25 10:47:45 CEST 2022 +# pho@mercat1.netperf.freebsd.org:/media/ob +# j/usr/src/i386.i386/sys/PHO\012 +# db> show proc +# Process 54680 (date) at 0x28905d50: +# state: NORMAL +# uid: 0 gids: 0, 0, 5 +# parent: pid 785 at 0x26c14000 +# ABI: FreeBSD ELF32 +# flag: 0x10004002 flag2: 0 +# arguments: date +%s +# reaper: 0x18c710a4 reapsubtree: 1 +# sigparent: 20 +# vmspace: 0x29332100 +# (map 0x29332100) +# (map.pmap 0x29332174) +# (pmap 0x293321b0) +# threads: 1 +# 102765 Run CPU 2 date +# db> + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +prog=sigreturn4 + +cat > /tmp/$prog.c <<EOF +#include <sys/types.h> +#include <sys/resource.h> +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/wait.h> + +#include <ucontext.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <libutil.h> +#include <pthread.h> +#include <pwd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define RUNTIME 120 +#define THREADS 1 + +static void +hand(int i __unused) { /* handler */ + _exit(1); +} + +static long +random_long(long mi, long ma) +{ + return (arc4random() % (ma - mi + 1) + mi); +} + +static void +flip(void *ap, size_t len) +{ + unsigned char *cp; + int byte; + unsigned char bit, buf, mask, old __unused; + + cp = (unsigned char *)ap; + byte = random_long(0, len); + bit = random_long(0,7); + mask = ~(1 << bit); + buf = cp[byte]; + old = cp[byte]; + buf = (buf & mask) | (~buf & ~mask); + cp[byte] = buf; +} + +static void * +churn(void *arg __unused) +{ + time_t start; + + start = time(NULL); + while (time(NULL) - start < 10) { + usleep(100); + } + return(NULL); +} + +static void * +calls(void *arg __unused) +{ + time_t start; + ucontext_t uc; + int n; + + start = time(NULL); + while (time(NULL) - start < 10) { + n = 0; + if (getcontext(&uc) == -1) + err(1, "getcontext"); + n++; + + if (n == 1) { + flip(&uc, sizeof(uc)); + alarm(1); + if (sigreturn(&uc) == -1) + err(1, "sigreturn()"); + } else + break; + } + return (NULL); +} + +int +main(int argc, char **argv) +{ + struct passwd *pw; + struct rlimit limit; + pid_t pid; + pthread_t rp, cp[THREADS]; + time_t start; + int e, j; + + if ((pw = getpwnam("nobody")) == NULL) + err(1, "failed to resolve nobody"); + + if (getenv("USE_ROOT") && argc == 2) + fprintf(stderr, "Running sigreturn4 as root for %s.\n", + argv[1]); + else { + if (setgroups(1, &pw->pw_gid) || + setegid(pw->pw_gid) || setgid(pw->pw_gid) || + seteuid(pw->pw_uid) || setuid(pw->pw_uid)) + err(1, "Can't drop privileges to \"nobody\""); + endpwent(); + } + + limit.rlim_cur = limit.rlim_max = 1000; +#if defined(RLIMIT_NPTS) + if (setrlimit(RLIMIT_NPTS, &limit) < 0) + err(1, "setrlimit"); +#endif + + signal(SIGALRM, hand); + signal(SIGILL, hand); + signal(SIGFPE, hand); + signal(SIGSEGV, hand); + signal(SIGBUS, hand); + signal(SIGURG, hand); + signal(SIGSYS, hand); + signal(SIGTRAP, hand); + + if (daemon(1, 1) == -1) + err(1, "daemon()"); + + start = time(NULL); + while ((time(NULL) - start) < RUNTIME) { + if ((pid = fork()) == 0) { + if ((e = pthread_create(&rp, NULL, churn, NULL)) != 0) + errc(1, e, "pthread_create"); + for (j = 0; j < THREADS; j++) + if ((e = pthread_create(&cp[j], NULL, calls, + NULL)) != 0) + errc(1, e, "pthread_create"); + for (j = 0; j < THREADS; j++) + pthread_join(cp[j], NULL); + + if ((e = pthread_kill(rp, SIGINT)) != 0) + errc(1, e, "pthread_kill"); + if ((e = pthread_join(rp, NULL)) != 0) + errc(1, e, "pthread_join"); + _exit(0); + } + waitpid(pid, NULL, 0); + } + + return (0); +} +EOF + +cd /tmp +cc -o $prog -Wall -Wextra -O0 $prog.c -lpthread || exit 1 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 300 ]; do + ./$prog > /dev/null 2>&1 +done +rm -f /tmp/$prog /tmp/$ptog.c /tmp/$prog.core +exit 0 diff --git a/tools/test/stress2/misc/sigstop2.sh b/tools/test/stress2/misc/sigstop2.sh index 286936c2fb1a..640af0801318 100755 --- a/tools/test/stress2/misc/sigstop2.sh +++ b/tools/test/stress2/misc/sigstop2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/smrstress.sh b/tools/test/stress2/misc/smrstress.sh index 5806f9231520..b174cb5aa087 100755 --- a/tools/test/stress2/misc/smrstress.sh +++ b/tools/test/stress2/misc/smrstress.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/smrstress2.sh b/tools/test/stress2/misc/smrstress2.sh index 8f9f4d86a4fd..054fc922708d 100755 --- a/tools/test/stress2/misc/smrstress2.sh +++ b/tools/test/stress2/misc/smrstress2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/snap12.sh b/tools/test/stress2/misc/snap12.sh index 759b00be33d4..bca6af6efe5d 100755 --- a/tools/test/stress2/misc/snap12.sh +++ b/tools/test/stress2/misc/snap12.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/snap13.sh b/tools/test/stress2/misc/snap13.sh new file mode 100755 index 000000000000..75550e76a784 --- /dev/null +++ b/tools/test/stress2/misc/snap13.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Test mounting of snapshots for different UFS types + +# Seen: mount of a -O1 snapshot failed +# Fixed by: +# f1549d7d5229 Write out corrected superblock when creating a UFS/FFS snapshot. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +set -u +s=0 +m2=$((mdstart + 1)) +mp2=$mntpoint$m2 +[ -d $mp2 ] || mkdir -p $mp2 +mount | grep -q "on $mntpoint " && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +[ -c /dev/md$m2 ] && mdconfig -d -u $m2 +mdconfig -a -t swap -s 2g -u $mdstart || exit 1 +for newfs_flags in "-O2" "-U" "-j" "-O1"; do + echo "newfs $newfs_flags md$mdstart" + newfs $newfs_flags md$mdstart > /dev/null + mount /dev/md$mdstart $mntpoint + touch $mntpoint/file + + rm -f $mntpoint/.snap/stress2 + mksnap_ffs $mntpoint $mntpoint/.snap/stress2 || { s=1; break; } + mdconfig -a -t vnode -f $mntpoint/.snap/stress2 -u $m2 -o readonly || + { s=2; break; } + mount -t ufs -o ro /dev/md$m2 $mp2 || { + echo "mount of a $newfs_flags snapshot failed" + dumpfs -s /dev/md$m2; s=3; break; } + [ -f $mp2/file ] || { s=4; ls -l $mp2; } + umount $mp2 + mdconfig -d -u $m2 + umount $mntpoint +done +mount | grep -q "on $mntpoint " && umount $mntpoint + +mdconfig -d -u $mdstart +exit $s diff --git a/tools/test/stress2/misc/socketpair4.sh b/tools/test/stress2/misc/socketpair4.sh index 65fb55d975ad..c9e07b3494fc 100755 --- a/tools/test/stress2/misc/socketpair4.sh +++ b/tools/test/stress2/misc/socketpair4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/softupdate.sh b/tools/test/stress2/misc/softupdate.sh index ecf7c5d04e9c..37f819579f83 100755 --- a/tools/test/stress2/misc/softupdate.sh +++ b/tools/test/stress2/misc/softupdate.sh @@ -47,6 +47,7 @@ mdconfig -a -t vnode -f $D -u $mdstart for mode in "" "-U"; do printf "newfs -O2 $mode /dev/md${mdstart}\n\n" newfs -O2 $mode /dev/md$mdstart > /dev/null 2>&1 + [ "$mode" = "" ] && tunefs -n disable md$mdstart mount /dev/md$mdstart $mntpoint for i in `jot 5`; do diff --git a/tools/test/stress2/misc/sort2.sh b/tools/test/stress2/misc/sort2.sh index ba3d5a0a01f8..fb2965ea6c02 100755 --- a/tools/test/stress2/misc/sort2.sh +++ b/tools/test/stress2/misc/sort2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/split.sh b/tools/test/stress2/misc/split.sh index 59e3c6f140e1..2709a38e77b5 100755 --- a/tools/test/stress2/misc/split.sh +++ b/tools/test/stress2/misc/split.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/su.sh b/tools/test/stress2/misc/su.sh index da29146c3ab6..c4ed6eee93ac 100755 --- a/tools/test/stress2/misc/su.sh +++ b/tools/test/stress2/misc/su.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/suj11.sh b/tools/test/stress2/misc/suj11.sh index 362d33caf8a4..01f3a49be087 100755 --- a/tools/test/stress2/misc/suj11.sh +++ b/tools/test/stress2/misc/suj11.sh @@ -42,7 +42,7 @@ newfs -j md$mdstart > /dev/null mount /dev/md$mdstart $mntpoint chmod 777 $mntpoint -export runRUNTIME=30m +export runRUNTIME=10m export RUNDIR=$mntpoint/stressX su $testuser -c 'cd ..; ./run.sh marcus.cfg' > /dev/null 2>&1 diff --git a/tools/test/stress2/misc/suj12.sh b/tools/test/stress2/misc/suj12.sh index d0cbecfb1a37..48b138fbd2d3 100755 --- a/tools/test/stress2/misc/suj12.sh +++ b/tools/test/stress2/misc/suj12.sh @@ -32,6 +32,9 @@ # OOM seen: https://people.freebsd.org/~pho/stress/log/suj12.txt +# watchdogd fired: +# https://people.freebsd.org/~pho/stress/log/log0428.txt + . ../default.cfg gnop load || exit 0 diff --git a/tools/test/stress2/misc/suj15.sh b/tools/test/stress2/misc/suj15.sh index 6ab9e653f12c..86bf2f4e3f1d 100755 --- a/tools/test/stress2/misc/suj15.sh +++ b/tools/test/stress2/misc/suj15.sh @@ -48,7 +48,7 @@ newfs -j md$mdstart > /dev/null mount /dev/md$mdstart $mntpoint chmod 777 $mntpoint -export runRUNTIME=30m +export runRUNTIME=10m export RUNDIR=$mntpoint/stressX su $testuser -c 'cd ..; ./run.sh jeff.cfg > /dev/null' & diff --git a/tools/test/stress2/misc/suj16.sh b/tools/test/stress2/misc/suj16.sh index b58f406e7564..64e64dd65fbc 100755 --- a/tools/test/stress2/misc/suj16.sh +++ b/tools/test/stress2/misc/suj16.sh @@ -46,7 +46,7 @@ newfs -j md$mdstart > /dev/null 2>&1 mount /dev/md$mdstart $mntpoint chmod 777 $mntpoint -export runRUNTIME=30m +export runRUNTIME=10m export RUNDIR=$mntpoint/stressX export creatINCARNATIONS=2 diff --git a/tools/test/stress2/misc/suj26.sh b/tools/test/stress2/misc/suj26.sh index 940ef5c92a29..427f94dbc664 100755 --- a/tools/test/stress2/misc/suj26.sh +++ b/tools/test/stress2/misc/suj26.sh @@ -45,7 +45,7 @@ newfs $opt md$mdstart > /dev/null 2>&1 mount /dev/md$mdstart $mntpoint chmod 777 $mntpoint -export runRUNTIME=30m +export runRUNTIME=10m export RUNDIR=$mntpoint/stressX export creatINCARNATIONS=2 diff --git a/tools/test/stress2/misc/suj27.sh b/tools/test/stress2/misc/suj27.sh index 8253243f5868..02cc70af5520 100755 --- a/tools/test/stress2/misc/suj27.sh +++ b/tools/test/stress2/misc/suj27.sh @@ -45,7 +45,7 @@ newfs $opt md$mdstart > /dev/null 2>&1 mount /dev/md$mdstart $mntpoint chmod 777 $mntpoint -export runRUNTIME=30m +export runRUNTIME=10m export RUNDIR=$mntpoint/stressX export creatINCARNATIONS=2 diff --git a/tools/test/stress2/misc/suj36.sh b/tools/test/stress2/misc/suj36.sh new file mode 100755 index 000000000000..686274418901 --- /dev/null +++ b/tools/test/stress2/misc/suj36.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# SU+J and snapshots + +# "panic: handle_disk_io_initiation: Unexpected type jnewblk" seen +# https://people.freebsd.org/~pho/stress/log/log0392.txt + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +set -eu +prog=$(basename "$0" .sh) +log=/tmp/$prog.log + +mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint +[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart +mdconfig -a -t swap -s 5g -u $mdstart +[ "$newfs_flags" = "-U" ] && newfs_flags="-j" +newfs $newfs_flags md$mdstart > /dev/null +mount /dev/md$mdstart $mntpoint +chmod 777 $mntpoint + +export LOAD=80 +export rwLOAD=80 +export runRUNTIME=10m +export RUNDIR=$mntpoint/stressX +export CTRLDIR=$mntpoint/stressX.control +export MAXSWAPPCT=80 +export TESTPROGS=`cd ..; find testcases/ -perm -1 -type f | \ + egrep -Ev "/run/|/badcode/|/pty/|/shm/|/socket/|sysctl|tcp|thr|udp"` + +su $testuser -c 'cd ..; ./testcases/run/run $TESTPROGS' > /dev/null & + +sleep 5 +for i in `jot 10`; do + for j in `jot 5`; do + rm -f $mntpoint/.snap/snap.$j + mksnap_ffs $mntpoint $mntpoint/.snap/snap.$j + sleep 10 + done + sleep 10 +done +wait + +../tools/killall.sh +for i in `jot 6`; do + mount | grep -q "on $mntpoint " || break + umount $mntpoint && break || sleep 10 + [ $i -eq 6 ] && + { echo FATAL; fstat -mf $mntpoint; exit 1; } +done +fsck_ffs -fy /dev/md$mdstart > $log 2>&1; s=$? +grep -q "WAS MODIFIED" $log && { tail -12 $log; s=100; } +mdconfig -d -u $mdstart +rm -f $log +exit $s diff --git a/tools/test/stress2/misc/suj4.sh b/tools/test/stress2/misc/suj4.sh index 27001a64a0e5..928909077cef 100755 --- a/tools/test/stress2/misc/suj4.sh +++ b/tools/test/stress2/misc/suj4.sh @@ -40,7 +40,7 @@ mount /dev/md$mdstart $mntpoint chmod 777 $mntpoint export RUNDIR=$mntpoint/stressX -export runRUNTIME=30m +export runRUNTIME=10m set `df -ik $mntpoint | tail -1 | awk '{print $4,$7}'` export KBLOCKS=$(($1 / 2)) export INODES=$(($2 / 2)) diff --git a/tools/test/stress2/misc/suj5.sh b/tools/test/stress2/misc/suj5.sh index 2e49e0706d6f..957065adc60c 100755 --- a/tools/test/stress2/misc/suj5.sh +++ b/tools/test/stress2/misc/suj5.sh @@ -28,7 +28,8 @@ [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 -# Deadlock seen +# "panic: general protection fault" seen: +# https://people.freebsd.org/~pho/stress/log/log0398.txt . ../default.cfg diff --git a/tools/test/stress2/misc/swap5.sh b/tools/test/stress2/misc/swap5.sh index a0d746e1d2e2..c9f715d57b9a 100755 --- a/tools/test/stress2/misc/swap5.sh +++ b/tools/test/stress2/misc/swap5.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/swap6.sh b/tools/test/stress2/misc/swap6.sh index 30a3fd8e703a..a1eaea6b86a6 100755 --- a/tools/test/stress2/misc/swap6.sh +++ b/tools/test/stress2/misc/swap6.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # @@ -33,7 +33,7 @@ . ../default.cfg [ `sysctl -n vm.swap_total` -eq 0 ] && exit 0 -min=5 # percent swap usage +min=10 # percent swap usage (cd ../testcases/swap; ./swap -t 10m -i 100 -l 100 -h > /dev/null) & sleep 1 mx=0 diff --git a/tools/test/stress2/misc/swapoff3.sh b/tools/test/stress2/misc/swapoff3.sh index 89b775a4f59c..5bd9e338a80f 100755 --- a/tools/test/stress2/misc/swapoff3.sh +++ b/tools/test/stress2/misc/swapoff3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Mark Johnston # diff --git a/tools/test/stress2/misc/swapoff4.sh b/tools/test/stress2/misc/swapoff4.sh index 8bba94faebd1..564715030478 100755 --- a/tools/test/stress2/misc/swapoff4.sh +++ b/tools/test/stress2/misc/swapoff4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/swapoff5.sh b/tools/test/stress2/misc/swapoff5.sh index fa4e0fe37a17..9801c5956716 100755 --- a/tools/test/stress2/misc/swapoff5.sh +++ b/tools/test/stress2/misc/swapoff5.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Mark Johnston # diff --git a/tools/test/stress2/misc/swapoff6.sh b/tools/test/stress2/misc/swapoff6.sh new file mode 100755 index 000000000000..b6ab08784f87 --- /dev/null +++ b/tools/test/stress2/misc/swapoff6.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# A swap test scenario, using swapoff(8) and sort(1) for VM pressure + +# Out of free pages seen:://people.freebsd.org/~pho/stress/log/log0540.txt + +. ../default.cfg +[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 + +[ `swapinfo | wc -l` -eq 1 ] && exit 0 +set -u +nmax=`sysctl -n hw.ncpu` +[ $nmax -gt 4 ] && nmax=4 + +for i in `jot $nmax`; do + timeout -k 2m 1m sort /dev/zero & + sleep .`jot -r 1 1 9` +done +while [ `swapinfo | tail -1 | awk '{sub("%","");print $NF}'` -lt 2 ]; do sleep 1; done + +start=`date +%s` +while [ $((`date +%s` - start)) -lt 300 ]; do + while ! swapoff -a > /dev/null 2>&1; do sleep .1; done + swapon -a > /dev/null + ncur=`pgrep sort | wc -l` + if [ $ncur -lt $nmax ]; then + echo "Starting $((nmax - ncur)) sort" + for i in `jot $((nmax - ncur))`; do + timeout -k 2m 1m sort /dev/zero & + sleep .`jot -r 1 1 9` + done + fi +done +pkill -9 sort +wait +exit 0 diff --git a/tools/test/stress2/misc/symlink.sh b/tools/test/stress2/misc/symlink.sh index 47257aa92a24..1d30636d6b25 100755 --- a/tools/test/stress2/misc/symlink.sh +++ b/tools/test/stress2/misc/symlink.sh @@ -71,6 +71,7 @@ tst() { s=0 for i in "" "-U" "-j"; do newfs $i /dev/md$mdstart > /dev/null 2>&1 + [ "$i" = "" ] && tunefs -n disable md$mdstart mount /dev/md$mdstart $mntpoint t1=`date +%s` diff --git a/tools/test/stress2/misc/symlink2.sh b/tools/test/stress2/misc/symlink2.sh index f13065badb4a..210702defe4a 100755 --- a/tools/test/stress2/misc/symlink2.sh +++ b/tools/test/stress2/misc/symlink2.sh @@ -53,6 +53,7 @@ for i in "" "-U"; do [ "$i" = "-U" -a "$newfs_flags" != "-U" ] && continue echo "newfs $i /dev/md$mdstart" newfs $i /dev/md$mdstart > /dev/null 2>&1 + [ "$i" = "" ] && tunefs -n disable md$mdstart mount /dev/md$mdstart $mntpoint mkdir $mntpoint/dir diff --git a/tools/test/stress2/misc/symlink5.sh b/tools/test/stress2/misc/symlink5.sh index 00ada39e5002..9332f906a3e0 100755 --- a/tools/test/stress2/misc/symlink5.sh +++ b/tools/test/stress2/misc/symlink5.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # @@ -79,6 +79,7 @@ for i in "" "-U"; do t1=`date +%s` echo "newfs $i /dev/md$mdstart" newfs $i /dev/md$mdstart > /dev/null 2>&1 + [ "$i" = "" ] && tunefs -n disable md$mdstart mount /dev/md$mdstart $mntpoint tst; s=$? diff --git a/tools/test/stress2/misc/syscall4.sh b/tools/test/stress2/misc/syscall4.sh index ce7e99dcde54..3937d45c0303 100755 --- a/tools/test/stress2/misc/syscall4.sh +++ b/tools/test/stress2/misc/syscall4.sh @@ -260,7 +260,7 @@ static void * calls(void *arg __unused) { time_t start; - int i, j, num; + int i __unused, j, num; unsigned long arg1, arg2, arg3, arg4, arg5, arg6, arg7; #ifdef __NP__ diff --git a/tools/test/stress2/misc/systrace.sh b/tools/test/stress2/misc/systrace.sh index aa7b8426dddf..c41675e77da3 100755 --- a/tools/test/stress2/misc/systrace.sh +++ b/tools/test/stress2/misc/systrace.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/systrace2.sh b/tools/test/stress2/misc/systrace2.sh index a8c4d05106a7..0ebdfd9549d1 100755 --- a/tools/test/stress2/misc/systrace2.sh +++ b/tools/test/stress2/misc/systrace2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/syzkaller11.sh b/tools/test/stress2/misc/syzkaller11.sh index 9586092cd5b3..788ea3a9557a 100755 --- a/tools/test/stress2/misc/syzkaller11.sh +++ b/tools/test/stress2/misc/syzkaller11.sh @@ -218,7 +218,7 @@ static void execute_one(void); static void loop(void) { - int iter; + int iter __unused; for (iter = 0;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller12.sh b/tools/test/stress2/misc/syzkaller12.sh index dc026dc348bc..f5468c6c5e1f 100755 --- a/tools/test/stress2/misc/syzkaller12.sh +++ b/tools/test/stress2/misc/syzkaller12.sh @@ -94,7 +94,7 @@ static void execute_one(void); static void loop(void) { - int iter; + int iter __unused; for (iter = 0;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller14.sh b/tools/test/stress2/misc/syzkaller14.sh index 5fa99004f838..9181fe71a2af 100755 --- a/tools/test/stress2/misc/syzkaller14.sh +++ b/tools/test/stress2/misc/syzkaller14.sh @@ -229,7 +229,7 @@ static void execute_one(void); static void loop(void) { - int iter; + int iter __unused; for (iter = 0;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller15.sh b/tools/test/stress2/misc/syzkaller15.sh index d15017d7eb12..7a13bd819f0b 100755 --- a/tools/test/stress2/misc/syzkaller15.sh +++ b/tools/test/stress2/misc/syzkaller15.sh @@ -112,7 +112,7 @@ static void execute_one(void); static void loop(void) { - int iter; + int iter __unused; for (iter = 0;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller16.sh b/tools/test/stress2/misc/syzkaller16.sh index 8671b46474ac..7035223b8f0e 100755 --- a/tools/test/stress2/misc/syzkaller16.sh +++ b/tools/test/stress2/misc/syzkaller16.sh @@ -273,7 +273,7 @@ static void execute_one(void); static void loop(void) { - int iter; + int iter __unused; for (iter = 0;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller19.sh b/tools/test/stress2/misc/syzkaller19.sh index b36b12e524f2..116ab539c152 100755 --- a/tools/test/stress2/misc/syzkaller19.sh +++ b/tools/test/stress2/misc/syzkaller19.sh @@ -78,7 +78,7 @@ static void execute_one(void); static void loop(void) { - int iter; + int iter __unused; for (iter = 0;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller24.sh b/tools/test/stress2/misc/syzkaller24.sh index 12a816598b8f..98d4f90b146f 100755 --- a/tools/test/stress2/misc/syzkaller24.sh +++ b/tools/test/stress2/misc/syzkaller24.sh @@ -81,7 +81,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller26.sh b/tools/test/stress2/misc/syzkaller26.sh index f14806199ff5..857ba0eaac65 100755 --- a/tools/test/stress2/misc/syzkaller26.sh +++ b/tools/test/stress2/misc/syzkaller26.sh @@ -82,7 +82,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller27.sh b/tools/test/stress2/misc/syzkaller27.sh index b003f6aec319..a84c921e462d 100755 --- a/tools/test/stress2/misc/syzkaller27.sh +++ b/tools/test/stress2/misc/syzkaller27.sh @@ -86,7 +86,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller28.sh b/tools/test/stress2/misc/syzkaller28.sh index c6ba56d1e222..7062d84a8234 100755 --- a/tools/test/stress2/misc/syzkaller28.sh +++ b/tools/test/stress2/misc/syzkaller28.sh @@ -220,7 +220,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller29.sh b/tools/test/stress2/misc/syzkaller29.sh index bc5dc94768d0..5976e2cc596d 100755 --- a/tools/test/stress2/misc/syzkaller29.sh +++ b/tools/test/stress2/misc/syzkaller29.sh @@ -26,7 +26,7 @@ # Fixed by r368116 -# May change policy for random threads to to domainset_fixed +# May change policy for random threads to domainset_fixed exit 0 . ../default.cfg @@ -79,7 +79,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller30.sh b/tools/test/stress2/misc/syzkaller30.sh index f798386a83d1..d159da78307c 100755 --- a/tools/test/stress2/misc/syzkaller30.sh +++ b/tools/test/stress2/misc/syzkaller30.sh @@ -29,7 +29,7 @@ # Fixed by r368462 -# May change policy for random threads to to domainset_fixed +# May change policy for random threads to domainset_fixed exit 0 . ../default.cfg diff --git a/tools/test/stress2/misc/syzkaller31.sh b/tools/test/stress2/misc/syzkaller31.sh index 12eb98bd8c57..9815ac16f404 100755 --- a/tools/test/stress2/misc/syzkaller31.sh +++ b/tools/test/stress2/misc/syzkaller31.sh @@ -228,7 +228,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller32.sh b/tools/test/stress2/misc/syzkaller32.sh index 03a13738c58a..1d96f1e3deff 100755 --- a/tools/test/stress2/misc/syzkaller32.sh +++ b/tools/test/stress2/misc/syzkaller32.sh @@ -231,7 +231,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller33.sh b/tools/test/stress2/misc/syzkaller33.sh index 7f017cd167f1..fac3318e4d0d 100755 --- a/tools/test/stress2/misc/syzkaller33.sh +++ b/tools/test/stress2/misc/syzkaller33.sh @@ -88,7 +88,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller34.sh b/tools/test/stress2/misc/syzkaller34.sh index 247079e1cd1a..d8b89991c2f2 100755 --- a/tools/test/stress2/misc/syzkaller34.sh +++ b/tools/test/stress2/misc/syzkaller34.sh @@ -53,7 +53,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller4.sh b/tools/test/stress2/misc/syzkaller4.sh index 2a14d4d2b776..06797980b2a0 100755 --- a/tools/test/stress2/misc/syzkaller4.sh +++ b/tools/test/stress2/misc/syzkaller4.sh @@ -215,7 +215,7 @@ static void execute_one(void); static void loop(void) { - int iter; + int iter __unused; for (iter = 0;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller42.sh b/tools/test/stress2/misc/syzkaller42.sh index b5b234de9cd6..e0a02e18df2d 100755 --- a/tools/test/stress2/misc/syzkaller42.sh +++ b/tools/test/stress2/misc/syzkaller42.sh @@ -75,7 +75,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller43.sh b/tools/test/stress2/misc/syzkaller43.sh index ffa6e1c6857c..fb32ea77ab66 100755 --- a/tools/test/stress2/misc/syzkaller43.sh +++ b/tools/test/stress2/misc/syzkaller43.sh @@ -214,7 +214,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller50.sh b/tools/test/stress2/misc/syzkaller50.sh index d50e90866b8c..e813db054458 100755 --- a/tools/test/stress2/misc/syzkaller50.sh +++ b/tools/test/stress2/misc/syzkaller50.sh @@ -71,7 +71,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller51.sh b/tools/test/stress2/misc/syzkaller51.sh index bd5b5da16d9a..772d6cc556c0 100755 --- a/tools/test/stress2/misc/syzkaller51.sh +++ b/tools/test/stress2/misc/syzkaller51.sh @@ -78,7 +78,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller53.sh b/tools/test/stress2/misc/syzkaller53.sh index ecb0843b8c1f..bfbabe70a571 100755 --- a/tools/test/stress2/misc/syzkaller53.sh +++ b/tools/test/stress2/misc/syzkaller53.sh @@ -119,7 +119,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller54.sh b/tools/test/stress2/misc/syzkaller54.sh index dc3ce0dc876c..252ba4e0f6f4 100755 --- a/tools/test/stress2/misc/syzkaller54.sh +++ b/tools/test/stress2/misc/syzkaller54.sh @@ -216,7 +216,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller55.sh b/tools/test/stress2/misc/syzkaller55.sh index 9914587926cf..e1d3e7a28121 100755 --- a/tools/test/stress2/misc/syzkaller55.sh +++ b/tools/test/stress2/misc/syzkaller55.sh @@ -77,7 +77,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller58.sh b/tools/test/stress2/misc/syzkaller58.sh index 0083e13f1692..6c11cd583b9d 100755 --- a/tools/test/stress2/misc/syzkaller58.sh +++ b/tools/test/stress2/misc/syzkaller58.sh @@ -216,7 +216,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller59.sh b/tools/test/stress2/misc/syzkaller59.sh index b628c25d3298..1644ce627934 100755 --- a/tools/test/stress2/misc/syzkaller59.sh +++ b/tools/test/stress2/misc/syzkaller59.sh @@ -94,7 +94,7 @@ static void execute_one(void); static void loop(void) { - int iter = 0; + int iter __unused = 0; for (;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller61.sh b/tools/test/stress2/misc/syzkaller61.sh new file mode 100755 index 000000000000..a25ae4cf00d8 --- /dev/null +++ b/tools/test/stress2/misc/syzkaller61.sh @@ -0,0 +1,319 @@ +#!/bin/sh + +# Seen: +# [root@mercat1 /usr/src/tools/test/stress2/misc]# pgrep syzkaller61 | xargs procstat -k +# PID TID COMM TDNAME KSTACK +# 13332 106396 syzkaller61 - mi_switch thread_suspend_check ast_suspend ast_handler ast doreti_ast +# 13332 560662 syzkaller61 - mi_switch sleepq_switch sleepq_catch_signals sleepq_wait_sig _sleep umtxq_sleep do_wait __umtx_op_wait_uint_private sys__umtx_op amd64_syscall fast_syscall_common +# 13332 560776 syzkaller61 - mi_switch thread_suspend_switch thread_single fork1 sys_rfork amd64_syscall fast_syscall_common +# 13662 356440 syzkaller61 - mi_switch thread_suspend_check ast_suspend ast_handler ast doreti_ast +# 13662 561098 syzkaller61 - mi_switch sleepq_switch sleepq_catch_signals sleepq_wait_sig _sleep umtxq_sleep do_wait __umtx_op_wait_uint_private sys__umtx_op amd64_syscall fast_syscall_common +# 13662 561160 syzkaller61 - mi_switch thread_suspend_switch thread_single fork1 sys_rfork amd64_syscall fast_syscall_common +# [root@mercat1 /usr/src/tools/test/stress2/misc]# + +[ `uname -p` != "amd64" ] && exit 0 + +. ../default.cfg +cat > /tmp/syzkaller61.c <<EOF +// https://syzkaller.appspot.com/bug?id=00d8ca63243899ffb67b15ec93aee4ffa2f06637 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// Reported-by: syzbot+647212368c3f32c6f13f@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <sys/types.h> + +#include <errno.h> +#include <pthread.h> +#include <pwd.h> +#include <setjmp.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +static __thread int clone_ongoing; +static __thread int skip_segv; +static __thread jmp_buf segv_env; + +static void segv_handler(int sig, siginfo_t* info, void* ctx __unused) +{ + if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) { + exit(sig); + } + uintptr_t addr = (uintptr_t)info->si_addr; + const uintptr_t prog_start = 1 << 20; + const uintptr_t prog_end = 100 << 20; + int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0; + int valid = addr < prog_start || addr > prog_end; + if (sig == SIGBUS) + valid = 1; + if (skip && valid) { + _longjmp(segv_env, 1); + } + exit(sig); +} + +static void install_segv_handler(void) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = segv_handler; + sa.sa_flags = SA_NODEFER | SA_SIGINFO; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); +} + +#define NONFAILING(...) \ + ({ \ + int ok = 1; \ + __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ + if (_setjmp(segv_env) == 0) { \ + __VA_ARGS__; \ + } else \ + ok = 0; \ + __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \ + ok; \ + }) + +static void kill_and_wait(int pid, int* status) +{ + kill(pid, SIGKILL); + while (waitpid(-1, status, 0) != pid) { + } +} + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void thread_start(void* (*fn)(void*), void* arg) +{ + pthread_t th; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128 << 10); + int i = 0; + for (; i < 100; i++) { + if (pthread_create(&th, &attr, fn, arg) == 0) { + pthread_attr_destroy(&attr); + return; + } + if (errno == EAGAIN) { + usleep(50); + continue; + } + break; + } + exit(1); +} + +typedef struct { + pthread_mutex_t mu; + pthread_cond_t cv; + int state; +} event_t; + +static void event_init(event_t* ev) +{ + if (pthread_mutex_init(&ev->mu, 0)) + exit(1); + if (pthread_cond_init(&ev->cv, 0)) + exit(1); + ev->state = 0; +} + +static void event_reset(event_t* ev) +{ + ev->state = 0; +} + +static void event_set(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + if (ev->state) + exit(1); + ev->state = 1; + pthread_mutex_unlock(&ev->mu); + pthread_cond_broadcast(&ev->cv); +} + +static void event_wait(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + while (!ev->state) + pthread_cond_wait(&ev->cv, &ev->mu); + pthread_mutex_unlock(&ev->mu); +} + +static int event_isset(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static int event_timedwait(event_t* ev, uint64_t timeout) +{ + uint64_t start = current_time_ms(); + uint64_t now = start; + pthread_mutex_lock(&ev->mu); + for (;;) { + if (ev->state) + break; + uint64_t remain = timeout - (now - start); + struct timespec ts; + ts.tv_sec = remain / 1000; + ts.tv_nsec = (remain % 1000) * 1000 * 1000; + pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); + now = current_time_ms(); + if (now - start > timeout) + break; + } + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +struct thread_t { + int created, call; + event_t ready, done; +}; + +static struct thread_t threads[16]; +static void execute_call(int call); +static int running; + +static void* thr(void* arg) +{ + struct thread_t* th = (struct thread_t*)arg; + for (;;) { + event_wait(&th->ready); + event_reset(&th->ready); + execute_call(th->call); + __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); + event_set(&th->done); + } + return 0; +} + +static void execute_one(void) +{ + int i, call, thread; + for (call = 0; call < 2; call++) { + for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); + thread++) { + struct thread_t* th = &threads[thread]; + if (!th->created) { + th->created = 1; + event_init(&th->ready); + event_init(&th->done); + event_set(&th->done); + thread_start(thr, th); + } + if (!event_isset(&th->done)) + continue; + event_reset(&th->done); + th->call = call; + __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); + event_set(&th->ready); + event_timedwait(&th->done, 50); + break; + } + } + for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) + sleep_ms(1); +} + +static void execute_one(void); + +#define WAIT_FLAGS 0 + +static void loop(void) +{ + int iter __unused = 0; + for (;; iter++) { + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + sleep_ms(1); + if (current_time_ms() - start < 5000) + continue; + kill_and_wait(pid, &status); + break; + } + } +} + +void execute_call(int call) +{ + switch (call) { + case 0: + NONFAILING(*(uint32_t*)0x20001f00 = 0x16); + NONFAILING(*(uint32_t*)0x20001f04 = 0); + NONFAILING(*(uint32_t*)0x20001f08 = 0); + NONFAILING(*(uint32_t*)0x20001f0c = 0); + NONFAILING(*(uint32_t*)0x20001f10 = 0); + NONFAILING(memset((void*)0x20001f14, 0, 60)); + syscall(SYS_procctl, 0ul, 0, 6ul, 0x20001f00ul); + break; + case 1: + syscall(SYS_rfork, 0x85000ul); + break; + } +} +int main(void) +{ + syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); + install_segv_handler(); + loop(); + return 0; +} +EOF +mycc -o /tmp/syzkaller61 -Wall -Wextra -O0 /tmp/syzkaller61.c -lpthread || + exit 1 + +(cd ../testcases/swap; ./swap -t 3m -i 10 -l 100 > /dev/null 2>&1) & +for i in `jot 300`; do + (cd /tmp; timeout -k 3s 2s ./syzkaller61) & + pids="$pids $!" +done +sleep 5 +pkill -9 syzkaller61 swap; sleep 1 +pgrep -q syzkaller61 && { pgrep syzkaller61 | xargs ps -lHp; exit 1; } +for pid in $pids; do + wait $pid +done +while pkill swap; do :; done +wait + +rm -rf /tmp/syzkaller61 /tmp/syzkaller61.c /tmp/syzkaller61.core \ + /tmp/syzkaller.?????? +exit 0 diff --git a/tools/test/stress2/misc/syzkaller62.sh b/tools/test/stress2/misc/syzkaller62.sh new file mode 100755 index 000000000000..aa2d33ebaf9e --- /dev/null +++ b/tools/test/stress2/misc/syzkaller62.sh @@ -0,0 +1,83 @@ +#!/bin/sh + +# panic: Assertion sb->sb_hiwat >= sb->uxdg_cc failed at ../../../kern/uipc_usrreq.c:1099 +# cpuid = 9 +# time = 1660909804 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe01401e7970 +# vpanic() at vpanic+0x151/frame 0xfffffe01401e79c0 +# panic() at panic+0x43/frame 0xfffffe01401e7a20 +# uipc_dgram_sbspace() at uipc_dgram_sbspace+0x51/frame 0xfffffe01401e7a30 +# uipc_sosend_dgram() at uipc_sosend_dgram+0x690/frame 0xfffffe01401e7ac0 +# sosend() at sosend+0x49/frame 0xfffffe01401e7af0 +# soo_write() at soo_write+0x43/frame 0xfffffe01401e7b20 +# filemon_close_log() at filemon_close_log+0xd5/frame 0xfffffe01401e7b90 +# filemon_dtr() at filemon_dtr+0x31/frame 0xfffffe01401e7bb0 +# devfs_destroy_cdevpriv() at devfs_destroy_cdevpriv+0xab/frame 0xfffffe01401e7bd0 +# devfs_close_f() at devfs_close_f+0x64/frame 0xfffffe01401e7c00 +# _fdrop() at _fdrop+0x1b/frame 0xfffffe01401e7c20 +# closef() at closef+0x1db/frame 0xfffffe01401e7cb0 +# fdescfree() at fdescfree+0x433/frame 0xfffffe01401e7d80 +# exit1() at exit1+0x4df/frame 0xfffffe01401e7df0 +# sys_exit() at sys_exit+0xd/frame 0xfffffe01401e7e00 +# amd64_syscall() at amd64_syscall+0x145/frame 0xfffffe01401e7f30 +# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe01401e7f30 +# --- syscall (1, FreeBSD ELF64, sys_exit), rip = 0x82301d16a, rsp = 0x8209bf628, rbp = 0x8209bf640 --- +# KDB: enter: panic +# [ thread pid 2876 tid 100222 ] +# Stopped at x32: movq $0,0x12a1323(%rip) +# db> x/s version +# version: FreeBSD 14.0-CURRENT #0 main-n257506-eed634d113d-dirty: Thu Aug 18 13:56:53 CEST 2022 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO\012 +# db> + +. ../default.cfg +cat > /tmp/syzkaller62.c <<EOF +// https://syzkaller.appspot.com/bug?id=582310beb894769fc836748eec49b8d2f905e5ef +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// Reported-by: syzbot+6e8be1ec8d77578a3df4@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <pwd.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <unistd.h> + +uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff}; + +int main(void) +{ + syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); + intptr_t res = 0; + memcpy((void*)0x20000040, "/dev/filemon\000", 13); + res = syscall(SYS_openat, 0xffffffffffffff9cul, 0x20000040ul, 0ul, 0ul); + if (res != -1) + r[0] = res; + res = syscall(SYS_socketpair, 1ul, 2ul, 0, 0x20000080ul); + if (res != -1) + r[1] = *(uint32_t*)0x20000084; + *(uint32_t*)0x200000c0 = r[1]; + syscall(SYS_ioctl, r[0], 0xc0045301ul, 0x200000c0ul); + *(uint32_t*)0x20000040 = 3; + syscall(SYS_setsockopt, r[1], 0xffff, 0x1001, 0x20000040ul, 4ul); + return 0; +} +EOF +mycc -o /tmp/syzkaller62 -Wall -Wextra -O0 /tmp/syzkaller62.c || exit 1 + +kldstat | grep -q filemon || { kldload filemon.ko && loaded=1; } + +(cd /tmp; timeout -k 3s 2s ./syzkaller62) + +rm -rf /tmp/syzkaller62 /tmp/syzkaller62.c /tmp/syzkaller62.core \ + /tmp/syzkaller.?????? +# Unload causes: Fatal trap 12: page fault while in kernel mode +#[ $loaded ] && kldunload -f filemon.ko +exit 0 diff --git a/tools/test/stress2/misc/syzkaller63.sh b/tools/test/stress2/misc/syzkaller63.sh new file mode 100755 index 000000000000..647801dbdbb9 --- /dev/null +++ b/tools/test/stress2/misc/syzkaller63.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +# Fatal trap 12: page fault while in kernel mode +# cpuid = 1; apic id = 01 +# fault virtual address = 0x20 +# fault code = supervisor read data, page not present +# instruction pointer = 0x20:0xfa1a2c +# stack pointer = 0x28:0x27a41a80 +# frame pointer = 0x28:0x27a41a98 +# code segment = base 0x0, limit 0xfffff, type 0x1b +# = DPL 0, pres 1, def32 1, gran 1 +# processor eflags = interrupt enabled, resume, IOPL = 0 +# current process = 804 (syzkaller63) +# trap number = 12 +# panic: page fault +# cpuid = 1 +# time = 1675071979 +# KDB: stack backtrace: +# db_trace_self_wrapper(d,2048e3a0,27a41a40,20,c,...) at db_trace_self_wrapper+0x28/frame 0x27a418d0 +# vpanic(146c355,27a4190c,27a4190c,27a41938,141f1d6,...) at vpanic+0xf4/frame 0x27a418ec +# panic(146c355,15010e8,0,fffff,1dfc39b,...) at panic+0x14/frame 0x27a41900 +# trap_fatal(2048e3a0,2048e3a0,27a4196c,1008e0a,18cd6638,...) at trap_fatal+0x346/frame 0x27a41938 +# trap_pfault(20,0,0) at trap_pfault+0x6f/frame 0x27a4196c +# trap(27a41a40,8,28,28,0,...) at trap+0x31b/frame 0x27a41a34 +# calltrap() at 0xffc0321f/frame 0x27a41a34 +# --- trap 0xc, eip = 0xfa1a2c, esp = 0x27a41a80, ebp = 0x27a41a98 --- +# kern_cpuset_getid(141f60e,0,9,0,0,0) at kern_cpuset_getid+0x10c/frame 0x27a41a98 +# sys_cpuset_getid(2048e3a0,2048e644,2048e3a0,2048e3a0,27a41b9c,...) at sys_cpuset_getid+0x32/frame 0x27a41ac0 +# syscall(27a41ba8,3b,3b,3b,ffbfe9fc,...) at syscall+0x1ef/frame 0x27a41b9c +# Xint0x80_syscall() at 0xffc03479/frame 0x27a41b9c +# --- syscall (486, FreeBSD ELF32, cpuset_getid), eip = 0x2056317d, esp = 0xffbfe990, ebp = 0xffbfe9b0 --- +# KDB: enter: panic +# [ thread pid 804 tid 100092 ] +# Stopped at kdb_enter+0x34: movl $0,kdb_why +# db> x/s version +# version: FreeBSD 14.0-CURRENT #0 main-n260354-34b867ca30479: Mon Jan 30 07:26:30 CET 2023 +# pho@mercat1.netperf.freebsd.org:/mnt25/obj/usr/src/i386.i386/sys/PHO +# db> + +. ../default.cfg +prog=$(basename "$0" .sh) +[ `uname -p` = "i386" ] || exit 0 + +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=69dd3c8d867306dd9f97e2dae6ab1557fd8d2679 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// Reported-by: syzbot+331e8402e0f7347f0f2a@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <pwd.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <unistd.h> + +int main(void) +{ + syscall(SYS_mmap, 0x10000000, 0x1000000, 7, 0x1012, -1, 0); + syscall(SYS_cpuset_getid, 0, 9, 0ull, 0); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1 + +(cd /tmp; timeout -k 3s 2s ./$prog) + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core \ + /tmp/syzkaller.?????? +exit 0 diff --git a/tools/test/stress2/misc/syzkaller64.sh b/tools/test/stress2/misc/syzkaller64.sh new file mode 100755 index 000000000000..f13fd415087b --- /dev/null +++ b/tools/test/stress2/misc/syzkaller64.sh @@ -0,0 +1,328 @@ +#!/bin/sh + +[ `uname -p` != "amd64" ] && exit 0 +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +[ "`sysctl -in kern.features.kasan`" != "1" ] && exit 0 + +. ../default.cfg +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=749aa1fdb67018e9c0179373a60d523511bff02c +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// Reported-by: syzbot+5cb51285603332d9be11@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <sys/types.h> + +#include <errno.h> +#include <pthread.h> +#include <pwd.h> +#include <setjmp.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/resource.h> +#include <sys/syscall.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +static __thread int clone_ongoing; +static __thread int skip_segv; +static __thread jmp_buf segv_env; + +static void segv_handler(int sig, siginfo_t* info, void* ctx __unused) +{ + if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) { + exit(sig); + } + uintptr_t addr = (uintptr_t)info->si_addr; + const uintptr_t prog_start = 1 << 20; + const uintptr_t prog_end = 100 << 20; + int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0; + int valid = addr < prog_start || addr > prog_end; + if (sig == SIGBUS) + valid = 1; + if (skip && valid) { + _longjmp(segv_env, 1); + } + exit(sig); +} + +static void install_segv_handler(void) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = segv_handler; + sa.sa_flags = SA_NODEFER | SA_SIGINFO; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); +} + +#define NONFAILING(...) \ + ({ \ + int ok = 1; \ + __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ + if (_setjmp(segv_env) == 0) { \ + __VA_ARGS__; \ + } else \ + ok = 0; \ + __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \ + ok; \ + }) + +static void kill_and_wait(int pid, int* status) +{ + kill(pid, SIGKILL); + while (waitpid(-1, status, 0) != pid) { + } +} + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void thread_start(void* (*fn)(void*), void* arg) +{ + pthread_t th; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128 << 10); + int i = 0; + for (; i < 100; i++) { + if (pthread_create(&th, &attr, fn, arg) == 0) { + pthread_attr_destroy(&attr); + return; + } + if (errno == EAGAIN) { + usleep(50); + continue; + } + break; + } + exit(1); +} + +typedef struct { + pthread_mutex_t mu; + pthread_cond_t cv; + int state; +} event_t; + +static void event_init(event_t* ev) +{ + if (pthread_mutex_init(&ev->mu, 0)) + exit(1); + if (pthread_cond_init(&ev->cv, 0)) + exit(1); + ev->state = 0; +} + +static void event_reset(event_t* ev) +{ + ev->state = 0; +} + +static void event_set(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + if (ev->state) + exit(1); + ev->state = 1; + pthread_mutex_unlock(&ev->mu); + pthread_cond_broadcast(&ev->cv); +} + +static void event_wait(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + while (!ev->state) + pthread_cond_wait(&ev->cv, &ev->mu); + pthread_mutex_unlock(&ev->mu); +} + +static int event_isset(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static int event_timedwait(event_t* ev, uint64_t timeout) +{ + uint64_t start = current_time_ms(); + uint64_t now = start; + pthread_mutex_lock(&ev->mu); + for (;;) { + if (ev->state) + break; + uint64_t remain = timeout - (now - start); + struct timespec ts; + ts.tv_sec = remain / 1000; + ts.tv_nsec = (remain % 1000) * 1000 * 1000; + pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); + now = current_time_ms(); + if (now - start > timeout) + break; + } + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static void sandbox_common() +{ + struct rlimit rlim; + rlim.rlim_cur = rlim.rlim_max = 128 << 20; + setrlimit(RLIMIT_AS, &rlim); + rlim.rlim_cur = rlim.rlim_max = 8 << 20; + setrlimit(RLIMIT_MEMLOCK, &rlim); + rlim.rlim_cur = rlim.rlim_max = 1 << 20; + setrlimit(RLIMIT_FSIZE, &rlim); + rlim.rlim_cur = rlim.rlim_max = 1 << 20; + setrlimit(RLIMIT_STACK, &rlim); + rlim.rlim_cur = rlim.rlim_max = 0; + setrlimit(RLIMIT_CORE, &rlim); + rlim.rlim_cur = rlim.rlim_max = 256; + setrlimit(RLIMIT_NOFILE, &rlim); +} + +static void loop(); + +static int do_sandbox_none(void) +{ + sandbox_common(); + loop(); + return 0; +} + +struct thread_t { + int created, call; + event_t ready, done; +}; + +static struct thread_t threads[16]; +static void execute_call(int call); +static int running; + +static void* thr(void* arg) +{ + struct thread_t* th = (struct thread_t*)arg; + for (;;) { + event_wait(&th->ready); + event_reset(&th->ready); + execute_call(th->call); + __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); + event_set(&th->done); + } + return 0; +} + +static void execute_one(void) +{ + int i, call, thread; + for (call = 0; call < 5; call++) { + for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); + thread++) { + struct thread_t* th = &threads[thread]; + if (!th->created) { + th->created = 1; + event_init(&th->ready); + event_init(&th->done); + event_set(&th->done); + thread_start(thr, th); + } + if (!event_isset(&th->done)) + continue; + event_reset(&th->done); + th->call = call; + __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); + event_set(&th->ready); + event_timedwait(&th->done, 50); + break; + } + } + for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) + sleep_ms(1); +} + +static void execute_one(void); + +#define WAIT_FLAGS 0 + +static void loop(void) +{ + int iter __unused = 0; + for (;; iter++) { + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + sleep_ms(1); + if (current_time_ms() - start < 5000) + continue; + kill_and_wait(pid, &status); + break; + } + } +} + +void execute_call(int call) +{ + switch (call) { + case 0: + syscall(SYS_thr_new, 0ul, 0ul); + break; + case 1: + syscall(SYS_setloginclass, 0ul); + break; + case 2: + syscall(SYS_vfork); + break; + case 3: + NONFAILING(*(uint32_t*)0x20001880 = 4); + syscall(SYS_sysarch, 8ul, 0x20001880ul); + break; + case 4: + syscall(SYS_getsid, 0); + break; + } +} +int main(void) +{ + syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); + install_segv_handler(); + do_sandbox_none(); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +(cd /tmp; timeout 2m ./$prog) + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/syzkaller.* +exit 0 diff --git a/tools/test/stress2/misc/syzkaller65.sh b/tools/test/stress2/misc/syzkaller65.sh new file mode 100755 index 000000000000..8806a55e2733 --- /dev/null +++ b/tools/test/stress2/misc/syzkaller65.sh @@ -0,0 +1,82 @@ +#!/bin/sh + +# panic: in_pcblookup_hash_locked: invalid local address +# cpuid = 11 +# time = 1678303805 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe0657e466d0 +# vpanic() at vpanic+0x152/frame 0xfffffe0657e46720 +# panic() at panic+0x43/frame 0xfffffe0657e46780 +# in_pcblookup_hash_locked() at in_pcblookup_hash_locked+0x4e2/frame 0xfffffe0657e467f0 +# in_pcb_lport_dest() at in_pcb_lport_dest+0x28a/frame 0xfffffe0657e468a0 +# in_pcbconnect_setup() at in_pcbconnect_setup+0x31b/frame 0xfffffe0657e46940 +# udp_send() at udp_send+0x68b/frame 0xfffffe0657e46a50 +# udp6_send() at udp6_send+0x287/frame 0xfffffe0657e46c10 +# sosend_dgram() at sosend_dgram+0x327/frame 0xfffffe0657e46c70 +# sousrsend() at sousrsend+0x7e/frame 0xfffffe0657e46cd0 +# kern_sendit() at kern_sendit+0x1bc/frame 0xfffffe0657e46d60 +# sendit() at sendit+0xba/frame 0xfffffe0657e46db0 +# sys_sendto() at sys_sendto+0x4d/frame 0xfffffe0657e46e00 +# amd64_syscall() at amd64_syscall+0x15a/frame 0xfffffe0657e46f30 +# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe0657e46f30 +# --- syscall (0, FreeBSD ELF64, syscall), rip = 0x822a3a31a, rsp = 0x8208224d8, rbp = 0x820822500 --- +# KDB: enter: panic +# [ thread pid 47141 tid 357973 ] +# Stopped at kdb_enter+0x32: movq $0,0x12906d3(%rip) +# db> x/s version +# FreeBSD 14.0-CURRENT #0 main-n261389-109abf744bf76: Wed Mar 8 06:10:24 CET 2023 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/a +# db> + +[ `uname -p` != "amd64" ] && exit 0 +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=7cae38958ddfe2c338548b4217587bd6d89b43e2 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// Reported-by: syzbot+c8e3dac881bba85bc029@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <pwd.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <unistd.h> + +uint64_t r[1] = {0xffffffffffffffff}; + +int main(void) +{ + syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); + intptr_t res = 0; + res = syscall(SYS_socket, 0x1cul, 2ul, 0); + if (res != -1) + r[0] = res; + *(uint32_t*)0x200001c0 = 0; + syscall(SYS_setsockopt, r[0], 0x29, 0x1b, 0x200001c0ul, 4ul); + *(uint8_t*)0x20000000 = 0x1c; + *(uint8_t*)0x20000001 = 0x1c; + *(uint16_t*)0x20000002 = htobe16(0x4e22); + *(uint32_t*)0x20000004 = 0; + memset((void*)0x20000008, 0, 10); + memset((void*)0x20000012, 255, 2); + *(uint32_t*)0x20000014 = htobe32(0); + *(uint32_t*)0x20000018 = 0; + syscall(SYS_sendto, r[0], 0ul, 0ul, 0ul, 0x20000000ul, 0x1cul); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +(cd /tmp; timeout 2m ./$prog) + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/syzkaller.* +exit 0 diff --git a/tools/test/stress2/misc/syzkaller66.sh b/tools/test/stress2/misc/syzkaller66.sh new file mode 100755 index 000000000000..8d1e9afe6f6c --- /dev/null +++ b/tools/test/stress2/misc/syzkaller66.sh @@ -0,0 +1,156 @@ +#!/bin/sh + +# panic: in_pcbconnect: inp is already connected +# cpuid = 2 +# time = 1687326262 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe016e604b60 +# vpanic() at vpanic+0x150/frame 0xfffffe016e604bb0 +# panic() at panic+0x43/frame 0xfffffe016e604c10 +# in_pcbconnect_setup() at in_pcbconnect_setup/frame 0xfffffe016e604c60 +# tcp_connect() at tcp_connect+0xa3/frame 0xfffffe016e604ca0 +# tcp_usr_connect() at tcp_usr_connect+0xf3/frame 0xfffffe016e604d10 +# soconnectat() at soconnectat+0xaf/frame 0xfffffe016e604d60 +# kern_connectat() at kern_connectat+0xe1/frame 0xfffffe016e604dc0 +# sys_connect() at sys_connect+0x75/frame 0xfffffe016e604e00 +# amd64_syscall() at amd64_syscall+0x157/frame 0xfffffe016e604f30 +# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe016e604f30 +# --- syscall (0, FreeBSD ELF64, syscall), rip = 0x823c81a6a, rsp = 0x8210ed3c8, rbp = 0x8210ed3e0 --- +# KDB: enter: panic +# [ thread pid 46907 tid 100356 ] +# Stopped at kdb_enter+0x32: movq $0,0xddf693(%rip) +# db> x/s version +# version: FreeBSD 14.0-CURRENT #0 main-n263725-1efa7dbc0798e: Wed Jun 21 09:13:50 CEST 2023 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO-KASAN\012 +# db> + +[ `uname -p` != "amd64" ] && exit 0 +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=44e3d85e927362a22cc594b9d1d3072f38da7972 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// Reported-by: syzbot+f0f7871ec5397602b446@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <sys/types.h> + +#include <pwd.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +static void kill_and_wait(int pid, int* status) +{ + kill(pid, SIGKILL); + while (waitpid(-1, status, 0) != pid) { + } +} + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void execute_one(void); + +#define WAIT_FLAGS 0 + +static void loop(void) +{ + int iter __unused = 0; + for (;; iter++) { + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + sleep_ms(1); + if (current_time_ms() - start < 5000) + continue; + kill_and_wait(pid, &status); + break; + } + } +} + +uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff}; + +void execute_one(void) +{ + intptr_t res = 0; + res = syscall(SYS_socket, 2ul, 1ul, 0); + if (res != -1) + r[0] = res; + *(uint8_t*)0x200001c0 = 0x10; + *(uint8_t*)0x200001c1 = 2; + *(uint16_t*)0x200001c2 = htobe16(0x4e22); + *(uint32_t*)0x200001c4 = htobe32(0x7f000001); + memset((void*)0x200001c8, 0, 8); + syscall(SYS_bind, r[0], 0x200001c0ul, 0x10ul); + syscall(SYS_listen, r[0], 0); + res = syscall(SYS_socket, 2ul, 1ul, 0); + if (res != -1) + r[1] = res; + *(uint8_t*)0x200000c0 = 0x10; + *(uint8_t*)0x200000c1 = 2; + *(uint16_t*)0x200000c2 = htobe16(0x4e22); + *(uint32_t*)0x200000c4 = htobe32(0x7f000001); + memset((void*)0x200000c8, 0, 8); + syscall(SYS_connect, r[1], 0x200000c0ul, 0x10ul); + *(uint64_t*)0x20002580 = 0; + *(uint32_t*)0x20002588 = 0; + *(uint64_t*)0x20002590 = 0; + *(uint64_t*)0x20002598 = 0; + *(uint64_t*)0x200025a0 = 0; + *(uint64_t*)0x200025a8 = 0; + *(uint32_t*)0x200025b0 = 0; + syscall(SYS_sendmsg, r[1], 0x20002580ul, 0x20104ul); + syscall(SYS_shutdown, r[1], 1ul); + *(uint8_t*)0x200000c0 = 0x10; + *(uint8_t*)0x200000c1 = 2; + *(uint16_t*)0x200000c2 = htobe16(0x4e22); + *(uint32_t*)0x200000c4 = htobe32(0x7f000001); + memset((void*)0x200000c8, 0, 8); + syscall(SYS_connect, r[1], 0x200000c0ul, 0x10ul); +} +int main(void) +{ + syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); + loop(); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1 + +(cd /tmp; timeout 2m ./$prog) + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/syzkaller.* +exit 0 diff --git a/tools/test/stress2/misc/syzkaller67.sh b/tools/test/stress2/misc/syzkaller67.sh new file mode 100755 index 000000000000..d5dc340442ae --- /dev/null +++ b/tools/test/stress2/misc/syzkaller67.sh @@ -0,0 +1,99 @@ +#!/bin/sh + +# panic: ASan: Invalid access, 8-byte read at 0xfffffe01fece46f8, StackMiddle(f2) +# cpuid = 4 +# time = 1687335671 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0xa5/frame 0xfffffe01fece42f0 +# kdb_backtrace() at kdb_backtrace+0xc7/frame 0xfffffe01fece4450 +# vpanic() at vpanic+0x1d7/frame 0xfffffe01fece4510 +# panic() at panic+0xb5/frame 0xfffffe01fece45e0 +# kasan_report() at kasan_report+0xdc/frame 0xfffffe01fece46b0 +# __cap_rights_is_set() at __cap_rights_is_set+0x186/frame 0xfffffe01fece47d0 +# fget_fcntl() at fget_fcntl+0xd7/frame 0xfffffe01fece48d0 +# kern_fcntl() at kern_fcntl+0x602/frame 0xfffffe01fece4c10 +# kern_fcntl_freebsd() at kern_fcntl_freebsd+0x244/frame 0xfffffe01fece4d30 +# ia32_syscall() at ia32_syscall+0x32a/frame 0xfffffe01fece4f30 +# int0x80_syscall_common() at int0x80_syscall_common+0x9c/frame 0xffffdb38 +# KDB: enter: panic +# [ thread pid 4224 tid 100231 ] +# Stopped at kdb_enter+0x34: movq $0,0x1e3f7c1(%rip) +# db> x/s version +# version: FreeBSD 14.0-CURRENT #0 main-n263725-1efa7dbc0798e: Wed Jun 21 09:13:50 CEST 2023 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO-KASAN +# db> + +uname -p | grep -Eq "amd64|i386" || exit 0 +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=81419dc41de046ccb99da6f333074b750ac36680 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// Reported-by: syzbot+d35497494d68b4859367@syzkaller.appspotmail.com +// i386 + ASan + +#define _GNU_SOURCE + +#include <pwd.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <unistd.h> + +uint64_t r[5] = {0x0, 0x0, 0x0, 0x0, 0x0}; + +int main(void) +{ + syscall(SYS_mmap, 0x10000000, 0x1000000, 7, 0x1012, -1, 0); + intptr_t res = 0; + syscall(SYS_munmap, 0x10ffa000, 0x3000); + syscall(SYS_mmap, 0x10ffd000, 0x1000, 4, 0x1010, -1, 0); + syscall(SYS_mmap, 0x10ffc000, 0x1000, 0, 0x1010, -1, 0); + syscall(SYS_mmap, 0x10ffc000, 0x1000, 0, 0x1010, -1, 0); + syscall(SYS_mprotect, 0x10ffe000, 0x2000, 7); + syscall(SYS_mprotect, 0x10ffd000, 0x3000, 0); + syscall(SYS_fork); + res = syscall(SYS_fork); + if (res != -1) + r[0] = res; + syscall(SYS_fork); + res = syscall(SYS_fork); + if (res != -1) + r[1] = res; + syscall(SYS_sigqueue, (intptr_t)r[1], 0x2b, 0); + res = syscall(SYS_fork); + if (res != -1) + r[2] = res; + syscall(SYS_sigqueue, (intptr_t)r[2], 0x2b, 0); + syscall(SYS_vfork); + syscall(SYS_fcntl, -1, 5, 0); + syscall(SYS_sigqueue, 0, 0x2b, 0); + syscall(SYS_getpgrp, (intptr_t)r[0]); + syscall(SYS_fork); + res = syscall(SYS_fork); + if (res != -1) + r[3] = res; + syscall(SYS_sigqueue, (intptr_t)r[3], 0x2b, 0); + syscall(SYS_getpid); + syscall(SYS_mmap, 0x10ffc000, 0x1000, 3, 0x10, -1, 7); + syscall(SYS_mmap, 0x10ffc000, 0x1000, 3, 0x10, -1, 7); + res = syscall(SYS_fork); + if (res != -1) + r[4] = res; + syscall(SYS_sigqueue, (intptr_t)r[4], 0xc, 0); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 -m32 /tmp/$prog.c || exit 1 + +(cd /tmp; timeout 2m ./$prog) + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/syzkaller.* +exit 0 diff --git a/tools/test/stress2/misc/syzkaller68.sh b/tools/test/stress2/misc/syzkaller68.sh new file mode 100755 index 000000000000..3d60af5215c5 --- /dev/null +++ b/tools/test/stress2/misc/syzkaller68.sh @@ -0,0 +1,235 @@ +#!/bin/sh + +# panic: mutex Giant owned at ../../../kern/kern_thread.c:1409 +# cpuid = 0 +# time = 1688501618 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe0171ba2510 +# vpanic() at vpanic+0x150/frame 0xfffffe0171ba2560 +# panic() at panic+0x43/frame 0xfffffe0171ba25c0 +# __mtx_assert() at __mtx_assert+0xc4/frame 0xfffffe0171ba25d0 +# thread_suspend_check() at thread_suspend_check+0x38/frame 0xfffffe0171ba2610 +# sig_intr() at sig_intr+0x78/frame 0xfffffe0171ba2640 +# fork1() at fork1+0x238/frame 0xfffffe0171ba26c0 +# kproc_create() at kproc_create+0x92/frame 0xfffffe0171ba2790 +# kproc_kthread_add() at kproc_kthread_add+0xdd/frame 0xfffffe0171ba28b0 +# zthr_create_timer() at zthr_create_timer+0x109/frame 0xfffffe0171ba2930 +# arc_init() at arc_init+0x1b44/frame 0xfffffe0171ba2970 +# dmu_init() at dmu_init+0x31/frame 0xfffffe0171ba2980 +# spa_init() at spa_init+0xed/frame 0xfffffe0171ba29a0 +# zfs_kmod_init() at zfs_kmod_init+0x1f/frame 0xfffffe0171ba29c0 +# zfs_modevent() at zfs_modevent+0module_register_init() at module_register_init+0xb0/frame 0xfffffe0171ba2a10 +# linker_load_module() at linker_load_module+0xbd2/frame 0xfffffe0171ba2d10 +# kern_kldload() at kern_kldload+0x16f/frame 0xfffffe0171ba2d60 +# vfs_byname_kld() at vfs_byname_kld+0x31/frame 0xfffffe0171ba2da0 +# sys_mount() at sys_mount+0xa9/frame 0xfffffe0171ba2e00 +# amd64_syscall() at amd64_syscall+0x150/frame 0xfffffe0171ba2f30 +# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe0171ba2f30 +# --- syscall (0, FreeBSD ELF64, syscall), rip = 0x823f70e9a, rsp = 0x82513af78, rbp = 0x82513af90 KDB: enter: panic +# [ thread pid 43886 tid 178779 ] +# Stopped at kdb_enter+0x32: movq $0,0xde5863(%rip) +# db> x/s version +# version: FreeBSD 14.0-CURRENT #0 main-n263953-d7614c010c762: Tue Jul 4 19:29:44 CEST 2023 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO +# db> + +uname -p | grep -Eq "amd64|i386" || exit 0 +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=85a795d15aa54816d63f71f69bfb3a2c61635472 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// Reported-by: syzbot+dce5858451a2329877ff@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <errno.h> +#include <pthread.h> +#include <pwd.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <time.h> +#include <unistd.h> + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void thread_start(void* (*fn)(void*), void* arg) +{ + pthread_t th; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128 << 10); + int i = 0; + for (; i < 100; i++) { + if (pthread_create(&th, &attr, fn, arg) == 0) { + pthread_attr_destroy(&attr); + return; + } + if (errno == EAGAIN) { + usleep(50); + continue; + } + break; + } + exit(1); +} + +typedef struct { + pthread_mutex_t mu; + pthread_cond_t cv; + int state; +} event_t; + +static void event_init(event_t* ev) +{ + if (pthread_mutex_init(&ev->mu, 0)) + exit(1); + if (pthread_cond_init(&ev->cv, 0)) + exit(1); + ev->state = 0; +} + +static void event_reset(event_t* ev) +{ + ev->state = 0; +} + +static void event_set(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + if (ev->state) + exit(1); + ev->state = 1; + pthread_mutex_unlock(&ev->mu); + pthread_cond_broadcast(&ev->cv); +} + +static void event_wait(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + while (!ev->state) + pthread_cond_wait(&ev->cv, &ev->mu); + pthread_mutex_unlock(&ev->mu); +} + +static int event_isset(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static int event_timedwait(event_t* ev, uint64_t timeout) +{ + uint64_t start = current_time_ms(); + uint64_t now = start; + pthread_mutex_lock(&ev->mu); + for (;;) { + if (ev->state) + break; + uint64_t remain = timeout - (now - start); + struct timespec ts; + ts.tv_sec = remain / 1000; + ts.tv_nsec = (remain % 1000) * 1000 * 1000; + pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); + now = current_time_ms(); + if (now - start > timeout) + break; + } + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +struct thread_t { + int created, call; + event_t ready, done; +}; + +static struct thread_t threads[16]; +static void execute_call(int call); +static int running; + +static void* thr(void* arg) +{ + struct thread_t* th = (struct thread_t*)arg; + for (;;) { + event_wait(&th->ready); + event_reset(&th->ready); + execute_call(th->call); + __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); + event_set(&th->done); + } + return 0; +} + +static void loop(void) +{ + int i, call, thread; + for (call = 0; call < 1; call++) { + for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); + thread++) { + struct thread_t* th = &threads[thread]; + if (!th->created) { + th->created = 1; + event_init(&th->ready); + event_init(&th->done); + event_set(&th->done); + thread_start(thr, th); + } + if (!event_isset(&th->done)) + continue; + event_reset(&th->done); + th->call = call; + __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); + event_set(&th->ready); + event_timedwait(&th->done, 50); + break; + } + } + for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) + sleep_ms(1); +} + +void execute_call(int call) +{ + switch (call) { + case 0: + memcpy((void*)0x20000440, "zfs\000", 4); + syscall(SYS_mount, 0x20000440ul, 0ul, 0x8300648ul, 0ul); + break; + } +} +int main(void) +{ + syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); + loop(); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +(cd /tmp; timeout 2m ./$prog) + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/syzkaller.* +exit 0 diff --git a/tools/test/stress2/misc/syzkaller69.sh b/tools/test/stress2/misc/syzkaller69.sh new file mode 100755 index 000000000000..fbaa3e5b9c9c --- /dev/null +++ b/tools/test/stress2/misc/syzkaller69.sh @@ -0,0 +1,494 @@ +#!/bin/sh + +# Fatal trap 12: page fault while in kernel mode +# cpuid = 6; apic id = 06 +# fault virtual address = 0xb8 +# fault code = supervisor read data, page not present +# instruction pointer = 0x20:0xffffffff80d3c17b +# stack pointer = 0x28:0xfffffe00e49fab80 +# frame pointer = 0x28:0xfffffe00e49facc0 +# code segment = base 0x0, limit 0xfffff, type 0x1b +# = DPL 0, pres 1, long 1, def32 0, gran 1 +# processor eflags = interrupt enabled, resume, IOPL = 0 +# current process = 12 (swi1: netisr 0) +# rdi: fffff802d2d8daa0 rsi: fffffe00e49fab48 rdx: ffffffff819d5a90 +# rcx: ffffffff819d5a98 r8: 00000000ffffffff r9: 0000000000000000 +# rax: 0000000000000000 rbx: 0000000000000002 rbp: fffffe00e49facc0 +# r10: fffff802d2d8daa0 r11: 0000000000010000 r12: 0000000000000000 +# r13: fffff802d2d8da80 r14: 0000000000000060 r15: fffff802d2d8dab8 +# trap number = 12 +# panic: page fault +# cpuid = 6 +# time = 1689053386 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00e49fa930 +# vpanic() at vpanic+0x149/frame 0xfffffe00e49fa980 +# panic() at panic+0x43/frame 0xfffffe00e49fa9e0 +# trap_fatal() at trap_fatal+0x40c/frame 0xfffffe00e49faa40 +# trap_pfault() at trap_pfault+0xae/frame 0xfffffe00e49faab0 +# calltrap() at calltrap+0x8/frame 0xfffffe00e49faab0 +# --- trap 0xc, rip = 0xffffffff80d3c17b, rsp = 0xfffffe00e49fab80, rbp = 0xfffffe00e49facc0 --- +# tcp_input_with_port() at tcp_input_with_port+0x70b/frame 0xfffffe00e49facc0 +# tcp6_input_with_port() at tcp6_input_with_port+0x6a/frame 0xfffffe00e49facf0 +# tcp6_input() at tcp6_input+0xb/frame 0xfffffe00e49fad00 +# ip6_input() at ip6_input+0xc97/frame 0xfffffe00e49fade0 +# swi_net() at swi_net+0x19b/frame 0xfffffe00e49fae60 +# ithread_loop() at ithread_loop+0x266/frame 0xfffffe00e49faef0 +# fork_exit() at fork_exit+0x82/frame 0xfffffe00e49faf30 +# fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe00e49faf30 +# --- trap 0, rip = 0, rsp = 0, rbp = 0 --- +# KDB: enter: panic +# [ thread pid 12 tid 100089 ] +# Stopped at kdb_enter+0x32: movq $0,0xde5053(%rip) +# db> x/s version +# version: FreeBSD 14.0-CURRENT #0 main-n264110-43ed91e00bbb1: Tue Jul 11 06:28:21 CEST 2023 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO +# db> + +uname -p | grep -Eq "amd64" || exit 0 +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=44d933862f436b628c77db28122dbfa4e00990aa +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// Reported-by: syzbot+e7d2e451f89fb444319b@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <sys/types.h> + +#include <dirent.h> +#include <errno.h> +#include <pthread.h> +#include <pwd.h> +#include <setjmp.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/resource.h> +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +static unsigned long long procid; + +static __thread int clone_ongoing; +static __thread int skip_segv; +static __thread jmp_buf segv_env; + +static void segv_handler(int sig, siginfo_t* info, void* ctx __unused) +{ + if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) { + exit(sig); + } + uintptr_t addr = (uintptr_t)info->si_addr; + const uintptr_t prog_start = 1 << 20; + const uintptr_t prog_end = 100 << 20; + int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0; + int valid = addr < prog_start || addr > prog_end; + if (sig == SIGBUS) + valid = 1; + if (skip && valid) { + _longjmp(segv_env, 1); + } + exit(sig); +} + +static void install_segv_handler(void) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = segv_handler; + sa.sa_flags = SA_NODEFER | SA_SIGINFO; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); +} + +#define NONFAILING(...) \ + ({ \ + int ok = 1; \ + __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ + if (_setjmp(segv_env) == 0) { \ + __VA_ARGS__; \ + } else \ + ok = 0; \ + __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \ + ok; \ + }) + +static void kill_and_wait(int pid, int* status) +{ + kill(pid, SIGKILL); + while (waitpid(-1, status, 0) != pid) { + } +} + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void use_temporary_dir(void) +{ + char tmpdir_template[] = "./syzkaller.XXXXXX"; + char* tmpdir = mkdtemp(tmpdir_template); + if (!tmpdir) + exit(1); + if (chmod(tmpdir, 0777)) + exit(1); + if (chdir(tmpdir)) + exit(1); +} + +static void reset_flags(const char* filename) +{ + struct stat st; + if (lstat(filename, &st)) + exit(1); + st.st_flags &= ~(SF_NOUNLINK | UF_NOUNLINK | SF_IMMUTABLE | UF_IMMUTABLE | + SF_APPEND | UF_APPEND); + if (lchflags(filename, st.st_flags)) + exit(1); +} +static void __attribute__((noinline)) remove_dir(const char* dir) +{ + DIR* dp = opendir(dir); + if (dp == NULL) { + if (errno == EACCES) { + if (rmdir(dir)) + exit(1); + return; + } + exit(1); + } + struct dirent* ep = 0; + while ((ep = readdir(dp))) { + if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0) + continue; + char filename[FILENAME_MAX]; + snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name); + struct stat st; + if (lstat(filename, &st)) + exit(1); + if (S_ISDIR(st.st_mode)) { + remove_dir(filename); + continue; + } + if (unlink(filename)) { + if (errno == EPERM) { + reset_flags(filename); + reset_flags(dir); + if (unlink(filename) == 0) + continue; + } + exit(1); + } + } + closedir(dp); + while (rmdir(dir)) { + if (errno == EPERM) { + reset_flags(dir); + if (rmdir(dir) == 0) + break; + } + exit(1); + } +} + +static void thread_start(void* (*fn)(void*), void* arg) +{ + pthread_t th; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128 << 10); + int i = 0; + for (; i < 100; i++) { + if (pthread_create(&th, &attr, fn, arg) == 0) { + pthread_attr_destroy(&attr); + return; + } + if (errno == EAGAIN) { + usleep(50); + continue; + } + break; + } + exit(1); +} + +typedef struct { + pthread_mutex_t mu; + pthread_cond_t cv; + int state; +} event_t; + +static void event_init(event_t* ev) +{ + if (pthread_mutex_init(&ev->mu, 0)) + exit(1); + if (pthread_cond_init(&ev->cv, 0)) + exit(1); + ev->state = 0; +} + +static void event_reset(event_t* ev) +{ + ev->state = 0; +} + +static void event_set(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + if (ev->state) + exit(1); + ev->state = 1; + pthread_mutex_unlock(&ev->mu); + pthread_cond_broadcast(&ev->cv); +} + +static void event_wait(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + while (!ev->state) + pthread_cond_wait(&ev->cv, &ev->mu); + pthread_mutex_unlock(&ev->mu); +} + +static int event_isset(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static int event_timedwait(event_t* ev, uint64_t timeout) +{ + uint64_t start = current_time_ms(); + uint64_t now = start; + pthread_mutex_lock(&ev->mu); + for (;;) { + if (ev->state) + break; + uint64_t remain = timeout - (now - start); + struct timespec ts; + ts.tv_sec = remain / 1000; + ts.tv_nsec = (remain % 1000) * 1000 * 1000; + pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); + now = current_time_ms(); + if (now - start > timeout) + break; + } + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static void sandbox_common() +{ + struct rlimit rlim; + rlim.rlim_cur = rlim.rlim_max = 128 << 20; + setrlimit(RLIMIT_AS, &rlim); + rlim.rlim_cur = rlim.rlim_max = 8 << 20; + setrlimit(RLIMIT_MEMLOCK, &rlim); + rlim.rlim_cur = rlim.rlim_max = 1 << 20; + setrlimit(RLIMIT_FSIZE, &rlim); + rlim.rlim_cur = rlim.rlim_max = 1 << 20; + setrlimit(RLIMIT_STACK, &rlim); + rlim.rlim_cur = rlim.rlim_max = 0; + setrlimit(RLIMIT_CORE, &rlim); + rlim.rlim_cur = rlim.rlim_max = 256; + setrlimit(RLIMIT_NOFILE, &rlim); +} + +static void loop(); + +static int do_sandbox_none(void) +{ + sandbox_common(); + loop(); + return 0; +} + +struct thread_t { + int created, call; + event_t ready, done; +}; + +static struct thread_t threads[16]; +static void execute_call(int call); +static int running; + +static void* thr(void* arg) +{ + struct thread_t* th = (struct thread_t*)arg; + for (;;) { + event_wait(&th->ready); + event_reset(&th->ready); + execute_call(th->call); + __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); + event_set(&th->done); + } + return 0; +} + +static void execute_one(void) +{ + int i, call, thread; + for (call = 0; call < 7; call++) { + for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); + thread++) { + struct thread_t* th = &threads[thread]; + if (!th->created) { + th->created = 1; + event_init(&th->ready); + event_init(&th->done); + event_set(&th->done); + thread_start(thr, th); + } + if (!event_isset(&th->done)) + continue; + event_reset(&th->done); + th->call = call; + __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); + event_set(&th->ready); + if (call == 3) + break; + event_timedwait(&th->done, 50); + break; + } + } + for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) + sleep_ms(1); +} + +static void execute_one(void); + +#define WAIT_FLAGS 0 + +static void loop(void) +{ + int iter = 0; + for (;; iter++) { + char cwdbuf[32]; + sprintf(cwdbuf, "./%d", iter); + if (mkdir(cwdbuf, 0777)) + exit(1); + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + if (chdir(cwdbuf)) + exit(1); + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + sleep_ms(1); + if (current_time_ms() - start < 5000) + continue; + kill_and_wait(pid, &status); + break; + } + remove_dir(cwdbuf); + } +} + +uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff}; + +void execute_call(int call) +{ + intptr_t res = 0; + switch (call) { + case 0: + res = syscall(SYS_socket, 0x1cul, 1ul, 0); + if (res != -1) + r[0] = res; + break; + case 1: + NONFAILING(*(uint32_t*)0x20000080 = 9); + syscall(SYS_setsockopt, r[0], 0xffff, 0x10000, 0x20000080ul, 4ul); + break; + case 2: + NONFAILING(*(uint8_t*)0x200000c0 = 0x1c); + NONFAILING(*(uint8_t*)0x200000c1 = 0x1c); + NONFAILING(*(uint16_t*)0x200000c2 = htobe16(0x4e20 + procid * 4)); + NONFAILING(*(uint32_t*)0x200000c4 = 0); + NONFAILING(memset((void*)0x200000c8, 0, 16)); + NONFAILING(*(uint32_t*)0x200000d8 = 0); + syscall(SYS_bind, r[0], 0x200000c0ul, 0x1cul); + break; + case 3: + NONFAILING(*(uint32_t*)0x20000080 = 9); + syscall(SYS_setsockopt, r[0], 0xffff, 0x10000, 0x20000080ul, 4ul); + break; + case 4: + NONFAILING(*(uint32_t*)0x20000040 = 0x72); + NONFAILING(*(uint8_t*)0x20000048 = 0x10); + NONFAILING(*(uint8_t*)0x20000049 = 2); + NONFAILING(*(uint16_t*)0x2000004a = htobe16(0x4e21 + procid * 4)); + NONFAILING(*(uint32_t*)0x2000004c = htobe32(0x7f000001)); + NONFAILING(memset((void*)0x20000050, 0, 8)); + NONFAILING(memset((void*)0x20000058, 0, 112)); + syscall(SYS_setsockopt, r[0], 0, 0x51, 0x20000040ul, 0x88ul); + break; + case 5: + res = syscall(SYS_socket, 0x1cul, 1ul, 0); + if (res != -1) + r[1] = res; + break; + case 6: + NONFAILING(*(uint8_t*)0x20000140 = 0x1c); + NONFAILING(*(uint8_t*)0x20000141 = 0x1c); + NONFAILING(*(uint16_t*)0x20000142 = htobe16(0x4e20 + procid * 4)); + NONFAILING(*(uint32_t*)0x20000144 = 0); + NONFAILING(memset((void*)0x20000148, 0, 16)); + NONFAILING(*(uint32_t*)0x20000158 = 0); + syscall(SYS_connect, r[1], 0x20000140ul, 0x1cul); + break; + } +} +int main(void) +{ + syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); + install_segv_handler(); + for (procid = 0; procid < 4; procid++) { + if (fork() == 0) { + use_temporary_dir(); + do_sandbox_none(); + } + } + sleep(1000000); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +(cd ../testcases/swap; ./swap -t 2m -i 10 -l 100 > /dev/null 2>&1) & + +(cd /tmp; timeout 2m ./$prog) +wait + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/syzkaller.* +exit 0 diff --git a/tools/test/stress2/misc/syzkaller7.sh b/tools/test/stress2/misc/syzkaller7.sh index f43747006862..c03a47d8b2d2 100755 --- a/tools/test/stress2/misc/syzkaller7.sh +++ b/tools/test/stress2/misc/syzkaller7.sh @@ -80,7 +80,7 @@ static void execute_one(void); static void loop(void) { - int iter; + int iter __unused; for (iter = 0;; iter++) { int pid = fork(); if (pid < 0) diff --git a/tools/test/stress2/misc/syzkaller70.sh b/tools/test/stress2/misc/syzkaller70.sh new file mode 100755 index 000000000000..7f63da7f6475 --- /dev/null +++ b/tools/test/stress2/misc/syzkaller70.sh @@ -0,0 +1,302 @@ +#!/bin/sh + +# db:1:pho1> bt +# Tracing pid 5640 tid 102468 td 0xfffffe00e4d26ac0 +# kdb_enter() at kdb_enter+0x32/frame 0xfffffe010dbcf260 +# vpanic() at vpanic+0x163/frame 0xfffffe010dbcf390 +# panic() at panic+0x43/frame 0xfffffe010dbcf3f0 +# vm_map_insert1() at vm_map_insert1+0x147/frame 0xfffffe010dbcf4a0 +# vm_map_insert() at vm_map_insert+0x69/frame 0xfffffe010dbcf510 +# vm_map_growstack() at vm_map_growstack+0x90e/frame 0xfffffe010dbcf650 +# vm_map_lookup() at vm_map_lookup+0x15f/frame 0xfffffe010dbcf6e0 +# vm_fault() at vm_fault+0x12f/frame 0xfffffe010dbcf820 +# vm_fault_trap() at vm_fault_trap+0x6f/frame 0xfffffe010dbcf860 +# trap_pfault() at trap_pfault+0x24a/frame 0xfffffe010dbcf8d0 +# calltrap() at calltrap+0x8/frame 0xfffffe010dbcf8d0 +# --- trap 0xc, rip = 0xffffffff81057a06, rsp = 0xfffffe010dbcf9a0, rbp = 0xfffffe010dbcf9a0 --- +# copyin_nosmap_erms() at copyin_nosmap_erms+0x156/frame 0xfffffe010dbcf9a0 +# uiomove_fromphys() at uiomove_fromphys+0x145/frame 0xfffffe010dbcfa10 +# uiomove_object_page() at uiomove_object_page+0x1dc/frame 0xfffffe010dbcfa70 +# uiomove_object() at uiomove_object+0xa4/frame 0xfffffe010dbcfac0 +# tmpfs_write() at tmpfs_write+0xe4/frame 0xfffffe010dbcfb10 +# VOP_WRITE_APV() at VOP_WRITE_APV+0xcf/frame 0xfffffe010dbcfc20 +# vn_write() at vn_write+0x2f4/frame 0xfffffe010dbcfcb0 +# vn_io_fault() at vn_io_fault+0x1e2/frame 0xfffffe010dbcfd40 +# dofilewrite() at dofilewrite+0x82/frame 0xfffffe010dbcfd90 +# kern_pwritev() at kern_pwritev+0x64/frame 0xfffffe010dbcfdd0 +# sys_pwritev() at sys_pwritev+0x3a/frame 0xfffffe010dbcfe00 +# amd64_syscall() at amd64_syscall+0x14f/frame 0xfffffe010dbcff30 +# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe010dbcff30 +# --- syscall (0, FreeBSD ELF64, syscall), rip = 0x822d56fca, rsp = 0x824255f58, rbp = 0x824255f90 --- +# FreeBSD 14.0-ALPHA1 #1 main-n264742-81b41b2ef5bfd5-dirty: Tue Aug 15 19:52:50 CEST 2023 + +uname -p | grep -Eq "amd64" || exit 0 +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=4c33ed3d5a9072d2ccaec3b2ef7a129f0997f477 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// Reported-by: syzbot+c325d6a75e4fd0a68714@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <sys/types.h> + +#include <errno.h> +#include <pthread.h> +#include <pwd.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +static void kill_and_wait(int pid, int* status) +{ + kill(pid, SIGKILL); + while (waitpid(-1, status, 0) != pid) { + } +} + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void thread_start(void* (*fn)(void*), void* arg) +{ + pthread_t th; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128 << 10); + int i = 0; + for (; i < 100; i++) { + if (pthread_create(&th, &attr, fn, arg) == 0) { + pthread_attr_destroy(&attr); + return; + } + if (errno == EAGAIN) { + usleep(50); + continue; + } + break; + } + exit(1); +} + +typedef struct { + pthread_mutex_t mu; + pthread_cond_t cv; + int state; +} event_t; + +static void event_init(event_t* ev) +{ + if (pthread_mutex_init(&ev->mu, 0)) + exit(1); + if (pthread_cond_init(&ev->cv, 0)) + exit(1); + ev->state = 0; +} + +static void event_reset(event_t* ev) +{ + ev->state = 0; +} + +static void event_set(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + if (ev->state) + exit(1); + ev->state = 1; + pthread_mutex_unlock(&ev->mu); + pthread_cond_broadcast(&ev->cv); +} + +static void event_wait(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + while (!ev->state) + pthread_cond_wait(&ev->cv, &ev->mu); + pthread_mutex_unlock(&ev->mu); +} + +static int event_isset(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static int event_timedwait(event_t* ev, uint64_t timeout) +{ + uint64_t start = current_time_ms(); + uint64_t now = start; + pthread_mutex_lock(&ev->mu); + for (;;) { + if (ev->state) + break; + uint64_t remain = timeout - (now - start); + struct timespec ts; + ts.tv_sec = remain / 1000; + ts.tv_nsec = (remain % 1000) * 1000 * 1000; + pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); + now = current_time_ms(); + if (now - start > timeout) + break; + } + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +struct thread_t { + int created, call; + event_t ready, done; +}; + +static struct thread_t threads[16]; +static void execute_call(int call); +static int running; + +static void* thr(void* arg) +{ + struct thread_t* th = (struct thread_t*)arg; + for (;;) { + event_wait(&th->ready); + event_reset(&th->ready); + execute_call(th->call); + __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); + event_set(&th->done); + } + return 0; +} + +static void execute_one(void) +{ + int i, call, thread; + for (call = 0; call < 4; call++) { + for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); + thread++) { + struct thread_t* th = &threads[thread]; + if (!th->created) { + th->created = 1; + event_init(&th->ready); + event_init(&th->done); + event_set(&th->done); + thread_start(thr, th); + } + if (!event_isset(&th->done)) + continue; + event_reset(&th->done); + th->call = call; + __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); + event_set(&th->ready); + event_timedwait(&th->done, 50); + break; + } + } + for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) + sleep_ms(1); +} + +static void execute_one(void); + +#define WAIT_FLAGS 0 + +static void loop(void) +{ + int iter __unused = 0; + for (;; iter++) { + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + sleep_ms(1); + if (current_time_ms() - start < 5000) + continue; + kill_and_wait(pid, &status); + break; + } + } +} + +uint64_t r[1] = {0xffffffffffffffff}; + +void execute_call(int call) +{ + intptr_t res = 0; + switch (call) { + case 0: + memcpy((void*)0x20000240, "./file0\000", 8); + res = syscall(SYS_open, /*file=*/0x20000240ul, + /*flags=*/0x40000400000002c2ul, /*mode=*/0ul); + if (res != -1) + r[0] = res; + break; + case 1: + *(uint64_t*)0x20000080 = 0x200006c0; + *(uint64_t*)0x20000088 = 0x100000; + syscall(SYS_pwritev, /*fd=*/r[0], /*vec=*/0x20000080ul, /*vlen=*/1ul, + /*off=*/0ul); + break; + case 2: + syscall(SYS_mmap, /*addr=*/0x20000000ul, /*len=*/0x200000ul, /*prot=*/3ul, + /*flags=*/0x410ul, /*fd=*/-1, /*offset=*/0ul); + break; + case 3: + syscall(SYS_mmap, /*addr=*/0x2000c000ul, /*len=*/0x4000ul, /*prot=*/0ul, + /*flags=*/0x2010ul, /*fd=*/-1, /*offset=*/0ul); + break; + } +} +int main(void) +{ + syscall(SYS_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=*/7ul, + /*flags=*/0x1012ul, /*fd=*/-1, /*offset=*/0ul); + loop(); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +mount | grep -q "on $mntpoint " && umount $mntpoint +mount -o size=10m -t tmpfs dummy $mntpoint + +cd $mntpoint +for i in `jot 20`; do + timeout 3m /tmp/$prog & +done +wait +cd - + +umount $mntpoint +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core +exit 0 diff --git a/tools/test/stress2/misc/syzkaller71.sh b/tools/test/stress2/misc/syzkaller71.sh new file mode 100755 index 000000000000..58cf7eeb5825 --- /dev/null +++ b/tools/test/stress2/misc/syzkaller71.sh @@ -0,0 +1,171 @@ +#!/bin/sh + +# panic: Counter goes negative +# cpuid = 4 +# time = 1694583637 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe01bac2a960 +# vpanic() at vpanic+0x132/frame 0xfffffe01bac2aa90 +# panic() at panic+0x43/frame 0xfffffe01bac2aaf0 +# sctp_inpcb_free() at sctp_inpcb_free+0xf28/frame 0xfffffe01bac2ab60 +# sctp_close() at sctp_close+0xc0/frame 0xfffffe01bac2abb0 +# soclose() at soclose+0x154/frame 0xfffffe01bac2ac10 +# _fdrop() at _fdrop+0x1b/frame 0xfffffe01bac2ac30 +# closef() at closef+0x1e3/frame 0xfffffe01bac2acc0 +# fdescfree() at fdescfree+0x41a/frame 0xfffffe01bac2ad80 +# exit1() at exit1+0x4a1/frame 0xfffffe01bac2adf0 +# sys_exit() at sys_exit+0xd/frame 0xfffffe01bac2ae00 +# amd64_syscall() at amd64_syscall+0x14f/frame 0xfffffe01bac2af30 +# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe01bac2af30 +# --- syscall (1, FreeBSD ELF64, exit), rip = 0x824db2f4a, rsp = 0x8211862b8, rbp = 0x8211862d0 --- +# KDB: enter: pani[ thread pid 9676 tid 346853 ] +# Stopped at kdb_enter+0x32: movq $0,0xe27583(%rip) +# db> x/s version +# version: FreeBSD 15.0-CURRENT #0 main-n265298-10db91ecec98b1: Tue Sep 12 12:16:45 CEST 2023 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO +# db> + +uname -p | grep -Eq "amd64" || exit 0 +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=d8a54d453b8e643b807a5c3c56728561f01c0fde +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// Reported-by: syzbot+d4e1d30d578891245f59@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <sys/types.h> + +#include <pwd.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +static unsigned long long procid; + +static void kill_and_wait(int pid, int* status) +{ + kill(pid, SIGKILL); + while (waitpid(-1, status, 0) != pid) { + } +} + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void execute_one(void); + +#define WAIT_FLAGS 0 + +static void loop(void) +{ + int iter __unused = 0; + for (;; iter++) { + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + sleep_ms(1); + if (current_time_ms() - start < 5000) + continue; + kill_and_wait(pid, &status); + break; + } + } +} + +uint64_t r[1] = {0xffffffffffffffff}; + +void execute_one(void) +{ + intptr_t res = 0; + res = syscall(SYS_socket, 0x1cul, 1ul, 0x84); + if (res != -1) + r[0] = res; + *(uint8_t*)0x20000040 = 0x1c; + *(uint8_t*)0x20000041 = 0x1c; + *(uint16_t*)0x20000042 = htobe16(0x4e22 + procid * 4); + *(uint32_t*)0x20000044 = 0; + *(uint64_t*)0x20000048 = htobe64(0); + *(uint64_t*)0x20000050 = htobe64(1); + *(uint32_t*)0x20000058 = 0; + syscall(SYS_bind, r[0], 0x20000040ul, 0x1cul); + *(uint8_t*)0x20000180 = 0x1c; + *(uint8_t*)0x20000181 = 0x1c; + *(uint16_t*)0x20000182 = htobe16(0x4e22 + procid * 4); + *(uint32_t*)0x20000184 = 0; + *(uint64_t*)0x20000188 = htobe64(0); + *(uint64_t*)0x20000190 = htobe64(1); + *(uint32_t*)0x20000198 = 0; + syscall(SYS_connect, r[0], 0x20000180ul, 0x1cul); + *(uint32_t*)0x20000300 = 0x80000021; + syscall(SYS_setsockopt, r[0], 0x84, 0x1b, 0x20000300ul, 4ul); + memset((void*)0x20000480, 163, 1); + syscall(SYS_sendto, r[0], 0x20000480ul, 0xfffffe5cul, 0x188ul, 0ul, 0ul); + *(uint16_t*)0x200000c0 = 0; + *(uint16_t*)0x200000c2 = 0x200; + *(uint32_t*)0x200000c4 = 0; + *(uint32_t*)0x200000c8 = 0; + *(uint32_t*)0x200000cc = 0; + syscall(SYS_setsockopt, r[0], 0x84, 0x21, 0x200000c0ul, 0x10ul); + syscall(SYS_shutdown, r[0], 0ul); + syscall(SYS_writev, r[0], 0ul, 0ul); +} +int main(void) +{ + syscall(SYS_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x1012ul, -1, 0ul); + for (procid = 0; procid < 4; procid++) { + if (fork() == 0) { + loop(); + } + } + sleep(1000000); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +mount | grep -q "on $mntpoint " && umount $mntpoint +mount -o size=10m -t tmpfs dummy $mntpoint + +cd $mntpoint +for i in `jot 20`; do + timeout 3m /tmp/$prog & +done +wait +cd - + +umount $mntpoint +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core +exit 0 diff --git a/tools/test/stress2/misc/syzkaller72.sh b/tools/test/stress2/misc/syzkaller72.sh new file mode 100755 index 000000000000..6dd69987a913 --- /dev/null +++ b/tools/test/stress2/misc/syzkaller72.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +# panic: sbflush_internal: ccc 0 mb 0xfffff8004eee95f0 mbcnt 0 +# cpuid = 9 +# time = 1704448830 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe016a2ccb70 +# vpanic() at vpanic+0x131/frame 0xfffffe016a2ccca0 +# panic() at panic+0x43/frame 0xfffffe016a2ccd00 +# sbrelease_internal() at sbrelease_internal+0x7c/frame 0xfffffe016a2ccd20 +# sbrelease() at sbrelease+0x5e/frame 0xfffffe016a2ccd50 +# sorflush() at sorflush+0x66/frame 0xfffffe016a2ccd70 +# soshutdown() at soshutdown+0x105/frame 0xfffffe016a2ccdb0 +# kern_shutdown() at kern_shutdown+0x60/frame 0xfffffe016a2ccdf0 +# ia32_syscall() at ia32_syscall+0x154/frame 0xfffffe016a2ccf30 +# int0x80_syscall_common() at int0x80_syscall_common+0x9c/frame 0xffffdb44 +# KDB: enter: panic +# [ thread pid 4927 tid 100275 ] +# Stopped at : movq $0,0xe37212(%rip) +# db> x/s version +# FreeBSD 15.0-CURRENT #0 main-n267418-24cd5c26fe3e: Fri Jan 5 08:21:43 CET 2024 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO +# db> + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=a9e90e96743f3e20b4a66d9d0d4c08c57ea8cc7f +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// Reported-by: syzbot+a58e1615881c01a51653@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <pwd.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <unistd.h> + +uint64_t r[1] = {0xffffffffffffffff}; + +int main(void) +{ + syscall(SYS_mmap, /*addr=*/0x10000000, /*len=*/0x1000000, /*prot=*/7, + /*flags=*/0x1012, /*fd=*/-1, /*offset=*/0); + intptr_t res = 0; + res = syscall(SYS_socket, /*domain=*/0x26, /*type=*/2, /*proto=*/0); + if (res != -1) + r[0] = res; + syscall(SYS_shutdown, /*fd=*/(intptr_t)r[0], /*how=*/0); + return 0; +} +EOF +mycc -o /tmp/$prog -m32 -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +start=`date +%s` +while [ $((`date +%s` - start)) -lt 120 ]; do + timeout 3m /tmp/$prog +done + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core +exit 0 diff --git a/tools/test/stress2/misc/syzkaller73.sh b/tools/test/stress2/misc/syzkaller73.sh new file mode 100755 index 000000000000..776ace385f21 --- /dev/null +++ b/tools/test/stress2/misc/syzkaller73.sh @@ -0,0 +1,537 @@ +#!/bin/sh + +# No issues seen (Looks a bit like syzkaller43.sh) + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=cf4c0a08d26692dc8f22b0fcc50db08fd17dd709 +// autogenerated by syzkaller (https://github.com/google/syzkaller) + +#define _GNU_SOURCE + +#include <sys/types.h> + +#include <dirent.h> +#include <errno.h> +#include <pthread.h> +#include <pwd.h> +#include <setjmp.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/resource.h> +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +#ifndef SYS_aio_writev +#define SYS_aio_writev 578 +#endif + +static __thread int clone_ongoing; +static __thread int skip_segv; +static __thread jmp_buf segv_env; + +static void segv_handler(int sig, siginfo_t* info, void* ctx __unused) +{ + if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) { + exit(sig); + } + uintptr_t addr = (uintptr_t)info->si_addr; + const uintptr_t prog_start = 1 << 20; + const uintptr_t prog_end = 100 << 20; + int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0; + int valid = addr < prog_start || addr > prog_end; + if (sig == SIGBUS) + valid = 1; + if (skip && valid) { + _longjmp(segv_env, 1); + } + exit(sig); +} + +static void install_segv_handler(void) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = segv_handler; + sa.sa_flags = SA_NODEFER | SA_SIGINFO; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); +} + +#define NONFAILING(...) \ + ({ \ + int ok = 1; \ + __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ + if (_setjmp(segv_env) == 0) { \ + __VA_ARGS__; \ + } else \ + ok = 0; \ + __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \ + ok; \ + }) + +static void kill_and_wait(int pid, int* status) +{ + kill(pid, SIGKILL); + while (waitpid(-1, status, 0) != pid) { + } +} + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void use_temporary_dir(void) +{ + char tmpdir_template[] = "./syzkaller.XXXXXX"; + char* tmpdir = mkdtemp(tmpdir_template); + if (!tmpdir) + exit(1); + if (chmod(tmpdir, 0777)) + exit(1); + if (chdir(tmpdir)) + exit(1); +} + +static void reset_flags(const char* filename) +{ + struct stat st; + if (lstat(filename, &st)) + exit(1); + st.st_flags &= ~(SF_NOUNLINK | UF_NOUNLINK | SF_IMMUTABLE | UF_IMMUTABLE | + SF_APPEND | UF_APPEND); + if (lchflags(filename, st.st_flags)) + exit(1); +} +static void __attribute__((noinline)) remove_dir(const char* dir) +{ + DIR* dp = opendir(dir); + if (dp == NULL) { + if (errno == EACCES) { + if (rmdir(dir)) + exit(1); + return; + } + exit(1); + } + struct dirent* ep = 0; + while ((ep = readdir(dp))) { + if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0) + continue; + char filename[FILENAME_MAX]; + snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name); + struct stat st; + if (lstat(filename, &st)) + exit(1); + if (S_ISDIR(st.st_mode)) { + remove_dir(filename); + continue; + } + if (unlink(filename)) { + if (errno == EPERM) { + reset_flags(filename); + reset_flags(dir); + if (unlink(filename) == 0) + continue; + } + exit(1); + } + } + closedir(dp); + while (rmdir(dir)) { + if (errno == EPERM) { + reset_flags(dir); + if (rmdir(dir) == 0) + break; + } + exit(1); + } +} + +static void thread_start(void* (*fn)(void*), void* arg) +{ + pthread_t th; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128 << 10); + int i = 0; + for (; i < 100; i++) { + if (pthread_create(&th, &attr, fn, arg) == 0) { + pthread_attr_destroy(&attr); + return; + } + if (errno == EAGAIN) { + usleep(50); + continue; + } + break; + } + exit(1); +} + +typedef struct { + pthread_mutex_t mu; + pthread_cond_t cv; + int state; +} event_t; + +static void event_init(event_t* ev) +{ + if (pthread_mutex_init(&ev->mu, 0)) + exit(1); + if (pthread_cond_init(&ev->cv, 0)) + exit(1); + ev->state = 0; +} + +static void event_reset(event_t* ev) +{ + ev->state = 0; +} + +static void event_set(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + if (ev->state) + exit(1); + ev->state = 1; + pthread_mutex_unlock(&ev->mu); + pthread_cond_broadcast(&ev->cv); +} + +static void event_wait(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + while (!ev->state) + pthread_cond_wait(&ev->cv, &ev->mu); + pthread_mutex_unlock(&ev->mu); +} + +static int event_isset(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static int event_timedwait(event_t* ev, uint64_t timeout) +{ + uint64_t start = current_time_ms(); + uint64_t now = start; + pthread_mutex_lock(&ev->mu); + for (;;) { + if (ev->state) + break; + uint64_t remain = timeout - (now - start); + struct timespec ts; + ts.tv_sec = remain / 1000; + ts.tv_nsec = (remain % 1000) * 1000 * 1000; + pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); + now = current_time_ms(); + if (now - start > timeout) + break; + } + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static void sandbox_common() +{ + struct rlimit rlim; + rlim.rlim_cur = rlim.rlim_max = 128 << 20; + setrlimit(RLIMIT_AS, &rlim); + rlim.rlim_cur = rlim.rlim_max = 8 << 20; + setrlimit(RLIMIT_MEMLOCK, &rlim); + rlim.rlim_cur = rlim.rlim_max = 1 << 20; + setrlimit(RLIMIT_FSIZE, &rlim); + rlim.rlim_cur = rlim.rlim_max = 1 << 20; + setrlimit(RLIMIT_STACK, &rlim); + rlim.rlim_cur = rlim.rlim_max = 0; + setrlimit(RLIMIT_CORE, &rlim); + rlim.rlim_cur = rlim.rlim_max = 256; + setrlimit(RLIMIT_NOFILE, &rlim); +} + +static void loop(); + +static int do_sandbox_none(void) +{ + sandbox_common(); + loop(); + return 0; +} + +struct thread_t { + int created, call; + event_t ready, done; +}; + +static struct thread_t threads[16]; +static void execute_call(int call); +static int running; + +static void* thr(void* arg) +{ + struct thread_t* th = (struct thread_t*)arg; + for (;;) { + event_wait(&th->ready); + event_reset(&th->ready); + execute_call(th->call); + __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); + event_set(&th->done); + } + return 0; +} + +static void execute_one(void) +{ + if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { + } + int i, call, thread; + for (call = 0; call < 24; call++) { + for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); + thread++) { + struct thread_t* th = &threads[thread]; + if (!th->created) { + th->created = 1; + event_init(&th->ready); + event_init(&th->done); + event_set(&th->done); + thread_start(thr, th); + } + if (!event_isset(&th->done)) + continue; + event_reset(&th->done); + th->call = call; + __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); + event_set(&th->ready); + event_timedwait(&th->done, 50); + break; + } + } + for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) + sleep_ms(1); +} + +static void execute_one(void); + +#define WAIT_FLAGS 0 + +static void loop(void) +{ + int iter = 0; + for (;; iter++) { + char cwdbuf[32]; + sprintf(cwdbuf, "./%d", iter); + if (mkdir(cwdbuf, 0777)) + exit(1); + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + if (chdir(cwdbuf)) + exit(1); + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + sleep_ms(10); + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + if (current_time_ms() - start < 5000) + continue; + kill_and_wait(pid, &status); + break; + } + remove_dir(cwdbuf); + } +} + +uint64_t r[3] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}; + +void execute_call(int call) +{ + intptr_t res = 0; + switch (call) { + case 0: + res = syscall(SYS_socket, /*domain=AF_INET6*/ 0x1cul, + /*type=SOCK_STREAM*/ 1ul, /*proto=*/0); + if (res != -1) + r[0] = res; + break; + case 1: + NONFAILING(*(uint32_t*)0x200000c0 = 0x101); + syscall(SYS_setsockopt, /*fd=*/r[0], /*level=*/0xffff, + /*optname=SO_SNDBUF*/ 0x1001, /*optval=*/0x200000c0ul, + /*optlen=*/4ul); + break; + case 2: + NONFAILING(*(uint8_t*)0x20000140 = 0x1c); + NONFAILING(*(uint8_t*)0x20000141 = 0x1c); + NONFAILING(*(uint16_t*)0x20000142 = htobe16(0x4e23)); + NONFAILING(*(uint32_t*)0x20000144 = 0); + NONFAILING(memset((void*)0x20000148, 0, 16)); + NONFAILING(*(uint32_t*)0x20000158 = 0); + syscall(SYS_bind, /*fd=*/r[0], /*addr=*/0x20000140ul, /*addrlen=*/0x1cul); + break; + case 3: + NONFAILING(*(uint32_t*)0x20000500 = r[0]); + NONFAILING(*(uint64_t*)0x20000508 = 0); + NONFAILING(*(uint64_t*)0x20000510 = 0); + NONFAILING(*(uint64_t*)0x20000518 = 0); + NONFAILING(*(uint32_t*)0x20000520 = 4); + NONFAILING(*(uint32_t*)0x20000524 = 0); + NONFAILING(*(uint64_t*)0x20000528 = 0); + NONFAILING(*(uint32_t*)0x20000530 = 0); + NONFAILING(*(uint32_t*)0x20000534 = 4); + NONFAILING(*(uint64_t*)0x20000538 = 0x822e); + NONFAILING(*(uint64_t*)0x20000540 = 0); + NONFAILING(*(uint64_t*)0x20000548 = 0x20000340); + NONFAILING(*(uint32_t*)0x20000550 = 0); + NONFAILING(*(uint32_t*)0x20000554 = 0); + NONFAILING(*(uint64_t*)0x20000558 = 0xfffffffffffffffe); + NONFAILING(*(uint64_t*)0x20000560 = 0); + NONFAILING(*(uint64_t*)0x20000568 = 0x20000380); + NONFAILING(memcpy((void*)0x20000380, "\x3c\x88\x80", 3)); + syscall(SYS_aio_writev, /*iocb=*/0x20000500ul); + break; + case 4: + NONFAILING(*(uint8_t*)0x20000180 = 0x1c); + NONFAILING(*(uint8_t*)0x20000181 = 0x1c); + NONFAILING(*(uint16_t*)0x20000182 = htobe16(0x4e23)); + NONFAILING(*(uint32_t*)0x20000184 = 0); + NONFAILING(memset((void*)0x20000188, 0, 16)); + NONFAILING(*(uint32_t*)0x20000198 = 0); + syscall(SYS_connect, /*fd=*/r[0], /*addr=*/0x20000180ul, + /*addrlen=*/0x1cul); + break; + case 5: + NONFAILING(memset((void*)0x20000200, 14, 1)); + syscall(SYS_sendto, /*fd=*/r[0], /*buf=*/0x20000200ul, /*len=*/0xff66ul, + /*f=*/0ul, /*addr=*/0ul, /*addrlen=*/0ul); + break; + case 6: + syscall(SYS_sendmsg, /*fd=*/r[0], /*msg=*/0ul, /*f=*/0ul); + break; + case 7: + syscall(SYS_socket, /*domain=AF_INET*/ 2ul, /*type=SOCK_STREAM*/ 1ul, + /*proto=*/0); + break; + case 8: + res = syscall(SYS_socket, /*domain=*/2ul, /*type=SOCK_SEQPACKET*/ 5ul, + /*proto=*/0x84); + if (res != -1) + r[1] = res; + break; + case 9: + syscall(SYS_openat, /*fd=*/0xffffffffffffff9cul, /*file=*/0ul, + /*flags=O_RDWR*/ 2ul, /*mode=*/0ul); + break; + case 10: + syscall(SYS_openat, /*fd=*/0xffffffffffffff9cul, /*file=*/0ul, + /*flags=O_RDWR*/ 2ul, /*mode=*/0ul); + break; + case 11: + syscall(SYS_socket, /*domain=*/2ul, /*type=SOCK_SEQPACKET*/ 5ul, + /*proto=*/0x84); + break; + case 12: + syscall(SYS_socket, /*domain=*/0x1cul, /*type=*/1ul, /*proto=*/0); + break; + case 13: + syscall(SYS_shutdown, /*fd=*/-1, /*how=*/0ul); + break; + case 14: + syscall(SYS_shutdown, /*fd=*/-1, /*how=*/0ul); + break; + case 15: + syscall(SYS_sendto, /*fd=*/-1, /*buf=*/0ul, /*len=*/0ul, /*f=*/0ul, + /*addr=*/0ul, /*addrlen=*/0ul); + break; + case 16: + syscall(SYS_sendmsg, /*fd=*/-1, /*msg=*/0ul, /*f=*/0ul); + break; + case 17: + syscall(SYS_rfork, /*flags=RFMEM|RFTHREAD|RFCFDG|RFNOWAIT*/ 0x3060ul); + break; + case 18: + syscall(SYS_rfork, /*flags=RFMEM|RFTHREAD|RFCFDG|RFNOWAIT*/ 0x3060ul); + break; + case 19: + syscall(SYS_openat, /*fd=*/0xffffff9cul, /*file=*/0ul, + /*flags=O_APPEND*/ 8ul, /*mode=*/0ul); + break; + case 20: + syscall(SYS_openat, /*fd=*/0xffffff9cul, /*file=*/0ul, + /*flags=O_APPEND*/ 8ul, /*mode=*/0ul); + break; + case 21: + syscall(SYS_connect, /*fd=*/r[1], /*addr=*/0ul, /*addrlen=*/0ul); + break; + case 22: + res = syscall(SYS_socket, /*domain=*/2ul, /*type=SOCK_STREAM*/ 1ul, + /*proto=*/0x84); + if (res != -1) + r[2] = res; + break; + case 23: + NONFAILING(*(uint32_t*)0x200001c0 = 0); + syscall(SYS_getsockopt, /*fd=*/r[2], /*level=*/0x84, /*opt=*/0xc, + /*val=*/0ul, /*len=*/0x200001c0ul); + break; + } +} +int main(void) +{ + syscall(SYS_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, + /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, + /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul, /*fd=*/-1, + /*offset=*/0ul); + const char* reason; + (void)reason; + install_segv_handler(); + use_temporary_dir(); + do_sandbox_none(); + return 0; +} +EOF +mycc -o /tmp/$prog -m32 -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +(cd ../testcases/swap; ./swap -t 2m -i 10 -l 100 > /dev/null 2>&1) & +sleep 1 +cd /tmp +start=`date +%s` +while [ $((`date +%s` - start)) -lt 120 ]; do + timeout 3m /tmp/$prog > /dev/null 2>&1 +done +while pkill swap; do :; done +wait + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core +exit 0 diff --git a/tools/test/stress2/misc/syzkaller74.sh b/tools/test/stress2/misc/syzkaller74.sh new file mode 100755 index 000000000000..886c6047585b --- /dev/null +++ b/tools/test/stress2/misc/syzkaller74.sh @@ -0,0 +1,469 @@ +#!/bin/sh + +# panic: _pctrie_lookup_node: freed node in iter path +# cpuid = 0 +# time = 1745029155 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe01085d2a30 +# vpanic() at vpanic+0x136/frame 0xfffffe01085d2b60 +# panic() at panic+0x43/frame 0xfffffe01085d2bc0 +# pctrie_iter_lookup_ge() at pctrie_iter_lookup_ge+0x166/frame 0xfffffe01085d2bd0 +# vm_object_page_clean() at vm_object_page_clean+0x22e/frame 0xfffffe01085d2c50 +# vnode_pager_clean_async() at vnode_pager_clean_async+0x48/frame 0xfffffe01085d2c70 +# vinactivef() at vinactivef+0x75/frame 0xfffffe01085d2cb0 +# vput_final() at vput_final+0x29c/frame 0xfffffe01085d2d00 +# vm_map_process_deferred() at vm_map_process_deferred+0xa9/frame 0xfffffe01085d2d20 +# vm_map_remove() at vm_map_remove+0xcb/frame 0xfffffe01085d2d50 +# vmspace_exit() at vmspace_exit+0xa8/frame 0xfffffe01085d2d80 +# exit1() at exit1+0x533/frame 0xfffffe01085d2df0 +# sys_exit() at sys_exit+0xd/frame 0xfffffe01085d2e00 +# amd64_syscall() at amd64_syscall+0x15a/frame 0xfffffe01085d2f30 +# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe01085d2f30 +# --- syscall (1, FreeBSD ELF64, exit), rip = 0x822a9b7fa, rsp = 0x8202b4de8, rbp = 0x8202b4e00 --- +# KDB: enter: panic +# [ thread pid 21141 tid 100328 ] +# Stopped at kdb_enter+0x33: movq $0,0x104d862(%rip) +# db> + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=8658267170f7f61f4317bb04c1fe9add379ffaf4 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// syzbot+b5f9ebf4c2c63a5db681@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <sys/types.h> + +#include <dirent.h> +#include <errno.h> +#include <pthread.h> +#include <pwd.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/resource.h> +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +static void kill_and_wait(int pid, int* status) +{ + kill(pid, SIGKILL); + while (waitpid(-1, status, 0) != pid) { + } +} + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void use_temporary_dir(void) +{ + char tmpdir_template[] = "./syzkaller.XXXXXX"; + char* tmpdir = mkdtemp(tmpdir_template); + if (!tmpdir) + exit(1); + if (chmod(tmpdir, 0777)) + exit(1); + if (chdir(tmpdir)) + exit(1); +} + +static void reset_flags(const char* filename) +{ + struct stat st; + if (lstat(filename, &st)) + exit(1); + st.st_flags &= ~(SF_NOUNLINK | UF_NOUNLINK | SF_IMMUTABLE | UF_IMMUTABLE | + SF_APPEND | UF_APPEND); + if (lchflags(filename, st.st_flags)) + exit(1); +} +static void __attribute__((noinline)) remove_dir(const char* dir) +{ + DIR* dp = opendir(dir); + if (dp == NULL) { + if (errno == EACCES) { + if (rmdir(dir)) + exit(1); + return; + } + exit(1); + } + struct dirent* ep = 0; + while ((ep = readdir(dp))) { + if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0) + continue; + char filename[FILENAME_MAX]; + snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name); + struct stat st; + if (lstat(filename, &st)) + exit(1); + if (S_ISDIR(st.st_mode)) { + remove_dir(filename); + continue; + } + if (unlink(filename)) { + if (errno == EPERM) { + reset_flags(filename); + reset_flags(dir); + if (unlink(filename) == 0) + continue; + } + exit(1); + } + } + closedir(dp); + while (rmdir(dir)) { + if (errno == EPERM) { + reset_flags(dir); + if (rmdir(dir) == 0) + break; + } + exit(1); + } +} + +static void thread_start(void* (*fn)(void*), void* arg) +{ + pthread_t th; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128 << 10); + int i = 0; + for (; i < 100; i++) { + if (pthread_create(&th, &attr, fn, arg) == 0) { + pthread_attr_destroy(&attr); + return; + } + if (errno == EAGAIN) { + usleep(50); + continue; + } + break; + } + exit(1); +} + +typedef struct { + pthread_mutex_t mu; + pthread_cond_t cv; + int state; +} event_t; + +static void event_init(event_t* ev) +{ + if (pthread_mutex_init(&ev->mu, 0)) + exit(1); + if (pthread_cond_init(&ev->cv, 0)) + exit(1); + ev->state = 0; +} + +static void event_reset(event_t* ev) +{ + ev->state = 0; +} + +static void event_set(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + if (ev->state) + exit(1); + ev->state = 1; + pthread_mutex_unlock(&ev->mu); + pthread_cond_broadcast(&ev->cv); +} + +static void event_wait(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + while (!ev->state) + pthread_cond_wait(&ev->cv, &ev->mu); + pthread_mutex_unlock(&ev->mu); +} + +static int event_isset(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static int event_timedwait(event_t* ev, uint64_t timeout) +{ + uint64_t start = current_time_ms(); + uint64_t now = start; + pthread_mutex_lock(&ev->mu); + for (;;) { + if (ev->state) + break; + uint64_t remain = timeout - (now - start); + struct timespec ts; + ts.tv_sec = remain / 1000; + ts.tv_nsec = (remain % 1000) * 1000 * 1000; + pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); + now = current_time_ms(); + if (now - start > timeout) + break; + } + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static void sandbox_common() +{ + struct rlimit rlim; + rlim.rlim_cur = rlim.rlim_max = 128 << 20; + setrlimit(RLIMIT_AS, &rlim); + rlim.rlim_cur = rlim.rlim_max = 8 << 20; + setrlimit(RLIMIT_MEMLOCK, &rlim); + rlim.rlim_cur = rlim.rlim_max = 1 << 20; + setrlimit(RLIMIT_FSIZE, &rlim); + rlim.rlim_cur = rlim.rlim_max = 1 << 20; + setrlimit(RLIMIT_STACK, &rlim); + rlim.rlim_cur = rlim.rlim_max = 0; + setrlimit(RLIMIT_CORE, &rlim); + rlim.rlim_cur = rlim.rlim_max = 256; + setrlimit(RLIMIT_NOFILE, &rlim); +} + +static void loop(); + +static int do_sandbox_none(void) +{ + sandbox_common(); + loop(); + return 0; +} + +struct thread_t { + int created, call; + event_t ready, done; +}; + +static struct thread_t threads[16]; +static void execute_call(int call); +static int running; + +static void* thr(void* arg) +{ + struct thread_t* th = (struct thread_t*)arg; + for (;;) { + event_wait(&th->ready); + event_reset(&th->ready); + execute_call(th->call); + __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); + event_set(&th->done); + } + return 0; +} + +static void execute_one(void) +{ + if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { + } + int i, call, thread; + for (call = 0; call < 12; call++) { + for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); + thread++) { + struct thread_t* th = &threads[thread]; + if (!th->created) { + th->created = 1; + event_init(&th->ready); + event_init(&th->done); + event_set(&th->done); + thread_start(thr, th); + } + if (!event_isset(&th->done)) + continue; + event_reset(&th->done); + th->call = call; + __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); + event_set(&th->ready); + event_timedwait(&th->done, 50); + break; + } + } + for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) + sleep_ms(1); +} + +static void execute_one(void); + +#define WAIT_FLAGS 0 + +static void loop(void) +{ + int iter = 0; + for (;; iter++) { + char cwdbuf[32]; + sprintf(cwdbuf, "./%d", iter); + if (mkdir(cwdbuf, 0777)) + exit(1); + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + if (chdir(cwdbuf)) + exit(1); + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + sleep_ms(10); + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + if (current_time_ms() - start < 5000) + continue; + kill_and_wait(pid, &status); + break; + } + remove_dir(cwdbuf); + } +} + +uint64_t r[5] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, + 0xffffffffffffffff, 0xffffffffffffffff}; + +void execute_call(int call) +{ + intptr_t res = 0; + switch (call) { + case 0: + memcpy((void*)0x200000000000, "./file0\000", 8); + res = syscall(SYS_openat, /*fd=*/0xffffff9c, /*file=*/0x200000000000ul, + /*flags=O_VERIFY|O_CREAT|O_WRONLY*/ 0x200201ul, /*mode=*/0ul); + if (res != -1) + r[0] = res; + break; + case 1: + *(uint32_t*)0x200000000240 = r[0]; + *(uint64_t*)0x200000000248 = 0x80000001; + *(uint64_t*)0x200000000250 = 0x2000000004c0; + memcpy((void*)0x2000000004c0, "\x45\x09\xee\x8f\xcd", 5); + *(uint64_t*)0x200000000258 = 5; + *(uint32_t*)0x200000000260 = 3; + *(uint32_t*)0x200000000264 = 0; + *(uint64_t*)0x200000000268 = 0x200000000000000; + *(uint32_t*)0x200000000270 = 8; + *(uint32_t*)0x200000000274 = 0; + *(uint64_t*)0x200000000278 = 1; + *(uint64_t*)0x200000000280 = 7; + *(uint64_t*)0x200000000288 = 0; + *(uint32_t*)0x200000000290 = 0; + *(uint32_t*)0x200000000294 = 0x20000005; + *(uint32_t*)0x200000000298 = 0x2e5562f1; + *(uint16_t*)0x2000000002a0 = 0xc088; + syscall(SYS_aio_write, /*iocb=*/0x200000000240ul); + break; + case 2: + memcpy((void*)0x200000000480, "./file0\000", 8); + res = syscall(SYS_open, /*file=*/0x200000000480ul, + /*flags=O_VERIFY*/ 0x200000ul, + /*mode=S_IWOTH|S_IWGRP|S_IXUSR|S_IWUSR*/ 0xd2ul); + if (res != -1) + r[1] = res; + break; + case 3: + syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x200000ul, + /*prot=PROT_WRITE|PROT_READ*/ 3ul, + /*flags=MAP_FIXED|MAP_PRIVATE*/ 0x12ul, /*fd=*/r[1], + /*offset=*/0ul); + break; + case 4: + memcpy((void*)0x200000000100, "./file0\000", 8); + res = syscall(SYS_open, /*file=*/0x200000000100ul, + /*flags=O_DIRECT*/ 0x10000ul, /*mode=*/0ul); + if (res != -1) + r[2] = res; + break; + case 5: + memcpy((void*)0x2000000016c0, "./file0\000", 8); + res = syscall(SYS_open, /*file=*/0x2000000016c0ul, /*flags=O_WRONLY*/ 1ul, + /*mode=*/0ul); + if (res != -1) + r[3] = res; + break; + case 6: + *(uint64_t*)0x200000000080 = 0x2000000006c0; + *(uint64_t*)0x200000000088 = 0x100000; + syscall(SYS_pwritev, /*fd=*/r[3], /*vec=*/0x200000000080ul, /*vlen=*/1ul, + /*off=*/0ul); + break; + case 7: + *(uint64_t*)0x200000001780 = 0x200000000180; + *(uint64_t*)0x200000001788 = 0x1b133353141e377d; + syscall(SYS_preadv, /*fd=*/r[2], /*vec=*/0x200000001780ul, + /*vlen=*/0x10000000000000d1ul, /*off=*/0ul); + break; + case 8: + memcpy((void*)0x200000000480, "./file0\000", 8); + res = syscall( + SYS_open, /*file=*/0x200000000480ul, + /*flags=O_NONBLOCK|O_CREAT|O_RDWR|0x80400000000000*/ 0x80400000000206ul, + /*mode=*/0ul); + if (res != -1) + r[4] = res; + break; + case 9: + syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x200000ul, + /*prot=PROT_WRITE|PROT_READ*/ 3ul, + /*flags=MAP_FIXED|MAP_SHARED|0x20000*/ 0x20011ul, /*fd=*/r[4], + /*offset=*/0ul); + break; + case 10: + syscall(SYS_setsockopt, /*fd=*/(intptr_t)-1, /*level=*/6, + /*optname=TCP_LOGID*/ 0x24, /*optval=*/0ul, /*optlen=*/0ul); + break; + case 11: + syscall(SYS_setsockopt, /*fd=*/(intptr_t)-1, /*level=*/6, + /*optname=TCP_LOGID*/ 0x24, /*optval=*/0ul, /*optlen=*/0ul); + break; + } +} +int main(void) +{ + syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, + /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, + /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul, + /*fd=*/(intptr_t)-1, /*offset=*/0ul); + const char* reason; + (void)reason; + use_temporary_dir(); + do_sandbox_none(); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +cd /tmp +timeout 3m /tmp/$prog > /dev/null 2>&1 + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core /tmp/$prog.?????? +exit 0 diff --git a/tools/test/stress2/misc/syzkaller75.sh b/tools/test/stress2/misc/syzkaller75.sh new file mode 100755 index 000000000000..05e1e56bc44d --- /dev/null +++ b/tools/test/stress2/misc/syzkaller75.sh @@ -0,0 +1,377 @@ +#!/bin/sh + +# panic: vm_pager_assert_in: page 0xfffffe001987bcc0 is mapped +# cpuid = 10 +# time = 1745335200 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe0108807700 +# vpanic() at vpanic+0x136/frame 0xfffffe0108807830 +# panic() at panic+0x43/frame 0xfffffe0108807890 +# vm_pager_assert_in() at vm_pager_assert_in+0x1fa/frame 0xfffffe01088078d0 +# vm_pager_get_pages() at vm_pager_get_pages+0x3d/frame 0xfffffe0108807920 +# vm_fault_getpages() at vm_fault_getpages+0x22b/frame 0xfffffe0108807980 +# vm_fault_object() at vm_fault_object+0x2ab/frame 0xfffffe01088079e0 +# vm_fault() at vm_fault+0x2d1/frame 0xfffffe0108807b40 +# vm_map_wire_locked() at vm_map_wire_locked+0x385/frame 0xfffffe0108807bf0 +# vm_mmap_object() at vm_mmap_object+0x2fd/frame 0xfffffe0108807c50 +# vn_mmap() at vn_mmap+0x152/frame 0xfffffe0108807ce0 +# kern_mmap() at kern_mmap+0x621/frame 0xfffffe0108807dc0 +# sys_mmap() at sys_mmap+0x42/frame 0xfffffe0108807e00 +# amd64_syscall() at amd64_syscall+0x15a/frame 0xfffffe0108807f30 +# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe0108807f30 +# --- syscall (0, FreeBSD ELF64, syscall), rip = 0x82438d7fa, rsp = 0x824847f68, rbp = 0x824847f90 --- +# KDB: enter: panic +# [ thread pid 43067 tid 146060 ] +# Stopped at kdb_enter+0x33: movq $0,0x124d7e2(%rip) +# db> x/s version +# version: FreeBSD 15.0-CURRENT #2 main-n276647-a098111a28ed-dirty: Tue Apr 22 16:37:39 CEST 2025 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO +# db> + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=bab5b2c0d3e8f95d52a06ab501ddb3c11200a5c9 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// syzbot+1cc9ede76727d2ea2e8d@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <sys/types.h> + +#include <errno.h> +#include <pthread.h> +#include <pwd.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +static void kill_and_wait(int pid, int* status) +{ + kill(pid, SIGKILL); + while (waitpid(-1, status, 0) != pid) { + } +} + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void thread_start(void* (*fn)(void*), void* arg) +{ + pthread_t th; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128 << 10); + int i = 0; + for (; i < 100; i++) { + if (pthread_create(&th, &attr, fn, arg) == 0) { + pthread_attr_destroy(&attr); + return; + } + if (errno == EAGAIN) { + usleep(50); + continue; + } + break; + } + exit(1); +} + +typedef struct { + pthread_mutex_t mu; + pthread_cond_t cv; + int state; +} event_t; + +static void event_init(event_t* ev) +{ + if (pthread_mutex_init(&ev->mu, 0)) + exit(1); + if (pthread_cond_init(&ev->cv, 0)) + exit(1); + ev->state = 0; +} + +static void event_reset(event_t* ev) +{ + ev->state = 0; +} + +static void event_set(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + if (ev->state) + exit(1); + ev->state = 1; + pthread_mutex_unlock(&ev->mu); + pthread_cond_broadcast(&ev->cv); +} + +static void event_wait(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + while (!ev->state) + pthread_cond_wait(&ev->cv, &ev->mu); + pthread_mutex_unlock(&ev->mu); +} + +static int event_isset(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static int event_timedwait(event_t* ev, uint64_t timeout) +{ + uint64_t start = current_time_ms(); + uint64_t now = start; + pthread_mutex_lock(&ev->mu); + for (;;) { + if (ev->state) + break; + uint64_t remain = timeout - (now - start); + struct timespec ts; + ts.tv_sec = remain / 1000; + ts.tv_nsec = (remain % 1000) * 1000 * 1000; + pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); + now = current_time_ms(); + if (now - start > timeout) + break; + } + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +struct thread_t { + int created, call; + event_t ready, done; +}; + +static struct thread_t threads[16]; +static void execute_call(int call); +static int running; + +static void* thr(void* arg) +{ + struct thread_t* th = (struct thread_t*)arg; + for (;;) { + event_wait(&th->ready); + event_reset(&th->ready); + execute_call(th->call); + __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); + event_set(&th->done); + } + return 0; +} + +static void execute_one(void) +{ + if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { + } + int i, call, thread; + for (call = 0; call < 11; call++) { + for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); + thread++) { + struct thread_t* th = &threads[thread]; + if (!th->created) { + th->created = 1; + event_init(&th->ready); + event_init(&th->done); + event_set(&th->done); + thread_start(thr, th); + } + if (!event_isset(&th->done)) + continue; + event_reset(&th->done); + th->call = call; + __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); + event_set(&th->ready); + event_timedwait(&th->done, 50); + break; + } + } + for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) + sleep_ms(1); +} + +static void execute_one(void); + +#define WAIT_FLAGS 0 + +static void loop(void) +{ +// int iter = 0; + for (;; /*iter++*/) { + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + sleep_ms(10); + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + if (current_time_ms() - start < 5000) + continue; + kill_and_wait(pid, &status); + break; + } + } +} + +uint64_t r[4] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, + 0xffffffffffffffff}; + +void execute_call(int call) +{ + intptr_t res = 0; + switch (call) { + case 0: + memcpy((void*)0x200000000200, "./file0\000", 8); + res = syscall(SYS_openat, /*fd=*/0xffffff9c, /*file=*/0x200000000200ul, + /*flags=O_VERIFY|O_CREAT|O_CLOEXEC|O_WRONLY*/ 0x300201ul, + /*mode=S_IWGRP|S_IXUSR|S_IWUSR*/ 0xd0ul); + if (res != -1) + r[0] = res; + break; + case 1: + *(uint32_t*)0x200000000240 = r[0]; + *(uint64_t*)0x200000000248 = 0x80000002; + *(uint64_t*)0x200000000250 = 0x200000000080; + memcpy((void*)0x200000000080, "\x1f\x9a\xc4", 3); + *(uint64_t*)0x200000000258 = 3; + *(uint32_t*)0x200000000260 = 0; + *(uint32_t*)0x200000000264 = 0; + *(uint64_t*)0x200000000268 = 0; + *(uint32_t*)0x200000000270 = 0; + *(uint32_t*)0x200000000274 = 0; + *(uint64_t*)0x200000000278 = 0; + *(uint64_t*)0x200000000280 = 7; + *(uint64_t*)0x200000000288 = 0; + *(uint32_t*)0x200000000290 = 0; + *(uint32_t*)0x200000000294 = 0; + *(uint64_t*)0x200000000298 = 0; + *(uint64_t*)0x2000000002a0 = 0; + *(uint64_t*)0x2000000002a8 = 0; + syscall(SYS_aio_write, /*iocb=*/0x200000000240ul); + break; + case 2: + syscall(SYS_mlockall, /*flags=MCL_FUTURE*/ 2ul); + break; + case 3: + memcpy((void*)0x200000000100, "./file0\000", 8); + res = syscall(SYS_open, /*file=*/0x200000000100ul, + /*flags=O_DIRECT*/ 0x10000ul, /*mode=*/0ul); + if (res != -1) + r[1] = res; + break; + case 4: + *(uint64_t*)0x200000001780 = 0x200000000180; + *(uint64_t*)0x200000001788 = 0x1b133353141e377d; + syscall(SYS_preadv, /*fd=*/r[1], /*vec=*/0x200000001780ul, + /*vlen=*/0x10000000000000d1ul, /*off=*/0ul); + break; + case 5: + memcpy((void*)0x200000000040, "./file0\000", 8); + syscall( + SYS_open, /*file=*/0x200000000040ul, + /*flags=O_TRUNC|O_NONBLOCK|O_NOFOLLOW|O_CREAT|O_APPEND|0x2*/ 0x70eul, + /*mode=*/0ul); + break; + case 6: + memcpy((void*)0x200000000480, "./file0\000", 8); + res = syscall( + SYS_open, /*file=*/0x200000000480ul, + /*flags=O_NONBLOCK|O_CREAT|O_RDWR|0x80400000000000*/ 0x80400000000206ul, + /*mode=*/0ul); + if (res != -1) + r[2] = res; + break; + case 7: + syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x200000ul, + /*prot=PROT_WRITE|PROT_READ*/ 3ul, + /*flags=MAP_FIXED|MAP_SHARED|0x20000*/ 0x20011ul, /*fd=*/r[2], + /*offset=*/0ul); + break; + case 8: + memcpy((void*)0x200000000040, "./file0\000", 8); + syscall(SYS_truncate, /*file=*/0x200000000040ul, /*len=*/0xaa480ul); + break; + case 9: + memcpy((void*)0x200000000480, "./file0\000", 8); + res = syscall(SYS_open, /*file=*/0x200000000480ul, /*flags=*/0ul, + /*mode=*/0ul); + if (res != -1) + r[3] = res; + break; + case 10: + syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x200000ul, + /*prot=PROT_WRITE|PROT_READ*/ 3ul, + /*flags=MAP_FIXED|MAP_PRIVATE*/ 0x12ul, /*fd=*/r[3], + /*offset=*/0ul); + break; + } +} +int main(void) +{ + syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, + /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, + /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul, + /*fd=*/(intptr_t)-1, /*offset=*/0ul); + const char* reason; + (void)reason; + loop(); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +(cd ../testcases/swap; ./swap -t 3m -i 30 -l 100 > /dev/null 2>&1) & +sleep 5 + +work=/tmp/$prog.dir +rm -rf $work +mkdir $work +cd /tmp/$prog.dir +for i in `jot 30`; do + ( + mkdir d$i + cd d$i + timeout 3m /tmp/$prog > /dev/null 2>&1 & + ) +done +while pgrep -q $prog; do sleep 2; done +while pkill swap; do :; done +wait + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core /tmp/$prog.?????? $work +exit 0 diff --git a/tools/test/stress2/misc/syzkaller76.sh b/tools/test/stress2/misc/syzkaller76.sh new file mode 100755 index 000000000000..67a566cbfa00 --- /dev/null +++ b/tools/test/stress2/misc/syzkaller76.sh @@ -0,0 +1,235 @@ +#!/bin/sh + +# panic: aio_process_rw: opcode 70 +# cpuid = 7 +# time = 1746175480 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe010844ccb0 +# vpanic() at vpanic+0x136/frame 0xfffffe010844cde0 +# panic() at panic+0x43/frame 0xfffffe010844ce40 +# aio_process_rw() at aio_process_rw+0x28e/frame 0xfffffe010844cea0 +# aio_daemon() at aio_daemon+0x286/frame 0xfffffe010844cef0 +# fork_exit() at fork_exit+0x82/frame 0xfffffe010844cf30 +# fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe010844cf30 +# --- trap 0xc, rip = 0x2020f02a472a, rsp = 0x2020ec9bb8d8, rbp = 0x2020ec9bb9d0 --- +# KDB: enter: panic +# [ thread pid 71553 tid 100216 ] +# Stopped at kdb_enter+0x33: movq $0,0x122f9c2(%rip) +# db> x/s version +# version: FreeBSD 15.0-CURRENT #0 main-n276945-2735c20d114f-dirty: Fri May 2 07:17:00 CEST 2025 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO +# db> + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=0549d8c089382a2593078734cc8166a0fc9049f1 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// syzbot+b6e15476c91852bb2264@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <pwd.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <unistd.h> + +uint64_t r[1] = {0xffffffffffffffff}; + +int main(void) +{ + syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, + /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, + /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul, + /*fd=*/(intptr_t)-1, /*offset=*/0ul); + const char* reason; + (void)reason; + intptr_t res = 0; + if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { + } + res = syscall(SYS_freebsd10_pipe, /*pipefd=*/0x2000000005c0ul); + if (res != -1) + r[0] = *(uint32_t*)0x2000000005c4; + syscall(SYS_close, /*fd=*/r[0]); + memcpy((void*)0x200000000080, ".\000", 2); + syscall(SYS_open, /*file=*/0x200000000080ul, /*flags=*/0ul, /*mode=*/0ul); + *(uint32_t*)0x200000000080 = 0; + *(uint32_t*)0x200000000084 = 0; + *(uint32_t*)0x200000000088 = 4; + *(uint64_t*)0x200000000090 = 0; + *(uint64_t*)0x200000000098 = 0; + *(uint32_t*)0x2000000000a0 = 0; + *(uint32_t*)0x2000000000a4 = 8; + *(uint64_t*)0x2000000000a8 = 0x7fffffffffffffff; + *(uint32_t*)0x2000000000b0 = 0; + *(uint32_t*)0x2000000000b4 = 0x100; + *(uint64_t*)0x2000000000b8 = 0; + *(uint32_t*)0x2000000000c0 = 0; + *(uint32_t*)0x2000000000c4 = 0; + *(uint32_t*)0x2000000000c8 = 0; + *(uint32_t*)0x2000000000cc = 3; + *(uint32_t*)0x2000000000d0 = 0; + *(uint32_t*)0x2000000000d4 = 0; + *(uint32_t*)0x2000000000d8 = 0x400008; + *(uint32_t*)0x2000000000dc = 0x8e; + *(uint32_t*)0x2000000000e0 = 0xfffffffd; + *(uint32_t*)0x2000000000e4 = 0xf; + *(uint32_t*)0x2000000000e8 = 0xfffffffc; + *(uint32_t*)0x2000000000ec = 0; + *(uint32_t*)0x2000000000f0 = 0; + *(uint32_t*)0x2000000000f4 = 0; + *(uint32_t*)0x2000000000f8 = 0xff; + *(uint32_t*)0x2000000000fc = 0; + *(uint32_t*)0x200000000100 = 0; + *(uint32_t*)0x200000000104 = 2; + *(uint32_t*)0x200000000108 = 0; + *(uint32_t*)0x20000000010c = 2; + *(uint32_t*)0x200000000110 = 2; + *(uint32_t*)0x200000000114 = 0x5bee; + *(uint32_t*)0x200000000118 = 0; + *(uint32_t*)0x20000000011c = 0xc; + *(uint32_t*)0x200000000120 = 3; + *(uint32_t*)0x200000000124 = 2; + *(uint32_t*)0x200000000128 = 0; + *(uint32_t*)0x20000000012c = 0x10000000; + *(uint32_t*)0x200000000130 = 0; + *(uint32_t*)0x200000000134 = 1; + *(uint32_t*)0x200000000138 = 0; + *(uint32_t*)0x20000000013c = 0x83; + *(uint32_t*)0x200000000140 = 0; + *(uint32_t*)0x200000000144 = 0; + *(uint32_t*)0x200000000148 = 0; + *(uint32_t*)0x20000000014c = 0; + *(uint32_t*)0x200000000150 = 0; + *(uint32_t*)0x200000000154 = 0xfff; + *(uint32_t*)0x200000000158 = 1; + *(uint32_t*)0x20000000015c = 0x4c; + *(uint32_t*)0x200000000160 = 0x1fffffc; + *(uint32_t*)0x200000000164 = 4; + *(uint32_t*)0x200000000168 = 0x40000001; + *(uint32_t*)0x20000000016c = 0; + *(uint32_t*)0x200000000170 = 8; + *(uint32_t*)0x200000000174 = 0; + *(uint32_t*)0x200000000178 = 0; + *(uint32_t*)0x20000000017c = 0x100001; + *(uint32_t*)0x200000000180 = 0; + *(uint32_t*)0x200000000184 = 0x1ff; + *(uint32_t*)0x200000000188 = 0xe; + *(uint32_t*)0x20000000018c = 8; + *(uint32_t*)0x200000000190 = 0; + *(uint32_t*)0x200000000194 = 0; + *(uint32_t*)0x200000000198 = 0; + *(uint32_t*)0x20000000019c = 0xc; + *(uint32_t*)0x2000000001a0 = 9; + *(uint32_t*)0x2000000001a4 = 2; + *(uint32_t*)0x2000000001a8 = 0x10000002; + *(uint32_t*)0x2000000001ac = 0x100000; + *(uint32_t*)0x2000000001b0 = 0x46; + *(uint32_t*)0x2000000001b4 = 6; + *(uint32_t*)0x2000000001b8 = 0x3ff; + *(uint32_t*)0x2000000001bc = 2; + *(uint32_t*)0x2000000001c0 = 0; + *(uint32_t*)0x2000000001c4 = 0xfffffffa; + *(uint32_t*)0x2000000001c8 = 0x200; + *(uint32_t*)0x2000000001cc = 0; + *(uint32_t*)0x2000000001d0 = 1; + *(uint32_t*)0x2000000001d4 = 3; + *(uint32_t*)0x2000000001d8 = 0; + *(uint32_t*)0x2000000001dc = 0x100; + *(uint32_t*)0x2000000001e0 = 0; + *(uint32_t*)0x2000000001e4 = 8; + *(uint32_t*)0x2000000001e8 = 0x108c6b2; + *(uint32_t*)0x2000000001ec = 0xfffffffa; + *(uint32_t*)0x2000000001f0 = 0; + *(uint32_t*)0x2000000001f4 = 5; + *(uint32_t*)0x2000000001f8 = 0; + *(uint32_t*)0x2000000001fc = 0; + *(uint32_t*)0x200000000200 = 0; + *(uint32_t*)0x200000000204 = 0; + *(uint32_t*)0x200000000208 = 0; + *(uint32_t*)0x20000000020c = 0x80; + *(uint32_t*)0x200000000210 = 0; + *(uint32_t*)0x200000000214 = 1; + *(uint32_t*)0x200000000218 = 0; + *(uint32_t*)0x20000000021c = 6; + *(uint32_t*)0x200000000220 = 0; + *(uint32_t*)0x200000000224 = 0; + *(uint32_t*)0x200000000228 = 0; + *(uint32_t*)0x20000000022c = 6; + *(uint32_t*)0x200000000230 = 0; + *(uint32_t*)0x200000000234 = 0; + *(uint32_t*)0x200000000238 = 0; + *(uint32_t*)0x20000000023c = 0xa9f; + syscall(SYS_ioctl, /*fd=*/(intptr_t)-1, /*cmd=*/0xc1c06d02ul, + /*arg=*/0x200000000080ul); + *(uint32_t*)0x200000000580 = -1; + *(uint64_t*)0x200000000588 = 0; + *(uint64_t*)0x200000000590 = 0x200000000180; + *(uint64_t*)0x200000000598 = 0; + *(uint32_t*)0x2000000005a0 = 0xfffff000; + *(uint32_t*)0x2000000005a4 = 3; + *(uint64_t*)0x2000000005a8 = 0; + *(uint32_t*)0x2000000005b0 = 0; + *(uint32_t*)0x2000000005b4 = 0; + *(uint64_t*)0x2000000005b8 = 0; + *(uint64_t*)0x2000000005c0 = 0; + *(uint64_t*)0x2000000005c8 = 0; + *(uint32_t*)0x2000000005d0 = 0; + *(uint32_t*)0x2000000005d4 = 0; + *(uint64_t*)0x2000000005d8 = 0; + *(uint16_t*)0x2000000005e0 = 0x4043; + *(uint32_t*)0x200000000620 = -1; + *(uint64_t*)0x200000000628 = 0; + *(uint64_t*)0x200000000630 = 0; + *(uint64_t*)0x200000000638 = 0; + *(uint32_t*)0x200000000640 = 0x10; + *(uint32_t*)0x200000000644 = 0; + *(uint64_t*)0x200000000648 = 0; + *(uint32_t*)0x200000000650 = 0; + *(uint32_t*)0x200000000654 = 0; + *(uint64_t*)0x200000000658 = 8; + *(uint64_t*)0x200000000660 = 0x3ff; + *(uint64_t*)0x200000000668 = 0; + *(uint32_t*)0x200000000670 = 1; + *(uint32_t*)0x200000000674 = 0; + *(uint32_t*)0x200000000678 = 3; + *(uint16_t*)0x200000000680 = 0; + *(uint32_t*)0x2000000006c0 = -1; + *(uint64_t*)0x2000000006c8 = 0; + *(uint64_t*)0x2000000006d0 = 0; + *(uint64_t*)0x2000000006d8 = 0; + *(uint32_t*)0x2000000006e0 = 0; + *(uint32_t*)0x2000000006e4 = 0; + *(uint64_t*)0x2000000006e8 = 2; + *(uint32_t*)0x2000000006f0 = 0; + *(uint32_t*)0x2000000006f4 = 0; + *(uint64_t*)0x2000000006f8 = 0x101; + *(uint64_t*)0x200000000700 = 0xb3; + *(uint64_t*)0x200000000708 = 0; + *(uint32_t*)0x200000000710 = 0; + *(uint32_t*)0x200000000714 = 0xa; + *(uint64_t*)0x200000000718 = 3; + *(uint32_t*)0x200000000720 = 0; + syscall(SYS_lio_listio, /*mode=*/0ul, /*list=*/0x200000000580ul, /*nent=*/3ul, + /*sig=*/0ul); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 +work=/tmp/$prog.dir +rm -rf $work +mkdir $work +cd /tmp/$prog.dir +timeout 3m /tmp/$prog > /dev/null 2>&1 + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core /tmp/$prog.?????? $work +exit 0 diff --git a/tools/test/stress2/misc/syzkaller77.sh b/tools/test/stress2/misc/syzkaller77.sh new file mode 100755 index 000000000000..c77a3fd2dd22 --- /dev/null +++ b/tools/test/stress2/misc/syzkaller77.sh @@ -0,0 +1,290 @@ +#!/bin/sh + +# panic: sofree:1883 curvnet is NULL, so=0xfffff8017ca59000 +# cpuid = 8 +# time = 1746559098 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe0182b5c8d0 +# vpanic() at vpanic+0x136/frame 0xfffffe0182b5ca00 +# panic() at panic+0x43/frame 0xfffffe0182b5ca60 +# sorele_locked() at sorele_locked+0x25f/frame 0xfffffe0182b5ca90 +# uipc_sendfile_wait() at uipc_sendfile_wait+0x1df/frame 0xfffffe0182b5caf0 +# vn_sendfile() at vn_sendfile+0x59b/frame 0xfffffe0182b5cd70 +# sendfile() at sendfile+0x129/frame 0xfffffe0182b5ce00 +# amd64_syscall() at amd64_syscall+0x15a/frame 0xfffffe0182b5cf30 +# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe0182b5cf30 +# --- syscall (0, FreeBSD ELF64, syscall), rip = 0x8223fb72a, rsp = 0x824baaf58, rbp = 0x824baaf90 --- +# KDB: enter: panic +# [ thread pid 6382 tid 103296 ] +# Stopped at kdb_enter+0x33: movq $0,0x122f202(%rip) +# db> x/s version +# version: FreeBSD 15.0-CURRENT #0 main-n277057-794e792121ba-dirty: Tue May 6 18:34:20 CEST 2025 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO +# db> + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=f04b36c4f2b84533225a1bd695a0aed2efa559e5 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// syzbot+7b0b20cf2c672c181d98@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <errno.h> +#include <pthread.h> +#include <pwd.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <time.h> +#include <unistd.h> + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void thread_start(void* (*fn)(void*), void* arg) +{ + pthread_t th; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128 << 10); + int i = 0; + for (; i < 100; i++) { + if (pthread_create(&th, &attr, fn, arg) == 0) { + pthread_attr_destroy(&attr); + return; + } + if (errno == EAGAIN) { + usleep(50); + continue; + } + break; + } + exit(1); +} + +typedef struct { + pthread_mutex_t mu; + pthread_cond_t cv; + int state; +} event_t; + +static void event_init(event_t* ev) +{ + if (pthread_mutex_init(&ev->mu, 0)) + exit(1); + if (pthread_cond_init(&ev->cv, 0)) + exit(1); + ev->state = 0; +} + +static void event_reset(event_t* ev) +{ + ev->state = 0; +} + +static void event_set(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + if (ev->state) + exit(1); + ev->state = 1; + pthread_mutex_unlock(&ev->mu); + pthread_cond_broadcast(&ev->cv); +} + +static void event_wait(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + while (!ev->state) + pthread_cond_wait(&ev->cv, &ev->mu); + pthread_mutex_unlock(&ev->mu); +} + +static int event_isset(event_t* ev) +{ + pthread_mutex_lock(&ev->mu); + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +static int event_timedwait(event_t* ev, uint64_t timeout) +{ + uint64_t start = current_time_ms(); + uint64_t now = start; + pthread_mutex_lock(&ev->mu); + for (;;) { + if (ev->state) + break; + uint64_t remain = timeout - (now - start); + struct timespec ts; + ts.tv_sec = remain / 1000; + ts.tv_nsec = (remain % 1000) * 1000 * 1000; + pthread_cond_timedwait(&ev->cv, &ev->mu, &ts); + now = current_time_ms(); + if (now - start > timeout) + break; + } + int res = ev->state; + pthread_mutex_unlock(&ev->mu); + return res; +} + +struct thread_t { + int created, call; + event_t ready, done; +}; + +static struct thread_t threads[16]; +static void execute_call(int call); +static int running; + +static void* thr(void* arg) +{ + struct thread_t* th = (struct thread_t*)arg; + for (;;) { + event_wait(&th->ready); + event_reset(&th->ready); + execute_call(th->call); + __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); + event_set(&th->done); + } + return 0; +} + +static void loop(void) +{ + if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { + } + int i, call, thread; + for (call = 0; call < 8; call++) { + for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); + thread++) { + struct thread_t* th = &threads[thread]; + if (!th->created) { + th->created = 1; + event_init(&th->ready); + event_init(&th->done); + event_set(&th->done); + thread_start(thr, th); + } + if (!event_isset(&th->done)) + continue; + event_reset(&th->done); + th->call = call; + __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); + event_set(&th->ready); + event_timedwait(&th->done, 50); + break; + } + } + for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++) + sleep_ms(1); +} + +uint64_t r[5] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, + 0xffffffffffffffff, 0xffffffffffffffff}; + +void execute_call(int call) +{ + intptr_t res = 0; + switch (call) { + case 0: + memcpy((void*)0x200000000480, "./file0\000", 8); + res = syscall( + SYS_open, /*file=*/0x200000000480ul, + /*flags=O_NONBLOCK|O_CREAT|O_RDWR|0x80000000000000*/ 0x80000000000206ul, + /*mode=*/0ul); + if (res != -1) + r[0] = res; + break; + case 1: + syscall(SYS_ftruncate, /*fd=*/r[0], /*len=*/0x3862ul); + break; + case 2: + res = syscall(SYS_socket, /*domain=*/2ul, /*type=*/2ul, /*proto=*/0x88); + if (res != -1) + r[1] = res; + break; + case 3: + res = syscall(SYS_socketpair, /*domain=*/1ul, /*type=SOCK_STREAM*/ 1ul, + /*proto=*/0, /*fds=*/0x200000000180ul); + if (res != -1) { + r[2] = *(uint32_t*)0x200000000180; + r[3] = *(uint32_t*)0x200000000184; + } + break; + case 4: + syscall(SYS_dup2, /*oldfd=*/r[2], /*newfd=*/r[1]); + break; + case 5: + memcpy((void*)0x200000000140, "./file0\000", 8); + res = syscall(SYS_open, /*file=*/0x200000000140ul, /*flags=*/0ul, + /*mode=*/0ul); + if (res != -1) + r[4] = res; + break; + case 6: + syscall(SYS_sendfile, /*fd=*/r[4], /*s=*/r[1], /*offset=*/0ul, + /*nbytes=*/0ul, /*hdtr=*/0ul, /*sbytes=*/0ul, + /*flags=SF_SYNC|SF_NOCACHE*/ 0x14ul); + break; + case 7: + syscall(SYS_dup2, /*oldfd=*/r[4], /*newfd=*/r[3]); + break; + } +} +int main(void) +{ + syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, + /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, + /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul, + /*fd=*/(intptr_t)-1, /*offset=*/0ul); + const char* reason; + (void)reason; + loop(); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +(cd ../testcases/swap; ./swap -t 3m -i 30 -l 100 > /dev/null 2>&1) & +sleep 5 + +work=/tmp/$prog.dir +rm -rf $work +mkdir $work +cd /tmp/$prog.dir +for i in `jot 30`; do + ( + mkdir d$i + cd d$i + timeout 3m /tmp/$prog > /dev/null 2>&1 & + ) +done +while pgrep -q $prog; do sleep 2; done +while pkill swap; do :; done +wait + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core /tmp/$prog.?????? $work +exit 0 diff --git a/tools/test/stress2/misc/syzkaller78.sh b/tools/test/stress2/misc/syzkaller78.sh new file mode 100755 index 000000000000..1858129d4c81 --- /dev/null +++ b/tools/test/stress2/misc/syzkaller78.sh @@ -0,0 +1,282 @@ +#!/bin/sh + +# Fatal trap 12: page fault while in kernel mode +# cpuid = 10; apic id = 07 +# fault virtual address = 0x0 +# fault code = supervisor read data, page not present +# instruction pointer = 0x20:0xffffffff80c3c276 +# stack pointer = 0x28:0xfffffe017273eb00 +# frame pointer = 0x28:0xfffffe017273eb30 +# code segment = base 0x0, limit 0xfffff, type 0x1b +# = DPL 0, pres 1, long 1, def32 0, gran 1 +# processor eflags = interrupt enabled, resume, IOPL = 0 +# current process = 43905 (syzkaller78) +# rdi: fffff8005b5d55e0 rsi: 0000000000000008 rdx: ffffffff81249e88 +# rcx: fffff8001b9aed00 r8: 0000000000000000 r9: fffff80003396000 +# rax: 0000000000000000 rbx: fffff8005b5d5400 rbp: fffffe017273eb30 +# r10: 0000000000000000 r11: fffff804d84e9c60 r12: fffff8005b5d55f8 +# r13: 0000000000000000 r14: fffff80497171700 r15: fffff8005b5d55c0 +# trap number = 12 +# panic: page fault +# cpuid = 7 +# time = 1746555157 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe017273e830 +# vpanic() at vpanic+0x136/frame 0xfffffe017273e960 +# panic() at panic+0x43/frame 0xfffffe017273e9c0 +# trap_pfault() at trap_pfault+0x48d/frame 0xfffffe017273ea30 +# calltrap() at calltrap+0x8/frame 0xfffffe017273ea30 +# --- trap 0xc, rip = 0xffffffff80c3c276, rsp = 0xfffffe017273eb00, rbp = 0xfffffe017273eb30 --- +# unp_dispose() at unp_dispose+0x3b6/frame 0xfffffe017273eb30 +# uipc_detach() at uipc_detach+0x35/frame 0xfffffe017273eb80 +# sorele_locked() at sorele_locked+0x107/frame 0xfffffe017273ebb0 +# soclose() at soclose+0x17d/frame 0xfffffe017273ec10 +# _fdrop() at _fdrop+0x1b/frame 0xfffffe017273ec30 +# closef() at closef+0x1e3/frame 0xfffffe017273ecc0 +# fdescfree() at fdescfree+0x41e/frame 0xfffffe017273ed80 +# exit1() at exit1+0x4a4/frame 0xfffffe017273edf0 +# sys_exit() at sys_exit+0xd/frameamd64_syscall() at amd64_syscall+0x15a/frame 0xfffffe017273ef30 +# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe017273ef30 +# --- syscall (1, FreeBSD ELF64, exit), rip = 0x823ab472a, rsp = 0x8208e3ea8, rbp = 0x8208e3ec0 --- +# KDB: enter: panic +# [ thread pid 43905 tid 103344 ] +# Stopped at kdb_enter+0x33: movq $0,0x122f202(%rip) +# db> + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=46eb92ee6e2f6acbd4250d0f2065b1f93296bd82 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// syzbot+0e99ffc200638909ca1c@syzkaller.appspotmail.com + +#define _GNU_SOURCE + +#include <sys/types.h> + +#include <dirent.h> +#include <errno.h> +#include <pwd.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +static unsigned long long procid; + +static void kill_and_wait(int pid, int* status) +{ + kill(pid, SIGKILL); + while (waitpid(-1, status, 0) != pid) { + } +} + +static void sleep_ms(uint64_t ms) +{ + usleep(ms * 1000); +} + +static uint64_t current_time_ms(void) +{ + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + exit(1); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +static void use_temporary_dir(void) +{ + char tmpdir_template[] = "./syzkaller.XXXXXX"; + char* tmpdir = mkdtemp(tmpdir_template); + if (!tmpdir) + exit(1); + if (chmod(tmpdir, 0777)) + exit(1); + if (chdir(tmpdir)) + exit(1); +} + +static void reset_flags(const char* filename) +{ + struct stat st; + if (lstat(filename, &st)) + exit(1); + st.st_flags &= ~(SF_NOUNLINK | UF_NOUNLINK | SF_IMMUTABLE | UF_IMMUTABLE | + SF_APPEND | UF_APPEND); + if (lchflags(filename, st.st_flags)) + exit(1); +} +static void __attribute__((noinline)) remove_dir(const char* dir) +{ + DIR* dp = opendir(dir); + if (dp == NULL) { + if (errno == EACCES) { + if (rmdir(dir)) + exit(1); + return; + } + exit(1); + } + struct dirent* ep = 0; + while ((ep = readdir(dp))) { + if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0) + continue; + char filename[FILENAME_MAX]; + snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name); + struct stat st; + if (lstat(filename, &st)) + exit(1); + if (S_ISDIR(st.st_mode)) { + remove_dir(filename); + continue; + } + if (unlink(filename)) { + if (errno == EPERM) { + reset_flags(filename); + reset_flags(dir); + if (unlink(filename) == 0) + continue; + } + exit(1); + } + } + closedir(dp); + while (rmdir(dir)) { + if (errno == EPERM) { + reset_flags(dir); + if (rmdir(dir) == 0) + break; + } + exit(1); + } +} + +static void execute_one(void); + +#define WAIT_FLAGS 0 + +static void loop(void) +{ + int iter = 0; + for (;; iter++) { + char cwdbuf[32]; + sprintf(cwdbuf, "./%d", iter); + if (mkdir(cwdbuf, 0777)) + exit(1); + int pid = fork(); + if (pid < 0) + exit(1); + if (pid == 0) { + if (chdir(cwdbuf)) + exit(1); + execute_one(); + exit(0); + } + int status = 0; + uint64_t start = current_time_ms(); + for (;;) { + sleep_ms(10); + if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) + break; + if (current_time_ms() - start < 5000) + continue; + kill_and_wait(pid, &status); + break; + } + remove_dir(cwdbuf); + } +} + +uint64_t r[5] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, + 0xffffffffffffffff, 0xffffffffffffffff}; + +void execute_one(void) +{ + intptr_t res = 0; + if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { + } + memcpy((void*)0x200000000480, "./file0\000", 8); + res = syscall( + SYS_open, /*file=*/0x200000000480ul, + /*flags=O_NONBLOCK|O_CREAT|O_RDWR|0x80000000000000*/ 0x80000000000206ul, + /*mode=*/0ul); + if (res != -1) + r[0] = res; + syscall(SYS_ftruncate, /*fd=*/r[0], /*len=*/0x3862ul); + memcpy((void*)0x200000000100, "./file0\000", 8); + res = syscall(SYS_open, /*file=*/0x200000000100ul, + /*flags=O_DIRECT*/ 0x10000ul, /*mode=*/0ul); + if (res != -1) + r[1] = res; + *(uint64_t*)0x2000000000c0 = 0x200000000340; + *(uint64_t*)0x2000000000c8 = 0x41; + syscall(SYS_readv, /*fd=*/r[1], /*vec=*/0x2000000000c0ul, /*vlen=*/1ul); + res = syscall(SYS_socket, /*domain=*/2ul, /*type=*/2ul, /*proto=*/0x88); + if (res != -1) + r[2] = res; + res = syscall(SYS_socketpair, /*domain=*/1ul, /*type=SOCK_STREAM*/ 1ul, + /*proto=*/0, /*fds=*/0x200000000180ul); + if (res != -1) + r[3] = *(uint32_t*)0x200000000180; + syscall(SYS_dup2, /*oldfd=*/r[3], /*newfd=*/r[2]); + memcpy((void*)0x200000000140, "./file0\000", 8); + res = + syscall(SYS_open, /*file=*/0x200000000140ul, /*flags=*/0ul, /*mode=*/0ul); + if (res != -1) + r[4] = res; + syscall(SYS_sendfile, /*fd=*/r[4], /*s=*/r[2], /*offset=*/0xcbul, + /*nbytes=*/0x2000ul, /*hdtr=*/0ul, /*sbytes=*/0ul, + /*flags=SF_USER_READAHEAD|SF_NODISKIO|0x2*/ 0xbul); +} +int main(void) +{ + syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, + /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, + /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul, + /*fd=*/(intptr_t)-1, /*offset=*/0ul); + const char* reason; + (void)reason; + for (procid = 0; procid < 4; procid++) { + if (fork() == 0) { + use_temporary_dir(); + loop(); + } + } + sleep(1000000); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +(cd ../testcases/swap; ./swap -t 3m -i 30 -l 100 > /dev/null 2>&1) & +sleep 5 + +work=/tmp/$prog.dir +rm -rf $work +mkdir $work +cd /tmp/$prog.dir +for i in `jot 30`; do + ( + mkdir d$i + cd d$i + timeout 3m /tmp/$prog > /dev/null 2>&1 & + ) +done +while pgrep -q $prog; do sleep 2; done +while pkill swap; do :; done +wait + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core /tmp/$prog.?????? $work +exit 0 diff --git a/tools/test/stress2/misc/syzkaller79.sh b/tools/test/stress2/misc/syzkaller79.sh new file mode 100755 index 000000000000..7413a2034a3d --- /dev/null +++ b/tools/test/stress2/misc/syzkaller79.sh @@ -0,0 +1,82 @@ +#!/bin/sh + +# panic: mutex so_rcv not owned at ../../../kern/uipc_usrreq.c:1750 +# cpuid = 5 +# time = 1746938647 +# KDB: stack backtrace: +# db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe01e75c5b40 +# vpanic() at vpanic+0x136/frame 0xfffffe01e75c5c70 +# panic() at panic+0x43/frame 0xfffffe01e75c5cd0 +# __mtx_assert() at __mtx_assert+0xa9/frame 0xfffffe01e75c5ce0 +# knote() at knote+0x45/frame 0xfffffe01e75c5d30 +# sowwakeup_locked() at sowwakeup_locked+0xc8/frame 0xfffffe01e75c5d50 +# socantsendmore() at socantsendmore+0x4f/frame 0xfffffe01e75c5d70 +# uipc_shutdown() at uipc_shutdown+0x113/frame 0xfffffe01e75c5db0 +# soshutdown() at soshutdown+0x3e/frame 0xfffffe01e75c5dd0 +# kern_shutdown() at kern_shutdown+0x5e/frame 0xfffffe01e75c5e00 +# amd64_syscall() at amd64_syscall+0x15a/frame 0xfffffe01e75c5f30 +# fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe01e75c5f30 +# --- syscall (0, FreeBSD ELF64, syscall), rip = 0x82281772a, rsp = 0x82092efd8, rbp = 0x82092f000 --- +# KDB: enter: panic +# [ thread pid 54792 tid 1014483 ] +# Stopped at kdb_enter+0x33: movq $0,0x122f192(%rip) +# db> x/s version +# version: FreeBSD 15.0-CURRENT #0 main-n277201-48578dcb6b7e-dirty: Sat May 10 13:10:42 CEST 2025 +# pho@mercat1.netperf.freebsd.org:/usr/src/sys/amd64/compile/PHO +# db> + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg +set -u +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +// https://syzkaller.appspot.com/bug?id=ac94349a29f2efc40e9274239e4ca9b2c473a4e7 +// autogenerated by syzkaller (https://github.com/google/syzkaller) +// syzkaller.appspot.com/x/repro.c?x=16c074d4580000 + +#define _GNU_SOURCE + +#include <pwd.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/endian.h> +#include <sys/syscall.h> +#include <unistd.h> + +uint64_t r[1] = {0xffffffffffffffff}; + +int main(void) +{ + syscall(SYS_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, + /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, + /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x1012ul, + /*fd=*/(intptr_t)-1, /*offset=*/0ul); + const char* reason; + (void)reason; + intptr_t res = 0; + if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { + } + res = syscall(SYS_socketpair, /*domain=*/1ul, /*type=SOCK_SEQPACKET*/ 5ul, + /*proto=*/0, /*fds=*/0x200000000040ul); + if (res != -1) + r[0] = *(uint32_t*)0x200000000044; + syscall(SYS_fcntl, /*fd=*/r[0], /*cmd=*/4ul, /*flags=FASYNC*/ 0x40ul); + syscall(SYS_shutdown, /*fd=*/r[0], /*how=*/2ul); + return 0; +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 + +work=/tmp/$prog.dir +rm -rf $work +mkdir $work +cd /tmp/$prog.dir +timeout 3m /tmp/$prog > /dev/null 2>&1 + +rm -rf /tmp/$prog /tmp/$prog.c /tmp/$prog.core /tmp/$prog.?????? $work +exit 0 diff --git a/tools/test/stress2/misc/tcp4.sh b/tools/test/stress2/misc/tcp4.sh index cc98a4e3d51f..da0b7c07283d 100755 --- a/tools/test/stress2/misc/tcp4.sh +++ b/tools/test/stress2/misc/tcp4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/timeout.sh b/tools/test/stress2/misc/timeout.sh index 079efe3006b5..90d160f6b771 100755 --- a/tools/test/stress2/misc/timeout.sh +++ b/tools/test/stress2/misc/timeout.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/tmpfs10.sh b/tools/test/stress2/misc/tmpfs10.sh index 870530c57ea7..6388f59959a4 100755 --- a/tools/test/stress2/misc/tmpfs10.sh +++ b/tools/test/stress2/misc/tmpfs10.sh @@ -26,7 +26,7 @@ # SUCH DAMAGE. # -# tmpfs(5) name lookup problem seen: +# tmpfs(4) name lookup problem seen: # $ ./tmpfs10.sh # tmpfs10: unlink(p01193.14729) at loop #2: No such file or directory diff --git a/tools/test/stress2/misc/tmpfs11.sh b/tools/test/stress2/misc/tmpfs11.sh index efb535b8ea94..629ca8ae3d31 100755 --- a/tools/test/stress2/misc/tmpfs11.sh +++ b/tools/test/stress2/misc/tmpfs11.sh @@ -28,7 +28,7 @@ [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 -# Test with two tmpfs(5) file systems mounted. +# Test with two tmpfs(4) file systems mounted. . ../default.cfg diff --git a/tools/test/stress2/misc/tmpfs13.sh b/tools/test/stress2/misc/tmpfs13.sh index 29b44cbc9ad4..231c42033f9d 100755 --- a/tools/test/stress2/misc/tmpfs13.sh +++ b/tools/test/stress2/misc/tmpfs13.sh @@ -40,6 +40,7 @@ . ../default.cfg N=`sysctl -n hw.ncpu` +[ $N -gt 32 ] && N=32 # Arbitrary cap usermem=`sysctl -n hw.usermem` [ `swapinfo | wc -l` -eq 1 ] && usermem=$((usermem/100*80)) size=$((usermem / 1024 / 1024 / 2)) diff --git a/tools/test/stress2/misc/tmpfs17.sh b/tools/test/stress2/misc/tmpfs17.sh index 878fcf6c95d1..d5f6c50d2e48 100755 --- a/tools/test/stress2/misc/tmpfs17.sh +++ b/tools/test/stress2/misc/tmpfs17.sh @@ -26,7 +26,7 @@ # SUCH DAMAGE. # -# tmpfs(5) option nonc test scenario +# tmpfs(4) option nonc test scenario . ../default.cfg [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 diff --git a/tools/test/stress2/misc/tmpfs19.sh b/tools/test/stress2/misc/tmpfs19.sh index ab1e96835955..4c8843ae1522 100755 --- a/tools/test/stress2/misc/tmpfs19.sh +++ b/tools/test/stress2/misc/tmpfs19.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/tmpfs2.sh b/tools/test/stress2/misc/tmpfs2.sh index 80885c331e14..09a2cfd68266 100755 --- a/tools/test/stress2/misc/tmpfs2.sh +++ b/tools/test/stress2/misc/tmpfs2.sh @@ -45,13 +45,15 @@ if [ $# -eq 0 ]; then else if [ $1 = find ]; then - for i in `jot 1024`; do + start=`date +%s` + while [ $((`date +%s`- start)) -lt 300 ]; do find ${mntpoint}* -type f > /dev/null 2>&1 done else # The test: Parallel mount and unmounts - for i in `jot 1024`; do + start=`date +%s` + while [ $((`date +%s`- start)) -lt 300 ]; do m=$1 opt=`[ $(( m % 2 )) -eq 0 ] && echo -f` mount -t tmpfs tmpfs ${mntpoint}$m diff --git a/tools/test/stress2/misc/tmpfs20.sh b/tools/test/stress2/misc/tmpfs20.sh index 763d70a49ae8..80fa04936c4f 100755 --- a/tools/test/stress2/misc/tmpfs20.sh +++ b/tools/test/stress2/misc/tmpfs20.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/tmpfs21.sh b/tools/test/stress2/misc/tmpfs21.sh index 295ba0bd20c0..936f2c125564 100755 --- a/tools/test/stress2/misc/tmpfs21.sh +++ b/tools/test/stress2/misc/tmpfs21.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Peter Holm # diff --git a/tools/test/stress2/misc/tmpfs22.sh b/tools/test/stress2/misc/tmpfs22.sh index 4439ad1bf1d5..0912b03b5848 100755 --- a/tools/test/stress2/misc/tmpfs22.sh +++ b/tools/test/stress2/misc/tmpfs22.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/tmpfs23.sh b/tools/test/stress2/misc/tmpfs23.sh index 2f956d512dda..170f4c10cb8b 100755 --- a/tools/test/stress2/misc/tmpfs23.sh +++ b/tools/test/stress2/misc/tmpfs23.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/tmpfs24.sh b/tools/test/stress2/misc/tmpfs24.sh new file mode 100755 index 000000000000..eb366cddc127 --- /dev/null +++ b/tools/test/stress2/misc/tmpfs24.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# A SEEK_HOLE / SEEK_DATA test scenario + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +prog=$(basename "$0" .sh) +exp=/tmp/$prog.exp +here=`pwd` +log=/tmp/$prog.log + +cc -o /tmp/lsholes -Wall -Wextra -O2 $here/../tools/lsholes.c | exit 1 +cat > $exp <<EXP +Min hole size is 4096, file size is 524288000. +data #1 @ 0, size=4096) +hole #2 @ 4096, size=4096 +data #3 @ 8192, size=4096) +hole #4 @ 12288, size=4096 +data #5 @ 16384, size=4096) +hole #6 @ 20480, size=524267520 +EXP + +set -eu +mount -t tmpfs dummy $mntpoint +set +e + +file=$mntpoint/file +truncate -s 500m $file +bs=`getconf MIN_HOLE_SIZE $file` +printf "\001" | dd of=$file seek=$((0*bs)) bs=1 count=1 conv=notrunc status=none +printf "\002" | dd of=$file seek=$((2*bs)) bs=1 count=1 conv=notrunc status=none +printf "\003" | dd of=$file seek=$((4*bs)) bs=1 count=1 conv=notrunc status=none +s1=0 +s2=0 +/tmp/lsholes $file > $log 2>&1; s1=$? + +cat $log +diff -u $exp $log || s2=1 + +umount $mntpoint +rm -f /tmp/lsholes $exp $log +exit $((s1 + s2)) diff --git a/tools/test/stress2/misc/tmpfs25.sh b/tools/test/stress2/misc/tmpfs25.sh new file mode 100755 index 000000000000..b4ee7bdeef34 --- /dev/null +++ b/tools/test/stress2/misc/tmpfs25.sh @@ -0,0 +1,86 @@ +#!/bin/sh + +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# Regression test for: +# Bug 223015 - [tmpfs] [patch] tmpfs does not support sparse files + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +set -eu +prog=$(basename "$0" .sh) +cont=/tmp/$prog.cont +sync=/tmp/$prog.sync +mount | grep -q "on $mntpoint " && umount $mntpoint +mount -t tmpfs -o size=100m dummy $mntpoint +iused=`df $mntpoint | tail -1 | awk '{print $3}'` + +list="1m 10m 40m 45m 49m 50m 60m 100m 1g 4g" +r=0 +for s in $list; do + truncate -s $s $mntpoint/sparse || { + echo "truncate -s $s failed" + r=1; break 2 + } + rm $mntpoint/sparse || break + used=`df $mntpoint | tail -1 | awk '{print $3}'` + [ $used -ne $iused ] && { + echo "truncate -s $s test: $iused / $used"; r=1; break; } +done + +touch $cont +for i in `jot 1000`; do + [ $r -ne 0 ] && break + file=$mntpoint/sparse.$i + for s in $list; do + [ ! -f $cont ] && break + for n in `jot 300`; do [ -f $sync ] && break; sleep .2; done + truncate -s $s $file || { + echo "truncate -s $s failed" + rm -f $cont + break + } + [ -f $file ] || { echo "No file $file"; break; } + rm $file || break + done & +done +touch $sync +wait + +used=`df $mntpoint | tail -1 | awk '{print $3}'` +if [ $used -ne $iused ]; then + [ `ls -al $mntpoint | wc -l` -gt 3 ] && + ls -al $mntpoint | head -10 + df -i $mntpoint + fstat -f $mntpoint +fi +umount $mntpoint +rm -f $cont $sync + +exit $r diff --git a/tools/test/stress2/misc/tmpfs26.sh b/tools/test/stress2/misc/tmpfs26.sh new file mode 100755 index 000000000000..25fa59ff37c3 --- /dev/null +++ b/tools/test/stress2/misc/tmpfs26.sh @@ -0,0 +1,179 @@ +#!/bin/sh + +# Bug 272678 - VFS: Incorrect data in read from concurrent write + +# Test scenario by: Kristian Nielsen <knielsen@knielsen-hq.org> + +. ../default.cfg + +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +#include <stdio.h> +#include <pthread.h> +#include <sys/select.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> + +#define MAGIC 0x42 + +const char *filename = "testfile.bin"; + +static FILE *write_file; +static FILE *read_file; +static pthread_mutex_t write_mutex; +static pthread_cond_t write_cond; +static pthread_mutex_t read_mutex; +static pthread_cond_t read_cond; +static pthread_mutex_t state_mutex; +static pthread_cond_t state_cond; +static int write_state; +static int read_state; + +void * +writer_routine(void *arg __unused) +{ + unsigned char data[44]; + + memset(data, MAGIC, sizeof(data)); + pthread_mutex_lock(&write_mutex); + + for (;;) { + + while (write_state != 1) + pthread_cond_wait(&write_cond, &write_mutex); + + fwrite(data, 1, sizeof(data), write_file); + fflush(write_file); + + pthread_mutex_lock(&state_mutex); + write_state = 2; + pthread_cond_signal(&state_cond); + pthread_mutex_unlock(&state_mutex); + } +} + +void * +reader_routine(void *arg __unused) +{ + + for (;;) { + unsigned char buf[387]; + int len; + + while (read_state != 1) + pthread_cond_wait(&read_cond, &read_mutex); + + len = fread(buf, 1, sizeof(buf), read_file); + if (len < (int)sizeof(buf) && ferror(read_file)) { + perror(" read file"); + exit(1); + } + for (int i = 0; i < len; ++i) { + if (buf[i] != MAGIC) { + fprintf(stderr, "ERROR! invalid value read 0x%2x at %d of %d, pos %ld\n", + buf[i], i, len, ftell(read_file)); + exit(126); + } + } + + pthread_mutex_lock(&state_mutex); + read_state = 2; + pthread_cond_signal(&state_cond); + pthread_mutex_unlock(&state_mutex); + } +} + +void +create_threads(void) +{ + pthread_t write_thread_id, read_thread_id; + pthread_attr_t attr; + + pthread_mutex_init(&write_mutex, NULL); + pthread_mutex_init(&read_mutex, NULL); + pthread_mutex_init(&state_mutex, NULL); + pthread_cond_init(&write_cond, NULL); + pthread_cond_init(&read_cond, NULL); + pthread_cond_init(&state_cond, NULL); + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&write_thread_id, &attr, writer_routine, NULL); + pthread_create(&read_thread_id, &attr, reader_routine, NULL); +} + +int +main(int argc, char *argv[]) +{ + int num_iter = 1000; + int i; + unsigned char buf[343]; + + if (argc >= 2) + num_iter = atoi(argv[1]); + + write_state = 0; + read_state = 0; + + create_threads(); + memset(buf, MAGIC, sizeof(buf)); + + for (i = 0; i < num_iter; ++i) { + /* Write the first part of the file. */ + pthread_mutex_lock(&write_mutex); + write_file = fopen(filename, "wb"); + if (!write_file) { + perror(" open file"); + exit(1); + } + fwrite(buf, 1, sizeof(buf), write_file); + fflush(write_file); + + /* Open a read handle on the file. */ + pthread_mutex_lock(&read_mutex); + read_file = fopen(filename, "rb"); + if (!read_file) { + perror(" open read file"); + exit(1); + } + + write_state = 1; + read_state = 1; + pthread_cond_signal(&write_cond); + pthread_mutex_unlock(&write_mutex); + pthread_cond_signal(&read_cond); + pthread_mutex_unlock(&read_mutex); + + pthread_mutex_lock(&state_mutex); + while (write_state != 2 || read_state != 2) + pthread_cond_wait(&state_cond, &state_mutex); + pthread_mutex_unlock(&state_mutex); + + /* Close and remove the file, ready for another iteration. */ + pthread_mutex_lock(&write_mutex); + fclose(write_file); + write_state = 0; + pthread_mutex_unlock(&write_mutex); + + pthread_mutex_lock(&read_mutex); + fclose(read_file); + read_state = 0; + pthread_mutex_unlock(&read_mutex); + + unlink(filename); + } + + return (0); +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O2 /tmp/$prog.c -lpthread || exit 1 + +mount -t tmpfs dummy $mntpoint +cd $mntpoint +/tmp/$prog; s=$? +cd - +umount $mntpoint + +rm /tmp/$prog /tmp/$prog.c +exit $s diff --git a/tools/test/stress2/misc/tmpfs27.sh b/tools/test/stress2/misc/tmpfs27.sh new file mode 100755 index 000000000000..5479dcd9188a --- /dev/null +++ b/tools/test/stress2/misc/tmpfs27.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# umount FS with memory mapped file. tmpfs version. + +# "panic: object with writable mappings does not have a reference" seen: +# https://people.freebsd.org/~pho/stress/log/log0518.txt + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +set -eu +prog=$(basename "$0" .sh) +here=`pwd` +mp1=$mntpoint + +mount -t tmpfs dummy $mp1 + +export RUNDIR=$mp1/stressX +export runRUNTIME=2m +export LOAD=70 +export mmapLOAD=100 +export TESTPROGS="testcases/mmap/mmap testcases/swap/swap" +set +e + +(cd ..; ./testcases/run/run $TESTPROGS > /dev/null 2>&1) & rpid=$! +sleep 5 + +start=`date +%s` +while [ $((`date +%s` - start)) -lt 120 ]; do + umount -f $mp1 && + mount -t tmpfs dummy $mp1 + mount | grep -q "on $mp1 " || break + pgrep -q mmap || break +done +pkill run swap mmap +while pgrep -q swap; do pkill swap; done +wait $rpid + +while mount | grep -q "on $mp1 "; do + umount $mp1 +done +exit 0 diff --git a/tools/test/stress2/misc/tmpfs28.sh b/tools/test/stress2/misc/tmpfs28.sh new file mode 100755 index 000000000000..d73e957b7f28 --- /dev/null +++ b/tools/test/stress2/misc/tmpfs28.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# A SEEK_HOLE / SEEK_DATA test scenario, variation of tmpfs24.sh + +# A regression test for "40c1672e886b - main - swap_pager: fix +# seek_data with invalid first page" + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +prog=$(basename "$0" .sh) +exp=/tmp/$prog.exp +here=`pwd` +log=/tmp/$prog.log + +cc -o /tmp/lsholes -Wall -Wextra -O2 $here/../tools/lsholes.c | exit 1 +cat > $exp <<EXP +Min hole size is 4096, file size is 524288000. +data #1 @ 0, size=4096) +hole #2 @ 4096, size=4096 +data #3 @ 8192, size=4096) +hole #4 @ 12288, size=4096 +data #5 @ 16384, size=4096) +hole #6 @ 20480, size=524267520 +EXP + +set -eu +mount -t tmpfs dummy $mntpoint +set +e + +file=$mntpoint/file +copy=$mntpoint/copy +truncate -s 500m $file +bs=`getconf MIN_HOLE_SIZE $file` +printf "\001" | dd of=$file seek=$((0*bs)) bs=1 count=1 conv=notrunc status=none +printf "\002" | dd of=$file seek=$((2*bs)) bs=1 count=1 conv=notrunc status=none +printf "\003" | dd of=$file seek=$((4*bs)) bs=1 count=1 conv=notrunc status=none +s1=0 +s2=0 +s3=0 +/tmp/lsholes $file > $log 2>&1 || s1=1 + +cmp -s $exp $log || { s2=2; sdiff $exp $log; } + +$here/../testcases/swap/swap -t 2m -i 20 -h > /dev/null & +sleep 10 +cp $file $copy +while pkill swap; do :; done +wait +cmp $file $copy || { echo "copy error"; s3=4; } + +umount $mntpoint +rm -f /tmp/lsholes $exp $log +exit $((s1 + s2 + s3)) diff --git a/tools/test/stress2/misc/tmpfs8.sh b/tools/test/stress2/misc/tmpfs8.sh index b17a329f69e7..b78f0e74562b 100755 --- a/tools/test/stress2/misc/tmpfs8.sh +++ b/tools/test/stress2/misc/tmpfs8.sh @@ -28,7 +28,7 @@ [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 -# Demonstrate rename(2) cache problem for tmpfs(5). Fixed in r226987. +# Demonstrate rename(2) cache problem for tmpfs(4). Fixed in r226987. # Variation of rename6.sh . ../default.cfg diff --git a/tools/test/stress2/misc/trim8.sh b/tools/test/stress2/misc/trim8.sh index f31a10b5be25..2aafac7cf5ab 100755 --- a/tools/test/stress2/misc/trim8.sh +++ b/tools/test/stress2/misc/trim8.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/truncate8.sh b/tools/test/stress2/misc/truncate8.sh index 132468b3ca78..e3192262e4f3 100755 --- a/tools/test/stress2/misc/truncate8.sh +++ b/tools/test/stress2/misc/truncate8.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/truncate9.sh b/tools/test/stress2/misc/truncate9.sh index c199605e70a8..75526dcabf19 100755 --- a/tools/test/stress2/misc/truncate9.sh +++ b/tools/test/stress2/misc/truncate9.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/truss2.sh b/tools/test/stress2/misc/truss2.sh index 6a5743550b04..0bf769a485ab 100755 --- a/tools/test/stress2/misc/truss2.sh +++ b/tools/test/stress2/misc/truss2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # diff --git a/tools/test/stress2/misc/udp2.sh b/tools/test/stress2/misc/udp2.sh index 3cd72d82734b..f305fc554c24 100755 --- a/tools/test/stress2/misc/udp2.sh +++ b/tools/test/stress2/misc/udp2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/ufsbench.sh b/tools/test/stress2/misc/ufsbench.sh index 03e8ba64e2f6..58abba0971c8 100755 --- a/tools/test/stress2/misc/ufsbench.sh +++ b/tools/test/stress2/misc/ufsbench.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/umount3.sh b/tools/test/stress2/misc/umount3.sh index c6920b80f99d..b28230d8b3af 100755 --- a/tools/test/stress2/misc/umount3.sh +++ b/tools/test/stress2/misc/umount3.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/umount4.sh b/tools/test/stress2/misc/umount4.sh index e46f319959a0..bcd062bb8106 100755 --- a/tools/test/stress2/misc/umount4.sh +++ b/tools/test/stress2/misc/umount4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Peter Holm # diff --git a/tools/test/stress2/misc/umountf11.sh b/tools/test/stress2/misc/umountf11.sh index b2a694037420..b41ec6bc5737 100755 --- a/tools/test/stress2/misc/umountf11.sh +++ b/tools/test/stress2/misc/umountf11.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/umountf12.sh b/tools/test/stress2/misc/umountf12.sh index 8a13f8fd480a..af74cf37a0b8 100755 --- a/tools/test/stress2/misc/umountf12.sh +++ b/tools/test/stress2/misc/umountf12.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/umountf4.sh b/tools/test/stress2/misc/umountf4.sh index 4f5ea0fff660..e26555e7c6f3 100755 --- a/tools/test/stress2/misc/umountf4.sh +++ b/tools/test/stress2/misc/umountf4.sh @@ -65,13 +65,15 @@ if [ $# -eq 0 ]; then else if [ $1 = find ]; then - for i in `jot 100`; do + start=`date +%s` + while [ $((`date +%s`- start)) -lt 300 ]; do find ${mntpoint}* -type f > /dev/null 2>&1 done else # The test: Parallel mount and unmounts - for i in `jot 100`; do + start=`date +%s` + while [ $((`date +%s`- start)) -lt 300 ]; do m=$1 opt=`[ $(( m % 2 )) -eq 0 ] && echo -f` mount $opt /dev/md${m} ${mntpoint}$m diff --git a/tools/test/stress2/misc/umountf6.sh b/tools/test/stress2/misc/umountf6.sh index aeb4454ea69c..628342689b38 100755 --- a/tools/test/stress2/misc/umountf6.sh +++ b/tools/test/stress2/misc/umountf6.sh @@ -65,13 +65,15 @@ if [ $# -eq 0 ]; then else if [ $1 = find ]; then - for i in `jot 100`; do + start=`date +%s` + while [ $((`date +%s`- start)) -lt 300 ]; do find ${mntpoint}* -type f > /dev/null 2>&1 done else # The test: Parallel mount and unmounts - for i in `jot 100`; do + start=`date +%s` + while [ $((`date +%s`- start)) -lt 300 ]; do m=$1 opt=`[ $(( m % 2 )) -eq 0 ] && echo -f` mount $opt /dev/md${m} ${mntpoint}$m diff --git a/tools/test/stress2/misc/unionfs13.sh b/tools/test/stress2/misc/unionfs13.sh index 9c2d57425053..0202e782a11c 100755 --- a/tools/test/stress2/misc/unionfs13.sh +++ b/tools/test/stress2/misc/unionfs13.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm # diff --git a/tools/test/stress2/misc/unionfs14.sh b/tools/test/stress2/misc/unionfs14.sh index ca9fa3a5b274..054e76e4b476 100755 --- a/tools/test/stress2/misc/unionfs14.sh +++ b/tools/test/stress2/misc/unionfs14.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/unionfs15.sh b/tools/test/stress2/misc/unionfs15.sh new file mode 100755 index 000000000000..87cea7c0b15d --- /dev/null +++ b/tools/test/stress2/misc/unionfs15.sh @@ -0,0 +1,86 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# O_PATH test scenario. Variation of nullfs29.sh + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +md1=$mdstart +md2=$((md1 + 1)) +mp1=/mnt$md1 +mp2=/mnt$md2 +mkdir -p $mp1 $mp2 +set -e +for i in $mp1 $mp2; do + mount | grep -q "on $i " && umount -f $i +done +for i in $md1 $md2; do + mdconfig -l | grep -q md$i && mdconfig -d -u $i +done + +mdconfig -a -t swap -s 2g -u $md1 +mdconfig -a -t swap -s 2g -u $md2 +newfs $newfs_flags -n md$md1 > /dev/null +newfs $newfs_flags -n md$md2 > /dev/null +mount /dev/md$md1 $mp1 +mount /dev/md$md2 $mp2 +mount -t unionfs -o noatime $mp1 $mp2 +set +e + +cat > /tmp/unionfs15.c <<EOF +#include <sys/stat.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int +main(void) { + int new_dir, new_file, ret; + struct stat sb; + char *dir = "test2"; + char *path= "test2/what2"; + + if (mkdir(dir, 0755) == -1) + err(1, "mkdir(test2)"); + new_dir = openat(AT_FDCWD, dir, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_PATH, 0700); + if (new_dir == -1) + err(1, "openat(%s)", dir); + + ret = fstatat(new_dir, "what2", &sb, AT_SYMLINK_NOFOLLOW); + if (ret == 0) + errx(1, "Expected fstatat() to fail"); + if (ret == -1 && errno != ENOENT) + err(1, "fstatat(%s)", dir); + + close(new_dir); + new_file = openat(AT_FDCWD, path, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0644); + if (new_file== -1) + err(1, "openat(%s)", path); +} + +EOF +mycc -o /tmp/unionfs15 -Wall -Wextra -O2 /tmp/unionfs15.c || exit 1 +cd $mp2 +/tmp/unionfs15; s=$? +cd $here +umount $mp2 + +while mount | grep -Eq "on $mp2 .*unionfs"; do + umount $mp2 && break + sleep 5 +done +umount $mp2 +umount $mp1 +mdconfig -d -u $md2 +mdconfig -d -u $md1 +rm -f /tmp/unionfs15.c /tmp/unionfs15 +exit $s diff --git a/tools/test/stress2/misc/unionfs16.sh b/tools/test/stress2/misc/unionfs16.sh new file mode 100755 index 000000000000..c1c65f7d8313 --- /dev/null +++ b/tools/test/stress2/misc/unionfs16.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# No problems seen with this test scenario + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +[ -d /usr/src/tools/test/stress2 ] || exit 0 +prog=$(basename "$0" .sh) +log=/tmp/$prog.log +md1=$mdstart +md2=$((md1 + 1)) +mp1=/mnt$md1 +mp2=/mnt$md2 +s=0 + +mkdir -p $mp1 $mp2 +set -e +for i in $mp1 $mp2; do + mount | grep -q "on $i " && umount -f $i +done +for i in $md1 $md2; do + mdconfig -l | grep -q md$i && mdconfig -d -u $i +done + +mdconfig -a -t swap -s 3g -u $md1 +mdconfig -a -t swap -s 3g -u $md2 +newfs $newfs_flags -n md$md1 > /dev/null +newfs $newfs_flags -n md$md2 > /dev/null +mount /dev/md$md1 $mp1 +mount /dev/md$md2 $mp2 +(cd $mp1; cp -a /usr/src/tools/test/stress2 .) +(cd $mp2; cp -a /usr/src/tools/test/stress2 .) +rm $mp1/stress2/testcases/run/run +rm $mp2/stress2/testcases/swap/swap +mount -u -o ro $mp1 +mount -t unionfs -o below $mp1 $mp2 +rm $mp2/stress2/testcases/mkdir/mkdir +chmod 777 $mp2 +set +e + +(cd $mp2/stress2; make > /dev/null 2>&1) +export RUNDIR=$mp2/stressX +export runRUNTIME=1m +su $testuser -c "cd $mp2/stress2; ./run.sh vfs.cfg" > /dev/null 2>&1 +umount $mp2 + +while mount | grep -Eq "unionfs.* on $mp2 "; do + umount $mp2 && break + sleep 5 +done +fsck_ffs -fy /dev/md$md2 > $log 2>&1 +grep -Eq "WAS MODIFIED" $log && { cat $log; s=1; } +umount $mp2 +umount $mp1 +mdconfig -d -u $md1 +mdconfig -d -u $md2 +rm -f $log +exit $s diff --git a/tools/test/stress2/misc/unionfs17.sh b/tools/test/stress2/misc/unionfs17.sh new file mode 100755 index 000000000000..9ddbd1cab8cb --- /dev/null +++ b/tools/test/stress2/misc/unionfs17.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# unionfs(4) test +# Variation of unionfs7.sh, but with tmpfs + +# "mkdir: rmdir(d17) Directory not empty" seen. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +mp1=/mnt$mdstart +mp2=/mnt$((mdstart + 1)) +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 + +mount -t unionfs -o noatime $mp1 $mp2 +set +e +export 'INODES=100000' + +export CTRLDIR=$mp2/stressX.control +export INCARNATIONS=10 +export LOAD=80 +export RUNDIR=$mp2/stressX +export runRUNTIME=5m +export rwLOAD=80 +export symlinkLOAD=80 + +export TESTPROGS=" +testcases/lockf2/lockf2 +testcases/symlink/symlink +testcases/openat/openat +testcases/rw/rw +testcases/fts/fts +testcases/link/link +testcases/lockf/lockf +testcases/creat/creat +testcases/mkdir/mkdir +testcases/rename/rename +testcases/mkfifo/mkfifo +testcases/dirnprename/dirnprename +testcases/dirrename/dirrename +testcases/swap/swap +" + +cp -r ../../stress2 $mp2 +export TESTPROGS=`echo $TESTPROGS | sed 's/\n/ /g'` + +set +e +chmod 777 $mp2 +su $testuser -c \ + "(cd $mp2/stress2; ./testcases/run/run $TESTPROGS)" + +while mount | grep -Eq "on $mp2 .*unionfs"; do + umount $mp2 && 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/unionfs18.sh b/tools/test/stress2/misc/unionfs18.sh new file mode 100755 index 000000000000..a7840db263e1 --- /dev/null +++ b/tools/test/stress2/misc/unionfs18.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Simple unionfs(4) + tmpfs(4) test + +# "rmdir: d2: Directory not empty" seen. + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +. ../default.cfg + +mp1=/mnt$mdstart +mp2=/mnt$((mdstart + 1)) +mkdir -p $mp1 $mp2 +set -e +for i in $mp1 $mp2; do + mount | grep -q "on $i " && umount -f $i +done + +md1=$mdstart +md2=$((md1 + 1)) +mp1=/mnt$md1 +mp2=/mnt$md2 +mkdir -p $mp1 $mp2 +for i in $mp1 $mp2; do + mount | grep -q "on $i " && umount -f $i +done + +if [ $# -eq 0 ]; then + echo "tmpfs version" + mount -o size=4g -t tmpfs dummy $mp1 + mount -o size=4g -t tmpfs dummy $mp2 +else + echo "UFS version" + for i in $md1 $md2; do + mdconfig -l | grep -q md$i && mdconfig -d -u $i + done + mdconfig -a -t swap -s 4g -u $md1 + mdconfig -a -t swap -s 4g -u $md2 + newfs $newfs_flags -n md$md1 > /dev/null + newfs $newfs_flags -n md$md2 > /dev/null + mount /dev/md$md1 $mp1 + mount /dev/md$md2 $mp2 +fi + +mount -t unionfs -o noatime $mp1 $mp2 +set +e + +N=3 # Tree depth +here=`pwd` +cd $mp2 +mkdir dir; cd dir +for j in `seq 1 $N`; do + mkdir d$j && cd d$j +done +for j in `seq $N 1`; do + cd .. && rmdir d$j +done +cd .. +rmdir dir || { s=1; find dir -ls; } +cd $here + +while mount | grep -Eq "on $mp2 .*unionfs"; do + umount $mp2 && break + sleep 5 +done +umount $mp2 +umount $mp1 +exit $s diff --git a/tools/test/stress2/misc/unionfs19.sh b/tools/test/stress2/misc/unionfs19.sh new file mode 100755 index 000000000000..a4e31ad0857e --- /dev/null +++ b/tools/test/stress2/misc/unionfs19.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# umount FS with memory mapped file +# "panic: general protection fault" seen: +# https://people.freebsd.org/~pho/stress/log/log0519.txt + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 + +. ../default.cfg + +prog=$(basename "$0" .sh) +here=`pwd` +log=/tmp/$prog.log +md1=$mdstart +md2=$((md1 + 1)) +mp1=/mnt$md1 +mp2=/mnt$md2 + +set -e +mdconfig -l | grep -q md$md && mdconfig -d -u $md1 +mdconfig -l | grep -q md$u2 && mdconfig -d -u $md2 + +mdconfig -s 2g -u $md1 +newfs $newfs_flags /dev/md$md1 > /dev/null +mdconfig -s 2g -u $md2 +newfs $newfs_flags /dev/md$md2 > /dev/null + +mkdir -p $mp1 $mp2 +mount /dev/md$md1 $mp1 +mount /dev/md$md2 $mp2 +mount -t unionfs -o noatime $mp1 $mp2 +mount | grep -E "$mp1|$mp2" +set +e + +export RUNDIR=$mp2/stressX +export runRUNTIME=2m +export LOAD=70 +export mmapLOAD=100 +export TESTPROGS="testcases/mmap/mmap testcases/swap/swap" + +(cd ..; ./testcases/run/run $TESTPROGS > /dev/null 2>&1) & rpid=$! +sleep 5 + +tail -F -n 0 /var/log/messages > $log & lpid=$! + +start=`date +%s` +while [ $((`date +%s` - start)) -lt 120 ]; do + umount -f $mp2 && + mount -t unionfs -o noatime $mp1 $mp2 + sleep 5 + mount | grep -q unionfs || break + pgrep -q mmap || break +done +pkill run swap mmap +while pgrep -q swap; do pkill swap; done +wait $rpid + +umount $mp2 # The unionfs mount +umount $mp2 +umount $mp1 + +mdconfig -d -u $md1 +mdconfig -d -u $md2 + +kill $lpid && wait $lpid +grep -m 1 "pager read error" $log && s=1 || s=0 +rm $log +exit $s diff --git a/tools/test/stress2/misc/unionfs4.sh b/tools/test/stress2/misc/unionfs4.sh index 2355005c1f8b..e23f90004a88 100755 --- a/tools/test/stress2/misc/unionfs4.sh +++ b/tools/test/stress2/misc/unionfs4.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # @@ -52,6 +52,8 @@ done mdconfig -a -t swap -s 2g -u $md1 mdconfig -a -t swap -s 2g -u $md2 +[ "$newfs_flags" = "-U" ] && + newfs_flags="-j" # "out of inodes" work around newfs $newfs_flags -n md$md1 > /dev/null newfs $newfs_flags -n md$md2 > /dev/null mount /dev/md$md1 $mp1 diff --git a/tools/test/stress2/misc/unionfs5.sh b/tools/test/stress2/misc/unionfs5.sh index 5e12ffbf5abd..a45ffde5c0b2 100755 --- a/tools/test/stress2/misc/unionfs5.sh +++ b/tools/test/stress2/misc/unionfs5.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # @@ -50,8 +50,8 @@ for i in $md1 $md2; do mdconfig -l | grep -q md$i && mdconfig -d -u $i done -mdconfig -a -t swap -s 2g -u $md1 -mdconfig -a -t swap -s 2g -u $md2 +mdconfig -a -t swap -s 5g -u $md1 +mdconfig -a -t swap -s 5g -u $md2 newfs $newfs_flags -n md$md1 > /dev/null newfs $newfs_flags -n md$md2 > /dev/null mount /dev/md$md1 $mp1 @@ -68,11 +68,12 @@ else echo "Using FFS" export RUNDIR=$mp1/stressX fi -export runRUNTIME=2m +export CTRLDIR=$mp2/stressX.control +export runRUNTIME=2m -(cd ../testcases/mkdir; ./mkdir -t 2m -i 20) +(cd ../testcases/mkdir; ./mkdir -t 2m -i 20 -l 100) -find $RUNDIR -ls | head -5 +find $RUNDIR -ls | grep -v 'stressX$' | head -5 while mount | grep -Eq "on $mp2 .*unionfs"; do umount $mp2 && break sleep 5 diff --git a/tools/test/stress2/misc/unionfs6.sh b/tools/test/stress2/misc/unionfs6.sh index 7291a6f61fd8..cae1995a2e0d 100755 --- a/tools/test/stress2/misc/unionfs6.sh +++ b/tools/test/stress2/misc/unionfs6.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # @@ -27,7 +27,7 @@ # SUCH DAMAGE. # -# unionfs(8) test +# unionfs(4) test # "panic: ufs dir vp 0xfffffe0157351068 ip 0xfffffe016a63d488 flags 0x3c06" seen [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 @@ -57,6 +57,10 @@ mount -t unionfs -o noatime $mp1 $mp2 set +e mount | grep -E "$mp1|$mp2" +set `df -ik $mp2 | tail -1 | awk '{print $4,$7}'` +export KBLOCKS=$(($1 / 4)) +export INODES=$(($2 / 4)) + export CTRLDIR=$mp2/stressX.control export INCARNATIONS=10 export LOAD=80 diff --git a/tools/test/stress2/misc/unionfs7.sh b/tools/test/stress2/misc/unionfs7.sh index ad4514c60532..6adcd01a5f83 100755 --- a/tools/test/stress2/misc/unionfs7.sh +++ b/tools/test/stress2/misc/unionfs7.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # @@ -27,7 +27,7 @@ # SUCH DAMAGE. # -# unionfs(8) test +# unionfs(4) test # "unionfs_get_node_status: 0xfffffe018f356770 is not exclusive locked but # should be" seen. @@ -60,6 +60,10 @@ mount -t unionfs -o noatime $mp1 $mp2 set +e mount | grep -E "$mp1|$mp2" +set `df -ik $mp2 | tail -1 | awk '{print $4,$7}'` +export KBLOCKS=$(($1 / 4)) +export INODES=$(($2 / 4)) + export CTRLDIR=$mp2/stressX.control export INCARNATIONS=10 export LOAD=80 diff --git a/tools/test/stress2/misc/unionfs8.sh b/tools/test/stress2/misc/unionfs8.sh index b0d9deb354d2..fdc37b16ff03 100755 --- a/tools/test/stress2/misc/unionfs8.sh +++ b/tools/test/stress2/misc/unionfs8.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # @@ -27,7 +27,7 @@ # SUCH DAMAGE. # -# unionfs(8) test with a cd9660 file system +# unionfs(4) test with a cd9660(4) file system # "panic: unionfs_noderem: vnode 0xfffffe014f9259c8 locked recursively" seen # https://people.freebsd.org/~pho/stress/log/log0233.txt @@ -51,8 +51,8 @@ for i in $md1 $md2; do mdconfig -l | grep -q md$i && mdconfig -d -u $i done -mdconfig -a -t swap -s 4g -u $md1 -mdconfig -a -t swap -s 4g -u $md2 +mdconfig -a -t swap -s 5g -u $md1 +mdconfig -a -t swap -s 5g -u $md2 newfs $newfs_flags -n md$md1 > /dev/null newfs $newfs_flags -n md$md2 > /dev/null mount /dev/md$md1 $mp1 @@ -69,6 +69,10 @@ mount -t unionfs -o below $mp1 $mp2 set +e mount | grep -E "$mp1|$mp2" +set `df -ik $mp2 | tail -1 | awk '{print $4,$7}'` +export KBLOCKS=$(($1 / 6)) +export INODES=$(($2 / 6)) + export CTRLDIR=$mp2/stressX.control export INCARNATIONS=10 export LOAD=80 diff --git a/tools/test/stress2/misc/unionfs9.sh b/tools/test/stress2/misc/unionfs9.sh index 80ab45e38f88..700eed13aeb5 100755 --- a/tools/test/stress2/misc/unionfs9.sh +++ b/tools/test/stress2/misc/unionfs9.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # @@ -33,6 +33,7 @@ # https://people.freebsd.org/~pho/stress/log/log0205.txt # https://people.freebsd.org/~pho/stress/log/log0226.txt +# https://people.freebsd.org/~pho/stress/log/log0404.txt [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 . ../default.cfg diff --git a/tools/test/stress2/misc/unix_socket.sh b/tools/test/stress2/misc/unix_socket.sh index a5486dd7d4f0..c4283f30de0d 100755 --- a/tools/test/stress2/misc/unix_socket.sh +++ b/tools/test/stress2/misc/unix_socket.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/unix_socket_detach.sh b/tools/test/stress2/misc/unix_socket_detach.sh index 66670daf5639..6d201273ac05 100755 --- a/tools/test/stress2/misc/unix_socket_detach.sh +++ b/tools/test/stress2/misc/unix_socket_detach.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2016 Mark Johnston <markj@FreeBSD.org> # diff --git a/tools/test/stress2/misc/vfork.sh b/tools/test/stress2/misc/vfork.sh index 20db95c2b9be..cabc30ebaa6c 100755 --- a/tools/test/stress2/misc/vfork.sh +++ b/tools/test/stress2/misc/vfork.sh @@ -31,6 +31,9 @@ # "panic: failed to set signal flags for ast p ... fl 4" seen. # Fixed in r302999. +# Test scenario updated after commit: +# ecc662c749b1 - main - PT_ATTACH: do not interrupt interruptible sleeps + . ../default.cfg cd /tmp @@ -46,38 +49,32 @@ main(void) fprintf(stderr, "%d\n", getpid()); if ((pid = vfork()) == 0) { -#if 0 - if (ptrace(PT_TRACE_ME, 0, 0, 0) == -1) - err(1, "PT_TRACEME"); -#endif sleep(30); _exit(0); } if (pid == -1) err(1, "vfork"); - - return (0); } EOF -mycc -o vfork1 -Wall -Wextra -g vfork1.c -rm vfork1.c +mycc -o vfork1 -Wall -Wextra -g vfork1.c || exit 1 +rm vfork1.c cat > vfork2.c <<- EOF #include <sys/types.h> +#include <sys/ptrace.h> +#include <sys/resource.h> +#include <sys/time.h> +#include <sys/wait.h> #include <err.h> #include <errno.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <strings.h> -#include <sys/ptrace.h> -#include <sys/resource.h> -#include <sys/time.h> -#include <sys/wait.h> #include <unistd.h> int -main(int argc, char **argv) +main(int argc, char *argv[]) { pid_t pid, rpid; struct rusage ru; @@ -86,6 +83,7 @@ main(int argc, char **argv) if (argc != 2) errx(1, "Usage: %s <pid>", argv[0]); pid = atoi(argv[1]); + status = 0; if (pid == -1) err(1, "fork()"); @@ -99,24 +97,17 @@ main(int argc, char **argv) err(0, "OK wait4"); } if (rpid == 0) { -// fprintf(stderr, "No rusage info.\n"); if (ptrace(PT_DETACH, pid, NULL, 0) == -1) err(1, "ptrace(%d) detach", pid); - if (wait(&status) == -1) - err(1, "wait"); } else { fprintf(stderr, "FAIL Got unexpected rusage.\n"); if (ru.ru_utime.tv_sec != 0) fprintf(stderr, "FAIL tv_sec\n"); } - if (status != 0x4000) - fprintf(stderr, "FAIL Child exit status 0x%x\n", status); - - return (0); } EOF -mycc -o vfork2 -Wall -Wextra -g vfork2.c -rm vfork2.c +mycc -o vfork2 -Wall -Wextra -g vfork2.c || exit 1 +rm vfork2.c ./vfork1 & sleep .2 @@ -127,5 +118,6 @@ childpid=`ps -lx | grep -v grep | grep vfork1 | ./vfork2 $childpid s=$? +pkill vfork1 rm -f vfork1 vfork2 exit $s diff --git a/tools/test/stress2/misc/vm_map.sh b/tools/test/stress2/misc/vm_map.sh index fb2a2b75b5a5..e209d8aacb2c 100755 --- a/tools/test/stress2/misc/vm_map.sh +++ b/tools/test/stress2/misc/vm_map.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/vunref.sh b/tools/test/stress2/misc/vunref.sh index f844a0dd3625..f08035a95694 100755 --- a/tools/test/stress2/misc/vunref.sh +++ b/tools/test/stress2/misc/vunref.sh @@ -82,7 +82,8 @@ if [ $# -eq 0 ]; then else if [ $1 = mmap ]; then touch $RUNDIR/active.$2 - for i in `jot 500`; do + start=`date +%s` + while [ $((`date +%s`- start)) -lt 300 ]; do cd ${mntpoint}$2 /tmp/vunref > /dev/null 2>&1 cd / diff --git a/tools/test/stress2/misc/write2.sh b/tools/test/stress2/misc/write2.sh index 82d7e1c988d7..f1f9deeef374 100755 --- a/tools/test/stress2/misc/write2.sh +++ b/tools/test/stress2/misc/write2.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2022 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/zfs10.sh b/tools/test/stress2/misc/zfs10.sh index 3f3fdd2622d7..9d8ae717dffa 100755 --- a/tools/test/stress2/misc/zfs10.sh +++ b/tools/test/stress2/misc/zfs10.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/zfs11.sh b/tools/test/stress2/misc/zfs11.sh index 97e71a5a13f7..84300aed0c0c 100755 --- a/tools/test/stress2/misc/zfs11.sh +++ b/tools/test/stress2/misc/zfs11.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/zfs12.sh b/tools/test/stress2/misc/zfs12.sh index cfabca2b9f6f..e8f82efc9b9b 100755 --- a/tools/test/stress2/misc/zfs12.sh +++ b/tools/test/stress2/misc/zfs12.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # diff --git a/tools/test/stress2/misc/zfs13.sh b/tools/test/stress2/misc/zfs13.sh index 2ccd4388270d..33630e0f1d75 100755 --- a/tools/test/stress2/misc/zfs13.sh +++ b/tools/test/stress2/misc/zfs13.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm # diff --git a/tools/test/stress2/misc/zfs14.sh b/tools/test/stress2/misc/zfs14.sh index 750119aff941..70b97e950dff 100755 --- a/tools/test/stress2/misc/zfs14.sh +++ b/tools/test/stress2/misc/zfs14.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/misc/zfs15.sh b/tools/test/stress2/misc/zfs15.sh new file mode 100755 index 000000000000..b40474507517 --- /dev/null +++ b/tools/test/stress2/misc/zfs15.sh @@ -0,0 +1,88 @@ +#!/bin/sh + +# Test scenario suggestion by: markj@ + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +kldstat -v | grep -q zfs.ko || { kldload zfs.ko; loaded=1; } || + exit 0 + +. ../default.cfg + +here=`pwd` +level=`jot -r 1 1 3` # Redundancy levels +mp1=/stress2_tank/test +s=0 +u1=$mdstart +u2=$((u1 + 1)) +u3=$((u1 + 2)) +u4=$((u1 + 3)) +u5=$((u1 + 4)) + +set -e +mdconfig -l | grep -q md$u1 && mdconfig -d -u $u1 +mdconfig -l | grep -q md$u2 && mdconfig -d -u $u2 +mdconfig -l | grep -q md$u3 && mdconfig -d -u $u3 +mdconfig -l | grep -q md$u4 && mdconfig -d -u $u4 +mdconfig -l | grep -q md$u5 && mdconfig -d -u $u5 + +mdconfig -s 512m -u $u1 +mdconfig -s 512m -u $u2 +mdconfig -s 512m -u $u3 +mdconfig -s 512m -u $u4 +mdconfig -s 512m -u $u5 + +zpool list | egrep -q "^stress2_tank" && zpool destroy stress2_tank +[ -d /stress2_tank ] && rm -rf /stress2_tank +zpool create stress2_tank raidz$level md$u1 md$u2 md$u3 md$u4 +zfs create stress2_tank/test +set +e + +export RUNDIR=/stress2_tank/test/stressX +export runRUNTIME=5m +export LOAD=80 +export symlinkLOAD=80 +export rwLOAD=80 +export TESTPROGS=" +testcases/lockf2/lockf2 +testcases/symlink/symlink +testcases/openat/openat +testcases/rw/rw +testcases/fts/fts +testcases/link/link +testcases/lockf/lockf +testcases/creat/creat +testcases/mkdir/mkdir +testcases/rename/rename +testcases/mkfifo/mkfifo +testcases/dirnprename/dirnprename +testcases/dirrename/dirrename +testcases/swap/swap +" + +(cd ..; ./testcases/run/run $TESTPROGS > /dev/null 2>&1) & + +sleep 60 +echo "zpool attach stress2_tank raidz$level-0 md$u5" +zpool attach stress2_tank raidz$level-0 md$u5 +sleep 30 +zfs snapshot stress2_tank/test@1 +wait + +while zpool status | grep -q "in progress"; do + sleep 5 +done +zpool scrub stress2_tank +zpool status | grep -q "errors: No known data errors" || + { zpool status; s=1; } + +zfs umount stress2_tank/test +zfs destroy -r stress2_tank +zpool destroy stress2_tank + +mdconfig -d -u $u1 +mdconfig -d -u $u2 +mdconfig -d -u $u3 +mdconfig -d -u $u4 +mdconfig -d -u $u5 +[ -n "$loaded" ] && kldunload zfs.ko +exit $s diff --git a/tools/test/stress2/misc/zfs16.sh b/tools/test/stress2/misc/zfs16.sh new file mode 100755 index 000000000000..258bf9ea4799 --- /dev/null +++ b/tools/test/stress2/misc/zfs16.sh @@ -0,0 +1,105 @@ +#!/bin/sh + +# No problems seen + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +kldstat -v | grep -q zfs.ko || { kldload zfs.ko; loaded=1; } || + exit 0 + +. ../default.cfg + +here=`pwd` +cd /tmp +sed '1,/^EOF/d' < $here/datamove.sh > zfs16.c +mycc -o zfs16 -Wall -O0 -g zfs16.c || exit 1 +rm -f zfs16.c + +mp1=/stress2_tank/test +u1=$mdstart +u2=$((u1 + 1)) + +set -eu +mdconfig -l | grep -q md$u1 && mdconfig -d -u $u1 +mdconfig -l | grep -q md$u2 && mdconfig -d -u $u2 + +mdconfig -s 2g -u $u1 +mdconfig -s 2g -u $u2 + +zpool list | egrep -q "^stress2_tank" && zpool destroy stress2_tank +[ -d /stress2_tank ] && rm -rf /stress2_tank +zpool create stress2_tank md$u1 md$u2 +zfs create stress2_tank/test +set +e + +(cd $here/../testcases/swap; ./swap -t 2m -i 20 -l 100 -h > /dev/null) & +sleep 2 +cd $mp1 +while pgrep -q swap; do + /tmp/zfs16; s=$? + rm -f /stress2_tank/test/* +done +cd $here +while pkill swap; do sleep 1; done +wait + +zfs umount stress2_tank/test +zfs destroy -r stress2_tank +zpool destroy stress2_tank +mdconfig -d -u $u1 +mdconfig -d -u $u2 +rm -f /tmp/zfs16 +set +u +[ $loaded ] && kldunload zfs.ko +exit $s +EOF +#include <sys/types.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/param.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> + +#define SIZ (500UL * 1024 * 1024) + +int +main(int argc __unused, char *argv[]) +{ + off_t hole; + size_t len; + int fd; + char *p, *path; + + len = SIZ; + + path = argv[1]; + if ((fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0622)) == -1) + err(1,"open()"); + if (ftruncate(fd, len) == -1) + err(1, "ftruncate"); + if ((p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == + MAP_FAILED) { + if (errno == ENOMEM) + return (1); + err(1, "mmap(1)"); + } + p[1 * 1024] = 1; + p[2 * 1024] = 1; + p[4 * 1024] = 1; + + if (msync(p, len, MS_SYNC | MS_INVALIDATE) == -1) + err(1, "msync()"); + + if ((hole = lseek(fd, 0, SEEK_HOLE)) == -1) + err(1, "lseek(SEEK_HOLE)"); + if (hole != SIZ) + printf("--> hole = %jd, file size=%jd\n", + (intmax_t)hole, (intmax_t)SIZ); + close(fd); + + return (hole == SIZ ? 0 : 1); +} diff --git a/tools/test/stress2/misc/zfs17.sh b/tools/test/stress2/misc/zfs17.sh new file mode 100755 index 000000000000..d20e39765afa --- /dev/null +++ b/tools/test/stress2/misc/zfs17.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Copy from nullfs over zfs to nullfs over ufs +# Test scenario description by: mjguzik + +# Page fault seen: +# https://people.freebsd.org/~pho/stress/log/log0498.txt + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +[ `sysctl -n kern.kstack_pages` -lt 4 ] && exit 0 + +. ../default.cfg + +set -u +kldstat -v | grep -q zfs.ko || { kldload zfs.ko || + exit 0; loaded=1; } + +u1=$mdstart +u2=$((u1 + 1)) +u3=$((u2 + 1)) +mp0=/stress2_tank/test # zfs mount +mp1=$mntpoint # nullfs of zfs +mp2=$mntpoint$mdstart # ufs +mp3=$mntpoint$((mdstart + 1)) # nullfs of ufs +mkdir -p $mp2 $mp3 + +mdconfig -l | grep -q md$u1 && mdconfig -d -u $u1 +mdconfig -l | grep -q md$u2 && mdconfig -d -u $u2 + +mdconfig -s 2g -u $u1 +mdconfig -s 2g -u $u2 + +zpool list | egrep -q "^stress2_tank" && zpool destroy stress2_tank +[ -d /stress2_tank ] && rm -rf /stress2_tank +zpool create stress2_tank raidz md$u1 md$u2 +zfs create ${mp0#/} + +mount | grep -q $mp1 && umount -f $mp1 +mount -t nullfs $mp0 $mp1 + +mdconfig -a -t swap -s 1g -u $u3 +newfs $newfs_flags /dev/md$u3 > /dev/null +mount /dev/md$u3 $mp2 +mount -t nullfs $mp2 $mp3 + +dd if=/dev/zero of=$diskimage bs=1m count=50 status=none +cp $diskimage $mp1 +cp $mp1/diskimage $mp3 +rm -f $diskimage + +umount $mp3 +umount $mp2 +mdconfig -d -u $u3 + +while mount | grep -q "on $mntpoint "; do + umount $mntpoint && break + sleep 1 +done + +zfs umount ${mp0#/} +zfs destroy -r stress2_tank +zpool destroy stress2_tank + +mdconfig -d -u $u2 +mdconfig -d -u $u1 +set +u +[ -n "$loaded" ] && kldunload zfs.ko +exit 0 diff --git a/tools/test/stress2/misc/zfs18.sh b/tools/test/stress2/misc/zfs18.sh new file mode 100755 index 000000000000..fb4f301f43c9 --- /dev/null +++ b/tools/test/stress2/misc/zfs18.sh @@ -0,0 +1,134 @@ +#!/bin/sh + +# File corruption scenario. +# Test program obtained from Kyle Evans <kevans@FreeBSD.org> + +# "panic: VERIFY3(rc->rc_count == number) failed (4849664 == 0)" seen. + +# Page fault seen: +# https://people.freebsd.org/~pho/stress/log/log0560.txt + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +[ `sysctl -n kern.kstack_pages` -lt 4 ] && exit 0 + +. ../default.cfg + +prog=$(basename "$0" .sh) +cat > /tmp/$prog.c <<EOF +#include <sys/mman.h> +#include <sys/stat.h> + +#include <assert.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> + +//#define FILE "2" +#define FILE "file" + +int +main(void) +{ + struct stat sb; + ssize_t wsz; + size_t bufsz; + void *buf, *obuf; + int mfd, fd; + int done = 0; + + mfd = open(FILE, O_RDONLY); + assert(mfd >= 0); + + assert(fstat(mfd, &sb) == 0); + bufsz = sb.st_size; + buf = obuf = mmap(NULL, bufsz, PROT_READ, MAP_SHARED, mfd, 0); + assert(buf != MAP_FAILED); + + /* O_RDWR */ + fd = open(FILE, O_RDWR); + if (fd < 0) + err(1, "open"); + assert(fd >= 0); + +again: + while (bufsz > 0) { + wsz = write(fd, buf, bufsz); + if (wsz < 0) + err(1, "write"); + else if (wsz == 0) + fprintf(stderr, "Huh?\n"); + bufsz -= wsz; + buf += wsz; + } + + bufsz = sb.st_size; + buf = obuf; + + if (++done < 2) + goto again; + + close(fd); + munmap(obuf, sb.st_size); + close(mfd); + return (0); +} +EOF +mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1 +set -u +kldstat -v | grep -q zfs.ko || { kldload zfs.ko || + exit 0; loaded=1; } + +u1=$mdstart +u2=$((u1 + 1)) +mp0=/stress2_tank/test # zfs mount + +mdconfig -l | grep -q md$u1 && mdconfig -d -u $u1 +mdconfig -l | grep -q md$u2 && mdconfig -d -u $u2 + +mdconfig -s 4g -u $u1 +mdconfig -s 4g -u $u2 + +zpool list | egrep -q "^stress2_tank" && zpool destroy stress2_tank +[ -d /stress2_tank ] && rm -rf /stress2_tank +zpool create stress2_tank raidz md$u1 md$u2 +zfs create ${mp0#/} + +here=`pwd` +cd /stress2_tank +# Optimized file creation: +#jot -b 'A' -s '' 875998989 > file +dd if=/dev/random of=file bs=1m count=$(((875998990/1024/1024)+1)) status=none +truncate -s 875998990 file +cat file file > file.post +mv file file.orig + +counter=1 +s=0 +start=`date +%s` +while [ $((`date +%s` - start)) -lt 300 ]; do + cp file.orig file + /tmp/$prog + if ! cmp file file.post; then + echo "Iteration #$counter" + od -t x8 file | head -1000 > /tmp/$prog.file1 + od -t x8 file.post | head -1000 > /tmp/$prog.file2 + diff /tmp/$prog.file1 /tmp/$prog.file2 | head -15 + rm /tmp/$prog.file1 /tmp/$prog.file2 + s=1 + break + fi + counter=$((counter + 1)) +done +cd $here + +zfs umount ${mp0#/} +zfs destroy -r stress2_tank +zpool destroy stress2_tank + +mdconfig -d -u $u2 +mdconfig -d -u $u1 +set +u +[ $loaded ] && kldunload zfs.ko +rm /tmp/$prog /tmp/$prog.c +exit $s diff --git a/tools/test/stress2/misc/zfs19.sh b/tools/test/stress2/misc/zfs19.sh new file mode 100755 index 000000000000..a3bb19c8be07 --- /dev/null +++ b/tools/test/stress2/misc/zfs19.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +# +# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org> +# +# SPDX-License-Identifier: BSD-2-Clause +# + +# Hunt for "vm_fault: pager read error, pid 99058 (mmap)" + +[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 +kldstat -v | grep -q zfs.ko || { kldload zfs.ko; loaded=1; } || + exit 0 + +. ../default.cfg + +prog=$(basename "$0" .sh) +here=`pwd` +log=/tmp/$prog.log +mp1=/stress2_tank/test +u1=$mdstart +u2=$((u1 + 1)) + +set -e +mdconfig -l | grep -q md$u1 && mdconfig -d -u $u1 +mdconfig -l | grep -q md$u2 && mdconfig -d -u $u2 + +mdconfig -s 2g -u $u1 +mdconfig -s 2g -u $u2 + +zpool list | egrep -q "^stress2_tank" && zpool destroy stress2_tank +[ -d /stress2_tank ] && rm -rf /stress2_tank +zpool create stress2_tank md$u1 md$u2 +zfs create stress2_tank/test +set +e + +export RUNDIR=/stress2_tank/test/stressX +export runRUNTIME=2m +export LOAD=70 +export mmapLOAD=100 +export TESTPROGS="testcases/mmap/mmap testcases/swap/swap" + +(cd ..; ./testcases/run/run $TESTPROGS > /dev/null 2>&1) & rpid=$! +sleep 5 + +tail -F -n 0 /var/log/messages > $log & lpid=$! + +start=`date +%s` +while [ $((`date +%s` - start)) -lt 120 ]; do + zfs umount -f stress2_tank/test && + zfs mount stress2_tank/test + sleep 5 + zfs list | grep -q /stress2_tank/test || break + pgrep -q mmap || break +done +pkill run swap mmap +while pgrep -q swap; do pkill swap; done +wait $rpid + +zfs umount stress2_tank/test +zfs destroy -r stress2_tank +zpool destroy stress2_tank + +mdconfig -d -u $u1 +mdconfig -d -u $u2 +[ -n "$loaded" ] && kldunload zfs.ko + +kill $lpid && wait $lpid +grep -m 1 "pager read error" $log && s=1 || s=0 +rm $log +s=0 # This is an expected behavior for zfs +exit $s diff --git a/tools/test/stress2/misc/zfs8.sh b/tools/test/stress2/misc/zfs8.sh index 7d1d9887ce29..5eb53cd78ead 100755 --- a/tools/test/stress2/misc/zfs8.sh +++ b/tools/test/stress2/misc/zfs8.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/zfs9.sh b/tools/test/stress2/misc/zfs9.sh index 274a42f18bdb..2b051c8cd3c3 100755 --- a/tools/test/stress2/misc/zfs9.sh +++ b/tools/test/stress2/misc/zfs9.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/zz-combo01.sh b/tools/test/stress2/misc/zz-combo01.sh index 8899ade3441f..19c102288c79 100755 --- a/tools/test/stress2/misc/zz-combo01.sh +++ b/tools/test/stress2/misc/zz-combo01.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/zz-combo02.sh b/tools/test/stress2/misc/zz-combo02.sh index 2d866858bb8f..d65caf2f3c22 100755 --- a/tools/test/stress2/misc/zz-combo02.sh +++ b/tools/test/stress2/misc/zz-combo02.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/zz-combo03.sh b/tools/test/stress2/misc/zz-combo03.sh index 7afaec11e861..1bc3424f9de3 100755 --- a/tools/test/stress2/misc/zz-combo03.sh +++ b/tools/test/stress2/misc/zz-combo03.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # diff --git a/tools/test/stress2/misc/zz-combo04.sh b/tools/test/stress2/misc/zz-combo04.sh index 69003ec73371..1cbe19b6d518 100755 --- a/tools/test/stress2/misc/zz-combo04.sh +++ b/tools/test/stress2/misc/zz-combo04.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm # diff --git a/tools/test/stress2/misc/zzbuildworld.sh b/tools/test/stress2/misc/zzbuildworld.sh index ae0956239648..e1bf867d8d5f 100755 --- a/tools/test/stress2/misc/zzbuildworld.sh +++ b/tools/test/stress2/misc/zzbuildworld.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019 Dell EMC Isilon # @@ -44,6 +44,7 @@ top=$mntpoint export MAKEOBJDIRPREFIX=$top/obj export log=$top/buildworld.`date +%Y%m%dT%H%M` n=$((`sysctl -n hw.ncpu` + 1)) +[ $n -gt 32 ] && n=32 # Arbitrary cap cd $src make -j$n buildworld > $log 2>&1 && s=0 ||s=1 grep '\*\*\*' $log && s=2 diff --git a/tools/test/stress2/testcases/swap/swap.c b/tools/test/stress2/testcases/swap/swap.c index 75bfe7856aed..c54605a4b0fe 100644 --- a/tools/test/stress2/testcases/swap/swap.c +++ b/tools/test/stress2/testcases/swap/swap.c @@ -155,10 +155,8 @@ test(void) c[i] = 0; i += page; } -#if 0 - if (op->hog != 1) - usleep(1000); -#endif + if (arc4random() % 100 < 10) + usleep(10000); } free((void *)c); diff --git a/tools/test/stress2/tools/bench.c b/tools/test/stress2/tools/bench.c index 606c8e6ed726..71918b7b0684 100644 --- a/tools/test/stress2/tools/bench.c +++ b/tools/test/stress2/tools/bench.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2018 Dell EMC Isilon * diff --git a/tools/test/stress2/tools/fail.sh b/tools/test/stress2/tools/fail.sh index 6d83d8fe0d22..a7b9c769892a 100755 --- a/tools/test/stress2/tools/fail.sh +++ b/tools/test/stress2/tools/fail.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/tools/fast.sh b/tools/test/stress2/tools/fast.sh index ce33eaa4c103..83809c8baf55 100755 --- a/tools/test/stress2/tools/fast.sh +++ b/tools/test/stress2/tools/fast.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/tools/flip.c b/tools/test/stress2/tools/flip.c index 8d01e9d78ea1..f2a4d86e115b 100644 --- a/tools/test/stress2/tools/flip.c +++ b/tools/test/stress2/tools/flip.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> * All rights reserved. @@ -57,7 +57,7 @@ flip(void *ap, size_t len) unsigned char bit, buf, mask, old __unused; cp = (unsigned char *)ap; - byte = random_long(0, len); + byte = random_long(0, len - 1); bit = random_long(0,7); mask = ~(1 << bit); buf = cp[byte]; @@ -70,14 +70,22 @@ flip(void *ap, size_t len) #endif } +static void +trash(char *c) +{ + if (arc4random() % 2 == 1) + *c = 0; + else + arc4random_buf(c, sizeof(c)); +} + int main(int argc, char *argv[]) { struct stat st; off_t pos; size_t size; - int fd, i, times; - char c; + int c, fd, i, times; times = 1; size = 0; @@ -111,19 +119,26 @@ main(int argc, char *argv[]) if (size == 0) { if (fstat(fd, &st) == -1) err(1, "stat %s", argv[0]); + if ((st.st_mode & S_IFREG) == 0) + errx(1, "%s must be a regular file\n", argv[0]); size = st.st_size; } for (i = 0; i < times; i++) { + char ch; + pos = arc4random() % size; if (lseek(fd, pos, SEEK_SET) == -1) err(1, "lseek()"); - if (read(fd, &c, 1) != 1) + if (read(fd, &ch, 1) != 1) err(1, "read()"); - flip(&c, 1); + if (arc4random() % 100 < 98) + flip(&ch, 1); + else + trash(&ch); if (lseek(fd, pos, SEEK_SET) == -1) err(1, "lseek()"); - if (write(fd, &c, 1) != 1) + if (write(fd, &ch, 1) != 1) err(1, "write()"); } diff --git a/tools/test/stress2/tools/lsholes.c b/tools/test/stress2/tools/lsholes.c index a583c1315093..736ae92a41c8 100644 --- a/tools/test/stress2/tools/lsholes.c +++ b/tools/test/stress2/tools/lsholes.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2021 Peter Holm <pho@FreeBSD.org> * @@ -40,7 +40,8 @@ main(int argc, char *argv[]) { struct stat st; off_t data, hole, pos; - long mx; + long mn; + intmax_t siz; int fd, n; char *name; @@ -54,33 +55,47 @@ main(int argc, char *argv[]) err(1, "open(%s)", name); if (fstat(fd, &st)) err(1, "fstat()"); - if ((mx = fpathconf(fd, _PC_MIN_HOLE_SIZE)) == -1) + if ((mn = fpathconf(fd, _PC_MIN_HOLE_SIZE)) == -1) err(1, "fpathconf()"); - fprintf(stderr, "file \"%s\" size = %jd, _PC_MIN_HOLE_SIZE = %ld\n", - name, (intmax_t)st.st_size, mx); + fprintf(stderr, "Min hole size is %ld, file size is %jd.\n", + mn, (intmax_t)st.st_size); n = 1; pos = 0; + while (pos < st.st_size) { - if ((hole = lseek(fd, pos, SEEK_HOLE)) == -1) + hole = lseek(fd, pos, SEEK_HOLE); + if (hole == -1 && errno != ENXIO) err(1, "lseek(SEEK_HOLE)"); - if ((data = lseek(fd, hole, SEEK_DATA)) == -1) { - if (errno == ENXIO) { - if (hole == st.st_size) - break; - fprintf(stderr, - "No data after hole @ %jd\n", - (intmax_t)hole); - break; - } - err(1, "lseek(SEEK_DATA)"); + data = lseek(fd, pos, SEEK_DATA); + if (data == -1 && errno != ENXIO) + err(1, "lseek(SEEK_data)"); + + if (hole >= 0 && data >= 0 && hole > data) { + siz = hole - data; + printf("data #%d @ %ld, size=%jd)\n", + n, (intmax_t)data, siz); + n++; + pos += siz; + } + if (hole >= 0 && data >= 0 && hole < data) { + siz = data - hole; + printf("hole #%d @ %ld, size=%jd\n", + n, (intmax_t)hole, siz); + n++; + pos += siz; + } + if (hole >= 0 && data == -1) { + siz = st.st_size - hole; + printf("hole #%d @ %ld, size=%jd\n", + n, (intmax_t)hole, siz); + n++; + pos += siz; } - pos = data; - printf("hole #%d @ %jd (0x%jx), size=%jd (0x%jx)\n", - n, (intmax_t)hole, (intmax_t)hole, (intmax_t)(data - hole), - (intmax_t)(data - hole)); - n++; } + if (hole == st.st_size) { + /* EOF */ + printf("hole #%d @ %ld, size=%jd\n", + n, (intmax_t)hole, 0L); + } close(fd); - if (hole != st.st_size) - errx(1, "No implicit hole at EOF"); } diff --git a/tools/test/stress2/tools/ministat.sh b/tools/test/stress2/tools/ministat.sh index 552828e97e59..d219122a0c42 100755 --- a/tools/test/stress2/tools/ministat.sh +++ b/tools/test/stress2/tools/ministat.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/tools/ps.sh b/tools/test/stress2/tools/ps.sh index 238192db1b0e..c8ed7d66ecac 100755 --- a/tools/test/stress2/tools/ps.sh +++ b/tools/test/stress2/tools/ps.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-2-Clause-FreeBSD +# SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> # diff --git a/tools/test/stress2/tools/serial.c b/tools/test/stress2/tools/serial.c new file mode 100644 index 000000000000..8dcf9c5da3a8 --- /dev/null +++ b/tools/test/stress2/tools/serial.c @@ -0,0 +1,44 @@ +/* Fill a file with a sequence of byte values from 0 - 0xff */ + +#include <sys/param.h> +#include <sys/mman.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +int +main(int argc, char *argv[]) +{ + size_t i, size; + int fd; + char *cp, *file; + + if (argc != 3) { + fprintf(stderr, "Usage: %s <file> <file length in bytes>\n", argv[0]); + exit(1); + } + file = argv[1]; + size = atol(argv[2]); + + if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) + err(1, "%s", file); + + if (lseek(fd, size - 1, SEEK_SET) == -1) + err(1, "lseek error"); + + /* write a dummy byte at the last location */ + if (write(fd, "\0", 1) != 1) + err(1, "write error"); + + if ((cp = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) + err(1, "mmap()"); + + for (i = 0; i < size; i++) + cp[i] = i & 0xff; + + if (munmap(cp, size) == -1) + err(1, "munmap"); + close(fd); +} diff --git a/tools/test/stress2/tools/swap.c b/tools/test/stress2/tools/swap.c index ce272b794ea7..9e07a8c46d1f 100644 --- a/tools/test/stress2/tools/swap.c +++ b/tools/test/stress2/tools/swap.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> * All rights reserved. diff --git a/tools/test/stress2/tools/vmstat.sh b/tools/test/stress2/tools/vmstat.sh index 89ff1e331fc5..f7006669a7c0 100755 --- a/tools/test/stress2/tools/vmstat.sh +++ b/tools/test/stress2/tools/vmstat.sh @@ -45,34 +45,28 @@ OIFS=$IFS while true; do # Type InUse MemUse [ -z "$optm" ] && vmstat -m | sed 1d | - sed 's/\(.* \)\([0-9][0-9]*\) *\(.*\)K .*/\1:\2:\3/' | - while IFS=: read -r p1 p2 p3; do - name=`echo $p1 | sed 's/^ *//;s/ *$//'` - memuse=$p3 + while read l; do + name=`echo $l | sed -E 's/ [0-9]+ .*//; s/^ *//'` + memuse=`echo $l | sed -E "s#$name##" | \ + awk '{print int(($2 + 1023) / 1024)}'` [ "$memuse" -ne 0 ] && echo "vmstat -m $name,$memuse" - done + done # ITEM SIZE LIMIT USED - [ -z "$optz" ] && vmstat -z | - grep -vE '(rl_entry):' | - sed "1,2d;/^$/d;s/: /, /" | - sed -E 's/[^[:print:]\r\t]/ /g' | + [ -z "$optz" ] && vmstat -z | sed 1d | while read l; do - IFS=',' - set $l - [ $# -lt 8 ] && - { echo "# args must be >= 8, but is $# in $l" 1>&2; - continue; } - size=$2 - used=$4 + name=`echo $l | sed 's/:.*//'` + l=`echo $l | sed 's/.*://'` + size=`echo $l | awk -F ',' '{print $1}'` + used=`echo $l | awk -F ',' '{print $3}'` [ -z "$used" -o -z "$size" ] && { echo "used/size not set $l" 1>&2; continue; } echo $used | egrep -q '^ *[0-9]{1,10}$' || { echo "Bad used: $used. l=$l" 1>&2; continue; } tot=$((((size * used) + 1023) / 1024)) [ $tot -ne 0 ] && - echo "vmstat -z $1,$tot" - done + echo "vmstat -z $name,$tot" + done r=`sysctl -n vm.stats.vm.v_wire_count` [ -n "$r" ] && @@ -98,6 +92,7 @@ done | awk $debug -F, ' close(cmd); printf "%s \"%s\" %'\''dK\r\n", t, name, size; + fflush n[name] = 0; } s[name] = size; |