xref: /freebsd/tools/test/stress2/misc/nfsdepth.sh (revision 19261079)
1#!/bin/sh
2
3#
4# Copyright (c) 2016 EMC Corp.
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[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
30
31. ../default.cfg
32
33# NFS test with deep directories.
34
35# Only issue seen is:
36# nfsdepth: mkdir(d93) l35: Permission denied
37
38[ -z "$nfs_export" ] && exit 0
39ping -c 2 `echo $nfs_export | sed 's/:.*//'` > /dev/null 2>&1 ||
40    exit 0
41
42odir=`pwd`
43cd /tmp
44sed '1,/^EOF/d' < $odir/$0 > nfsdepth.c
45mycc -o nfsdepth -Wall -Wextra -g nfsdepth.c || exit 1
46rm -f nfsdepth.c
47cd $odir
48
49mount | grep "$mntpoint" | grep nfs > /dev/null && umount $mntpoint
50mount -t nfs -o tcp -o rw -o soft $nfs_export $mntpoint
51
52work=$mntpoint/nfsdepth.`jot -rc 8 a z | tr -d '\n'`.dir
53mkdir -p $work
54chmod 777 $work
55
56su $testuser -c "cd $work; /tmp/nfsdepth"
57s=$?
58if [ $s -eq 0 ]; then
59	su $testuser -c "rm -rf $work 2>/dev/null"
60	rm -rf $work
61else
62	find $work -ls
63fi
64
65umount $mntpoint > /dev/null 2>&1
66while mount | grep "$mntpoint" | grep -q nfs; do
67	umount $mntpoint > /dev/null 2>&1
68done
69
70rm -f /tmp/nfsdepth
71exit $s
72
73EOF
74#include <sys/param.h>
75#include <sys/stat.h>
76#include <sys/wait.h>
77
78#include <err.h>
79#include <errno.h>
80#include <signal.h>
81#include <stdio.h>
82#include <stdlib.h>
83#include <unistd.h>
84
85static unsigned long actual, size;
86volatile int done_testing;
87int fail;
88
89#define DEPTH 200
90#define PARALLEL 8
91#define RUNTIME 180
92
93void
94handler(int s __unused)
95{
96	done_testing = 1;
97}
98
99void
100mkDir(char *path, int level) {
101	int n, r;
102	char newPath[MAXPATHLEN + 1];
103
104	n = 0;
105	do {
106		r = mkdir(path, 0770);
107		if (r == -1 && errno == EACCES && n < 10) {
108			warn("mkdir(%s) l%d", path, __LINE__);
109			n++;
110			errno = EAGAIN;
111			usleep(10000);
112		}
113		if (r == -1 && errno == EINTR)
114			(void)rmdir(path);
115	} while (r == -1 && (errno == EINTR || errno == EAGAIN));
116
117	if (r == -1) {
118		warn("mkdir(%s), pid %d, l%d", path, getpid(), __LINE__);
119		fail++;
120	} else {
121		actual++;
122		do {
123			r = chdir (path);
124		if (r == -1 && errno == EACCES && n < 10) {
125			warn("chdir(%s) .%d", path, __LINE__);
126			n++;
127			errno = EAGAIN;
128			usleep(10000);
129		}
130		} while (r == -1 && (errno == EINTR || errno == EAGAIN));
131		if (r == -1)
132			err(1, "chdir(%s), pid %d, l%d", path, getpid(), __LINE__);
133	}
134
135	if (done_testing == 0 && fail == 0 && level < (int)size) {
136		sprintf(newPath,"d%d", level + 1);
137		mkDir(newPath, level + 1);
138	}
139}
140
141void
142rmDir(char *path, int level) {
143	int n, r;
144	char newPath[MAXPATHLEN + 1];
145
146	if (level == 0)
147		return;
148
149	if (level < (int)actual) {
150		sprintf(newPath,"d%d", level+1);
151		rmDir(newPath, level+1);
152	}
153	n = 0;
154	do {
155		r = chdir ("..");
156		if (r == -1 && errno == EACCES && n < 10) {
157			warn("chdir(%s) l%d", path, __LINE__);
158			n++;
159			errno = EAGAIN;
160			usleep(10000);
161		}
162	} while (r == -1 && (errno == EINTR || errno == EAGAIN));
163	if (r == -1)
164		err(1, "chdir(%s), pid %d,  l%d", "..", getpid(), __LINE__);
165	n = 0;
166	do {
167		r = rmdir(path);
168		if (r == -1 && errno == EACCES && n < 10) {
169			warn("rmdir(%s) l%d", path, __LINE__);
170			n++;
171			errno = EAGAIN;
172			usleep(10000);
173		}
174	} while (r == -1 && (errno == EINTR || errno == EAGAIN));
175	if (r == -1)
176		err(1, "rmdir(%s), pid %d,  l%d", path, getpid(), __LINE__);
177}
178
179int
180test2(void)
181{
182	char path[MAXPATHLEN + 1];
183
184	fail = actual = 0;
185	umask(0);
186	sprintf(path,"p%05d.d%d", getpid(), 1);
187	mkDir(path, 1);
188	rmDir(path, 1);
189
190	_exit (fail);
191}
192
193int
194test(void)
195{
196	pid_t pid;
197	time_t start;
198	int status;
199
200	size = (arc4random() % DEPTH) + 1;
201
202	signal(SIGHUP, handler);
203	start = time(NULL);
204	while (time(NULL) - start < RUNTIME && fail == 0) {
205		if ((pid = fork()) == 0) {
206			done_testing = 0;
207			test2();
208		}
209
210		status = 0;
211		while (wait4(pid, &status, WNOHANG, NULL) != pid) {
212			if (kill(pid, SIGHUP) == -1)
213				err(1, "kill(%d)", pid);
214			usleep(100000 + (arc4random() % 10000));
215		}
216		if (status != 0)
217			fail++;
218	}
219
220	_exit (status != 0);
221}
222
223int
224main(void)
225{
226	int e, i, pids[PARALLEL], status;
227
228	e = 0;
229	for (i = 0; i < PARALLEL; i++) {
230		if ((pids[i] = fork()) == 0)
231			test();
232	}
233	for (i = 0; i < PARALLEL; i++) {
234		waitpid(pids[i], &status, 0);
235		e += status == 0 ? 0 : 1;
236	}
237
238	return (e);
239}
240