xref: /freebsd/tools/test/stress2/misc/sendfile5.sh (revision d4eeb02986980bf33dd56c41ceb9fc5f180c0d47)
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
62newfs $newfs_flags md$mdstart > /dev/null
63mount /dev/md$mdstart $mntpoint
64echo "Testing FFS"
65cp $diskimage $mntpoint
66/tmp/sendfile5 $mntpoint/$file
67umount $mntpoint
68mdconfig -d -u $mdstart
69
70mount -t nullfs $dir $mntpoint
71echo "Testing nullfs(5)"
72/tmp/sendfile5 $mntpoint/$file
73umount $mntpoint
74
75rm -f /tmp/sendfile5 $diskimage
76exit
77EOF
78#include <sys/types.h>
79#include <sys/fcntl.h>
80#include <sys/socket.h>
81#include <sys/stat.h>
82#include <sys/uio.h>
83#include <sys/wait.h>
84#include <err.h>
85#include <errno.h>
86#include <stdlib.h>
87#include <unistd.h>
88
89int
90main(int argc, char *argv[])
91{
92	const char *from_name;
93	char *buf;
94	int sv[2];
95	struct stat st;
96	off_t written, pos;
97	int child, error, from, status;
98
99	if (argc != 2)
100		errx(1, "Usage: %s from", argv[0]);
101	from_name = argv[1];
102
103	from = open(from_name, O_RDONLY);
104	if (from == -1)
105		err(1, "open read %s", from_name);
106
107	error = fstat(from, &st);
108	if (error == -1)
109		err(1, "stat %s", from_name);
110
111	error = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
112	if (error == -1)
113		err(1, "socketpair");
114
115	child = fork();
116	if (child == -1)
117		err(1, "fork");
118	else if (child != 0) {
119		close(sv[1]);
120		pos = 0;
121		for (;;) {
122			error = sendfile(from, sv[0], pos, st.st_size - pos,
123			    NULL, &written, 0);
124			if (error == -1) {
125				if (errno != EAGAIN)
126					err(1, "sendfile");
127			}
128			pos += written;
129			if (pos == st.st_size)
130				break;
131		}
132		close(sv[0]);
133		waitpid(child, &status, 0);
134	} else {
135		close(sv[0]);
136		buf = malloc(st.st_size);
137		if (buf == NULL)
138			err(1, "malloc %jd", st.st_size);
139		pos = 0;
140		for (;;) {
141			written = 413;
142			if (written > st.st_size - pos)
143				written = st.st_size - pos;
144#if 0
145			written = st.st_size - pos;
146			if (written > 1000)
147				written = 1000;
148			written = arc4random_uniform(written) + 1;
149#endif
150			error = read(sv[1], buf + pos, written);
151			if (error == -1)
152				err(1, "read");
153			else if (error == 0)
154				errx(1, "short read");
155			pos += error;
156			if (pos == st.st_size)
157				break;
158		}
159		close(sv[1]);
160		_exit(0);
161	}
162
163	return (0);
164}
165