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