xref: /freebsd/tools/test/stress2/misc/mmap44.sh (revision 94a294e59d1772f316fef613b83e92f37294954c)
11ec33855SPeter Holm#!/bin/sh
21ec33855SPeter Holm
31ec33855SPeter Holm#
41ec33855SPeter Holm# SPDX-License-Identifier: BSD-2-Clause
51ec33855SPeter Holm#
61ec33855SPeter Holm# Copyright (c) 2024 Peter Holm <pho@FreeBSD.org>
71ec33855SPeter Holm#
81ec33855SPeter Holm# Redistribution and use in source and binary forms, with or without
91ec33855SPeter Holm# modification, are permitted provided that the following conditions
101ec33855SPeter Holm# are met:
111ec33855SPeter Holm# 1. Redistributions of source code must retain the above copyright
121ec33855SPeter Holm#    notice, this list of conditions and the following disclaimer.
131ec33855SPeter Holm# 2. Redistributions in binary form must reproduce the above copyright
141ec33855SPeter Holm#    notice, this list of conditions and the following disclaimer in the
151ec33855SPeter Holm#    documentation and/or other materials provided with the distribution.
161ec33855SPeter Holm#
171ec33855SPeter Holm# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
181ec33855SPeter Holm# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191ec33855SPeter Holm# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201ec33855SPeter Holm# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
211ec33855SPeter Holm# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221ec33855SPeter Holm# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231ec33855SPeter Holm# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241ec33855SPeter Holm# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251ec33855SPeter Holm# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261ec33855SPeter Holm# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271ec33855SPeter Holm# SUCH DAMAGE.
281ec33855SPeter Holm#
291ec33855SPeter Holm
301ec33855SPeter Holm# Demonstrate issue described in:
311ec33855SPeter Holm# [Bug 276002] nfscl: data corruption using both copy_file_range and mmap'd I/O
321ec33855SPeter Holm
331ec33855SPeter Holm[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
341ec33855SPeter Holm. ../default.cfg
351ec33855SPeter Holmset -u
361ec33855SPeter Holmprog=$(basename "$0" .sh)
371ec33855SPeter Holmlog=/tmp/$prog.log
381ec33855SPeter Holmgrep -q $mntpoint /etc/exports ||
391ec33855SPeter Holm    { echo "$mntpoint missing from /etc/exports"; exit 0; }
401ec33855SPeter Holm
411ec33855SPeter Holmcat > /tmp/$prog.c <<EOF
421ec33855SPeter Holm#include <sys/mman.h>
431ec33855SPeter Holm#include <sys/stat.h>
441ec33855SPeter Holm
451ec33855SPeter Holm#include <err.h>
461ec33855SPeter Holm#include <fcntl.h>
471ec33855SPeter Holm#include <pthread.h>
481ec33855SPeter Holm#include <stdio.h>
491ec33855SPeter Holm#include <stdlib.h>
501ec33855SPeter Holm#include <string.h>
511ec33855SPeter Holm#include <unistd.h>
521ec33855SPeter Holm
531ec33855SPeter Holmstatic off_t siz;
541ec33855SPeter Holmstatic pthread_mutex_t write_mutex;
551ec33855SPeter Holmstatic int fd, go;
561ec33855SPeter Holmstatic char *cp;
571ec33855SPeter Holm
581ec33855SPeter Holmstatic void *
591ec33855SPeter Holmmemread(void *arg __unused)
601ec33855SPeter Holm{
611ec33855SPeter Holm	int i;
621ec33855SPeter Holm	char c;
631ec33855SPeter Holm
641ec33855SPeter Holm	while (go == 1) {
651ec33855SPeter Holm		i = arc4random() % siz;
661ec33855SPeter Holm		c = cp[i];
671ec33855SPeter Holm		if (c != 0x77) /* No unused vars here */
681ec33855SPeter Holm			usleep(arc4random() % 400);
691ec33855SPeter Holm	}
701ec33855SPeter Holm	return (0);
711ec33855SPeter Holm}
721ec33855SPeter Holm
731ec33855SPeter Holmstatic void *
741ec33855SPeter Holmmemwrite(void *arg __unused)
751ec33855SPeter Holm{
761ec33855SPeter Holm	int i;
771ec33855SPeter Holm	char c;
781ec33855SPeter Holm
791ec33855SPeter Holm	while (go == 1) {
801ec33855SPeter Holm		i = arc4random() % siz;
811ec33855SPeter Holm		pthread_mutex_lock(&write_mutex);
821ec33855SPeter Holm		c = cp[i];
831ec33855SPeter Holm		cp[i] = 0xee;	/* This value seems to linger with NFS */
841ec33855SPeter Holm		cp[i] = c;
851ec33855SPeter Holm		pthread_mutex_unlock(&write_mutex);
861ec33855SPeter Holm		usleep(arc4random() % 400);
871ec33855SPeter Holm	}
881ec33855SPeter Holm	return (0);
891ec33855SPeter Holm}
901ec33855SPeter Holm
911ec33855SPeter Holmstatic void *
921ec33855SPeter Holmwr(void *arg __unused)
931ec33855SPeter Holm{
941ec33855SPeter Holm	off_t pos;
951ec33855SPeter Holm	int r, s;
961ec33855SPeter Holm	char buf[1024];
971ec33855SPeter Holm
981ec33855SPeter Holm	while (go == 1) {
991ec33855SPeter Holm		s = arc4random() % sizeof(buf) + 1;
1001ec33855SPeter Holm		pos = arc4random() % (siz - s);
1011ec33855SPeter Holm		pthread_mutex_lock(&write_mutex);
1021ec33855SPeter Holm		if (lseek(fd, pos, SEEK_SET) == -1)
1031ec33855SPeter Holm			err(1, "lseek(%d)", (int)pos);
1041ec33855SPeter Holm		if ((r = read(fd, buf, s)) != s) {
1051ec33855SPeter Holm			fprintf(stderr, "r = %d, s = %d, pos = %d\n", r, s, (int)pos);
1061ec33855SPeter Holm			err(1, "read():2");
1071ec33855SPeter Holm		}
1081ec33855SPeter Holm		if (lseek(fd, pos, SEEK_SET) == -1)
1091ec33855SPeter Holm			err(1, "lseek(%d)", (int)pos);
1101ec33855SPeter Holm		if (write(fd, buf, s) != s)
1111ec33855SPeter Holm			err(1, "write()");
1121ec33855SPeter Holm		pthread_mutex_unlock(&write_mutex);
1131ec33855SPeter Holm		usleep(arc4random() % 400);
1141ec33855SPeter Holm	}
1151ec33855SPeter Holm	return (0);
1161ec33855SPeter Holm}
1171ec33855SPeter Holm
1181ec33855SPeter Holmstatic void *
1191ec33855SPeter Holms1(void *arg __unused)
1201ec33855SPeter Holm{
1211ec33855SPeter Holm
1221ec33855SPeter Holm	while (go == 1) {
1231ec33855SPeter Holm		if (fdatasync(fd) == -1)
1241ec33855SPeter Holm			err(1, "fdatasync()");
1251ec33855SPeter Holm		usleep(arc4random() % 1000);
1261ec33855SPeter Holm	}
1271ec33855SPeter Holm	return (0);
1281ec33855SPeter Holm}
1291ec33855SPeter Holm
1301ec33855SPeter Holmstatic void *
1311ec33855SPeter Holms2(void *arg __unused)
1321ec33855SPeter Holm{
1331ec33855SPeter Holm
1341ec33855SPeter Holm	while (go == 1) {
1351ec33855SPeter Holm		if (fsync(fd) == -1)
1361ec33855SPeter Holm			err(1, "fdatasync()");
1371ec33855SPeter Holm		usleep(arc4random() % 1000);
1381ec33855SPeter Holm	}
1391ec33855SPeter Holm	return (0);
1401ec33855SPeter Holm}
1411ec33855SPeter Holm
1421ec33855SPeter Holmstatic void *
1431ec33855SPeter Holmtr(void *arg __unused)
1441ec33855SPeter Holm{
1451ec33855SPeter Holm	int i, s;
1461ec33855SPeter Holm	char buf[1024];
1471ec33855SPeter Holm
1481ec33855SPeter Holm	memset(buf, 0x5a, sizeof(buf));
1491ec33855SPeter Holm	while (go == 1) {
1501ec33855SPeter Holm		pthread_mutex_lock(&write_mutex);
1511ec33855SPeter Holm		if (lseek(fd, arc4random() % siz, SEEK_END) == -1)
1521ec33855SPeter Holm			err(1, "lseek() END");
1531ec33855SPeter Holm		s = sizeof(buf);
1541ec33855SPeter Holm		for (i = 0; i < 50; i++) {
1551ec33855SPeter Holm			if (write(fd, buf, s) != s)
1561ec33855SPeter Holm				warn("write()");
1571ec33855SPeter Holm		}
1581ec33855SPeter Holm		if (ftruncate(fd, siz) == -1)
1591ec33855SPeter Holm			err(1, "truncate()");
1601ec33855SPeter Holm		pthread_mutex_unlock(&write_mutex);
1611ec33855SPeter Holm		usleep(arc4random() % 400);
1621ec33855SPeter Holm	}
1631ec33855SPeter Holm	return (0);
1641ec33855SPeter Holm}
1651ec33855SPeter Holm
1661ec33855SPeter Holmint
1671ec33855SPeter Holmmain(int argc, char *argv[])
1681ec33855SPeter Holm{
1691ec33855SPeter Holm	struct stat st;
1701ec33855SPeter Holm	pthread_t tp[6];
1711ec33855SPeter Holm	int e, i;
1721ec33855SPeter Holm
1731ec33855SPeter Holm	if (argc != 2) {
1741ec33855SPeter Holm		fprintf(stderr, "Usage: %s <file>\n", argv[0]);
1751ec33855SPeter Holm		exit(1);
1761ec33855SPeter Holm	}
1771ec33855SPeter Holm	if ((fd = open(argv[1], O_RDWR)) == -1)
1781ec33855SPeter Holm		err(1, "open(%s)", argv[1]);
1791ec33855SPeter Holm	if (fstat(fd, &st) == -1)
1801ec33855SPeter Holm		err(1, "stat(%s)", argv[1]);
1811ec33855SPeter Holm	siz = st.st_size;
1821ec33855SPeter Holm	cp = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1831ec33855SPeter Holm	if (cp == MAP_FAILED)
1841ec33855SPeter Holm		err(1, "mmap()");
1851ec33855SPeter Holm
1861ec33855SPeter Holm	go = 1;
1871ec33855SPeter Holm	pthread_mutex_init(&write_mutex, NULL);
1881ec33855SPeter Holm	if ((e = pthread_create(&tp[0], NULL, memwrite, NULL)) != 0)
1891ec33855SPeter Holm		errc(1, e, "pthread_create");
1901ec33855SPeter Holm	if ((e = pthread_create(&tp[1], NULL, memread, NULL)) != 0)
1911ec33855SPeter Holm		errc(1, e, "pthread_create");
1921ec33855SPeter Holm	if ((e = pthread_create(&tp[2], NULL, wr, NULL)) != 0)
1931ec33855SPeter Holm		errc(1, e, "pthread_create");
1941ec33855SPeter Holm	if ((e = pthread_create(&tp[3], NULL, s1, NULL)) != 0)
1951ec33855SPeter Holm		errc(1, e, "pthread_create");
1961ec33855SPeter Holm	if ((e = pthread_create(&tp[4], NULL, s2, NULL)) != 0)
1971ec33855SPeter Holm		errc(1, e, "pthread_create");
1981ec33855SPeter Holm	if ((e = pthread_create(&tp[5], NULL, tr, NULL)) != 0)
1991ec33855SPeter Holm		errc(1, e, "pthread_create");
2001ec33855SPeter Holm
2011ec33855SPeter Holm	sleep(60);
2021ec33855SPeter Holm	go = 0;
2031ec33855SPeter Holm	for (i = 0; i < (int)(sizeof(tp) / sizeof(tp[0])); i++)
2041ec33855SPeter Holm		pthread_join(tp[i], NULL);
2051ec33855SPeter Holm	if (munmap(cp, siz) == -1)
2061ec33855SPeter Holm		err(1, "munmap()");
2071ec33855SPeter Holm	close(fd);
2081ec33855SPeter Holm}
2091ec33855SPeter HolmEOF
2101ec33855SPeter Holmmycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1
2111ec33855SPeter Holm
2121ec33855SPeter Holmmycc -o /tmp/serial -Wall -Wextra -O2 ../tools/serial.c || exit 1
2131ec33855SPeter Holmmount | grep -q "on $mntpoint " && umount -f $mntpoint
2141ec33855SPeter Holmmdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart
2151ec33855SPeter Holmmdconfig -s 5g -u $mdstart
2161ec33855SPeter Holmnewfs -n $newfs_flags /dev/md$mdstart > /dev/null
2171ec33855SPeter Holmmount /dev/md$mdstart $mntpoint
2181ec33855SPeter Holm
2191ec33855SPeter Holmmp2=${mntpoint}2
2201ec33855SPeter Holmmkdir -p $mp2
2211ec33855SPeter Holmmount | grep -q "on $mp2 " && umount -f $mp2
222*94a294e5SPeter Holmmount -t nfs -o retrycnt=3 127.0.0.1:$mntpoint $mp2 || exit 1
2231ec33855SPeter Holmsleep .2
2241ec33855SPeter Holm
2251ec33855SPeter Holmhere=`pwd`
2261ec33855SPeter Holmmount | grep $mntpoint
2271ec33855SPeter Holmcd $mp2
2281ec33855SPeter Holm$here/../testcases/swap/swap -t 5m -i 20 > /dev/null &
2291ec33855SPeter Holmsleep 2
2301ec33855SPeter Holm
2311ec33855SPeter Holmsize=262144
2321ec33855SPeter Holm/tmp/serial file $size
2331ec33855SPeter Holmcp file file.orig
2341ec33855SPeter Holm
2351ec33855SPeter Holms=0
2361ec33855SPeter Holm/tmp/$prog file || s=1
2371ec33855SPeter Holm
2381ec33855SPeter Holmwhile pgrep -q swap; do pkill swap; done
2391ec33855SPeter Holmwait
2401ec33855SPeter Holmif ! cmp -s file.orig file; then
2411ec33855SPeter Holm	od -t x1 file.orig > /var/tmp/$prog.file1
2421ec33855SPeter Holm	od -t x1 file      > /var/tmp/$prog.file2
2431ec33855SPeter Holm	diff /var/tmp/$prog.file1 /var/tmp/$prog.file2 > $log
2441ec33855SPeter Holm	head -20 $log
2451ec33855SPeter Holm	rm /var/tmp/$prog.file1 /var/tmp/$prog.file2
2461ec33855SPeter Holm	ls -ls file.orig file
2471ec33855SPeter Holm	s=2
2481ec33855SPeter Holmfi
2491ec33855SPeter Holm
2501ec33855SPeter Holmcd $here
2511ec33855SPeter Holmumount $mp2
2521ec33855SPeter Holmumount $mntpoint
2531ec33855SPeter Holmmdconfig -d -u $mdstart
2541ec33855SPeter Holmrm -f /tmp/serial /tmp/$prog /tmp/$prog.c $log
2551ec33855SPeter Holmexit $s
256