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# $FreeBSD$ 29# 30 31# Variation of the datamove.sh scenario by not using "sysctl vm.old_msync=1" 32 33# Deadlock seen 34 35# Test scenario by ups 36 37here=`pwd` 38cd /tmp 39sed '1,/^EOF/d' < $here/$0 > dl.c 40cc -o dl -Wall dl.c 41rm -f dl.c 42 43for i in `jot 3`; do 44 $here/../testcases/swap/swap -t 10m -i 200 -h & 45 /tmp/dl 46 ps | grep swap | grep -v swap | awk '{print $1}' | xargs kill 47done 48rm -rf /tmp/dl 49exit 0 50EOF 51#include <err.h> 52#include <fcntl.h> 53#include <stdio.h> 54#include <stdlib.h> 55#include <sys/mman.h> 56#include <sys/stat.h> 57#include <sys/types.h> 58#include <sys/wait.h> 59#include <unistd.h> 60 61 62int prepareFile(char *filename, int *fdp); 63int mapBuffer (char **bufferp, int fd1, int fd2); 64int startIO (int fd, char *buffer); 65 66int pagesize; 67 68#define FILESIZE (32*1024) 69char wbuffer [FILESIZE]; 70 71/* Create a FILESIZE sized file - then remove file data from the cache */ 72int 73prepareFile(char *filename, int *fdp) 74{ 75 int fd; 76 int len; 77 int status; 78 void *addr; 79 80 fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); 81 if (fd == -1) { 82 perror("Creating file"); 83 return fd; 84 } 85 len = write(fd, wbuffer, FILESIZE); 86 if (len < 0) { 87 perror("Write failed"); 88 return 1; 89 } 90 status = fsync(fd); 91 if (status != 0) { 92 perror("fsync failed"); 93 return 1; 94 } 95 addr = mmap(NULL, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 96 if (addr == MAP_FAILED) { 97 perror("Mmap failed"); 98 return 1; 99 } 100 status = msync(addr, FILESIZE, MS_INVALIDATE | MS_SYNC); 101 if (status != 0) { 102 perror("Msync failed"); 103 return 1; 104 } 105 if (munmap(addr, FILESIZE) == -1) { 106 perror("munmap failed"); 107 return 1; 108 } 109 110 *fdp = fd; 111 return 0; 112} 113 114 115/* mmap a 2 page buffer - first page is from fd1, second page from fd2 */ 116int 117mapBuffer(char **bufferp, int fd1, int fd2) 118{ 119 void *addr; 120 char *buffer; 121 122 addr = mmap(NULL, pagesize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0); 123 if (addr == MAP_FAILED) { 124 perror("Mmap failed"); 125 return 1; 126 } 127 buffer = addr; 128 addr = mmap(buffer + pagesize, pagesize, PROT_READ | PROT_WRITE, MAP_FIXED | 129 MAP_SHARED, fd2, 0); 130 131 if (addr == MAP_FAILED) { 132 perror("Mmap2 failed"); 133 return 1; 134 } 135 *bufferp = buffer; 136 return 0; 137} 138 139void 140unmapBuffer(char *bufferp) 141{ 142 if (munmap(bufferp, pagesize * 2) == -1) 143 err(1, "unmap 1. buffer"); 144 if (munmap(bufferp + pagesize * 2, pagesize * 2) == -1) 145 err(1, "unmap 2. buffer"); 146} 147 148int 149startIO(int fd, char *buffer) 150{ 151 ssize_t len; 152 153 len = write(fd, buffer, 2 * pagesize); 154 if (len == -1) { 155 perror("write failed"); 156 return 1; 157 } 158 return 0; 159} 160 161 162int 163main(int argc, char *argv[], char *envp[]) 164{ 165 166 int fdA, fdB, fdDelayA, fdDelayB; 167 int status; 168 int i; 169 char *bufferA, *bufferB; 170 pid_t pid; 171 172 pagesize = getpagesize(); 173 174 for (i = 0; i < 1000; i++) { 175 if ((prepareFile("A", &fdA)) 176 || (prepareFile("B", &fdB)) 177 || (prepareFile("DelayA", &fdDelayA)) 178 || (prepareFile("DelayB", &fdDelayB)) 179 || (mapBuffer(&bufferA, fdDelayA, fdB)) 180 || (mapBuffer(&bufferB, fdDelayB, fdA))) 181 exit(1); 182 183 pid = fork(); 184 185 if (pid == 0) { 186 status = startIO(fdA, bufferA); 187 exit(status); 188 } 189 if (pid == -1) { 190 perror("fork"); 191 exit(1); 192 } 193 status = startIO(fdB, bufferB); 194 if (wait(&status) == -1) 195 err(1, "wait"); 196 197 close(fdA); 198 close(fdB); 199 close(fdDelayA); 200 close(fdDelayB); 201 unmapBuffer(bufferA); 202 unmapBuffer(bufferB); 203 unlink("A"); 204 unlink("B"); 205 unlink("DelayA"); 206 unlink("DelayB"); 207 } 208 exit(status); 209 210} 211