xref: /freebsd/tools/test/stress2/misc/mmap43.sh (revision 6580f5c38dd5b01aeeaed16b370f1a12423437f0)
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