1#!/bin/sh 2 3# 4# Copyright (c) 2013 EMC Corp. 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) over posix shmfd 30# Test scenario by kib@ 31 32[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 33 34. ../default.cfg 35 36[ -r /boot/kernel/kernel ] || exit 0 37here=`pwd` 38dir=`dirname $diskimage` 39cd /tmp 40sed '1,/^EOF/d' < $here/$0 > sendfile_shm.c 41mycc -o sendfile_shm -Wall -Wextra -O2 sendfile_shm.c || exit 1 42rm -f sendfile_shm.c 43cd $here 44 45daemon ../testcases/swap/swap -t 2m -i 20 > /dev/null 2>&1 46sleep 5 47for i in `jot 10`; do 48 /tmp/sendfile_shm /boot/kernel/kernel $dir/sendfile_shm.$i > \ 49 /dev/null & 50done 51wait 52while pkill -9 swap; do 53 sleep .5 54done 55for i in `jot 10`; do 56 cmp -s /boot/kernel/kernel $dir/sendfile_shm.$i 2>/dev/null || 57 { e=1; ls -al $dir/sendfile_shm.* /boot/kernel/kernel; } 58 rm -f $dir/sendfile_shm.$i 59 [ $e ] && break 60done 61[ -n "$e" ] && echo FAIL 62wait 63 64rm -f /tmp/sendfile_shm 65exit 66EOF 67/* $Id: sendfile_shm1.c,v 1.2 2013/08/25 14:35:14 kostik Exp kostik $ */ 68 69#include <sys/types.h> 70#include <sys/event.h> 71#include <sys/mman.h> 72#include <sys/stat.h> 73#include <sys/socket.h> 74#include <sys/time.h> 75#include <sys/uio.h> 76#include <err.h> 77#include <fcntl.h> 78#include <signal.h> 79#include <stdint.h> 80#include <stdio.h> 81#include <stdlib.h> 82#include <string.h> 83#include <unistd.h> 84 85#define PAGE_SIZE 4096 86 87static void 88load(int infd, int shmfd, off_t size) 89{ 90 off_t c, r; 91 char buf[100]; 92 93 for (c = 0; c < size; c += r) { 94 r = read(infd, buf, sizeof(buf)); 95 if (r == -1) 96 err(1, "read disk"); 97 else if (r == 0) 98 errx(1, "too short"); 99 write(shmfd, buf, r); 100 } 101} 102 103static void 104sendfd(int s, int shmfd, off_t size) 105{ 106 off_t sbytes; 107 int error; 108 109 error = sendfile(shmfd, s, 0, size, NULL, &sbytes, 0); 110 if (error == -1) 111 err(1, "sendfile(%d, %d, %jd)", s, shmfd, size); 112 printf("sent %jd bytes, requested %jd\n", (uintmax_t)sbytes, 113 (uintmax_t)size); 114} 115 116static void 117receivefd(int s, int outfd, off_t size) 118{ 119 char buf[100]; 120 off_t c, r, r1; 121 122 for (c = 0; c < size; c += r) { 123 r = read(s, buf, sizeof(buf)); 124 if (r == -1) 125 err(1, "read sock"); 126 else if (r == 0) 127 break; 128 else { 129 r1 = write(outfd, buf, r); 130 if (r1 == -1) 131 err(1, "write disk"); 132 else if (r1 != r) { 133 err(1, "short write %jd %jd", 134 (uintmax_t)r, (uintmax_t)r1); 135 } 136 } 137 } 138 printf("received %jd bytes\n", (uintmax_t)c); 139} 140 141int 142main(int argc, char *argv[]) 143{ 144 struct stat st; 145 struct sigaction sa; 146 pid_t child; 147 int s[2], infd, outfd, shmfd, error; 148 149 if (argc != 3) { 150 fprintf(stderr, "usage: sendfile_shm infile outfile\n"); 151 exit(2); 152 } 153 154 memset(&sa, 0, sizeof(sa)); 155 sa.sa_handler = SIG_IGN; 156 error = sigaction(SIGPIPE, &sa, NULL); 157 if (error == -1) 158 err(1, "sigaction SIGPIPE"); 159 160 infd = open(argv[1], O_RDONLY); 161 if (infd == -1) 162 err(1, "open %s", argv[1]); 163 error = fstat(infd, &st); 164 if (error == -1) 165 err(1, "stat"); 166 167 outfd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0666); 168 if (outfd == -1) 169 err(1, "open %s", argv[2]); 170 171 shmfd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0600); 172 if (shmfd == -1) 173 err(1, "shm_open"); 174 error = ftruncate(shmfd, st.st_size); 175 if (error == -1) 176 err(1, "ftruncate"); 177 load(infd, shmfd, st.st_size); 178 179 error = socketpair(AF_UNIX, SOCK_STREAM, 0, s); 180 if (error == -1) 181 err(1, "socketpair"); 182 183 fflush(stdout); 184 fflush(stderr); 185 child = fork(); 186 if (child == -1) 187 err(1, "fork"); 188 else if (child == 0) { 189 close(s[1]); 190 sendfd(s[0], shmfd, st.st_size); 191 exit(0); 192 } else { 193 close(shmfd); 194 close(s[0]); 195 sleep(1); 196 receivefd(s[1], outfd, st.st_size); 197 } 198 199 return (0); 200} 201