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