xref: /freebsd/tools/test/stress2/misc/nfs15.sh (revision 81ad6265)
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# Test effort to reproduce reported: "observed a hang in a multi-threaded
30# process that had hit an assertion failure and was attempting to dump core".
31# Problem never seen.
32
33# Most interesting load are:
34# - coredumping of the multithreaded program with the current dir on NFS,
35#   which also accesses NFS files;
36# - advisory locking tests on NFS files, while e.g. sending SIGSTOP/SIGCONT
37#   to the test programs.
38
39# See also pthread9.sh
40
41# https://people.freebsd.org/~pho/stress/log/kostik897.txt
42# Fixed in r302013.
43
44# "panic: mutex sleepq chain not owned at subr_sleepqueue.c:1009" seen:
45# https://people.freebsd.org/~pho/stress/log/kostik914.txt
46# Fixed in r302328.
47
48[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
49
50. ../default.cfg
51
52[ -z "$nfs_export" ] && exit 0
53ping -c 2 `echo $nfs_export | sed 's/:.*//'` > /dev/null 2>&1 ||
54    exit 0
55
56USE_TIMEOUT=1
57here=`pwd`
58cd /tmp
59sed '1,/^EOF/d' < $here/$0 > nfs15.c
60mycc -o nfs15 -Wall -Wextra -O2 -g nfs15.c -lpthread || exit 1
61rm -f nfs15.c
62cd $here
63
64mount | grep "on $mntpoint " | grep nfs > /dev/null && umount $mntpoint
65
66mount -t nfs -o tcp -o retrycnt=3 -o intr,soft -o rw -o nolockd \
67    $nfs_export $mntpoint || exit 1
68sleep 2
69wd=$mntpoint/nfs15.dir
70rm -rf $wd
71mkdir $wd
72
73(cd $wd; /tmp/nfs15)
74rm -rf $wd
75
76while mount | grep "on $mntpoint " | grep -q nfs; do
77	umount $mntpoint || sleep 1
78done
79
80rm -f /tmp/nfs15
81exit 0
82EOF
83#include <sys/stat.h>
84#include <sys/param.h>
85#include <sys/mman.h>
86#include <sys/wait.h>
87
88#include <machine/atomic.h>
89
90#include <err.h>
91#include <errno.h>
92#include <fcntl.h>
93#include <pthread.h>
94#include <signal.h>
95#include <stdio.h>
96#include <stdlib.h>
97#include <string.h>
98#include <unistd.h>
99
100#define PARALLEL 4
101#define RUNTIME 300
102#define SYNC 0
103
104volatile u_int *share;
105
106static void *
107t1(void *data __unused)
108{
109	atomic_add_int(&share[SYNC], 1);
110	usleep(arc4random() % 8000);
111	raise(SIGABRT);
112
113	return (NULL);
114}
115
116static void *
117t2(void *data __unused)
118{
119	int fd, i, r;
120	char file[80];
121
122	for (i = 0; i < 100; i++) {
123		atomic_add_int(&share[SYNC], 1);
124		snprintf(file, sizeof(file), "file.%06d", i);
125		if ((fd = open(file, O_WRONLY | O_CREAT | O_APPEND,
126		    DEFFILEMODE)) == -1)
127			err(1, "open(%s)", file);
128		do {
129			r = lockf(fd, F_LOCK, 0);
130		} while (r == -1 && errno == EDEADLK);
131		if (r == -1)
132			err(1, "lockf(%s, F_LOCK)", file);
133		write(fd, "x", 1);
134		if (lseek(fd, 0, SEEK_SET) == -1)
135			err(1, "lseek");
136		if (lockf(fd, F_ULOCK, 0) == -1)
137			err(1, "lockf(%s, F_ULOCK)", file);
138		close(fd);
139	}
140
141	return (NULL);
142}
143
144int
145test(void)
146{
147	pthread_t tid[3];
148	int i, rc;
149
150	for (i = 0; i < 10; i++) {
151		if ((rc = pthread_create(&tid[0], NULL, t2, NULL)) == -1)
152			errc(1, rc, "pthread_create");
153		if ((rc = pthread_create(&tid[1], NULL, t2, NULL)) == -1)
154			errc(1, rc, "pthread_create");
155		if ((rc = pthread_create(&tid[2], NULL, t1, NULL)) == -1)
156			errc(1, rc, "pthread_create");
157
158		if ((rc = pthread_join(tid[0], NULL)) == -1)
159			errc(1, rc, "pthread_join");
160		if ((rc = pthread_join(tid[1], NULL)) == -1)
161			errc(1, rc, "pthread_join");
162		if ((rc = pthread_join(tid[2], NULL)) == -1)
163			errc(1, rc, "pthread_join");
164	}
165
166	_exit(0);
167}
168
169int
170main(void)
171{
172	pid_t pids[PARALLEL];
173	size_t len;
174	time_t start;
175        int i, status;
176
177	len = PAGE_SIZE;
178	if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE,
179	    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
180		err(1, "mmap");
181
182	start = time(NULL);
183	while (time(NULL) - start < RUNTIME) {
184		for (i = 0; i < PARALLEL; i++) {
185			if ((pids[i] = fork()) == 0)
186				test();
187		}
188
189		for(;;) {
190			if (share[SYNC] > 0)
191				atomic_add_int(&share[SYNC], -1);
192			for (i = 0; i < PARALLEL; i++)
193				kill(pids[i], SIGSTOP);
194			usleep(100 + arc4random() % 1000);
195			for (i = 0; i < PARALLEL; i++)
196				kill(pids[i], SIGCONT);
197			usleep(100 + arc4random() % 400);
198			if (share[SYNC] == 0) { /* If all procs are done */
199				usleep(500);
200				if (share[SYNC] == 0)
201					break;
202			}
203		}
204
205		for (i = 0; i < PARALLEL; i++) {
206			if (waitpid(pids[i], &status, 0) != pids[i])
207				err(1, "waitpid");
208		}
209	}
210
211	return (0);
212}
213