xref: /freebsd/tools/test/stress2/misc/suj30.sh (revision 1f1e2261)
1#!/bin/sh
2
3#
4# Copyright (c) 2012 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# SUJ rename test scenario by Andrey Zonov <zont@FreeBSD.org>
30# "panic: flush_pagedep_deps: MKDIR_PARENT" seen:
31# http://people.freebsd.org/~pho/stress/log/suj30.txt
32
33[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
34
35. ../default.cfg
36
37here=`pwd`
38cd /tmp
39sed '1,/^EOF/d' < $here/$0 > suj30.c
40mycc -o suj30 -Wall -Wextra -O2 suj30.c -lpthread
41rm -f suj30.c
42
43mount | grep "on $mntpoint " | grep -q md$mdstart && umount $mntpoint
44mdconfig -l | grep -q md$mdstart &&  mdconfig -d -u $mdstart
45
46mdconfig -a -t swap -s 4g -u $mdstart
47newfs -j md$mdstart > /dev/null
48mount /dev/md$mdstart $mntpoint
49chmod 777 $mntpoint
50
51for i in `jot 10`; do
52	/tmp/suj30 $mntpoint/test-$i 100000 &
53done
54wait
55
56while mount | grep -q $mntpoint; do
57	umount $mntpoint || sleep 1
58done
59mdconfig -d -u $mdstart
60rm -f /tmp/suj30
61exit 0
62EOF
63/*
64 * Andrey Zonov (c) 2012
65 *
66 * compile as `cc -o rename rename.c -lpthread'
67 */
68
69#include <sys/types.h>
70#include <sys/stat.h>
71#include <sys/time.h>
72#include <sys/queue.h>
73#include <err.h>
74#include <errno.h>
75#include <fcntl.h>
76#include <pthread.h>
77#ifdef __FreeBSD__
78#include <pthread_np.h>
79#define	__NP__
80#endif
81#include <sched.h>
82#include <stdio.h>
83#include <stdlib.h>
84#include <string.h>
85#include <time.h>
86#include <unistd.h>
87
88#define	LOCK(x)		pthread_mutex_lock(&x.mtx)
89#define	UNLOCK(x)	pthread_mutex_unlock(&x.mtx)
90#define	SIGNAL(x)	pthread_cond_signal(&x.wait)
91#define	WAIT(x)		pthread_cond_wait(&x.wait, &x.mtx)
92
93int max;
94int exited;
95char *dirname1;
96char *dirname2;
97
98struct file {
99	char *name;
100	STAILQ_ENTRY(file) next;
101};
102
103struct files {
104	pthread_mutex_t mtx;
105	pthread_cond_t wait;
106	STAILQ_HEAD(, file) list;
107};
108
109static struct files newfiles;
110static struct files renamedfiles;
111
112void *loop_create(void *arg __unused);
113void *loop_rename(void *arg __unused);
114void *loop_unlink(void *arg __unused);
115
116int
117main(int argc, char **argv)
118{
119	int i;
120	int rc;
121	pthread_t tid[3];
122
123	if (argc != 3)
124		errx(1, "usage: pthread_count <dirname> <max>");
125
126	asprintf(&dirname1, "%s.1", argv[1]);
127	asprintf(&dirname2, "%s.2", argv[1]);
128	if (mkdir(dirname1, 0755) == -1)
129		err(1, "mkdir(%s)", dirname1);
130	if (mkdir(dirname2, 0755) == -1)
131		err(1, "mkdir(%s)", dirname2);
132	max = atoi(argv[2]);
133
134	STAILQ_INIT(&newfiles.list);
135	STAILQ_INIT(&renamedfiles.list);
136
137	rc = pthread_mutex_init(&newfiles.mtx, NULL);
138	if (rc != 0)
139		errc(1, rc, "pthread_mutex_init()");
140	rc = pthread_cond_init(&newfiles.wait, NULL);
141	if (rc != 0)
142		errc(1, rc, "pthread_cond_init()");
143	rc = pthread_mutex_init(&renamedfiles.mtx, NULL);
144	if (rc != 0)
145		errc(1, rc, "pthread_mutex_init()");
146	rc = pthread_cond_init(&renamedfiles.wait, NULL);
147	if (rc != 0)
148		errc(1, rc, "pthread_cond_init()");
149
150	rc = pthread_create(&tid[0], NULL, loop_create, NULL);
151	if (rc != 0)
152		errc(1, rc, "pthread_create()");
153	rc = pthread_create(&tid[1], NULL, loop_rename, NULL);
154	if (rc != 0)
155		errc(1, rc, "pthread_create()");
156	rc = pthread_create(&tid[2], NULL, loop_unlink, NULL);
157	if (rc != 0)
158		errc(1, rc, "pthread_create()");
159
160	for (i = 0; i < 3; i++) {
161		rc = pthread_join(tid[i], NULL);
162		if (rc != 0)
163			errc(1, rc, "pthread_join(%d)", i);
164	}
165
166	rc = pthread_mutex_destroy(&newfiles.mtx);
167	if (rc != 0)
168		errc(1, rc, "pthread_mutex_destroy(newfiles)");
169	rc = pthread_cond_destroy(&newfiles.wait);
170	if (rc != 0)
171		errc(1, rc, "pthread_cond_destroy(newfiles)");
172	rc = pthread_mutex_destroy(&renamedfiles.mtx);
173	if (rc != 0)
174		errc(1, rc, "pthread_mutex_destroy(renamedfiles)");
175	rc = pthread_cond_destroy(&renamedfiles.wait);
176	if (rc != 0)
177		errc(1, rc, "pthread_cond_destroy(renamedfiles)");
178	rmdir(dirname1);
179	rmdir(dirname2);
180	free(dirname1);
181	free(dirname2);
182
183	exit(0);
184}
185
186void *
187loop_create(void *arg __unused)
188{
189	int i;
190	struct file *file;
191
192#ifdef __NP__
193	pthread_set_name_np(pthread_self(), __func__);
194#endif
195
196	for (i = 0; i < max; i++) {
197		file = malloc(sizeof(*file));
198		asprintf(&file->name, "%s/filename_too-long:%d", dirname1, i);
199		if (mkdir(file->name, 0666) == -1) {
200			warn("mkdir(%s)", file->name);
201			free(file->name);
202			free(file);
203			break;
204		}
205		LOCK(newfiles);
206		STAILQ_INSERT_TAIL(&newfiles.list, file, next);
207		UNLOCK(newfiles);
208		SIGNAL(newfiles);
209	}
210	exited = 1;
211	SIGNAL(newfiles);
212	pthread_exit(NULL);
213}
214
215void *
216loop_rename(void *arg __unused)
217{
218	char *filename, *newname;
219	struct file *file;
220
221#ifdef	__NP__
222	pthread_set_name_np(pthread_self(), __func__);
223#endif
224
225	for ( ;; ) {
226		LOCK(newfiles);
227		while (STAILQ_EMPTY(&newfiles.list) && exited < 1)
228			WAIT(newfiles);
229		if (STAILQ_EMPTY(&newfiles.list) && exited == 1) {
230			UNLOCK(newfiles);
231			break;
232		}
233		file = STAILQ_FIRST(&newfiles.list);
234		STAILQ_REMOVE_HEAD(&newfiles.list, next);
235		UNLOCK(newfiles);
236		filename = strrchr(file->name, '/');
237		asprintf(&newname, "%s/%s", dirname2, filename);
238		if (rename(file->name, newname) == -1)
239			err(1, "rename(%s, %s)", file->name, newname);
240		free(file->name);
241		file->name = newname;
242		LOCK(renamedfiles);
243		STAILQ_INSERT_TAIL(&renamedfiles.list, file, next);
244		UNLOCK(renamedfiles);
245		SIGNAL(renamedfiles);
246	}
247	exited = 2;
248	SIGNAL(renamedfiles);
249	pthread_exit(NULL);
250}
251
252void *
253loop_unlink(void *arg __unused)
254{
255	struct file *file;
256
257#ifdef	__NP__
258	pthread_set_name_np(pthread_self(), __func__);
259#endif
260
261	for ( ;; ) {
262		LOCK(renamedfiles);
263		while (STAILQ_EMPTY(&renamedfiles.list) && exited < 2)
264			WAIT(renamedfiles);
265		if (STAILQ_EMPTY(&renamedfiles.list) && exited == 2) {
266			UNLOCK(renamedfiles);
267			break;
268		}
269		file = STAILQ_FIRST(&renamedfiles.list);
270		STAILQ_REMOVE_HEAD(&renamedfiles.list, next);
271		UNLOCK(renamedfiles);
272		rmdir(file->name);
273		free(file->name);
274		free(file);
275	}
276	pthread_exit(NULL);
277}
278