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