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