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# Vnode reference leak test scenario by kib@. 30# Will fail with "umount: unmount of /mnt5 failed: Device busy" 31# vnode leak not seen on HEAD. 32 33[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 34 35. ../default.cfg 36here=`pwd` 37mounts=2 # Number of parallel scripts 38D=$diskimage 39 40[ -d "$RUNDIR" ] || mkdir $RUNDIR 41cd $RUNDIR 42 43if [ $# -eq 0 ]; then 44 sed '1,/^EOF/d' < $here/$0 > vunref.c 45 mycc -o /tmp/vunref -Wall -Wextra -O2 vunref.c 46 rm -f vunref.c 47 cd $here 48 49 rm -f $RUNDIR/active.* 50 for i in `jot $mounts`; do 51 m=$(( i + mdstart - 1 )) 52 [ ! -d ${mntpoint}$m ] && mkdir ${mntpoint}$m 53 mount | grep "$mntpoint" | grep -q md$m && umount -f ${mntpoint}$m 54 mdconfig -l | grep -q md$m && mdconfig -d -u $m 55 56 dd if=/dev/zero of=$D.$m bs=1m count=10 status=none 57 mdconfig -a -t vnode -f $D.$m -u $m 58 newfs md${m} > /dev/null 2>&1 59 done 60 61 # start the parallel tests 62 for i in `jot $mounts`; do 63 m=$((i + mdstart - 1)) 64 $0 mmap $m & 65 sleep 0.2 66 $0 $m & 67 done 68 69 sleep 2 70 71 while [ ! -z "`ls $RUNDIR/active.* 2>/dev/null`" ] ; do 72 ../testcases/swap/swap -t 2m -i 20 73 done 74 wait 75 76 for i in `jot $mounts`; do 77 m=$((i + mdstart - 1)) 78 mdconfig -d -u $m 79 rm -f $D$m 80 done 81 rm -f /tmp/vunref $RUNDIR/active.* $diskimage.* ${mntpoint}*/p* 82else 83 if [ $1 = mmap ]; then 84 touch $RUNDIR/active.$2 85 for i in `jot 500`; do 86 cd ${mntpoint}$2 87 /tmp/vunref > /dev/null 2>&1 88 cd / 89 [ -f $RUNDIR/active.$2 ] || exit 90 sleep 0.1 91 done 92 rm -f $RUNDIR/active.$2 93 else 94 # The test: Parallel mount and unmounts 95 m=$1 96 mount $opt /dev/md${m} ${mntpoint}$m 97 while [ -f $RUNDIR/active.$m ] ; do 98 sleep 0.1 99 n=0 100 while mount | grep -qw $mntpoint$m; do 101 umount ${mntpoint}$m > /dev/null 2>&1 && n=0 102 if [ $((n += 1)) -gt 600 ]; then 103 echo "*** Leak detected ***" 104 fstat $mntpoint$m 105 rm -f $RUNDIR/active.* 106 exit 1 107 fi 108 sleep 0.1 109 done 110 mount $opt /dev/md${m} ${mntpoint}$m 111 done 112 mount | grep "$mntpoint" | grep -q md$m && umount ${mntpoint}$m 113 fi 114fi 115exit 116EOF 117#include <sys/param.h> 118#include <sys/mman.h> 119#include <sys/mount.h> 120#include <sys/stat.h> 121#include <sys/wait.h> 122#include <err.h> 123#include <errno.h> 124#include <fcntl.h> 125#include <stdio.h> 126#include <stdlib.h> 127#include <string.h> 128#include <unistd.h> 129 130#define INPUTFILE "/bin/date" 131 132int 133test(void) 134{ 135 int i; 136 pid_t pid; 137 char file[128]; 138 int fdin, fdout; 139 char *src, *dst; 140 struct stat statbuf; 141 142 pid = getpid(); 143 for (i = 0; i < 100; i++) { 144 sprintf(file,"p%05d.%05d", pid, i); 145 146 if ((fdin = open(INPUTFILE, O_RDONLY)) < 0) 147 err(1, INPUTFILE); 148 149 if ((fdout = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) 150 err(1, "%s", file); 151 152 if (fstat(fdin, &statbuf) < 0) 153 err(1, "fstat error"); 154 155 if (lseek(fdout, statbuf.st_size - 1, SEEK_SET) == -1) 156 err(1, "lseek error"); 157 158 /* write a dummy byte at the last location */ 159 if (write(fdout, "", 1) != 1) 160 err(1, "write error"); 161 162 if ((src = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fdin, 0)) == 163 (caddr_t) - 1) 164 err(1, "mmap error for input"); 165 166 if ((dst = mmap(0, statbuf.st_size, PROT_READ | PROT_WRITE, 167 MAP_SHARED, fdout, 0)) == (caddr_t) - 1) 168 err(1, "mmap error for output"); 169 170 memcpy(dst, src, statbuf.st_size); 171 172 if (munmap(src, statbuf.st_size) == -1) 173 err(1, "munmap"); 174 close(fdin); 175 176 if (munmap(dst, statbuf.st_size) == -1) 177 err(1, "munmap"); 178 close(fdout); 179 180 if (unlink(file) == -1) 181 err(3, "unlink(%s)", file); 182 } 183 184 return (0); 185} 186 187int 188main() 189{ 190 int i; 191 char path[MAXPATHLEN+1]; 192 struct statfs buf; 193 194 if (getcwd(path, sizeof(path)) == NULL) 195 err(1, "getcwd()"); 196 197 if (statfs(path, &buf) < 0) 198 err(1, "statfs(%s)", path); 199 200 if (!strcmp(buf.f_mntonname, "/")) 201 return (1); 202 203 for (i = 0; i < 2; i++) { 204 if (fork() == 0) 205 test(); 206 } 207 for (i = 0; i < 2; i++) 208 wait(NULL); 209 210 return (0); 211} 212