git: fb7687edea52 - main - stress2: New tests added
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 03 Apr 2025 09:21:37 UTC
The branch main has been updated by pho:
URL: https://cgit.FreeBSD.org/src/commit/?id=fb7687edea52ff1ddbae5fe947055fb37bd23ae3
commit fb7687edea52ff1ddbae5fe947055fb37bd23ae3
Author: Peter Holm <pho@FreeBSD.org>
AuthorDate: 2025-04-03 09:20:41 +0000
Commit: Peter Holm <pho@FreeBSD.org>
CommitDate: 2025-04-03 09:20:41 +0000
stress2: New tests added
---
datamove6.sh | 50 ++++++
ftruncate3.sh | 96 +++++++++++
growfs3.sh | 41 +++++
kcmp.sh | 67 +++++++
marcus8.sh | 41 +++++
mprotect3.sh | 70 ++++++++
mprotect4.sh | 109 ++++++++++++
mprotect5.sh | 118 +++++++++++++
mprotect6.sh | 146 ++++++++++++++++
msdos17.sh | 144 ++++++++++++++++
msdos20.sh | 87 ++++++++++
msdos21.sh | 25 +++
newfs8.sh | 69 ++++++++
nullfs31.sh | 75 ++++++++
nullfs32.sh | 43 +++++
pthread10.sh | 106 ++++++++++++
rangelocks.sh | 194 +++++++++++++++++++++
rangelocks2.sh | 178 +++++++++++++++++++
rename16.sh | 261 ++++++++++++++++++++++++++++
rmdir.sh | 119 +++++++++++++
rsync.sh | 49 ++++++
rsync2.sh | 17 ++
rsync3.sh | 43 +++++
seekhole2.sh | 65 +++++++
syzkaller71.sh | 171 ++++++++++++++++++
syzkaller72.sh | 70 ++++++++
syzkaller73.sh | 537 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
27 files changed, 2991 insertions(+)
diff --git a/datamove6.sh b/datamove6.sh
new file mode 100755
index 000000000000..88bfea425bdc
--- /dev/null
+++ b/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/ftruncate3.sh b/ftruncate3.sh
new file mode 100755
index 000000000000..7373ae8d22a8
--- /dev/null
+++ b/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/growfs3.sh b/growfs3.sh
new file mode 100755
index 000000000000..33e8327cdbbc
--- /dev/null
+++ b/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/kcmp.sh b/kcmp.sh
new file mode 100755
index 000000000000..7c571dd8e8a1
--- /dev/null
+++ b/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/marcus8.sh b/marcus8.sh
new file mode 100755
index 000000000000..0c6110c8ec4c
--- /dev/null
+++ b/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/mprotect3.sh b/mprotect3.sh
new file mode 100755
index 000000000000..9bd4a6f9be79
--- /dev/null
+++ b/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/mprotect4.sh b/mprotect4.sh
new file mode 100755
index 000000000000..c233d20852a2
--- /dev/null
+++ b/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/mprotect5.sh b/mprotect5.sh
new file mode 100755
index 000000000000..ab4d2eeee118
--- /dev/null
+++ b/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/mprotect6.sh b/mprotect6.sh
new file mode 100755
index 000000000000..ef1443c216d3
--- /dev/null
+++ b/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/msdos17.sh b/msdos17.sh
new file mode 100755
index 000000000000..392a9a622b9a
--- /dev/null
+++ b/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/msdos20.sh b/msdos20.sh
new file mode 100755
index 000000000000..96c224a629f3
--- /dev/null
*** 2207 LINES SKIPPED ***