1#!/bin/sh 2 3# 4# Copyright (c) 2009 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# Test scenario with a 20G files on two UFS2 FSs with 64k/64k 30# Test program will hang (deadlock) in "nbufkv" 31 32# Test scenario by John-Mark Gurney <jmg at funkthat dot com> 33 34[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 35 36. ../default.cfg 37 38dir=`dirname $diskimage` 39d1=$dir/diskimage1 40d2=$dir/diskimage2 41rm -f $d1 $d2 42 43size=20 # G 44avail=$((`sysctl -n hw.physmem` / 1024 / 1024 / 1024)) 45[ $((size * 2)) -gt $avail ] && size=$((avail / 2)) 46[ `df -k $dir | tail -1 | awk '{print $4}'` -lt \ 47 $((size * 2 * 1024 * 1024)) ] && 48 echo "Not enough disk space on $dir." && exit 0 49 50odir=`pwd` 51 52USE_TIMEOUT=1 53cd /tmp 54sed '1,/^EOF/d' < $odir/$0 > nbufkv.c 55mycc -o nbufkv -Wall nbufkv.c 56rm -f nbufkv.c 57cd $odir 58 59u1=$mdstart 60u2=$((u1 + 1)) 61mp1=$mntpoint 62mp2=${mntpoint}2 63[ -d $mp1 ] || mkdir $mp1 64[ -d $mp2 ] || mkdir $mp2 65dd if=/dev/zero of=$d1 bs=1m count=${size}k status=none || exit 1 66cp $d1 $d2 || exit 1 67 68mount | grep -q /dev/md$u2 && umount -f /dev/md$u2 69mount | grep -q /dev/md$u1 && umount -f /dev/md$u1 70[ -c /dev/md$u2 ] && mdconfig -d -u $u2 71[ -c /dev/md$u1 ] && mdconfig -d -u $u1 72 73mdconfig -a -t vnode -f $d1 -u $u1 || exit 1 74newfs -b 65536 -f 65536 -O2 md$u1 > /dev/null 75 76mdconfig -a -t vnode -f $d2 -u $u2 || exit 1 77newfs -b 65536 -f 65536 -O2 md$u2 > /dev/null 78 79mount /dev/md$u1 $mp1 80mount /dev/md$u2 $mp2 81 82/tmp/nbufkv $mp1 & 83/tmp/nbufkv $mp2 & 84wait 85 86umount /dev/md$u2 87umount /dev/md$u1 88 89mount | grep -q /dev/md$u2 && umount -f /dev/md$u2 90mount | grep -q /dev/md$u1 && umount -f /dev/md$u1 91 92mdconfig -d -u $u2 93mdconfig -d -u $u1 94 95rm -rf $d1 $d2 /tmp/nbufkv 96exit 97EOF 98#include <sys/param.h> 99 100#include <err.h> 101#include <fcntl.h> 102#include <signal.h> 103#include <stdio.h> 104#include <stdlib.h> 105#include <unistd.h> 106 107void 108handler(int i) { 109 fprintf(stderr, "FAIL. Timerout.\n"); 110 _exit(0); 111} 112 113void 114work(int fd, size_t n) 115{ 116 int i; 117 118 for (i = 0; i < 128 * 1024; i++) { 119 n = n - PAGE_SIZE; 120 if (lseek(fd, n , SEEK_SET) == -1) 121 err(1, "lseek()"); 122 if (write(fd, "1", 1) != 1) 123 err(1, "write()"); 124 } 125 126} 127 128int 129main(int argc, char **argv) 130{ 131 132 int fd; 133 off_t len; 134 char path[128]; 135 136 len = 20; 137 len = len * 1024 * 1024 * 1024; 138 139 sprintf(path, "%s/nbufkv.%06d", argv[1], getpid()); 140 if ((fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0640)) == -1) 141 err(1,"open(%s)", path); 142 if (ftruncate(fd, len) == -1) 143 err(1, "ftruncate"); 144 145 signal(SIGALRM, handler); 146 alarm(1200); 147 work(fd, len); 148 149 close(fd); 150 if (unlink(path) == -1) 151 err(1, "unlink(%s)", path); 152 153 return (0); 154} 155