xref: /freebsd/tools/test/stress2/misc/pg_zero.sh (revision f88300a7b56e32808e91fc893e7f1afc67ce72fd)
1#!/bin/sh
2
3# Regression test for:
4# D53963: vm_fault: only rely on PG_ZERO when the page was newly allocated
5# Test scenario suggestions by: kib
6
7# Problem seen:
8# b[0] is 4. Expected 0
9# b[0] is 4. Expected 0
10
11. ../default.cfg
12
13set -u
14prog=$(basename "$0" .sh)
15cat > /tmp/$prog.c <<EOF
16#include <sys/param.h>
17#include <sys/mman.h>
18#include <sys/stat.h>
19#include <sys/wait.h>
20
21#include <err.h>
22#include <errno.h>
23#include <fcntl.h>
24#include <pthread.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29
30static int debug = 0;
31static int fail, fd, ok, parallel;
32static volatile int done, go;
33static char *buf;
34static char *path = "/dev/md$mdstart";
35
36#define PARALLEL 3
37#define RUNTIME 180
38
39void *
40wr(void *arg __unused)
41{
42	int n;
43
44	while (done != 1) {
45		while (go == 0) {
46			usleep(10);
47		}
48		go = 2;
49		n = write(fd, buf, 512);
50		if (n == -1 && errno != EFAULT)
51			warn("write()");
52		if (debug == 1) {
53			if (n == -1)
54				fail++;
55			else
56				ok++;
57		}
58	}
59
60	return (NULL);
61}
62
63int
64test(void)
65{
66	size_t len;
67	int i, pagesize;
68	char *a, *b, *c, *p;
69
70	pagesize = sysconf(_SC_PAGESIZE);
71	len = 3 * pagesize;
72	if ((p = mmap(NULL, len, PROT_READ | PROT_WRITE,
73	    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
74		err(1, "mmap(%ld pages", len);
75	if (mlock(p, len) == -1)
76		err(1, "mlock()");
77
78	a = p;
79	b = a + pagesize;
80	buf = b;
81	c = b + pagesize;
82
83	memset(a, 2, pagesize);
84	memset(b, 4, pagesize);
85	memset(c, 8, pagesize);
86
87	if (munlock(b, pagesize) == -1)
88		err(1, "munlock(b)");
89	go = 1;
90	while (go == 1)
91		usleep(10);
92	if (munmap(b, pagesize) == -1)
93		err(1, "munmap(b)");
94
95	if (mmap(b, pagesize, PROT_READ | PROT_WRITE,
96	    MAP_ANON | MAP_FIXED, -1, 0) == MAP_FAILED)
97		err(1, "mmap(%d pages", pagesize);
98
99	for (i = 0; i < pagesize; i++) {
100		if (b[i] != 0) {
101			fprintf(stderr, "b[%d] is %d. Expected 0\n", i, (int)b[i]);
102			return (1);
103		}
104	}
105	go = 0;
106
107	if (munmap(p, len) == -1)
108		err(1, "Final munmap()");
109
110	return (0);
111}
112
113int
114run(void)
115{
116	pthread_t tid;
117	time_t start;
118	int e;
119
120	ok = fail = 0;
121	go = 0;
122	e = pthread_create(&tid, NULL, wr, NULL);
123	if (e)
124		errc(1, e, "pthread_create()");
125	fail = ok = 0;
126	start = time(NULL);
127	while ((time(NULL) - start) < 30) {
128		if (lseek(fd, 0, SEEK_SET) == -1)
129			err(1, "lseek(0)");
130		if (fsync(fd) != 0)
131			err(1, "fsync()");
132		if ((e = test()) != 0)
133			break;
134	}
135	done = 1;
136	pthread_join(tid, NULL);
137	if (debug == 1)
138		fprintf(stderr, "Fail = %3d, OK = %5d, parallel = %d\n", fail, ok, parallel);
139	_exit(e);
140}
141
142int
143main(void)
144{
145	pid_t pids[PARALLEL];
146	time_t start;
147	int e, i, status;
148
149	if ((fd = open(path, O_WRONLY)) == -1)
150		err(1, "open(%s)", path);
151	e = 0;
152	start = time(NULL);
153	while ((time(NULL) - start) < RUNTIME && e == 0) {
154		parallel = arc4random() % PARALLEL + 1;
155		for (i = 0; i < parallel; i++) {
156			if ((pids[i] = fork()) == 0)
157				run();
158			if (pids[i] == -1)
159				err(1, "fork()");
160		}
161		for (i = 0; i < parallel; i++) {
162			if (waitpid(pids[i], &status, 0) == -1)
163				err(1, "waitpid(%d)", pids[i]);
164			if (status != 0) {
165				if (WIFSIGNALED(status))
166					fprintf(stderr,
167					    "pid %d exit signal %d\n",
168					    pids[i], WTERMSIG(status));
169			}
170			e += status == 0 ? 0 : 1;
171		}
172	}
173	close(fd);
174
175	return (e);
176}
177EOF
178
179mycc -o /tmp/$prog -Wall -Wextra -O0 -g /tmp/$prog.c -pthread || exit 1
180
181mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart
182truncate -s 2g $diskimage
183mdconfig -a -t vnode -f $diskimage -u $mdstart
184../testcases/swap/swap -t 3m -i 20 -l 100 > /dev/null &
185sleep 3
186cd /tmp; ./$prog; s=$?; cd -
187pkill swap
188wait
189rm -f /tmp/$prog.c /tmp/$prog $diskimage
190mdconfig -d -u $mdstart
191exit $s
192