xref: /freebsd/tools/test/stress2/misc/rename14.sh (revision fb3ef04d2028110f06d68b09009f1f2ca0f4128e)
1#!/bin/sh
2
3#
4# SPDX-License-Identifier: BSD-2-Clause
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# "panic: handle_workitem_remove: DIRCHG and worklist not empty." seen:
31# https://people.freebsd.org/~pho/stress/log/rename14.txt
32# Fixed by r356714
33
34# Based on a syzkaller scenario reported by tuexen@freebsd.org
35
36# "panic: journal_jremref: Lost inodedep":
37# https://people.freebsd.org/~pho/stress/log/log0279.txt
38
39. ../default.cfg
40[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1
41
42dir=/tmp
43odir=`pwd`
44cd $dir
45sed -e '1,/^EOF/d' < $odir/$0 > $dir/rename14.c
46mycc -o rename14 -Wall -Wextra -O0 -g rename14.c -lpthread || exit 1
47rm -f rename14.c
48cd $odir
49
50set -e
51mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint
52[ -c /dev/md$mdstart ] &&  mdconfig -d -u $mdstart
53mdconfig -a -t swap -s 2g -u $mdstart
54[ `jot -r 1 0 1` -eq 1 ] && opt="-U -n" || opt="-j -n"
55newfs -j -n md$mdstart > /dev/null
56mount /dev/md$mdstart $mntpoint
57set +e
58
59s=0
60(cd /mnt; /tmp/rename14)
61[ -f rename14.core -a $s -eq 0 ] &&
62    { ls -l rename14.core; mv rename14.core $dir; s=1; }
63cd $odir
64
65for i in `jot 6`; do
66	mount | grep -q "on $mntpoint " || break
67	umount $mntpoint && break || sleep 10
68	[ $i -eq 6 ] &&
69	    { echo FATAL; fstat -mf $mntpoint; exit 1; }
70done
71checkfs /dev/md$mdstart || s=2
72mdconfig -d -u $mdstart
73rm -rf $dir/rename14
74exit $s
75
76EOF
77#include <sys/param.h>
78#include <sys/mman.h>
79#include <sys/stat.h>
80#include <sys/wait.h>
81
82#include <machine/atomic.h>
83
84#include <err.h>
85#include <errno.h>
86#include <fcntl.h>
87#include <pthread.h>
88#include <stdio.h>
89#include <stdlib.h>
90#include <time.h>
91#include <unistd.h>
92
93static sig_atomic_t done_testing;
94static volatile u_int *share;
95
96#define PARALLEL 10
97#define RUNTIME (3 * 60)
98#define SYNC 0
99
100static void *
101t1(void *data __unused)
102{
103	char n1[80];
104
105	snprintf(n1, sizeof(n1), "file1.%d", getpid());
106        while (done_testing == 0) {
107		rmdir(n1);
108		usleep(50000);
109        }
110
111        return (NULL);
112}
113
114static void *
115t2(void *data __unused)
116{
117	time_t start;
118	char n0[80], n00[80], n1[80];
119
120	snprintf(n0, sizeof(n0), "file0.%d", getpid());
121	snprintf(n00, sizeof(n00), "file0.%d/file0", getpid());
122	snprintf(n1, sizeof(n1), "file1.%d", getpid());
123	if (mkdir(n0, 0) == -1)
124		err(1, "mkdir(%s)", n0);
125
126	start = time(NULL);
127	while (time(NULL) - start < 60) {
128		if (mkdir(n00, 0) == -1)
129			err(1, "mkdir(%s)", n00);
130		if (rename(n00, n1) == -1)
131			err(1, "rename(i%s, %s)", n00, n1);
132        }
133	if (rmdir(n0) == -1)
134		err(1, "rmdir(%s)", n0);
135	done_testing = 1;
136
137        return (NULL);
138}
139
140static void
141test(void)
142{
143        pthread_t tid[2];
144        int r;
145
146	atomic_add_int(&share[SYNC], 1);
147	while (share[SYNC] != PARALLEL)
148		;
149
150	done_testing = 0;
151	if ((r = pthread_create(&tid[0], NULL, t1, NULL)) != 0)
152		errc(1, r, "pthread_create");
153	if ((r = pthread_create(&tid[1], NULL, t2, NULL)) != 0)
154		errc(1, r, "pthread_create");
155
156	if ((r = pthread_join(tid[0], NULL)) != 0)
157		errc(1, r, "pthread_join");
158	if ((r = pthread_join(tid[1], NULL)) != 0)
159		errc(1, r, "pthread_join");
160
161	_exit(0);
162}
163
164int
165main(void)
166{
167	pid_t pids[PARALLEL];
168	size_t len;
169	time_t start;
170	int e, i, status;
171
172	e = 0;
173	len = PAGE_SIZE;
174	if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE,
175	    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
176		err(1, "mmap");
177
178	start = time(NULL);
179	while ((time(NULL) - start) < RUNTIME && e == 0) {
180		share[SYNC] = 0;
181		for (i = 0; i < PARALLEL; i++) {
182			if ((pids[i] = fork()) == 0)
183				test();
184			if (pids[i] == -1)
185				err(1, "fork()");
186		}
187		for (i = 0; i < PARALLEL; i++) {
188			if (waitpid(pids[i], &status, 0) == -1)
189				err(1, "waitpid(%d)", pids[i]);
190			if (status != 0) {
191				if (WIFSIGNALED(status))
192					fprintf(stderr,
193					    "pid %d exit signal %d\n",
194					    pids[i], WTERMSIG(status));
195			}
196			e += status == 0 ? 0 : 1;
197		}
198	}
199
200	return (e);
201}
202