xref: /freebsd/tools/test/stress2/misc/holdcnt04.sh (revision d11f81afd5a4a71d5f725950b0592ca212084780)
1#!/bin/sh
2
3#
4# Copyright (c) 2017 Dell EMC Isilon
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# Lite version of holdcnt0.sh
30
31[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
32[ `sysctl -n vm.swap_total` -ne 0 ] && exit 0
33[ `sysctl -n hw.physmem` -lt 5250000000 ] && exit 0
34
35. ../default.cfg
36
37here=`pwd`
38cd /tmp
39sed '1,/^EOF/d' < $here/$0 > holdcnt04.c
40mycc -o holdcnt04 -Wall -Wextra -g holdcnt04.c || exit 1
41rm -f holdcnt04.c
42cd $here
43
44mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint
45mdconfig -l | grep -q md$mdstart &&  mdconfig -d -u $mdstart
46mdconfig -a -t swap -s 2g -u $mdstart
47bsdlabel -w md$mdstart auto
48newfs md${mdstart}$part > /dev/null
49mount /dev/md${mdstart}$part $mntpoint
50
51(cd $mntpoint; /tmp/holdcnt04) &
52pid=$!
53sleep 5
54while kill -0 $! 2> /dev/null; do
55	(cd ../testcases/swap; ./swap -t 1m -i 1) > /dev/null 2>&1
56done
57wait $pid; s=$?
58
59while mount | grep -q md${mdstart}$part; do
60	umount $mntpoint || sleep 1
61done
62mdconfig -d -u $mdstart
63rm -f /tmp/holdcnt04
64exit $s
65EOF
66/*
67   A test that causes the page daemon to generate cached pages
68   within a bunch of files and has some consumer that is trying to
69   allocate new pages to the same files.
70*/
71
72#include <sys/types.h>
73#include <sys/mman.h>
74#include <sys/stat.h>
75#include <sys/wait.h>
76
77#include <err.h>
78#include <errno.h>
79#include <fcntl.h>
80#include <setjmp.h>
81#include <signal.h>
82#include <stdio.h>
83#include <stdlib.h>
84#include <time.h>
85#include <unistd.h>
86
87#define BUFSIZE (1024 * 1024)
88#define FILES 20
89#define RPARALLEL 8
90#define WPARALLEL 2
91
92static jmp_buf jbuf;
93static off_t maxsize;
94static int ps;
95static char *buf;
96static volatile char val;
97
98static void
99hand(int i __unused) {  /* handler */
100        longjmp(jbuf, 1);
101}
102
103static void
104cleanup(void)
105{
106	int i;
107	char file[80];
108
109	for (i = 0; i < FILES; i++) {
110		snprintf(file, sizeof(file), "f%06d", i);
111		unlink(file);
112	}
113}
114
115static void
116init(void)
117{
118	int fd, i;
119	char file[80];
120
121	for (i = 0; i < FILES; i++) {
122		snprintf(file, sizeof(file), "f%06d", i);
123		if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0644)) ==
124		    -1)
125			err(1, "open(%s)", file);
126		if (write(fd, buf, BUFSIZE) != BUFSIZE)
127			err(1, "write");
128		close(fd);
129	}
130
131}
132
133static void
134writer(void)
135{
136	struct stat statbuf;
137	time_t start;
138	int fd, i;
139	char file[80];
140
141	setproctitle("writer");
142	start = time(NULL);
143	while (time(NULL) - start < 600) {
144		for (i = 0; i < FILES; i++) {
145			snprintf(file, sizeof(file), "f%06d", i);
146			if ((fd = open(file, O_RDWR | O_APPEND)) == -1) {
147				if (errno != ENOENT)
148					err(1, "open(%s) append", file);
149				goto err;
150			}
151			if (fstat(fd, &statbuf) < 0)
152				err(1, "fstat error");
153			if (statbuf.st_size < maxsize) {
154				if (write(fd, buf, ps) != ps) {
155					warn("writer");
156					goto err;
157				}
158			}
159			close(fd);
160		}
161	}
162err:
163	cleanup();
164
165	_exit(0);
166}
167
168static void
169reader(void)
170{
171	struct stat statbuf;
172	void *p;
173	size_t len;
174	int fd, i, j, n;
175	char file[80];
176
177	setproctitle("reader");
178	signal(SIGSEGV, hand);
179	signal(SIGBUS, hand);
180	fd = 0;
181	for (;;) {
182		(void)setjmp(jbuf);
183		for (i = 0; i < FILES; i++) {
184			snprintf(file, sizeof(file), "f%06d", i);
185			if (fd > 0)
186				close(fd);
187			if ((fd = open(file, O_RDWR)) == -1) {
188				if (errno != ENOENT)
189					warn("reader(%s)", file);
190				_exit(0);
191			}
192			if (fstat(fd, &statbuf) < 0)
193				err(1, "fstat error");
194			if (statbuf.st_size >= maxsize) {
195				if (ftruncate(fd, ps) == -1)
196					err(1, "ftruncate");
197				continue;
198			}
199			len = statbuf.st_size;
200			if ((p = mmap(p, len, PROT_READ, MAP_SHARED, fd, 0))
201			    == MAP_FAILED)
202				err(1, "mmap()");
203			close(fd);
204			n = statbuf.st_size / ps;
205			for (j = 0; j < n; j++) {
206				val = *(char *)p;
207				p = p + ps;
208			}
209#if 0
210			if (munmap(p, len) == -1)
211				perror("munmap");
212#endif
213		}
214	}
215	_exit(0);
216}
217int
218main(void)
219{
220	pid_t rpid[RPARALLEL], wpid[WPARALLEL];
221	int e, i, s;
222
223	maxsize = 1LL * 1024 * 1024 * 1024 / FILES;
224	buf = malloc(BUFSIZE);
225	ps = getpagesize();
226
227	init();
228	e = 0;
229	for (i = 0; i < WPARALLEL; i++) {
230		if ((wpid[i] = fork()) == 0)
231			writer();
232	}
233	for (i = 0; i < RPARALLEL; i++) {
234		if ((rpid[i] = fork()) == 0)
235			reader();
236	}
237
238	for (i = 0; i < WPARALLEL; i++)
239		waitpid(wpid[i], &s, 0);
240	e += s == 0 ? 0 : 1;
241	for (i = 0; i < RPARALLEL; i++)
242		waitpid(rpid[i], &s, 0);
243	e += s == 0 ? 0 : 1;
244
245	free(buf);
246
247	return (e);
248}
249