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