1#!/bin/sh 2 3# 4# Copyright (c) 2009 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# Threaded variation of datamove.sh 30 31# Based on a test scenario by ups and suggestions by kib 32 33[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 34 35. ../default.cfg 36 37here=`pwd` 38cd /tmp 39sed '1,/^EOF/d' < $here/$0 > datamove3.c 40mycc -o datamove3 -Wall datamove3.c -lpthread 41rm -f datamove3.c 42 43n=5 44old=`sysctl vm.old_msync | awk '{print $NF}'` 45sysctl vm.old_msync=1 46for i in `jot $n`; do 47 mkdir -p /tmp/datamove3.dir.$i 48 cd /tmp/datamove3.dir.$i 49 /tmp/datamove3 & 50done 51cd /tmp 52for i in `jot $n`; do 53 wait 54done 55for i in `jot $n`; do 56 rm -rf /tmp/datamove3.dir.$i 57done 58sysctl vm.old_msync=$old 59 60rm -rf /tmp/datamove3 61exit 0 62EOF 63/*- 64 * Copyright (c) 2006, Stephan Uphoff <ups@freebsd.org> 65 * All rights reserved. 66 * 67 * Redistribution and use in source and binary forms, with or without 68 * modification, are permitted provided that the following conditions 69 * are met: 70 * 1. Redistributions of source code must retain the above copyright 71 * notice unmodified, this list of conditions, and the following 72 * disclaimer. 73 * 2. Redistributions in binary form must reproduce the above copyright 74 * notice, this list of conditions and the following disclaimer in the 75 * documentation and/or other materials provided with the distribution. 76 * 77 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 78 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 79 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 80 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 81 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 82 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 83 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 84 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 85 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 86 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 87 */ 88 89#include <err.h> 90#include <fcntl.h> 91#include <pthread.h> 92#include <stdio.h> 93#include <stdio.h> 94#include <stdlib.h> 95#include <string.h> 96#include <sys/mman.h> 97#include <sys/stat.h> 98#include <sys/types.h> 99#include <unistd.h> 100 101struct args { 102 char *bp; 103 int fd1; 104 int fd2; 105} a[2]; 106 107int prepareFile(char *, int *); 108void * mapBuffer(void *); 109int startIO(int, char *); 110 111int pagesize; 112 113#define FILESIZE (32*1024) 114char wbuffer [FILESIZE]; 115 116/* Create a FILESIZE sized file - then remove file data from the cache */ 117int 118prepareFile(char *filename, int *fdp) 119{ 120 int fd; 121 int len; 122 int status; 123 void *addr; 124 125 fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); 126 if (fd == -1) { 127 perror("Creating file"); 128 return fd; 129 } 130 len = write(fd, wbuffer, FILESIZE); 131 if (len < 0) { 132 perror("Write failed"); 133 return 1; 134 } 135 status = fsync(fd); 136 if (status != 0) { 137 perror("fsync failed"); 138 return 1; 139 } 140 addr = mmap(NULL, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 141 if (addr == MAP_FAILED) { 142 perror("Mmap failed"); 143 return 1; 144 } 145 status = msync(addr, FILESIZE, MS_INVALIDATE | MS_SYNC); 146 if (status != 0) { 147 perror("Msync failed"); 148 return 1; 149 } 150 munmap(addr, FILESIZE); 151 152 *fdp = fd; 153 return 0; 154} 155 156/* mmap a 2 page buffer - first page is from fd1, second page from fd2 */ 157void * 158mapBuffer(void *ar) 159{ 160 void *addr; 161 char *buffer; 162 int i; 163 164 i = (intptr_t)ar; 165 addr = mmap(NULL, pagesize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, a[i].fd1, 0); 166 if (addr == MAP_FAILED) { 167 err(1, "Mmap failed"); 168 } 169 buffer = addr; 170 addr = mmap(buffer + pagesize, pagesize, PROT_READ | PROT_WRITE, MAP_FIXED | 171 MAP_SHARED, a[i].fd2, 0); 172 173 if (addr == MAP_FAILED) { 174 err(1, "Mmap2 failed"); 175 } 176 a[i].bp = buffer; 177 sleep(1); 178 return (NULL); 179} 180 181int 182startIO(int fd, char *buffer) 183{ 184 ssize_t len; 185 186 len = write(fd, buffer, 2 * pagesize); 187 if (len == -1) { 188 warn("startIO(%d, %p): write failed", fd, buffer); 189 return 1; 190 } 191 return 0; 192} 193 194int 195main(int argc, char *argv[], char *envp[]) 196{ 197 198 int fdA, fdB, fdDelayA, fdDelayB; 199 int r, status; 200 char *bufferA, *bufferB; 201 pid_t pid; 202 pthread_t threads[2]; 203 204 pagesize = getpagesize(); 205 206 if ((prepareFile("A", &fdA)) 207 || (prepareFile("B", &fdB)) 208 || (prepareFile("DelayA", &fdDelayA)) 209 || (prepareFile("DelayB", &fdDelayB))) 210 exit(1); 211 212 a[0].fd1 = fdDelayA; 213 a[0].fd2 = fdB; 214 215 a[1].fd1 = fdDelayB; 216 a[1].fd2 = fdA; 217 218 if ((r = pthread_create(&threads[0], NULL, mapBuffer, (void *)0)) != 0) 219 errc(1, r, "pthread_create()"); 220 if ((r = pthread_create(&threads[1], NULL, mapBuffer, (void *)1)) != 0) 221 errc(1, r, "pthread_create()"); 222 223 while (a[0].bp == NULL || a[1].bp == NULL) 224 pthread_yield(); 225 226 bufferA = a[0].bp; 227 bufferB = a[1].bp; 228 229 pid = fork(); 230 231 if (pid == 0) { 232 status = startIO(fdA, bufferA); 233 exit(status); 234 } 235 if (pid == -1) { 236 exit(1); 237 } 238 status = startIO(fdB, bufferB); 239 exit(status); 240 241} 242