xref: /freebsd/tools/test/stress2/misc/sendfile17.sh (revision fd45b686f9d92f583366c75b22c04c7ee49709c0)
1#!/bin/sh
2
3#
4# SPDX-License-Identifier: BSD-2-Clause
5#
6# Copyright (c) 2018 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# sendfile() over socket pairs test. Variation of sendfile15.sh with
31# ualarm(2) added.
32
33# Page fault seen: https://people.freebsd.org/~pho/stress/log/dougm029.txt
34
35. ../default.cfg
36[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1
37
38dir=/tmp
39odir=`pwd`
40cd $dir
41sed '1,/^EOF/d' < $odir/$0 > $dir/sendfile17.c
42mycc -o sendfile17 -Wall -Wextra -O0 -g sendfile17.c || exit 1
43rm -f sendfile17.c
44cd $odir
45
46set -e
47mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint
48[ -c /dev/md$mdstart ] &&  mdconfig -d -u $mdstart
49mdconfig -a -t swap -s 3g -u $mdstart
50newfs $newfs_flags md$mdstart > /dev/null
51mount /dev/md$mdstart $mntpoint
52set +e
53
54cd $mntpoint
55dd if=/dev/random of=input bs=4k count=1 status=none
56(cd $odir/../testcases/swap; ./swap -t 5m -i 20 > /dev/null) &
57$dir/sendfile17
58s=$?
59while pgrep -q swap; do
60	pkill swap
61done
62wait
63[ -f sendfile17.core -a $s -eq 0 ] &&
64    { ls -l sendfile17.core; mv sendfile17.core $dir; s=1; }
65cd $odir
66
67for i in `jot 6`; do
68	mount | grep -q "on $mntpoint " || break
69	umount $mntpoint && break || sleep 10
70	[ $i -eq 6 ] &&
71	    { echo FATAL; fstat -mf $mntpoint; exit 1; }
72done
73mdconfig -d -u $mdstart
74rm -rf $dir/sendfile17
75exit $s
76
77EOF
78#include <sys/param.h>
79#include <sys/fcntl.h>
80#include <sys/mman.h>
81#include <sys/socket.h>
82#include <sys/stat.h>
83#include <sys/stat.h>
84#include <sys/uio.h>
85#include <sys/wait.h>
86
87#include <machine/atomic.h>
88
89#include <err.h>
90#include <errno.h>
91#include <fcntl.h>
92#include <stdio.h>
93#include <stdlib.h>
94#include <time.h>
95#include <unistd.h>
96
97static volatile u_int *share;
98
99#define PARALLEL 32
100#define RUNTIME (5 * 60)
101#define SYNC 0
102
103static void
104handler(int i __unused) {
105	_exit(0);
106}
107
108static void
109test(void)
110{
111	struct stat st;
112	off_t written, pos;
113	int child, error, from, n, status, sv[2];
114	char *buf;
115	const char *from_name;
116
117	atomic_add_int(&share[SYNC], 1);
118	while (share[SYNC] != PARALLEL)
119		usleep(100);
120
121	from_name = "input";
122
123	if ((from = open(from_name, O_RDONLY)) == -1)
124		err(1, "open read %s", from_name);
125
126	if ((error = fstat(from, &st)) == -1)
127		err(1, "stat %s", from_name);
128
129	if ((error = socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) == -1)
130		err(1, "socketpair");
131
132	signal(SIGALRM, handler);
133	child = fork();
134	if (child == -1)
135		err(1, "fork");
136	else if (child != 0) {
137		setproctitle("parent");
138		close(sv[1]);
139		pos = 0;
140		for (;;) {
141			if (arc4random() % 100 < 20)
142				ualarm(arc4random() % 10000, 0);
143			error = sendfile(from, sv[0], pos, st.st_size - pos,
144			    NULL, &written, 0);
145			if (error == -1) {
146				if (errno != EAGAIN && errno != EPIPE &&
147				    errno != ENOTCONN)
148					err(1, "sendfile");
149				_exit(0);;
150			}
151			ualarm(0, 0);
152			pos += written;
153			if (pos == st.st_size)
154				break;
155		}
156		close(sv[0]);
157		if (waitpid(child, &status, 0) != child)
158			err(1, "waitpid(%d)", child);
159	} else {
160		setproctitle("child");
161		close(sv[0]);
162		buf = malloc(st.st_size);
163		if (buf == NULL)
164			err(1, "malloc %jd", st.st_size);
165		pos = 0;
166		for (;;) {
167			written = st.st_size - pos;
168			if (arc4random() % 100 < 20)
169				ualarm(arc4random() % 10000, 0);
170			n = read(sv[1], buf + pos, written);
171			ualarm(0, 0);
172			if (n == -1 && errno != ENOTCONN)
173				err(1, "read");
174			else if (n == 0)
175				_exit(0);
176			pos += n;
177			if (pos == st.st_size)
178				break;
179		}
180		close(sv[1]);
181		_exit(0);
182	}
183
184	_exit(0);
185}
186
187int
188main(void)
189{
190	pid_t pids[PARALLEL];
191	size_t len;
192	time_t start;
193	int e, i, status;
194
195	e = 0;
196	len = PAGE_SIZE;
197	if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE,
198	    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
199		err(1, "mmap");
200
201	start = time(NULL);
202	while ((time(NULL) - start) < RUNTIME && e == 0) {
203		share[SYNC] = 0;
204		for (i = 0; i < PARALLEL; i++) {
205			if ((pids[i] = fork()) == 0)
206				test();
207			if (pids[i] == -1)
208				err(1, "fork()");
209		}
210		for (i = 0; i < PARALLEL; i++) {
211			if (waitpid(pids[i], &status, 0) == -1)
212				err(1, "waitpid(%d)", pids[i]);
213			if (status != 0) {
214				if (WIFSIGNALED(status))
215					fprintf(stderr,
216					    "pid %d exit signal %d\n",
217					    pids[i], WTERMSIG(status));
218			}
219			e += status == 0 ? 0 : 1;
220		}
221	}
222
223	return (e);
224}
225