xref: /freebsd/tools/test/stress2/misc/sendfile24.sh (revision bdd1243d)
1#!/bin/sh
2
3#
4# SPDX-License-Identifier: BSD-2-Clause
5#
6# Copyright (c) 2020 Peter Holm <pho@FreeBSD.org>
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(2) test with disk read errors
31
32# 0 2986 2924   0  52  0   4392 2132 vmopar   D+    0   0:00.00 umount /mnt
33# seen.
34# Fixed by r361852
35
36# Test scenario suggestion by chs@
37
38[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1
39kldstat | grep -q geom_nop || { gnop load 2>/dev/null || exit 0 &&
40    notloaded=1; }
41gnop status || exit 1
42
43. ../default.cfg
44
45dir=/tmp
46odir=`pwd`
47cd $dir
48sed '1,/^EOF/d' < $odir/$0 > $dir/sendfile24.c
49mycc -o sendfile24 -Wall -Wextra -O0 -g sendfile24.c || exit 1
50cd $odir
51
52set -e
53mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint
54[ -c /dev/md$mdstart ] &&  mdconfig -d -u $mdstart
55
56mdconfig -a -t swap -s 2g -u $mdstart
57gnop create /dev/md$mdstart
58newfs $newfs_flags /dev/md$mdstart.nop > /dev/null
59mount /dev/md$mdstart.nop $mntpoint
60chmod 777 $mntpoint
61set +e
62
63dd if=/dev/zero of=$mntpoint/file bs=4k count=1 status=none
64gnop configure -e 5 -r 1 /dev/md$mdstart.nop
65
66start=`date +%s`
67echo 'Expect:
68    sendfile24: sendfile: sendfile24: read(), sendfile24.c:61: Broken pipe
69    Connection reset by peer'
70while [ $((`date +%s` - start)) -lt 10 ]; do
71	(cd $mntpoint; umount $mntpoint) > /dev/null 2>&1
72	/tmp/sendfile24 $mntpoint/file /dev/null 12345
73done
74umount $mntpoint
75
76gnop destroy /dev/md$mdstart.nop
77mdconfig -d -u $mdstart
78[ $notloaded ] && gnop unload
79rm -f /tmp/sendfile24 /tmp/sendfile24.c
80
81exit 0
82EOF
83#include <sys/param.h>
84#include <sys/socket.h>
85#include <sys/stat.h>
86#include <err.h>
87#include <fcntl.h>
88#include <netdb.h>
89#include <netinet/in.h>
90#include <signal.h>
91#include <stdio.h>
92#include <stdlib.h>
93#include <string.h>
94#include <unistd.h>
95
96int port;
97char *inputFile;
98char *outputFile;
99int bufsize = 4096;
100
101static void
102reader(void) {
103	int tcpsock, msgsock;
104	int on;
105	socklen_t len;
106	struct sockaddr_in inetaddr, inetpeer;
107	int n, *buf, fd;
108
109	on = 1;
110	if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
111		err(1, "socket(), %s:%d", __FILE__, __LINE__);
112
113	if (setsockopt(tcpsock,
114	    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
115		err(1, "setsockopt(), %s:%d", __FILE__, __LINE__);
116
117	inetaddr.sin_family = AF_INET;
118	inetaddr.sin_addr.s_addr = INADDR_ANY;
119	inetaddr.sin_port = htons(port);
120	inetaddr.sin_len = sizeof(inetaddr);
121
122	if (bind(tcpsock,
123	    (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0)
124		err(1, "bind(), %s:%d", __FILE__, __LINE__);
125
126	if (listen(tcpsock, 5) < 0)
127		err(1, "listen(), %s:%d", __FILE__, __LINE__);
128
129	len = sizeof(inetpeer);
130	if ((msgsock = accept(tcpsock,
131	    (struct sockaddr *)&inetpeer, &len)) < 0)
132		err(1, "accept(), %s:%d", __FILE__, __LINE__);
133
134	if ((buf = malloc(bufsize)) == NULL)
135		err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__);
136
137	if ((fd = open(outputFile, O_RDWR | O_CREAT | O_TRUNC, 0640)) == -1)
138		err(1, "open(%s)", outputFile);
139
140	for (;;) {
141		if ((n = read(msgsock, buf, bufsize)) < 0)
142			err(1, "read(), %s:%d", __FILE__, __LINE__);
143		if (n == 0)
144			break;
145
146		if ((write(fd, buf, n)) != n)
147			err(1, "write");
148	}
149	close(msgsock);
150	close(fd);
151	return;
152}
153
154static void
155writer(void) {
156	int tcpsock, on;
157	struct sockaddr_in inetaddr;
158	struct hostent *hostent;
159	struct stat statb;
160	off_t off = 0;
161	size_t size;
162	int i, r, fd;
163
164	on = 1;
165	for (i = 1; i < 5; i++) {
166		if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
167			err(1, "socket(), %s:%d", __FILE__, __LINE__);
168
169		if (setsockopt(tcpsock,
170		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
171			err(1, "setsockopt(), %s:%d", __FILE__, __LINE__);
172
173		size = getpagesize() -4;
174		if (setsockopt(tcpsock, SOL_SOCKET, SO_SNDBUF, (void *)&size,
175		    sizeof(size)) < 0)
176			err(1, "setsockopt(SO_SNDBUF), %s:%d",
177			    __FILE__, __LINE__);
178
179		hostent = gethostbyname ("localhost");
180		memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr,
181			sizeof (struct in_addr));
182
183		inetaddr.sin_family = AF_INET;
184		inetaddr.sin_port = htons(port);
185		inetaddr.sin_len = sizeof(inetaddr);
186
187		r = connect(tcpsock, (struct sockaddr *) &inetaddr,
188			sizeof(inetaddr));
189		if (r == 0)
190			break;
191		sleep(1);
192		close(tcpsock);
193	}
194	if (r < 0)
195		err(1, "connect(), %s:%d", __FILE__, __LINE__);
196
197        if (stat(inputFile, &statb) != 0)
198                err(1, "stat(%s)", inputFile);
199
200	if ((fd = open(inputFile, O_RDONLY)) == -1)
201		err(1, "open(%s)", inputFile);
202
203	if (sendfile(fd, tcpsock, 0, statb.st_size, NULL, &off, 0) == -1)
204		err(1, "sendfile");
205
206	return;
207}
208
209int
210main(int argc, char **argv)
211{
212	pid_t pid;
213
214	if (argc != 4) {
215		fprintf(stderr, "Usage: %s <inputFile outputFile portNumber\n",
216		    argv[0]);
217		return (1);
218	}
219	inputFile = argv[1];
220	outputFile = argv[2];
221	port = atoi(argv[3]);
222
223	if ((pid = fork()) == 0) {
224		writer();
225		exit(EXIT_SUCCESS);
226	} else if (pid > 0) {
227		reader();
228		kill(pid, SIGINT);
229	} else
230		err(1, "fork(), %s:%d",  __FILE__, __LINE__);
231
232	return (0);
233}
234