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