1#!/bin/sh 2 3# 4# Copyright (c) 2010 Peter Holm <pho@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# Scenario that causes "panic: brelse: free buffer onto another queue???" 30# Idea for scenario by kib@. Fixed in r203818 31 32# When UFS partition is full, then some high load causes 33# panic: brelse: free buffer onto another queue??? 34 35[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 36 37. ../default.cfg 38 39here=`pwd` 40cd /tmp 41sed '1,/^EOF/d' < $here/$0 > fragments.c 42rm -f /tmp/fragments 43mycc -o fragments -Wall -Wextra -O2 -g fragments.c 44rm -f fragments.c 45cd $here 46 47mount | grep "$mntpoint" | grep -q md$mdstart && umount -f $mntpoint 48mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart 49 50mdconfig -a -t swap -s 1g -u $mdstart 51newfs $newfs_flags -m 0 md$mdstart > /dev/null 2>&1 52mount /dev/md$mdstart $mntpoint 53chmod 777 $mntpoint 54 55cd $mntpoint 56su $testuser -c "/tmp/fragments" 57cd $here 58 59umount $mntpoint 60mount | grep "$mntpoint" | grep -q md$mdstart && umount -f $mntpoint 61mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart 62 63rm -f /tmp/fragments 64exit 65EOF 66#include <sys/param.h> 67#include <sys/mount.h> 68#include <sys/stat.h> 69#include <sys/wait.h> 70#include <err.h> 71#include <errno.h> 72#include <fcntl.h> 73#include <signal.h> 74#include <stdio.h> 75#include <stdlib.h> 76#include <string.h> 77#include <unistd.h> 78 79#define LOOPS 600 80#define PARALLEL 8 81 82static pid_t pid; 83static char *buf; 84 85static volatile sig_atomic_t stop; 86 87void 88handler(int i __unused) { 89 stop = 1; 90} 91 92void 93cleanup(int n) 94{ 95 int i, j, start; 96 int nb = 0; 97 char file[128]; 98 struct statfs sbuf; 99 struct stat sb; 100 101 if (n == -1) { 102 for (i = 0; i < LOOPS; i++) { 103 sprintf(file,"t%05d", i); 104 unlink(file); 105 } 106 return; 107 } 108 109 start = arc4random() % n; 110 for (i = 0; i < LOOPS; i++) { 111 j = (start + i) % LOOPS; 112 sprintf(file,"t%05d", j); 113 if (stat(file, &sb) != 0) 114 continue; 115 116 if (sb.st_size == 0) { 117 unlink(file); 118 continue; 119 } 120 if (truncate(file, 0) == 0) { 121 nb++; 122 continue; 123 } 124 if (nb > 10) 125 break; 126 } 127 128 for (i = 0; i < 10; i++) { 129 if (statfs(".", &sbuf) < 0) 130 err(1, "statfs(%s)", "."); 131 132 if (sbuf.f_bfree > 8) 133 return; 134 } 135 136 for (i = 0; i < LOOPS; i++) { 137 j = (start + i) % LOOPS; 138 sprintf(file,"t%05d", j); 139 if (unlink(file) == 0) { 140 return; 141 } 142 } 143} 144 145void 146fragments(void) 147{ 148 int i, len; 149 char file[128]; 150 int fd; 151 152 for (i = 0;; i++) { 153 sprintf(file,"d%d/f%05d.%05d", i/1000, pid, i); 154 155 if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) { 156 if (errno != ENOSPC) 157 warn("open(%s)", file); 158 break; 159 } 160 161 len = 2 * 1024; 162 if (write(fd, buf, len) != len) { 163 } 164 165 close(fd); 166 } 167} 168 169void 170blocks(void) 171{ 172 int i, len; 173 char file[128]; 174 int fd; 175 176 for (i = 0;; i++) { 177 sprintf(file,"d%d/b%05d.%05d", i/1000, pid, i); 178 179 if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) { 180 if (errno != ENOSPC) 181 warn("open(%s)", file); 182 break; 183 } 184 185 len = 16 * 1024; 186 if (write(fd, buf, len) != len) { 187 } 188 189 close(fd); 190 } 191} 192 193void 194setup(void) 195{ 196 int i; 197 char file[128]; 198 199 for (i = 0; i < 300; i++) { 200 sprintf(file,"d%d", i); 201 if (mkdir(file, 0700) == -1) 202 warn("mkdir(%s)", file); 203 } 204 205 blocks(); 206 fragments(); 207 208 for (i = 0;i < 8; i++) { 209 sprintf(file,"d%d/b%05d.%05d", i/1000, pid, i); 210 unlink(file); 211 } 212 for (i = 0;i < 1; i++) { 213 sprintf(file,"d%d/f%05d.%05d", i/1000, pid, i); 214 unlink(file); 215 } 216 217} 218 219int 220test(void) 221{ 222 int i, len, n; 223 char file[128]; 224 int fd; 225 226 for (i = 0; i < LOOPS; i++) { 227 sprintf(file,"t%05d", i); 228 229 if ((fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) { 230 continue; 231 } 232// n = arc4random() % (12 + 1); 233 n = 0; 234 len = (arc4random() % (16 * 1024) + 1) + n * 16; 235 while (len > 0) { 236 if (write(fd, buf, len) == len) 237 break; 238 len = len / 2; 239 usleep(1000); 240 } 241 close(fd); 242 if (len == 0) { 243 cleanup(i); 244 } 245 } 246 247 exit(0); 248 249 return (0); 250} 251 252int 253main() 254{ 255 int i, j, status; 256 257 pid = getpid(); 258 if ((buf = malloc(12 * 16 * 1024)) == NULL) 259 err(1, "malloc()"); 260 261 setup(); 262 signal(SIGALRM, handler); 263 alarm(30 * 60); 264 for (j = 0; j < 50 && stop == 0; j++) { 265 for (i = 0; i < PARALLEL; i++) { 266 if (fork() == 0) 267 test(); 268 } 269 for (i = 0; i < PARALLEL; i++) 270 wait(&status); 271 cleanup(-1); 272 } 273 return (0); 274} 275