]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/test/stress2/misc/sendfile22.sh
contrib/bc: update to version 5.1.1
[FreeBSD/FreeBSD.git] / tools / test / stress2 / misc / sendfile22.sh
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 # Variation of sendfile21.sh: without the use of socketpair().
31 # No problems seen.
32
33 . ../default.cfg
34 [ `id -u` -ne 0 ] && echo "Must be root!" && exit 1
35
36 dir=/tmp
37 odir=`pwd`
38 cd $dir
39 sed '1,/^EOF/d' < $odir/$0 > $dir/sendfile22.c
40 mycc -o sendfile22 -Wall -Wextra -O0 -g sendfile22.c || exit 1
41 rm -f sendfile22.c
42 cd $odir
43
44 set -e
45 mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint
46 [ -c /dev/md$mdstart ] &&  mdconfig -d -u $mdstart
47 mdconfig -a -t swap -s 1g -u $mdstart
48 bsdlabel -w md$mdstart auto
49 newfs_flags=""
50 newfs $newfs_flags -n md$mdstart > /dev/null
51 mount /dev/md$mdstart $mntpoint
52 set +e
53
54 cd $mntpoint
55 dd if=/dev/random of=input bs=4k count=100 status=none
56
57 (cd $odir/../testcases/swap; ./swap -t 5m -i 20 -l 100 > /dev/null) &
58 sleep 30
59 n=1
60 start=` date +%s`
61 while [ $((` date +%s` - start)) -lt 180 ]; do
62         rm -f output
63         umount $mntpoint 2>/dev/null # busy umount
64         $dir/sendfile22
65         s=$?
66         cmp -s input output || break
67         [ `stat -f '%z' input` -ne ` stat -f '%z' output` ] && break
68         n=$((n + 1))
69 done
70 while pgrep -q swap; do
71         pkill swap
72 done
73 cmp -s input output || { echo "Loop #$n"; ls -l; s=1; }
74 wait
75 [ -f sendfile22.core -a $s -eq 0 ] &&
76     { ls -l sendfile22.core; mv sendfile22.core $dir; s=1; }
77 cd $odir
78
79 for i in `jot 18`; do
80         mount | grep -q "on $mntpoint " || break
81         umount $mntpoint && break || sleep 10
82         [ $i -eq 18 ] &&
83             { echo FATAL; fstat -mf $mntpoint; exit 1; }
84 done
85 mdconfig -d -u $mdstart
86 rm -rf $dir/sendfile22
87 exit $s
88
89 EOF
90 #include <sys/param.h>
91 #include <sys/fcntl.h>
92 #include <sys/mman.h>
93 #include <sys/socket.h>
94 #include <sys/stat.h>
95 #include <sys/uio.h>
96 #include <sys/wait.h>
97
98 #include <netinet/in.h>
99
100 #include <err.h>
101 #include <errno.h>
102 #include <fcntl.h>
103 #include <netdb.h>
104 #include <stdio.h>
105 #include <stdlib.h>
106 #include <string.h>
107 #include <strings.h>
108 #include <unistd.h>
109
110 static void
111 test(void)
112 {
113         struct stat st;
114         struct sockaddr_in inetaddr, inetpeer;
115         struct hostent *hostent;
116         socklen_t len;
117         off_t i, j, rd, written, pos;
118         pid_t pid;
119         int error, from, i1, msgsock, n, on, port, r, status, tcpsock, to;
120         char buf[4086], *cp;
121         const char *from_name, *to_name;
122
123         from_name = "input";
124         to_name = "output";
125         port = 12345;
126
127         if ((from = open(from_name, O_RDONLY)) == -1)
128                 err(1, "open read %s", from_name);
129
130         if ((error = fstat(from, &st)) == -1)
131                 err(1, "stat %s", from_name);
132
133         pid = fork();
134         if (pid == -1)
135                 err(1, "fork");
136         else if (pid != 0) {
137                 setproctitle("parent");
138
139                 alarm(300);
140                 on = 1;
141                 for (i1 = 1; i1 < 5; i1++) {
142                         if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
143                                 err(1, "socket(), %s:%d", __FILE__, __LINE__);
144
145                         if (setsockopt(tcpsock,
146                             SOL_SOCKET, SO_REUSEADDR, (char *)&on,
147                             sizeof(on)) < 0)
148                                 err(1, "setsockopt(), %s:%d", __FILE__,
149                                                 __LINE__);
150
151                         hostent = gethostbyname ("localhost");
152                         bzero((char *) &inetaddr, sizeof(inetaddr));
153                         memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr,
154                                 sizeof (struct in_addr));
155
156                         inetaddr.sin_family = AF_INET;
157                         inetaddr.sin_port = htons(port);
158                         inetaddr.sin_len = sizeof(inetaddr);
159
160                         r = connect(tcpsock, (struct sockaddr *) &inetaddr,
161                                 sizeof(inetaddr));
162                         if (r == 0)
163                                 break;
164                         sleep(1);
165                         close(tcpsock);
166                 }
167                 if (r < 0)
168                         err(1, "connect(), %s:%d", __FILE__, __LINE__);
169
170                 if ((cp = mmap(NULL, st.st_size, PROT_READ,
171                     MAP_PRIVATE, from, 0)) == MAP_FAILED)
172                         err(1, "mmap");
173                 if (fsync(from) == -1)
174                         err(1, "fsync()");
175
176                 for (i = 0, j = 0; i < st.st_size; i += PAGE_SIZE, j++) {
177                         (void)cp[i];
178                         if (j % 2 == 1) {
179                                 if (msync(cp + i, PAGE_SIZE, MS_INVALIDATE)
180                                     == -1)
181                                         err(1, "msync(), j = %d", (int)j);
182                         }
183                 }
184                 if (munmap(cp, st.st_size) == -1)
185                         err(1, "munmap()");
186
187                 pos = 0;
188                 for (;;) {
189                         error = sendfile(from, tcpsock, pos, st.st_size -
190                             pos, NULL, &written, 0);
191                         if (error == -1)
192                                 err(1, "sendfile");
193                         if (written != st.st_size)
194                                 fprintf(stderr, "sendfile sent %d bytes\n",
195                                     (int)written);
196                         pos += written;
197                         if (pos == st.st_size)
198                                 break;
199                 }
200                 if (pos != st.st_size)
201                         fprintf(stderr, "%d written, expected %d\n",
202                             (int)pos, (int)st.st_size);
203                 close(tcpsock);
204                 if (waitpid(pid, &status, 0) != pid)
205                         err(1, "waitpid(%d)", pid);
206         } else {
207                 setproctitle("child");
208                 close(from);
209                 alarm(300);
210                 on = 1;
211                 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
212                         err(1, "socket(), %s:%d", __FILE__, __LINE__);
213
214                 if (setsockopt(tcpsock,
215                     SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
216                         err(1, "setsockopt(), %s:%d", __FILE__, __LINE__);
217
218                 inetaddr.sin_family = AF_INET;
219                 inetaddr.sin_addr.s_addr = INADDR_ANY;
220                 inetaddr.sin_port = htons(port);
221                 inetaddr.sin_len = sizeof(inetaddr);
222
223                 if (bind(tcpsock,
224                     (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0)
225                         err(1, "bind(), %s:%d", __FILE__, __LINE__);
226
227                 if (listen(tcpsock, 5) < 0)
228                         err(1, "listen(), %s:%d", __FILE__, __LINE__);
229
230                 len = sizeof(inetpeer);
231                 if ((msgsock = accept(tcpsock,
232                     (struct sockaddr *)&inetpeer, &len)) < 0)
233                         err(1, "accept(), %s:%d", __FILE__, __LINE__);
234
235                 if ((to = open(to_name, O_RDWR | O_CREAT, DEFFILEMODE)) ==
236                     -1)
237                         err(1, "open write %s", to_name);
238
239                 rd = 0;
240                 for (;;) {
241                         n = read(msgsock, buf, sizeof(buf));
242                         if (n == -1)
243                                 err(1, "read");
244                         else if (n == 0)
245                                 break;
246                         rd += n;
247                         if (write(to, buf, n) != n)
248                                 err(1, "write()");
249                 }
250                 close(to);
251                 if (rd != st.st_size)
252                         fprintf(stderr, "Short read %d, expected %d\n",
253                             (int)rd, (int)st.st_size);
254                 _exit(0);
255         }
256
257         _exit(0);
258 }
259
260 int
261 main(void)
262 {
263         pid_t pid;
264         int e, status;
265
266         e = 0;
267         if ((pid = fork()) == 0)
268                 test();
269         if (pid == -1)
270                 err(1, "fork()");
271         if (waitpid(pid, &status, 0) == -1)
272                 err(1, "waitpid(%d)", pid);
273         if (status != 0) {
274                 if (WIFSIGNALED(status))
275                         fprintf(stderr,
276                             "pid %d exit signal %d\n",
277                             pid, WTERMSIG(status));
278         }
279         e += status == 0 ? 0 : 1;
280
281         return (e);
282 }