xref: /freebsd/tools/test/stress2/misc/mmap43.sh (revision 4b15965daa99044daf184221b7c283bf7f2d7e66)
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=`dirname $diskimage`/$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		# Workaround for known UFS SU ENOSPC issue
153		echo "Flush file system buffers and retry."
154		(cd $mntpoint; umount $mntpoint) > /dev/null 2>&1 # busy umount
155		cp file.orig file || exit 1
156	}
157	for i in `jot $n`; do
158		timeout -k 70s 1m /tmp/$prog.sort /dev/zero &
159	done
160	sleep $n
161	/tmp/$prog
162	while pkill $prog.sort; do sleep .2; done
163	wait
164	m=`md5 < file`
165	if [ $md5 != $m ]; then
166		echo "Failed @ iteration $counter"
167		ls -l
168		od -t x8 file      > /var/tmp/$prog.file1
169		od -t x8 file.post > /var/tmp/$prog.file2
170		diff /var/tmp/$prog.file1 /var/tmp/$prog.file2 > $log
171		head -10 $log
172		rm /var/tmp/$prog.file1 /var/tmp/$prog.file2
173		s=1
174		break
175	fi
176	echo "`date +%T` Loop #$counter, elapsed $((`date +%s` - st)) seconds."
177	counter=$((counter + 1))
178done
179cd $here
180
181umount $mntpoint
182mdconfig -d -u $mdstart
183rm /tmp/$prog /tmp/$prog.c /tmp/$prog.sort
184[ $s -eq 0 ] &&
185	printf "OK   File size is %9d, tail is %4d bytes. (%3d loops)\n" $size $tail $counter ||
186	printf "FAIL File size is %9d, tail is %4d bytes. (%3d loops)\n" $size $tail $counter
187exit $s
188