The branch main has been updated by pho: URL: https://cgit.FreeBSD.org/src/commit/?id=f88300a7b56e32808e91fc893e7f1afc67ce72fd
commit f88300a7b56e32808e91fc893e7f1afc67ce72fd Author: Peter Holm <[email protected]> AuthorDate: 2025-12-09 10:33:09 +0000 Commit: Peter Holm <[email protected]> CommitDate: 2025-12-09 10:34:44 +0000 stress2: Added a regression test --- tools/test/stress2/misc/pg_zero.sh | 191 +++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) diff --git a/tools/test/stress2/misc/pg_zero.sh b/tools/test/stress2/misc/pg_zero.sh new file mode 100755 index 000000000000..4d34a59616e1 --- /dev/null +++ b/tools/test/stress2/misc/pg_zero.sh @@ -0,0 +1,191 @@ +#!/bin/sh + +# Regression test for: +# D53963: vm_fault: only rely on PG_ZERO when the page was newly allocated +# Test scenario suggestions by: kib + +# Problem seen: +# b[0] is 4. Expected 0 +# b[0] is 4. Expected 0 + +. ../default.cfg + +set -u +prog=$(basename "$0" .sh) +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 <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static int debug = 0; +static int fail, fd, ok, parallel; +static volatile int done, go; +static char *buf; +static char *path = "/dev/md$mdstart"; + +#define PARALLEL 3 +#define RUNTIME 180 + +void * +wr(void *arg __unused) +{ + int n; + + while (done != 1) { + while (go == 0) { + usleep(10); + } + go = 2; + n = write(fd, buf, 512); + if (n == -1 && errno != EFAULT) + warn("write()"); + if (debug == 1) { + if (n == -1) + fail++; + else + ok++; + } + } + + return (NULL); +} + +int +test(void) +{ + size_t len; + int i, pagesize; + char *a, *b, *c, *p; + + pagesize = sysconf(_SC_PAGESIZE); + len = 3 * pagesize; + if ((p = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) + err(1, "mmap(%ld pages", len); + if (mlock(p, len) == -1) + err(1, "mlock()"); + + a = p; + b = a + pagesize; + buf = b; + c = b + pagesize; + + memset(a, 2, pagesize); + memset(b, 4, pagesize); + memset(c, 8, pagesize); + + if (munlock(b, pagesize) == -1) + err(1, "munlock(b)"); + go = 1; + while (go == 1) + usleep(10); + if (munmap(b, pagesize) == -1) + err(1, "munmap(b)"); + + if (mmap(b, pagesize, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_FIXED, -1, 0) == MAP_FAILED) + err(1, "mmap(%d pages", pagesize); + + for (i = 0; i < pagesize; i++) { + if (b[i] != 0) { + fprintf(stderr, "b[%d] is %d. Expected 0\n", i, (int)b[i]); + return (1); + } + } + go = 0; + + if (munmap(p, len) == -1) + err(1, "Final munmap()"); + + return (0); +} + +int +run(void) +{ + pthread_t tid; + time_t start; + int e; + + ok = fail = 0; + go = 0; + e = pthread_create(&tid, NULL, wr, NULL); + if (e) + errc(1, e, "pthread_create()"); + fail = ok = 0; + start = time(NULL); + while ((time(NULL) - start) < 30) { + if (lseek(fd, 0, SEEK_SET) == -1) + err(1, "lseek(0)"); + if (fsync(fd) != 0) + err(1, "fsync()"); + if ((e = test()) != 0) + break; + } + done = 1; + pthread_join(tid, NULL); + if (debug == 1) + fprintf(stderr, "Fail = %3d, OK = %5d, parallel = %d\n", fail, ok, parallel); + _exit(e); +} + +int +main(void) +{ + pid_t pids[PARALLEL]; + time_t start; + int e, i, status; + + if ((fd = open(path, O_WRONLY)) == -1) + err(1, "open(%s)", path); + e = 0; + start = time(NULL); + while ((time(NULL) - start) < RUNTIME && e == 0) { + parallel = arc4random() % PARALLEL + 1; + for (i = 0; i < parallel; i++) { + if ((pids[i] = fork()) == 0) + run(); + 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; + } + } + close(fd); + + return (e); +} +EOF + +mycc -o /tmp/$prog -Wall -Wextra -O0 -g /tmp/$prog.c -pthread || exit 1 + +mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart +truncate -s 2g $diskimage +mdconfig -a -t vnode -f $diskimage -u $mdstart +../testcases/swap/swap -t 3m -i 20 -l 100 > /dev/null & +sleep 3 +cd /tmp; ./$prog; s=$?; cd - +pkill swap +wait +rm -f /tmp/$prog.c /tmp/$prog $diskimage +mdconfig -d -u $mdstart +exit $s
