1#!/bin/sh 2 3# 4# Copyright (c) 2016 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# Variation of the datamove2.sh, using NULLFS 30# No problems seen. 31 32[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 33 34. ../default.cfg 35 36here=`pwd` 37cd /tmp 38sed '1,/^EOF/d' < $here/$0 > datamove5.c 39mycc -o datamove5 -Wall -Wextra -O2 -g datamove5.c 40rm -f datamove5.c 41 42mp1=$mntpoint 43mp2=${mntpoint}2 44[ -d $mp2 ] || mkdir $mp2 45 46mount | grep -wq $mp2 && umount $mp2 47mount | grep -wq $mp1 && umount $mp1 48mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart 49mdconfig -a -t swap -s 2g -u $mdstart || exit 1 50newfs $newfs_flags md$mdstart > /dev/null 51mount /dev/md$mdstart $mp1 52 53mount -t nullfs $opt $mp1 $mp2 54chmod 777 $mp2 55 56for i in `jot 5`; do 57 su $testuser -c "cd $mp2; /tmp/datamove5" 58done 59 60while mount | grep -wq $mp2; do 61 umount $mp2 || sleep 1 62done 63while mount | grep $mp1 | grep -q /dev/md; do 64 umount $mp1 || sleep 1 65done 66mdconfig -d -u $mdstart 67 68rm -rf /tmp/datamove5 69exit 0 70EOF 71/*- 72 * Copyright (c) 2006, Stephan Uphoff <ups@freebsd.org> 73 * All rights reserved. 74 * 75 * Redistribution and use in source and binary forms, with or without 76 * modification, are permitted provided that the following conditions 77 * are met: 78 * 1. Redistributions of source code must retain the above copyright 79 * notice unmodified, this list of conditions, and the following 80 * disclaimer. 81 * 2. Redistributions in binary form must reproduce the above copyright 82 * notice, this list of conditions and the following disclaimer in the 83 * documentation and/or other materials provided with the distribution. 84 * 85 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 86 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 87 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 88 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 89 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 90 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 91 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 92 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 93 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 94 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 95 */ 96 97#include <err.h> 98#include <fcntl.h> 99#include <stdio.h> 100#include <stdlib.h> 101#include <sys/mman.h> 102#include <sys/stat.h> 103#include <sys/types.h> 104#include <sys/wait.h> 105#include <unistd.h> 106 107int prepareFile(char *filename, int *fdp); 108int mapBuffer (char **bufferp, int fd1, int fd2); 109int startIO (int fd, char *buffer); 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(filename); 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 if (munmap(addr, FILESIZE) == -1) { 151 perror("munmap failed"); 152 return 1; 153 } 154 155 *fdp = fd; 156 return 0; 157} 158 159/* mmap a 2 page buffer - first page is from fd1, second page from fd2 */ 160int 161mapBuffer(char **bufferp, int fd1, int fd2) 162{ 163 void *addr; 164 char *buffer; 165 166 addr = mmap(NULL, pagesize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0); 167 if (addr == MAP_FAILED) { 168 perror("Mmap failed"); 169 return 1; 170 } 171 buffer = addr; 172 addr = mmap(buffer + pagesize, pagesize, PROT_READ | PROT_WRITE, MAP_FIXED | 173 MAP_SHARED, fd2, 0); 174 175 if (addr == MAP_FAILED) { 176 perror("Mmap2 failed"); 177 return 1; 178 } 179 *bufferp = buffer; 180 return 0; 181} 182 183void 184unmapBuffer(char *bufferp) 185{ 186 if (munmap(bufferp, pagesize * 2) == -1) 187 err(1, "unmap 1. buffer"); 188 /* 189 The following unmaps something random, which could trigger: 190 Program received signal SIGSEGV, Segmentation fault. 191 free (cp=0x28070000) at /usr/src/libexec/rtld-elf/malloc.c:311 192 */ 193 194#if 0 195 if (munmap(bufferp + pagesize * 2, pagesize * 2) == -1) 196 err(1, "unmap 2. buffer"); 197#endif 198} 199 200int 201startIO(int fd, char *buffer) 202{ 203 ssize_t len; 204 205 len = write(fd, buffer, 2 * pagesize); 206 if (len == -1) { 207 perror("write failed"); 208 return 1; 209 } 210 return 0; 211} 212 213int 214main() 215{ 216 217 int fdA, fdB, fdDelayA, fdDelayB; 218 int status; 219 int i; 220 char *bufferA, *bufferB; 221 pid_t pid; 222 223 pagesize = getpagesize(); 224 225 for (i = 0; i < 1000; i++) { 226 if ((prepareFile("A", &fdA)) 227 || (prepareFile("B", &fdB)) 228 || (prepareFile("DelayA", &fdDelayA)) 229 || (prepareFile("DelayB", &fdDelayB)) 230 || (mapBuffer(&bufferA, fdDelayA, fdB)) 231 || (mapBuffer(&bufferB, fdDelayB, fdA))) 232 exit(1); 233 234 pid = fork(); 235 236 if (pid == 0) { 237 status = startIO(fdA, bufferA); 238 exit(status); 239 } 240 if (pid == -1) { 241 perror("fork"); 242 exit(1); 243 } 244 status = startIO(fdB, bufferB); 245 if (wait(&status) == -1) 246 err(1, "wait"); 247 248 close(fdA); 249 close(fdB); 250 close(fdDelayA); 251 close(fdDelayB); 252 unmapBuffer(bufferA); 253 unmapBuffer(bufferB); 254 unlink("A"); 255 unlink("B"); 256 unlink("DelayA"); 257 unlink("DelayB"); 258 } 259 exit(status); 260 261} 262