1#!/bin/sh 2 3# 4# Copyright (c) 2020 Jeffrey Roberson <jeff@FreeBSD.org> 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. ../default.cfg 30 31# "panic: freeing mapped page 0xfffffe000aa73910" seen: 32# https://people.freebsd.org/~pho/stress/log/collapse.txt 33 34odir=`pwd` 35cd /tmp 36sed '1,/^EOF/d' < $odir/$0 > collapse.c 37mycc -o collapse -Wall -Wextra -g -O0 collapse.c || exit 1 38rm -f collapse.c 39cd $odir 40 41daemon sh -c '(cd ../testcases/swap; ./swap -t 20m -i 16 -l 85)' > \ 42 /dev/null 2>&1 43sleep 2 44/tmp/collapse 45while pgrep -q swap; do 46 pkill -9 swap 47done 48rm -f /tmp/collapse 49exit 0 50 51EOF 52#include <sys/param.h> 53#include <sys/mman.h> 54#include <sys/wait.h> 55 56#include <err.h> 57#include <errno.h> 58#include <fcntl.h> 59#include <stdio.h> 60#include <stdlib.h> 61#include <string.h> 62#include <time.h> 63#include <unistd.h> 64 65#define ADRSPACE (256 * 1024) 66#define DEPTH 6 67#define WIDTH 3 68#define PARALLEL 4 69#define RUNTIME 1200 70#define CHILDTIME 5 71#define STARTTIME 5 72#define TOUCH 16 73 74char *p; 75 76static void 77child(int depth, time_t start) 78{ 79 time_t run, delay; 80 int i, shared, off; 81 int len; 82 83 /* Pick a random bit of address space to change inherit on. */ 84 for (i = 0; i < ADRSPACE; i += len) { 85 shared = arc4random() & 0x1; 86 len = roundup2(arc4random() % ((ADRSPACE - i) / 4), 87 PAGE_SIZE); 88 if (minherit(p + i, len, shared ? INHERIT_SHARE : 89 INHERIT_COPY) != 0) 90 err(1, "minherit"); 91 } 92 93 for (i = 0; depth != 0 && i < WIDTH; i++) 94 if (fork() == 0) 95 child(depth - 1, start); 96 97 /* 98 * Touch all of the memory and exit at a random time to collapse 99 * some portion of the chain. 100 */ 101 delay = arc4random() % (CHILDTIME - 1); 102 run = arc4random() % (CHILDTIME - delay); 103 for (;;) { 104 if (time(NULL) >= start + delay) 105 break; 106 usleep(100); 107 } 108 while (time(NULL) - start < run) { 109 off = rounddown2(arc4random() % ADRSPACE, PAGE_SIZE); 110 bzero(p + off, PAGE_SIZE); 111 usleep((run * 1000) / TOUCH); 112 } 113 114 _exit(0); 115} 116 117static void 118work(int depth) 119{ 120 121 if ((p = mmap(NULL, ADRSPACE, PROT_READ | PROT_WRITE, 122 MAP_SHARED | MAP_ANON, -1, 0)) == MAP_FAILED) { 123 if (errno == ENOMEM) 124 return; 125 err(1, "mmap()"); 126 } 127 child(depth, time(NULL) + STARTTIME); 128} 129 130int 131main(void) 132{ 133 pid_t pids[PARALLEL]; 134 time_t start; 135 int i, n; 136 137 start = time(NULL); 138 while (time(NULL) - start < RUNTIME) { 139 n = arc4random() % PARALLEL + 1; 140 for (i = 0; i < n; i++) { 141 if ((pids[i] = fork()) == 0) 142 work(DEPTH); 143 } 144 145 sleep(CHILDTIME + STARTTIME + 1); 146 147 for (i = 0; i < n; i++) 148 if (waitpid(pids[i], NULL, 0) != pids[i]) 149 err(1, "waitpid(%d)", pids[i]); 150 } 151 152 return (0); 153} 154