xref: /freebsd/tools/test/stress2/misc/sendfile5.sh (revision dd41de95a84d979615a2ef11df6850622bf6184e)
1#!/bin/sh
2
3#
4# Copyright (c) 2011 Peter Holm <pho@FreeBSD.org>
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28
29# sendfile(2) test by kib@
30# Deadlock seen.
31
32[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
33
34. ../default.cfg
35
36here=`pwd`
37file=`basename $diskimage`
38dir=`dirname $diskimage`
39cd /tmp
40sed '1,/^EOF/d' < $here/$0 > sendfile5.c
41mycc -o sendfile5 -Wall -Wextra -O2 sendfile5.c
42rm -f sendfile5.c
43need=1024
44[ `df -k $(dirname $diskimage) | tail -1 | awk '{print int($4 / 1024)}'` \
45    -lt $need ] &&
46    printf "Need %d MB on %s.\n" $need `dirname $diskimage` && exit 0
47dd if=/dev/zero of=$diskimage bs=1m count=$need status=none
48cd $here
49
50mount | grep $mntpoint | grep -q /dev/md && umount -f $mntpoint
51mdconfig -l | grep -q md$mdstart &&  mdconfig -d -u $mdstart
52
53kldstat | grep -q tmpfs.ko || loaded=1
54mount -t tmpfs tmpfs $mntpoint
55echo "Testing tmpfs(5)"
56cp $diskimage $mntpoint
57/tmp/sendfile5 $mntpoint/$file
58umount $mntpoint
59[ $loaded ] && kldunload tmpfs.ko
60
61mdconfig -a -t swap -s 2g -u $mdstart || exit 1
62bsdlabel -w md$mdstart auto
63newfs $newfs_flags md${mdstart}$part > /dev/null
64mount /dev/md${mdstart}$part $mntpoint
65echo "Testing FFS"
66cp $diskimage $mntpoint
67/tmp/sendfile5 $mntpoint/$file
68umount $mntpoint
69mdconfig -d -u $mdstart
70
71mount -t nullfs $dir $mntpoint
72echo "Testing nullfs(5)"
73/tmp/sendfile5 $mntpoint/$file
74umount $mntpoint
75
76rm -f /tmp/sendfile5 $diskimage
77exit
78EOF
79#include <sys/types.h>
80#include <sys/fcntl.h>
81#include <sys/socket.h>
82#include <sys/stat.h>
83#include <sys/uio.h>
84#include <sys/wait.h>
85#include <err.h>
86#include <errno.h>
87#include <stdlib.h>
88#include <unistd.h>
89
90int
91main(int argc, char *argv[])
92{
93	const char *from_name;
94	char *buf;
95	int sv[2];
96	struct stat st;
97	off_t written, pos;
98	int child, error, from, status;
99
100	if (argc != 2)
101		errx(1, "Usage: %s from", argv[0]);
102	from_name = argv[1];
103
104	from = open(from_name, O_RDONLY);
105	if (from == -1)
106		err(1, "open read %s", from_name);
107
108	error = fstat(from, &st);
109	if (error == -1)
110		err(1, "stat %s", from_name);
111
112	error = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
113	if (error == -1)
114		err(1, "socketpair");
115
116	child = fork();
117	if (child == -1)
118		err(1, "fork");
119	else if (child != 0) {
120		close(sv[1]);
121		pos = 0;
122		for (;;) {
123			error = sendfile(from, sv[0], pos, st.st_size - pos,
124			    NULL, &written, 0);
125			if (error == -1) {
126				if (errno != EAGAIN)
127					err(1, "sendfile");
128			}
129			pos += written;
130			if (pos == st.st_size)
131				break;
132		}
133		close(sv[0]);
134		waitpid(child, &status, 0);
135	} else {
136		close(sv[0]);
137		buf = malloc(st.st_size);
138		if (buf == NULL)
139			err(1, "malloc %jd", st.st_size);
140		pos = 0;
141		for (;;) {
142			written = 413;
143			if (written > st.st_size - pos)
144				written = st.st_size - pos;
145#if 0
146			written = st.st_size - pos;
147			if (written > 1000)
148				written = 1000;
149			written = arc4random_uniform(written) + 1;
150#endif
151			error = read(sv[1], buf + pos, written);
152			if (error == -1)
153				err(1, "read");
154			else if (error == 0)
155				errx(1, "short read");
156			pos += error;
157			if (pos == st.st_size)
158				break;
159		}
160		close(sv[1]);
161		_exit(0);
162	}
163
164	return (0);
165}
166