1#!/bin/sh 2 3# 4# Copyright (c) 2015 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# Copy of holdcnt02.sh, but with mmap'ed write. 30# Use 16 GB RAM or less. 31# Deadlock seen: 32# https://people.freebsd.org/~pho/stress/log/alan018.txt 33 34# Test scenario suggestion by alc@ 35 36[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 37[ `swapinfo | wc -l` -eq 1 ] && exit 0 38[ `sysctl -n hw.physmem` -lt $((32 * 1024 * 1024 * 1024)) ] && exit 0 39 40. ../default.cfg 41 42here=`pwd` 43cd /tmp 44sed '1,/^EOF/d' < $here/$0 > holdcnt03.c 45mycc -o holdcnt03 -Wall -Wextra -g holdcnt03.c || exit 1 46rm -f holdcnt03.c 47cd $here 48 49trap "rm -f /tmp/holdcnt03 `dirname $diskimage`/f000???" EXIT INT 50(cd `dirname $diskimage`; /tmp/holdcnt03) & 51pid=$! 52sleep 5 53while kill -0 $! 2> /dev/null; do 54 (cd ../testcases/swap; ./swap -t 1m -i 1) > /dev/null 2>&1 55done 56wait $pid 57exit 58EOF 59/* 60 A test that causes the page daemon to generate cached pages 61 within a bunch of files and has some consumer that is trying to 62 allocate new pages to the same files. 63*/ 64 65#include <sys/types.h> 66#include <sys/mman.h> 67#include <sys/stat.h> 68#include <sys/wait.h> 69 70#include <err.h> 71#include <errno.h> 72#include <fcntl.h> 73#include <setjmp.h> 74#include <signal.h> 75#include <stdio.h> 76#include <stdlib.h> 77#include <time.h> 78#include <unistd.h> 79 80#define BUFSIZE (1024 * 1024) 81#define FILES 200 82#define RPARALLEL 8 83#define WPARALLEL 2 84 85static jmp_buf jbuf; 86static off_t maxsize; 87static int ps; 88static char *buf; 89 90static void 91hand(int i __unused) { /* handler */ 92 longjmp(jbuf, 1); 93} 94 95static void 96cleanup(void) 97{ 98 int i; 99 char file[80]; 100 101 for (i = 0; i < FILES; i++) { 102 snprintf(file, sizeof(file), "f%06d", i); 103 unlink(file); 104 } 105} 106 107static void 108init(void) 109{ 110 char file[80]; 111 int fd, i; 112 113 for (i = 0; i < FILES; i++) { 114 snprintf(file, sizeof(file), "f%06d", i); 115 if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) 116 err(1, "open(%s)", file); 117 if (write(fd, buf, BUFSIZE) != BUFSIZE) 118 err(1, "write"); 119 close(fd); 120 } 121 122} 123 124static void 125writer(void) 126{ 127 int fd, i; 128 char file[80]; 129 time_t start; 130 struct stat statbuf; 131 132 setproctitle("writer"); 133 start = time(NULL); 134 while (time(NULL) - start < 600) { 135 for (i = 0; i < FILES; i++) { 136 snprintf(file, sizeof(file), "f%06d", i); 137 if ((fd = open(file, O_RDWR | O_APPEND)) == -1) { 138 if (errno != ENOENT) 139 err(1, "open(%s) append", file); 140 goto err; 141 } 142 if (fstat(fd, &statbuf) < 0) 143 err(1, "fstat error"); 144 if (statbuf.st_size < maxsize) { 145 if (write(fd, buf, ps) != ps) { 146 warn("writer"); 147 goto err; 148 } 149 } 150 close(fd); 151 } 152 } 153err: 154 cleanup(); 155 156 _exit(0); 157} 158 159static void 160touch(void) 161{ 162 int fd, i, j, n; 163 void *p; 164 size_t len; 165 char file[80]; 166 struct stat statbuf; 167 168 setproctitle("touch"); 169 signal(SIGSEGV, hand); 170 signal(SIGBUS, hand); 171 fd = 0; 172 for (;;) { 173 (void)setjmp(jbuf); 174 for (i = 0; i < FILES; i++) { 175 snprintf(file, sizeof(file), "f%06d", i); 176 if (fd > 0) 177 close(fd); 178 if ((fd = open(file, O_RDWR)) == -1) { 179 if (errno != ENOENT) 180 warn("touch(%s)", file); 181 _exit(0); 182 } 183 if (fstat(fd, &statbuf) < 0) 184 err(1, "fstat error"); 185 if (statbuf.st_size >= maxsize) { 186 if (ftruncate(fd, ps) == -1) 187 err(1, "ftruncate"); 188 continue; 189 } 190 len = statbuf.st_size; 191 if ((p = mmap(p, len, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) 192 err(1, "mmap()"); 193 close(fd); 194 n = statbuf.st_size / ps; 195 for (j = 0; j < n; j++) { 196 *(char *)p = 1; 197 p = p + ps; 198 } 199 if (munmap(p, len) == -1) 200 perror("munmap"); 201 } 202 } 203 _exit(0); 204} 205 206int 207main(void) 208{ 209 pid_t rpid[RPARALLEL], wpid[WPARALLEL]; 210 int e, i, s; 211 212 maxsize = 2LL * 1024 * 1024 * 1024 / FILES; 213 buf = malloc(BUFSIZE); 214 ps = getpagesize(); 215 216 init(); 217 e = 0; 218 for (i = 0; i < WPARALLEL; i++) { 219 if ((wpid[i] = fork()) == 0) 220 writer(); 221 } 222 for (i = 0; i < RPARALLEL; i++) { 223 if ((rpid[i] = fork()) == 0) 224 touch(); 225 } 226 227 for (i = 0; i < WPARALLEL; i++) 228 waitpid(wpid[i], &s, 0); 229 e += s == 0 ? 0 : 1; 230 for (i = 0; i < RPARALLEL; i++) 231 waitpid(rpid[i], &s, 0); 232 e += s == 0 ? 0 : 1; 233 234 free(buf); 235 236 return (e); 237} 238