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