xref: /freebsd/tools/test/stress2/misc/sendfile24.sh (revision c1d255d3)
1#!/bin/sh
2
3#
4# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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, t, *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	t = 0;
135	if ((buf = malloc(bufsize)) == NULL)
136		err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__);
137
138	if ((fd = open(outputFile, O_RDWR | O_CREAT | O_TRUNC, 0640)) == -1)
139		err(1, "open(%s)", outputFile);
140
141	for (;;) {
142		if ((n = read(msgsock, buf, bufsize)) < 0)
143			err(1, "read(), %s:%d", __FILE__, __LINE__);
144		t += n;
145		if (n == 0)
146			break;
147
148		if ((write(fd, buf, n)) != n)
149			err(1, "write");
150	}
151	close(msgsock);
152	close(fd);
153	return;
154}
155
156static void
157writer(void) {
158	int tcpsock, on;
159	struct sockaddr_in inetaddr;
160	struct hostent *hostent;
161	struct stat statb;
162	off_t off = 0;
163	size_t size;
164	int i, r, fd;
165
166	on = 1;
167	for (i = 1; i < 5; i++) {
168		if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
169			err(1, "socket(), %s:%d", __FILE__, __LINE__);
170
171		if (setsockopt(tcpsock,
172		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
173			err(1, "setsockopt(), %s:%d", __FILE__, __LINE__);
174
175		size = getpagesize() -4;
176		if (setsockopt(tcpsock, SOL_SOCKET, SO_SNDBUF, (void *)&size,
177		    sizeof(size)) < 0)
178			err(1, "setsockopt(SO_SNDBUF), %s:%d",
179			    __FILE__, __LINE__);
180
181		hostent = gethostbyname ("localhost");
182		memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr,
183			sizeof (struct in_addr));
184
185		inetaddr.sin_family = AF_INET;
186		inetaddr.sin_port = htons(port);
187		inetaddr.sin_len = sizeof(inetaddr);
188
189		r = connect(tcpsock, (struct sockaddr *) &inetaddr,
190			sizeof(inetaddr));
191		if (r == 0)
192			break;
193		sleep(1);
194		close(tcpsock);
195	}
196	if (r < 0)
197		err(1, "connect(), %s:%d", __FILE__, __LINE__);
198
199        if (stat(inputFile, &statb) != 0)
200                err(1, "stat(%s)", inputFile);
201
202	if ((fd = open(inputFile, O_RDONLY)) == -1)
203		err(1, "open(%s)", inputFile);
204
205	if (sendfile(fd, tcpsock, 0, statb.st_size, NULL, &off, 0) == -1)
206		err(1, "sendfile");
207
208	return;
209}
210
211int
212main(int argc, char **argv)
213{
214	pid_t pid;
215
216	if (argc != 4) {
217		fprintf(stderr, "Usage: %s <inputFile outputFile portNumber\n",
218		    argv[0]);
219		return (1);
220	}
221	inputFile = argv[1];
222	outputFile = argv[2];
223	port = atoi(argv[3]);
224
225	if ((pid = fork()) == 0) {
226		writer();
227		exit(EXIT_SUCCESS);
228	} else if (pid > 0) {
229		reader();
230		kill(pid, SIGINT);
231	} else
232		err(1, "fork(), %s:%d",  __FILE__, __LINE__);
233
234	return (0);
235}
236