xref: /freebsd/tools/test/stress2/misc/mmap44.sh (revision 1ec33855a82b6e937bcb5412f5b5ea971b3df375)
1*1ec33855SPeter Holm#!/bin/sh
2*1ec33855SPeter Holm
3*1ec33855SPeter Holm#
4*1ec33855SPeter Holm# SPDX-License-Identifier: BSD-2-Clause
5*1ec33855SPeter Holm#
6*1ec33855SPeter Holm# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org>
7*1ec33855SPeter Holm#
8*1ec33855SPeter Holm# Redistribution and use in source and binary forms, with or without
9*1ec33855SPeter Holm# modification, are permitted provided that the following conditions
10*1ec33855SPeter Holm# are met:
11*1ec33855SPeter Holm# 1. Redistributions of source code must retain the above copyright
12*1ec33855SPeter Holm#    notice, this list of conditions and the following disclaimer.
13*1ec33855SPeter Holm# 2. Redistributions in binary form must reproduce the above copyright
14*1ec33855SPeter Holm#    notice, this list of conditions and the following disclaimer in the
15*1ec33855SPeter Holm#    documentation and/or other materials provided with the distribution.
16*1ec33855SPeter Holm#
17*1ec33855SPeter Holm# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18*1ec33855SPeter Holm# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*1ec33855SPeter Holm# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*1ec33855SPeter Holm# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21*1ec33855SPeter Holm# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*1ec33855SPeter Holm# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*1ec33855SPeter Holm# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*1ec33855SPeter Holm# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*1ec33855SPeter Holm# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*1ec33855SPeter Holm# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*1ec33855SPeter Holm# SUCH DAMAGE.
28*1ec33855SPeter Holm#
29*1ec33855SPeter Holm
30*1ec33855SPeter Holm# Demonstrate issue described in:
31*1ec33855SPeter Holm# [Bug 276002] nfscl: data corruption using both copy_file_range and mmap'd I/O
32*1ec33855SPeter Holm
33*1ec33855SPeter Holm[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
34*1ec33855SPeter Holm. ../default.cfg
35*1ec33855SPeter Holmset -u
36*1ec33855SPeter Holmprog=$(basename "$0" .sh)
37*1ec33855SPeter Holmlog=/tmp/$prog.log
38*1ec33855SPeter Holmgrep -q $mntpoint /etc/exports ||
39*1ec33855SPeter Holm    { echo "$mntpoint missing from /etc/exports"; exit 0; }
40*1ec33855SPeter Holm
41*1ec33855SPeter Holmcat > /tmp/$prog.c <<EOF
42*1ec33855SPeter Holm#include <sys/mman.h>
43*1ec33855SPeter Holm#include <sys/stat.h>
44*1ec33855SPeter Holm
45*1ec33855SPeter Holm#include <err.h>
46*1ec33855SPeter Holm#include <fcntl.h>
47*1ec33855SPeter Holm#include <pthread.h>
48*1ec33855SPeter Holm#include <stdio.h>
49*1ec33855SPeter Holm#include <stdlib.h>
50*1ec33855SPeter Holm#include <string.h>
51*1ec33855SPeter Holm#include <unistd.h>
52*1ec33855SPeter Holm
53*1ec33855SPeter Holmstatic off_t siz;
54*1ec33855SPeter Holmstatic pthread_mutex_t write_mutex;
55*1ec33855SPeter Holmstatic int fd, go;
56*1ec33855SPeter Holmstatic char *cp;
57*1ec33855SPeter Holm
58*1ec33855SPeter Holmstatic void *
59*1ec33855SPeter Holmmemread(void *arg __unused)
60*1ec33855SPeter Holm{
61*1ec33855SPeter Holm	int i;
62*1ec33855SPeter Holm	char c;
63*1ec33855SPeter Holm
64*1ec33855SPeter Holm	while (go == 1) {
65*1ec33855SPeter Holm		i = arc4random() % siz;
66*1ec33855SPeter Holm		c = cp[i];
67*1ec33855SPeter Holm		if (c != 0x77) /* No unused vars here */
68*1ec33855SPeter Holm			usleep(arc4random() % 400);
69*1ec33855SPeter Holm	}
70*1ec33855SPeter Holm	return (0);
71*1ec33855SPeter Holm}
72*1ec33855SPeter Holm
73*1ec33855SPeter Holmstatic void *
74*1ec33855SPeter Holmmemwrite(void *arg __unused)
75*1ec33855SPeter Holm{
76*1ec33855SPeter Holm	int i;
77*1ec33855SPeter Holm	char c;
78*1ec33855SPeter Holm
79*1ec33855SPeter Holm	while (go == 1) {
80*1ec33855SPeter Holm		i = arc4random() % siz;
81*1ec33855SPeter Holm		pthread_mutex_lock(&write_mutex);
82*1ec33855SPeter Holm		c = cp[i];
83*1ec33855SPeter Holm		cp[i] = 0xee;	/* This value seems to linger with NFS */
84*1ec33855SPeter Holm		cp[i] = c;
85*1ec33855SPeter Holm		pthread_mutex_unlock(&write_mutex);
86*1ec33855SPeter Holm		usleep(arc4random() % 400);
87*1ec33855SPeter Holm	}
88*1ec33855SPeter Holm	return (0);
89*1ec33855SPeter Holm}
90*1ec33855SPeter Holm
91*1ec33855SPeter Holmstatic void *
92*1ec33855SPeter Holmwr(void *arg __unused)
93*1ec33855SPeter Holm{
94*1ec33855SPeter Holm	off_t pos;
95*1ec33855SPeter Holm	int r, s;
96*1ec33855SPeter Holm	char buf[1024];
97*1ec33855SPeter Holm
98*1ec33855SPeter Holm	while (go == 1) {
99*1ec33855SPeter Holm		s = arc4random() % sizeof(buf) + 1;
100*1ec33855SPeter Holm		pos = arc4random() % (siz - s);
101*1ec33855SPeter Holm		pthread_mutex_lock(&write_mutex);
102*1ec33855SPeter Holm		if (lseek(fd, pos, SEEK_SET) == -1)
103*1ec33855SPeter Holm			err(1, "lseek(%d)", (int)pos);
104*1ec33855SPeter Holm		if ((r = read(fd, buf, s)) != s) {
105*1ec33855SPeter Holm			fprintf(stderr, "r = %d, s = %d, pos = %d\n", r, s, (int)pos);
106*1ec33855SPeter Holm			err(1, "read():2");
107*1ec33855SPeter Holm		}
108*1ec33855SPeter Holm		if (lseek(fd, pos, SEEK_SET) == -1)
109*1ec33855SPeter Holm			err(1, "lseek(%d)", (int)pos);
110*1ec33855SPeter Holm		if (write(fd, buf, s) != s)
111*1ec33855SPeter Holm			err(1, "write()");
112*1ec33855SPeter Holm		pthread_mutex_unlock(&write_mutex);
113*1ec33855SPeter Holm		usleep(arc4random() % 400);
114*1ec33855SPeter Holm	}
115*1ec33855SPeter Holm	return (0);
116*1ec33855SPeter Holm}
117*1ec33855SPeter Holm
118*1ec33855SPeter Holmstatic void *
119*1ec33855SPeter Holms1(void *arg __unused)
120*1ec33855SPeter Holm{
121*1ec33855SPeter Holm
122*1ec33855SPeter Holm	while (go == 1) {
123*1ec33855SPeter Holm		if (fdatasync(fd) == -1)
124*1ec33855SPeter Holm			err(1, "fdatasync()");
125*1ec33855SPeter Holm		usleep(arc4random() % 1000);
126*1ec33855SPeter Holm	}
127*1ec33855SPeter Holm	return (0);
128*1ec33855SPeter Holm}
129*1ec33855SPeter Holm
130*1ec33855SPeter Holmstatic void *
131*1ec33855SPeter Holms2(void *arg __unused)
132*1ec33855SPeter Holm{
133*1ec33855SPeter Holm
134*1ec33855SPeter Holm	while (go == 1) {
135*1ec33855SPeter Holm		if (fsync(fd) == -1)
136*1ec33855SPeter Holm			err(1, "fdatasync()");
137*1ec33855SPeter Holm		usleep(arc4random() % 1000);
138*1ec33855SPeter Holm	}
139*1ec33855SPeter Holm	return (0);
140*1ec33855SPeter Holm}
141*1ec33855SPeter Holm
142*1ec33855SPeter Holmstatic void *
143*1ec33855SPeter Holmtr(void *arg __unused)
144*1ec33855SPeter Holm{
145*1ec33855SPeter Holm	int i, s;
146*1ec33855SPeter Holm	char buf[1024];
147*1ec33855SPeter Holm
148*1ec33855SPeter Holm	memset(buf, 0x5a, sizeof(buf));
149*1ec33855SPeter Holm	while (go == 1) {
150*1ec33855SPeter Holm		pthread_mutex_lock(&write_mutex);
151*1ec33855SPeter Holm		if (lseek(fd, arc4random() % siz, SEEK_END) == -1)
152*1ec33855SPeter Holm			err(1, "lseek() END");
153*1ec33855SPeter Holm		s = sizeof(buf);
154*1ec33855SPeter Holm		for (i = 0; i < 50; i++) {
155*1ec33855SPeter Holm			if (write(fd, buf, s) != s)
156*1ec33855SPeter Holm				warn("write()");
157*1ec33855SPeter Holm		}
158*1ec33855SPeter Holm		if (ftruncate(fd, siz) == -1)
159*1ec33855SPeter Holm			err(1, "truncate()");
160*1ec33855SPeter Holm		pthread_mutex_unlock(&write_mutex);
161*1ec33855SPeter Holm		usleep(arc4random() % 400);
162*1ec33855SPeter Holm	}
163*1ec33855SPeter Holm	return (0);
164*1ec33855SPeter Holm}
165*1ec33855SPeter Holm
166*1ec33855SPeter Holmint
167*1ec33855SPeter Holmmain(int argc, char *argv[])
168*1ec33855SPeter Holm{
169*1ec33855SPeter Holm	struct stat st;
170*1ec33855SPeter Holm	pthread_t tp[6];
171*1ec33855SPeter Holm	int e, i;
172*1ec33855SPeter Holm
173*1ec33855SPeter Holm	if (argc != 2) {
174*1ec33855SPeter Holm		fprintf(stderr, "Usage: %s <file>\n", argv[0]);
175*1ec33855SPeter Holm		exit(1);
176*1ec33855SPeter Holm	}
177*1ec33855SPeter Holm	if ((fd = open(argv[1], O_RDWR)) == -1)
178*1ec33855SPeter Holm		err(1, "open(%s)", argv[1]);
179*1ec33855SPeter Holm	if (fstat(fd, &st) == -1)
180*1ec33855SPeter Holm		err(1, "stat(%s)", argv[1]);
181*1ec33855SPeter Holm	siz = st.st_size;
182*1ec33855SPeter Holm	cp = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
183*1ec33855SPeter Holm	if (cp == MAP_FAILED)
184*1ec33855SPeter Holm		err(1, "mmap()");
185*1ec33855SPeter Holm
186*1ec33855SPeter Holm	go = 1;
187*1ec33855SPeter Holm	pthread_mutex_init(&write_mutex, NULL);
188*1ec33855SPeter Holm	if ((e = pthread_create(&tp[0], NULL, memwrite, NULL)) != 0)
189*1ec33855SPeter Holm		errc(1, e, "pthread_create");
190*1ec33855SPeter Holm	if ((e = pthread_create(&tp[1], NULL, memread, NULL)) != 0)
191*1ec33855SPeter Holm		errc(1, e, "pthread_create");
192*1ec33855SPeter Holm	if ((e = pthread_create(&tp[2], NULL, wr, NULL)) != 0)
193*1ec33855SPeter Holm		errc(1, e, "pthread_create");
194*1ec33855SPeter Holm	if ((e = pthread_create(&tp[3], NULL, s1, NULL)) != 0)
195*1ec33855SPeter Holm		errc(1, e, "pthread_create");
196*1ec33855SPeter Holm	if ((e = pthread_create(&tp[4], NULL, s2, NULL)) != 0)
197*1ec33855SPeter Holm		errc(1, e, "pthread_create");
198*1ec33855SPeter Holm	if ((e = pthread_create(&tp[5], NULL, tr, NULL)) != 0)
199*1ec33855SPeter Holm		errc(1, e, "pthread_create");
200*1ec33855SPeter Holm
201*1ec33855SPeter Holm	sleep(60);
202*1ec33855SPeter Holm	go = 0;
203*1ec33855SPeter Holm	for (i = 0; i < (int)(sizeof(tp) / sizeof(tp[0])); i++)
204*1ec33855SPeter Holm		pthread_join(tp[i], NULL);
205*1ec33855SPeter Holm	if (munmap(cp, siz) == -1)
206*1ec33855SPeter Holm		err(1, "munmap()");
207*1ec33855SPeter Holm	close(fd);
208*1ec33855SPeter Holm}
209*1ec33855SPeter HolmEOF
210*1ec33855SPeter Holmmycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1
211*1ec33855SPeter Holm
212*1ec33855SPeter Holmmycc -o /tmp/serial -Wall -Wextra -O2 ../tools/serial.c || exit 1
213*1ec33855SPeter Holmmount | grep -q "on $mntpoint " && umount -f $mntpoint
214*1ec33855SPeter Holmmdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart
215*1ec33855SPeter Holmmdconfig -s 5g -u $mdstart
216*1ec33855SPeter Holmnewfs -n $newfs_flags /dev/md$mdstart > /dev/null
217*1ec33855SPeter Holmmount /dev/md$mdstart $mntpoint
218*1ec33855SPeter Holm
219*1ec33855SPeter Holmmp2=${mntpoint}2
220*1ec33855SPeter Holmmkdir -p $mp2
221*1ec33855SPeter Holmmount | grep -q "on $mp2 " && umount -f $mp2
222*1ec33855SPeter Holmmount -t nfs 127.0.0.1:$mntpoint $mp2; s=$?
223*1ec33855SPeter Holmsleep .2
224*1ec33855SPeter Holm
225*1ec33855SPeter Holmhere=`pwd`
226*1ec33855SPeter Holmmount | grep $mntpoint
227*1ec33855SPeter Holmcd $mp2
228*1ec33855SPeter Holm$here/../testcases/swap/swap -t 5m -i 20 > /dev/null &
229*1ec33855SPeter Holmsleep 2
230*1ec33855SPeter Holm
231*1ec33855SPeter Holmsize=262144
232*1ec33855SPeter Holm/tmp/serial file $size
233*1ec33855SPeter Holmcp file file.orig
234*1ec33855SPeter Holm
235*1ec33855SPeter Holms=0
236*1ec33855SPeter Holm/tmp/$prog file || s=1
237*1ec33855SPeter Holm
238*1ec33855SPeter Holmwhile pgrep -q swap; do pkill swap; done
239*1ec33855SPeter Holmwait
240*1ec33855SPeter Holmif ! cmp -s file.orig file; then
241*1ec33855SPeter Holm	od -t x1 file.orig > /var/tmp/$prog.file1
242*1ec33855SPeter Holm	od -t x1 file      > /var/tmp/$prog.file2
243*1ec33855SPeter Holm	diff /var/tmp/$prog.file1 /var/tmp/$prog.file2 > $log
244*1ec33855SPeter Holm	head -20 $log
245*1ec33855SPeter Holm	rm /var/tmp/$prog.file1 /var/tmp/$prog.file2
246*1ec33855SPeter Holm	ls -ls file.orig file
247*1ec33855SPeter Holm	s=2
248*1ec33855SPeter Holmfi
249*1ec33855SPeter Holm
250*1ec33855SPeter Holmcd $here
251*1ec33855SPeter Holmumount $mp2
252*1ec33855SPeter Holmumount $mntpoint
253*1ec33855SPeter Holmmdconfig -d -u $mdstart
254*1ec33855SPeter Holmrm -f /tmp/serial /tmp/$prog /tmp/$prog.c $log
255*1ec33855SPeter Holmexit $s
256