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