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 50bsdlabel -w md$mdstart auto 51newfs $newfs_flags md${mdstart}$part > /dev/null 52mount /dev/md${mdstart}$part $mp1 53 54mount -t nullfs $opt $mp1 $mp2 55chmod 777 $mp2 56 57for i in `jot 5`; do 58 su $testuser -c "cd $mp2; /tmp/datamove5" 59done 60 61while mount | grep -wq $mp2; do 62 umount $mp2 || sleep 1 63done 64while mount | grep $mp1 | grep -q /dev/md; do 65 umount $mp1 || sleep 1 66done 67mdconfig -d -u $mdstart 68 69rm -rf /tmp/datamove5 70exit 0 71EOF 72/*- 73 * Copyright (c) 2006, Stephan Uphoff <ups@freebsd.org> 74 * All rights reserved. 75 * 76 * Redistribution and use in source and binary forms, with or without 77 * modification, are permitted provided that the following conditions 78 * are met: 79 * 1. Redistributions of source code must retain the above copyright 80 * notice unmodified, this list of conditions, and the following 81 * disclaimer. 82 * 2. Redistributions in binary form must reproduce the above copyright 83 * notice, this list of conditions and the following disclaimer in the 84 * documentation and/or other materials provided with the distribution. 85 * 86 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 87 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 88 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 89 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 90 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 91 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 92 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 93 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 94 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 95 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 96 */ 97 98#include <err.h> 99#include <fcntl.h> 100#include <stdio.h> 101#include <stdlib.h> 102#include <sys/mman.h> 103#include <sys/stat.h> 104#include <sys/types.h> 105#include <sys/wait.h> 106#include <unistd.h> 107 108int prepareFile(char *filename, int *fdp); 109int mapBuffer (char **bufferp, int fd1, int fd2); 110int startIO (int fd, char *buffer); 111 112int pagesize; 113 114#define FILESIZE (32*1024) 115char wbuffer [FILESIZE]; 116 117/* Create a FILESIZE sized file - then remove file data from the cache */ 118int 119prepareFile(char *filename, int *fdp) 120{ 121 int fd; 122 int len; 123 int status; 124 void *addr; 125 126 fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); 127 if (fd == -1) { 128 perror(filename); 129 return fd; 130 } 131 len = write(fd, wbuffer, FILESIZE); 132 if (len < 0) { 133 perror("Write failed"); 134 return 1; 135 } 136 status = fsync(fd); 137 if (status != 0) { 138 perror("fsync failed"); 139 return 1; 140 } 141 addr = mmap(NULL, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 142 if (addr == MAP_FAILED) { 143 perror("Mmap failed"); 144 return 1; 145 } 146 status = msync(addr, FILESIZE, MS_INVALIDATE | MS_SYNC); 147 if (status != 0) { 148 perror("Msync failed"); 149 return 1; 150 } 151 if (munmap(addr, FILESIZE) == -1) { 152 perror("munmap failed"); 153 return 1; 154 } 155 156 *fdp = fd; 157 return 0; 158} 159 160/* mmap a 2 page buffer - first page is from fd1, second page from fd2 */ 161int 162mapBuffer(char **bufferp, int fd1, int fd2) 163{ 164 void *addr; 165 char *buffer; 166 167 addr = mmap(NULL, pagesize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0); 168 if (addr == MAP_FAILED) { 169 perror("Mmap failed"); 170 return 1; 171 } 172 buffer = addr; 173 addr = mmap(buffer + pagesize, pagesize, PROT_READ | PROT_WRITE, MAP_FIXED | 174 MAP_SHARED, fd2, 0); 175 176 if (addr == MAP_FAILED) { 177 perror("Mmap2 failed"); 178 return 1; 179 } 180 *bufferp = buffer; 181 return 0; 182} 183 184void 185unmapBuffer(char *bufferp) 186{ 187 if (munmap(bufferp, pagesize * 2) == -1) 188 err(1, "unmap 1. buffer"); 189 /* 190 The following unmaps something random, which could trigger: 191 Program received signal SIGSEGV, Segmentation fault. 192 free (cp=0x28070000) at /usr/src/libexec/rtld-elf/malloc.c:311 193 */ 194 195#if 0 196 if (munmap(bufferp + pagesize * 2, pagesize * 2) == -1) 197 err(1, "unmap 2. buffer"); 198#endif 199} 200 201int 202startIO(int fd, char *buffer) 203{ 204 ssize_t len; 205 206 len = write(fd, buffer, 2 * pagesize); 207 if (len == -1) { 208 perror("write failed"); 209 return 1; 210 } 211 return 0; 212} 213 214int 215main() 216{ 217 218 int fdA, fdB, fdDelayA, fdDelayB; 219 int status; 220 int i; 221 char *bufferA, *bufferB; 222 pid_t pid; 223 224 pagesize = getpagesize(); 225 226 for (i = 0; i < 1000; i++) { 227 if ((prepareFile("A", &fdA)) 228 || (prepareFile("B", &fdB)) 229 || (prepareFile("DelayA", &fdDelayA)) 230 || (prepareFile("DelayB", &fdDelayB)) 231 || (mapBuffer(&bufferA, fdDelayA, fdB)) 232 || (mapBuffer(&bufferB, fdDelayB, fdA))) 233 exit(1); 234 235 pid = fork(); 236 237 if (pid == 0) { 238 status = startIO(fdA, bufferA); 239 exit(status); 240 } 241 if (pid == -1) { 242 perror("fork"); 243 exit(1); 244 } 245 status = startIO(fdB, bufferB); 246 if (wait(&status) == -1) 247 err(1, "wait"); 248 249 close(fdA); 250 close(fdB); 251 close(fdDelayA); 252 close(fdDelayB); 253 unmapBuffer(bufferA); 254 unmapBuffer(bufferB); 255 unlink("A"); 256 unlink("B"); 257 unlink("DelayA"); 258 unlink("DelayB"); 259 } 260 exit(status); 261 262} 263