xref: /freebsd/tools/test/stress2/misc/fragments.sh (revision 1f1e2261)
1#!/bin/sh
2
3#
4# Copyright (c) 2010 Peter Holm <pho@FreeBSD.org>
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# Scenario that causes "panic: brelse: free buffer onto another queue???"
30# Idea for scenario by kib@. Fixed in r203818
31
32# When UFS partition is full, then some high load causes
33# panic: brelse: free buffer onto another queue???
34
35[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
36
37. ../default.cfg
38
39here=`pwd`
40cd /tmp
41sed '1,/^EOF/d' < $here/$0 > fragments.c
42rm -f /tmp/fragments
43mycc -o fragments -Wall -Wextra -O2 -g fragments.c
44rm -f fragments.c
45cd $here
46
47mount | grep "$mntpoint" | grep -q md$mdstart && umount -f $mntpoint
48mdconfig -l | grep -q md$mdstart &&  mdconfig -d -u $mdstart
49
50mdconfig -a -t swap -s 1g -u $mdstart
51newfs $newfs_flags -m 0 md$mdstart > /dev/null 2>&1
52mount /dev/md$mdstart $mntpoint
53chmod 777 $mntpoint
54
55cd $mntpoint
56su $testuser -c "/tmp/fragments"
57cd $here
58
59umount $mntpoint
60mount | grep "$mntpoint" | grep -q md$mdstart && umount -f $mntpoint
61mdconfig -l | grep -q md$mdstart &&  mdconfig -d -u $mdstart
62
63rm -f /tmp/fragments
64exit
65EOF
66#include <sys/param.h>
67#include <sys/mount.h>
68#include <sys/stat.h>
69#include <sys/wait.h>
70#include <err.h>
71#include <errno.h>
72#include <fcntl.h>
73#include <signal.h>
74#include <stdio.h>
75#include <stdlib.h>
76#include <string.h>
77#include <unistd.h>
78
79#define LOOPS 600
80#define PARALLEL 8
81
82static	pid_t pid;
83static	char *buf;
84
85static volatile sig_atomic_t stop;
86
87void
88handler(int i __unused) {
89	stop = 1;
90}
91
92void
93cleanup(int n)
94{
95	int i, j, start;
96	int nb = 0;
97	char file[128];
98	struct statfs sbuf;
99	struct stat sb;
100
101	if (n == -1) {
102		for (i = 0; i < LOOPS; i++) {
103			sprintf(file,"t%05d", i);
104			unlink(file);
105		}
106		return;
107	}
108
109	start = arc4random() % n;
110	for (i = 0; i < LOOPS; i++) {
111		j = (start + i) % LOOPS;
112		sprintf(file,"t%05d", j);
113		if (stat(file, &sb) != 0)
114			continue;
115
116		if (sb.st_size == 0) {
117			unlink(file);
118			continue;
119		}
120		if (truncate(file, 0) == 0) {
121			nb++;
122			continue;
123		}
124		if (nb > 10)
125			break;
126	}
127
128	for (i = 0; i < 10; i++) {
129		if (statfs(".", &sbuf) < 0)
130			err(1, "statfs(%s)", ".");
131
132		if (sbuf.f_bfree > 8)
133			return;
134	}
135
136	for (i = 0; i < LOOPS; i++) {
137		j = (start + i) % LOOPS;
138		sprintf(file,"t%05d", j);
139		if (unlink(file) == 0) {
140			return;
141		}
142	}
143}
144
145void
146fragments(void)
147{
148	int i, len;
149	char file[128];
150	int fd;
151
152	for (i = 0;; i++) {
153		sprintf(file,"d%d/f%05d.%05d", i/1000, pid, i);
154
155		if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) {
156			if (errno != ENOSPC)
157				warn("open(%s)", file);
158			break;
159		}
160
161		len =  2 * 1024;
162		if (write(fd, buf, len) != len) {
163		}
164
165		close(fd);
166	}
167}
168
169void
170blocks(void)
171{
172	int i, len;
173	char file[128];
174	int fd;
175
176	for (i = 0;; i++) {
177		sprintf(file,"d%d/b%05d.%05d", i/1000, pid, i);
178
179		if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) {
180			if (errno != ENOSPC)
181				warn("open(%s)", file);
182			break;
183		}
184
185		len =  16 * 1024;
186		if (write(fd, buf, len) != len) {
187		}
188
189		close(fd);
190	}
191}
192
193void
194setup(void)
195{
196	int i;
197	char file[128];
198
199	for (i = 0; i < 300; i++) {
200		sprintf(file,"d%d", i);
201		if (mkdir(file, 0700) == -1)
202			warn("mkdir(%s)", file);
203	}
204
205	blocks();
206	fragments();
207
208	for (i = 0;i < 8; i++) {
209		sprintf(file,"d%d/b%05d.%05d", i/1000, pid, i);
210		unlink(file);
211	}
212	for (i = 0;i < 1; i++) {
213		sprintf(file,"d%d/f%05d.%05d", i/1000, pid, i);
214		unlink(file);
215	}
216
217}
218
219int
220test(void)
221{
222	int i, len, n;
223	char file[128];
224	int fd;
225
226	for (i = 0; i < LOOPS; i++) {
227		sprintf(file,"t%05d", i);
228
229		if ((fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) {
230			continue;
231		}
232//		n = arc4random() % (12 + 1);
233		n = 0;
234                len = (arc4random() % (16 * 1024) + 1) + n * 16;
235		while (len > 0) {
236			if (write(fd, buf, len) == len)
237				break;
238			len = len / 2;
239			usleep(1000);
240		}
241		close(fd);
242		if (len == 0) {
243			cleanup(i);
244		}
245	}
246
247	exit(0);
248
249	return (0);
250}
251
252int
253main()
254{
255	int i, j, status;
256
257	pid = getpid();
258	if ((buf = malloc(12 * 16 * 1024)) == NULL)
259		err(1, "malloc()");
260
261	setup();
262	signal(SIGALRM, handler);
263	alarm(30 * 60);
264	for (j = 0; j < 50 && stop == 0; j++) {
265		for (i = 0; i < PARALLEL; i++) {
266			if (fork() == 0)
267				test();
268		}
269		for (i = 0; i < PARALLEL; i++)
270			wait(&status);
271		cleanup(-1);
272	}
273        return (0);
274}
275