1#!/bin/sh 2 3# 4# Copyright (c) 2011 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# Variation of suj20.sh, with focus on the FS state after a panic / power 30# cycle. 31 32# Demonstrate "multiple references to blocks" in FS after reboot from a 33# looping mksnap_ffs(8). 34 35[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 36 37. ../default.cfg 38 39# Scenario by mckusick@ 40# 41# create a bunch of files/directories 42# create a snapshot 43# remove many (but not all) of those files/directories 44# create some new files/directories in what remains of those 45# original files/directories. 46# create another snapshot 47# repeat { 48# remove many (somewhat different) of those files/directories 49# create some new files/directories in what remains of those 50# remaining files/directories. 51# create a new snapshot 52# remove oldest snapshot 53# } 54 55snap () { 56 for i in `jot 5`; do 57 mksnap_ffs $1 $2 2>&1 | grep -v "Resource temporarily unavailable" 58 [ ! -s $2 ] && rm -f $2 || return 0 59 sleep 1 60 done 61 return 1 62} 63 64D=$diskimage 65 66if [ -n "`find $D -mtime -1h 2>/dev/null`" ]; then 67 # FS left by previous crash 68 mdconfig -a -t vnode -f $D -u $mdstart 69 fsck -t ufs -y md${mdstart}$part 70 fsck -t ufs -y md${mdstart}$part 71 rm -f $D 72 exit 0 73fi 74 75here=`pwd` 76cd /tmp 77sed '1,/^EOF/d' < $here/$0 > suj22.c 78mycc -o suj22 -Wall -Wextra -O2 suj22.c 79rm -f suj22.c 80 81mount | grep "$mntpoint" | grep -q md$mdstart && umount $mntpoint 82mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart 83 84dd if=/dev/zero of=$D bs=1m count=1k status=none || exit 1 85mdconfig -a -t vnode -f $D -u $mdstart 86bsdlabel -w md$mdstart auto 87newfs -j md${mdstart}$part > /dev/null 88mount /dev/md${mdstart}$part $mntpoint 89 90cd $mntpoint 91chmod 777 $mntpoint 92/tmp/suj22 93snap $mntpoint $mntpoint/.snap/snap1 94/tmp/suj22 prune 95snap $mntpoint $mntpoint/.snap/snap2 96/tmp/suj22 97for i in `jot 10`; do 98 /tmp/suj22 prune 99 /tmp/suj22 100 snap $mntpoint $mntpoint/.snap/snap$((i + 2)) || break 101 sn=`ls -tU $mntpoint/.snap | tail -1` 102 rm -f $mntpoint/.snap/$sn 103done 104cd $here 105 106while mount | grep -q $mntpoint; do 107 umount $mntpoint || sleep 1 108done 109fsck -t ufs -y md${mdstart}$part 110fsck -t ufs -y md${mdstart}$part 111mdconfig -d -u $mdstart 112rm -f /tmp/suj22 $D 113exit 0 114EOF 115#include <sys/types.h> 116#include <err.h> 117#include <errno.h> 118#include <fcntl.h> 119#include <stdio.h> 120#include <stdlib.h> 121#include <sys/stat.h> 122#include <unistd.h> 123 124static char buf[4096]; 125#define ND 100 126#define NF 100 127 128void 129setup(void) 130{ 131 int d, f, fd, i, n; 132 char name[128]; 133 134 for (d = 0; d < ND; d++) { 135 snprintf(name, sizeof(name), "d%03d", d); 136 if (mkdir(name, 00700) == -1 && errno != EEXIST) 137 err(1, "mkdir(%s)", name); 138 if (chdir(name) == -1) 139 err(1, "chdir(%s)", name); 140 for (f = 0; f < NF; f++) { 141 if (arc4random() % 100 < 33) 142 continue; 143 snprintf(name, sizeof(name), "f%03d", f); 144 if ((fd = open(name, O_RDWR | O_CREAT | O_TRUNC, 0640)) == -1) 145 err(1, "open(%s)", name); 146 n = arc4random() % 10; 147 for (i = 0; i < n; i++) { 148 if (write(fd, buf, sizeof(buf)) != sizeof(buf)) 149 err(1, "write()"); 150 } 151 close(fd); 152 } 153 if (chdir("..") == -1) 154 err(1, "chdir(%s)", ".."); 155 } 156} 157void 158 159prune(void) 160{ 161 int d, f; 162 char name[128]; 163 164 for (d = 0; d < ND; d++) { 165 snprintf(name, sizeof(name), "d%03d", d); 166 if (chdir(name) == -1) 167 err(1, "chdir(%s)", name); 168 for (f = 0; f < NF; f++) { 169 if (arc4random() % 100 < 33) 170 continue; 171 snprintf(name, sizeof(name), "f%03d", f); 172 if (unlink(name) == -1 && errno != ENOENT) 173 err(1, "unlink(%s)", name); 174 } 175 if (chdir("..") == -1) 176 err(1, "chdir(%s)", ".."); 177 } 178 for (d = 0; d < ND; d++) { 179 if (arc4random() % 100 > 10) 180 continue; 181 snprintf(name, sizeof(name), "rm -rf d%03d", d); 182 system(name); 183 } 184} 185 186int 187main(int argc, char **argv __unused) 188{ 189 if (argc == 1) 190 setup(); 191 if (argc == 2) 192 prune(); 193 194 return (0); 195} 196