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