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. Short read seen. 31 32. ../default.cfg 33[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 34 35dir=/tmp 36odir=`pwd` 37cd $dir 38sed '1,/^EOF/d' < $odir/$0 > $dir/sendfile23.c 39mycc -o sendfile23 -Wall -Wextra -O0 -g sendfile23.c || exit 1 40rm -f sendfile23.c 41cd $odir 42 43set -e 44mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint 45[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart 46mdconfig -a -t swap -s 1g -u $mdstart 47newfs $newfs_flags -n md$mdstart > /dev/null 48mount /dev/md$mdstart $mntpoint 49set +e 50 51cd $mntpoint 52dd if=/dev/random of=input bs=4k count=100 status=none 53 54(cd $odir/../testcases/swap; ./swap -t 5m -i 20 -l 100 > /dev/null) & 55sleep 30 56n=1 57start=` date +%s` 58while [ $((` date +%s` - start)) -lt 180 ]; do 59 rm -f output 60# The umount is needed to trigger the short read error 61 umount $mntpoint 2>/dev/null # busy umount 62 $dir/sendfile23 63 s=$? 64 cmp -s input output || break 65 [ `stat -f '%z' input` -ne ` stat -f '%z' output` ] && break 66 n=$((n + 1)) 67done 68while pgrep -q swap; do 69 pkill swap 70done 71cmp -s input output || { echo "Loop #$n"; ls -l; s=1; } 72wait 73[ -f sendfile23.core -a $s -eq 0 ] && 74 { ls -l sendfile23.core; mv sendfile23.core $dir; s=1; } 75cd $odir 76 77for i in `jot 6`; do 78 mount | grep -q "on $mntpoint " || break 79 umount $mntpoint && break || sleep 10 80 [ $i -eq 6 ] && 81 { echo FATAL; fstat -mf $mntpoint; exit 1; } 82done 83mdconfig -d -u $mdstart 84rm -rf $dir/sendfile23 85exit $s 86 87EOF 88#include <sys/param.h> 89#include <sys/fcntl.h> 90#include <sys/mman.h> 91#include <sys/socket.h> 92#include <sys/stat.h> 93#include <sys/uio.h> 94#include <sys/wait.h> 95 96#include <err.h> 97#include <errno.h> 98#include <fcntl.h> 99#include <stdio.h> 100#include <stdlib.h> 101#include <unistd.h> 102 103#define DEBUG 1 104 105static void 106test(void) 107{ 108 struct stat st; 109 off_t rd, written, pos; 110 pid_t pid; 111 int error, from, n, status, sv[2], to; 112 char buf[4086]; 113 const char *from_name, *to_name; 114 115 from_name = "input"; 116 to_name = "output"; 117 118 if ((error = socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) == -1) 119 err(1, "socketpair"); 120 121 if ((from = open(from_name, O_RDONLY)) == -1) 122 err(1, "open read %s", from_name); 123 124 if ((error = fstat(from, &st)) == -1) 125 err(1, "stat %s", from_name); 126 127 pid = fork(); 128 if (pid == -1) 129 err(1, "fork"); 130 else if (pid != 0) { 131 setproctitle("parent"); 132 close(sv[1]); 133 134 pos = 0; 135 for (;;) { 136 error = sendfile(from, sv[0], pos, st.st_size - pos, 137 NULL, &written, 0); 138 if (error == -1) 139 err(1, "sendfile"); 140 if (written != st.st_size) 141 fprintf(stderr, "sendfile sent %d bytes\n", 142 (int)written); 143 pos += written; 144 if (pos == st.st_size) 145 break; 146 } 147 close(sv[0]); 148 if (pos != st.st_size) 149 fprintf(stderr, "%d written, expected %d\n", 150 (int) pos, (int)st.st_size); 151 if (waitpid(pid, &status, 0) != pid) 152 err(1, "waitpid(%d)", pid); 153 _exit(WEXITSTATUS(status)); 154 } else { 155 setproctitle("child"); 156 close(from); 157 close(sv[0]); 158 159 if ((to = open(to_name, O_RDWR | O_CREAT, DEFFILEMODE)) == 160 -1) 161 err(1, "open write %s", to_name); 162 163 rd = 0; 164 for (;;) { 165 n = read(sv[1], buf, sizeof(buf)); 166 if (n == -1) 167 err(1, "read"); 168 else if (n == 0) 169 break; 170 rd += n; 171 if (write(to, buf, n) != n) 172 err(1, "write()"); 173 } 174 close(to); 175 close(sv[1]); 176 if (rd != st.st_size) 177 fprintf(stderr, "Short read %d, expected %d\n", 178 (int)rd, (int)st.st_size); 179 _exit(0); 180 } 181 _exit(0); 182} 183 184int 185main(void) 186{ 187 pid_t pid; 188 int e, status; 189 190 e = 0; 191 if ((pid = fork()) == 0) 192 test(); 193 if (pid == -1) 194 err(1, "fork()"); 195 if (waitpid(pid, &status, 0) == -1) 196 err(1, "waitpid(%d)", pid); 197 if (status != 0) { 198 if (WIFSIGNALED(status)) 199 fprintf(stderr, 200 "pid %d exit signal %d\n", 201 pid, WTERMSIG(status)); 202 } 203 e += status == 0 ? 0 : 1; 204 205 return (e); 206} 207