xref: /freebsd/tools/test/stress2/misc/holdcnt0.sh (revision 18054d0220cfc8df9c9568c437bd6fbb59d53c3c)
1#!/bin/sh
2
3#
4# Copyright (c) 2013 EMC Corp.
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28
29# "panic: cluster_wbuild: page 0xc2eebc10 failed shared busing" seen.
30# "panic: vdrop: holdcnt 0" seen.
31# "panic: cleaned vnode isn't" seen.
32# OoVM seen with r285808:
33# https://people.freebsd.org/~pho/stress/log/holdcnt0.txt
34
35# Test scenario suggestion by alc@
36
37[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
38[ `swapinfo | wc -l` -eq 1 ] && exit 0
39[ `sysctl -n hw.physmem` -lt $((32 * 1024 * 1024 * 1024)) ] && exit 0
40
41. ../default.cfg
42
43here=`pwd`
44cd /tmp
45sed '1,/^EOF/d' < $here/$0 > holdcnt0.c
46mycc -o holdcnt0 -Wall -Wextra -g holdcnt0.c || exit 1
47rm -f holdcnt0.c
48cd $here
49
50mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint
51mdconfig -l | grep -q md$mdstart &&  mdconfig -d -u $mdstart
52mdconfig -a -t swap -s 5g -u $mdstart
53bsdlabel -w md$mdstart auto
54newfs md${mdstart}$part > /dev/null
55mount /dev/md${mdstart}$part $mntpoint
56
57(cd $mntpoint; /tmp/holdcnt0) &
58pid=$!
59sleep 5
60while kill -0 $! 2> /dev/null; do
61	(cd ../testcases/swap; ./swap -t 1m -i 1) > /dev/null 2>&1
62done
63wait $pid; s=$?
64
65while mount | grep -q md${mdstart}$part; do
66	umount $mntpoint || sleep 1
67done
68mdconfig -d -u $mdstart
69rm -f /tmp/holdcnt0
70exit $s
71EOF
72/*
73   A test that causes the page daemon to generate cached pages
74   within a bunch of files and has some consumer that is trying to
75   allocate new pages to the same files.
76*/
77
78#include <sys/types.h>
79#include <sys/mman.h>
80#include <sys/stat.h>
81#include <sys/wait.h>
82
83#include <err.h>
84#include <errno.h>
85#include <fcntl.h>
86#include <setjmp.h>
87#include <signal.h>
88#include <stdio.h>
89#include <stdlib.h>
90#include <time.h>
91#include <unistd.h>
92
93#define BUFSIZE (1024 * 1024)
94#define FILES 200
95#define RPARALLEL 8
96#define WPARALLEL 2
97
98static jmp_buf jbuf;
99static off_t maxsize;
100static int ps;
101static char *buf;
102static volatile char val;
103
104static void
105hand(int i __unused) {  /* handler */
106
107#if defined(DEBUG)
108	fprintf(stderr, "%d ", i);
109#endif
110        longjmp(jbuf, 1);
111}
112
113static void
114cleanup(void)
115{
116	int i;
117	char file[80];
118
119	for (i = 0; i < FILES; i++) {
120		snprintf(file, sizeof(file), "f%06d", i);
121		unlink(file);
122	}
123}
124
125static void
126init(void)
127{
128	int fd, i;
129	char file[80];
130
131	for (i = 0; i < FILES; i++) {
132		snprintf(file, sizeof(file), "f%06d", i);
133		if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0644)) ==
134		    -1)
135			err(1, "open(%s)", file);
136		if (write(fd, buf, BUFSIZE) != BUFSIZE)
137			err(1, "write");
138		close(fd);
139	}
140
141}
142
143static void
144writer(void)
145{
146	struct stat statbuf;
147	time_t start;
148	int fd, i;
149	char file[80];
150
151	setproctitle("writer");
152	start = time(NULL);
153	while (time(NULL) - start < 600) {
154		for (i = 0; i < FILES; i++) {
155			snprintf(file, sizeof(file), "f%06d", i);
156			if ((fd = open(file, O_RDWR | O_APPEND)) == -1) {
157				if (errno != ENOENT)
158					err(1, "open(%s) append", file);
159				goto err;
160			}
161			if (fstat(fd, &statbuf) < 0)
162				err(1, "fstat error");
163			if (statbuf.st_size < maxsize) {
164				if (write(fd, buf, ps) != ps) {
165					warn("writer");
166					goto err;
167				}
168			}
169			close(fd);
170		}
171	}
172err:
173	cleanup();
174
175	_exit(0);
176}
177
178static void
179reader(void)
180{
181	struct stat statbuf;
182	void *p;
183	size_t len;
184	int fd, i, j, n;
185	char file[80];
186
187	setproctitle("reader");
188	signal(SIGSEGV, hand);
189	signal(SIGBUS, hand);
190	fd = 0;
191	for (;;) {
192		(void)setjmp(jbuf);
193		for (i = 0; i < FILES; i++) {
194			snprintf(file, sizeof(file), "f%06d", i);
195			if (fd > 0)
196				close(fd);
197			if ((fd = open(file, O_RDWR)) == -1) {
198				if (errno != ENOENT)
199					warn("reader(%s)", file);
200				_exit(0);
201			}
202			if (fstat(fd, &statbuf) < 0)
203				err(1, "fstat error");
204			if (statbuf.st_size >= maxsize) {
205				if (ftruncate(fd, ps) == -1)
206					err(1, "ftruncate");
207				continue;
208			}
209			len = statbuf.st_size;
210			if ((p = mmap(p, len, PROT_READ, MAP_SHARED, fd, 0))
211			    == MAP_FAILED)
212				err(1, "mmap()");
213			close(fd);
214			n = statbuf.st_size / ps;
215			for (j = 0; j < n; j++) {
216				val = *(char *)p;
217				p = p + ps;
218			}
219#if 0
220			if (munmap(p, len) == -1)
221				perror("munmap");
222#endif
223		}
224	}
225	_exit(0);
226}
227int
228main(void)
229{
230	pid_t rpid[RPARALLEL], wpid[WPARALLEL];
231	int e, i, s;
232
233	maxsize = 2LL * 1024 * 1024 * 1024 / FILES;
234	buf = malloc(BUFSIZE);
235	ps = getpagesize();
236
237	init();
238	e = 0;
239	for (i = 0; i < WPARALLEL; i++) {
240		if ((wpid[i] = fork()) == 0)
241			writer();
242	}
243	for (i = 0; i < RPARALLEL; i++) {
244		if ((rpid[i] = fork()) == 0)
245			reader();
246	}
247
248	for (i = 0; i < WPARALLEL; i++) {
249		waitpid(wpid[i], &s, 0);
250		if (e == 0)
251			e = s;
252	}
253	for (i = 0; i < RPARALLEL; i++) {
254		waitpid(rpid[i], &s, 0);
255		if (e == 0)
256			e = s;
257	}
258	free(buf);
259
260	return (e);
261}
262