1#!/bin/sh 2 3# Test program obtained from Kyle Evans <kevans@FreeBSD.org> 4 5# Demonstrate UFS SU file corruption 6 7[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 8 9. ../default.cfg 10 11set -u 12prog=$(basename "$0" .sh) 13log=/tmp/$prog.log 14rm -f $log 15cat > /tmp/$prog.c <<EOF 16#include <sys/mman.h> 17#include <sys/stat.h> 18 19#include <assert.h> 20#include <err.h> 21#include <fcntl.h> 22#include <stdio.h> 23#include <unistd.h> 24 25#define FILE "file" 26 27int 28main(void) 29{ 30 struct stat sb; 31 ssize_t wsz; 32 size_t bufsz; 33 void *buf, *obuf; 34 int mfd, fd; 35 int done = 0; 36 37 mfd = open(FILE, O_RDONLY); 38 assert(mfd >= 0); 39 40 assert(fstat(mfd, &sb) == 0); 41 bufsz = sb.st_size; 42 buf = obuf = mmap(NULL, bufsz, PROT_READ, MAP_SHARED, mfd, 0); 43 assert(buf != MAP_FAILED); 44 45 /* O_RDWR */ 46 fd = open(FILE, O_RDWR); 47 if (fd < 0) 48 err(1, "open"); 49 assert(fd >= 0); 50 51again: 52 while (bufsz > 0) { 53 wsz = write(fd, buf, bufsz); 54 if (wsz < 0) 55 err(1, "write"); 56 else if (wsz == 0) 57 fprintf(stderr, "Huh?\n"); 58 bufsz -= wsz; 59 buf += wsz; 60 } 61 62 bufsz = sb.st_size; 63 buf = obuf; 64 65 if (++done < 2) 66 goto again; 67 68 close(fd); 69 munmap(obuf, sb.st_size); 70 close(mfd); 71 return (0); 72} 73EOF 74mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1 75 76cat > /tmp/$prog.serial.c <<EOF 77/* Fill a file with sequential numbers */ 78#include <sys/param.h> 79#include <sys/mman.h> 80#include <err.h> 81#include <fcntl.h> 82#include <stdio.h> 83#include <stdlib.h> 84#include <unistd.h> 85 86int 87main(int argc, char *argv[]) 88{ 89 size_t i, size; 90 long ix, *lp; 91 int fd; 92 char *file; 93 94 if (argc != 3) { 95 fprintf(stderr, "Usage: %s <file> <file length in bytes>\n", argv[0]); 96 exit(1); 97 } 98 file = argv[1]; 99 size = atol(argv[2]); 100 101 if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) 102 err(1, "%s", file); 103 104 if (lseek(fd, size - 1, SEEK_SET) == -1) 105 err(1, "lseek error"); 106 107 /* write a dummy byte at the last location */ 108 if (write(fd, "\0", 1) != 1) 109 err(1, "write error"); 110 111 if ((lp = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) 112 err(1, "mmap()"); 113 114 for (i = 0, ix = 0; i < size; i += sizeof(long), ix++) 115 lp[ix] = ix; 116 117 if (munmap(lp, size) == -1) 118 err(1, "munmap"); 119 close(fd); 120} 121EOF 122mycc -o /tmp/$prog.serial -Wall -Wextra -O0 /tmp/$prog.serial.c || exit 1 123 124mount | grep -q "on $mntpoint " && umount -f $mntpoint 125mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart 126mdconfig -s 5g -u $mdstart 127 128newfs -n $newfs_flags /dev/md$mdstart > /dev/null 129mount /dev/md$mdstart $mntpoint 130 131here=`pwd` 132cd $mntpoint 133 134size=875998990 135pagesize=`sysctl -n hw.pagesize` 136tail=$((size % pagesize)) 137/tmp/$prog.serial file $size 138 139cat file file > file.post 140mv file file.orig 141md5=`md5 < file.post` 142 143cp /usr/bin/sort /tmp/$prog.sort 144counter=1 145n=$((`sysctl -n hw.ncpu`)) 146[ $n -gt 10 ] && n=10 147s=0 148start=`date +%s` 149while [ $((`date +%s` - start)) -lt 300 ]; do 150 st=`date +%s` 151 cp file.orig file 152 for i in `jot $n`; do 153 timeout -k 70s 1m /tmp/$prog.sort /dev/zero & 154 done 155 sleep $n 156 /tmp/$prog 157 while pkill $prog.sort; do sleep .2; done 158 wait 159 m=`md5 < file` 160 if [ $md5 != $m ]; then 161 echo "Failed @ iteration $counter" 162 ls -l 163 od -t x8 file > /var/tmp/$prog.file1 164 od -t x8 file.post > /var/tmp/$prog.file2 165 diff /var/tmp/$prog.file1 /var/tmp/$prog.file2 > $log 166 head -10 $log 167 rm /var/tmp/$prog.file1 /var/tmp/$prog.file2 168 s=1 169 break 170 fi 171 echo "`date +%T` Loop #$counter, elapsed $((`date +%s` - st)) seconds." 172 counter=$((counter + 1)) 173done 174cd $here 175 176umount $mntpoint 177mdconfig -d -u $mdstart 178rm /tmp/$prog /tmp/$prog.c /tmp/$prog.sort 179[ $s -eq 0 ] && 180 printf "OK File size is %9d, tail is %4d bytes. (%3d loops)\n" $size $tail $counter || 181 printf "FAIL File size is %9d, tail is %4d bytes. (%3d loops)\n" $size $tail $counter 182exit $s 183