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 70 fsck -t ufs -y md$mdstart 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 86newfs -j md$mdstart > /dev/null 87mount /dev/md$mdstart $mntpoint 88 89cd $mntpoint 90chmod 777 $mntpoint 91/tmp/suj22 92snap $mntpoint $mntpoint/.snap/snap1 93/tmp/suj22 prune 94snap $mntpoint $mntpoint/.snap/snap2 95/tmp/suj22 96for i in `jot 10`; do 97 /tmp/suj22 prune 98 /tmp/suj22 99 snap $mntpoint $mntpoint/.snap/snap$((i + 2)) || break 100 sn=`ls -tU $mntpoint/.snap | tail -1` 101 rm -f $mntpoint/.snap/$sn 102done 103cd $here 104 105while mount | grep -q $mntpoint; do 106 umount $mntpoint || sleep 1 107done 108fsck -t ufs -y md$mdstart 109fsck -t ufs -y md$mdstart 110mdconfig -d -u $mdstart 111rm -f /tmp/suj22 $D 112exit 0 113EOF 114#include <sys/types.h> 115#include <err.h> 116#include <errno.h> 117#include <fcntl.h> 118#include <stdio.h> 119#include <stdlib.h> 120#include <sys/stat.h> 121#include <unistd.h> 122 123static char buf[4096]; 124#define ND 100 125#define NF 100 126 127void 128setup(void) 129{ 130 int d, f, fd, i, n; 131 char name[128]; 132 133 for (d = 0; d < ND; d++) { 134 snprintf(name, sizeof(name), "d%03d", d); 135 if (mkdir(name, 00700) == -1 && errno != EEXIST) 136 err(1, "mkdir(%s)", name); 137 if (chdir(name) == -1) 138 err(1, "chdir(%s)", name); 139 for (f = 0; f < NF; f++) { 140 if (arc4random() % 100 < 33) 141 continue; 142 snprintf(name, sizeof(name), "f%03d", f); 143 if ((fd = open(name, O_RDWR | O_CREAT | O_TRUNC, 0640)) == -1) 144 err(1, "open(%s)", name); 145 n = arc4random() % 10; 146 for (i = 0; i < n; i++) { 147 if (write(fd, buf, sizeof(buf)) != sizeof(buf)) 148 err(1, "write()"); 149 } 150 close(fd); 151 } 152 if (chdir("..") == -1) 153 err(1, "chdir(%s)", ".."); 154 } 155} 156void 157 158prune(void) 159{ 160 int d, f; 161 char name[128]; 162 163 for (d = 0; d < ND; d++) { 164 snprintf(name, sizeof(name), "d%03d", d); 165 if (chdir(name) == -1) 166 err(1, "chdir(%s)", name); 167 for (f = 0; f < NF; f++) { 168 if (arc4random() % 100 < 33) 169 continue; 170 snprintf(name, sizeof(name), "f%03d", f); 171 if (unlink(name) == -1 && errno != ENOENT) 172 err(1, "unlink(%s)", name); 173 } 174 if (chdir("..") == -1) 175 err(1, "chdir(%s)", ".."); 176 } 177 for (d = 0; d < ND; d++) { 178 if (arc4random() % 100 > 10) 179 continue; 180 snprintf(name, sizeof(name), "rm -rf d%03d", d); 181 system(name); 182 } 183} 184 185int 186main(int argc, char **argv __unused) 187{ 188 if (argc == 1) 189 setup(); 190 if (argc == 2) 191 prune(); 192 193 return (0); 194} 195