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