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