xref: /freebsd/tools/test/stress2/misc/rangelocks2.sh (revision ef777be98543f7daae90bd123d4fc1ec4a54efc2)
1#!/bin/sh
2
3#
4# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org>
5#
6# SPDX-License-Identifier: BSD-2-Clause
7#
8
9. ../default.cfg
10
11set -u
12prog=$(basename "$0" .sh)
13dir=/tmp
14odir=`pwd`
15cd $dir
16sed '1,/^EOF/d' < $odir/$0 > $dir/$prog.c
17mycc -o $prog -Wall -Wextra -O2 -g $prog.c || exit 1
18rm -f $prog.c
19cd $odir
20
21mdconfig -l | grep -q md$mdstart && mdconfig -d -u $mdstart
22set -e
23mdconfig -a -t swap -s 6g -u $mdstart
24newfs $newfs_flags -n /dev/md$mdstart > /dev/null
25mount /dev/md$mdstart $mntpoint
26set +e
27wd="$mntpoint/$prog.dir"
28mkdir -p $wd
29dd if=/dev/zero of=$wd/file bs=1m count=5k status=none
30
31[ `jot -r 1 1 100` -le 25 ] &&
32    ../testcases/swap/swap -t 10m -i 20 > /dev/null 2>&1 &
33cd $wd
34touch $wd/out
35/tmp/$prog $wd/file $wd/out; s=$?
36cd $odir
37while pkill swap; do :; done
38wait
39
40umount $mntpoint
41mdconfig -d -u $mdstart
42rm -rf /tmp/$prog $wd
43exit $s
44
45EOF
46#include <sys/param.h>
47#include <sys/mman.h>
48#include <sys/stat.h>
49#include <sys/wait.h>
50
51#include <machine/atomic.h>
52
53#include <err.h>
54#include <errno.h>
55#include <fcntl.h>
56#include <sched.h>
57#include <stdio.h>
58#include <stdlib.h>
59#include <time.h>
60#include <unistd.h>
61
62#define DONE 1
63#define MAXBLK (100 * 1024 * 1024)
64#define MAXPROC 32
65#define MAXSIZ (5LL * 1024 * 1024 *1024)
66#define RUNTIME (5 * 60)
67#define SYNC 0
68
69static volatile u_int *share;
70static int parallel;
71
72static char *file, *file2;
73
74static off_t
75newpos(int lng)
76{
77	off_t p;
78
79	do {
80		arc4random_buf(&p, sizeof(p));
81		p = p & 0xfffffff;
82	} while (p + lng > MAXSIZ);
83	return (p);
84}
85
86static void
87test(int indx, int num)
88{
89	off_t pos, pos2;
90	ssize_t i, l;
91	time_t start;
92	int fd, fd2, n;
93
94	atomic_add_int(&share[SYNC], 1);
95	while (share[SYNC] != (unsigned int)parallel)
96		sched_yield();
97
98	n = 0;
99	start = time(NULL);
100	while (share[DONE] != (unsigned int)parallel) {
101		setproctitle("test(%d) num %d, n %d", indx, num, n);
102		if ((fd = open(file, O_RDWR)) == -1)
103			err(1, "open(%s)", file);
104		if ((fd2 = open(file2, O_RDWR)) == -1)
105			err(1, "open(%s)", file2);
106
107		for (i = 0; i < arc4random() % 512; i++) {
108			l = arc4random() % MAXBLK + 1;
109			pos = newpos(l);
110			pos2 = newpos(l);
111			if (copy_file_range(fd, &pos, fd2, &pos2, l, 0) == -1)
112				err(1, "copy_file_range()");
113		}
114
115		close(fd2);
116		close(fd);
117		if (n++ == 0)
118			atomic_add_int(&share[DONE], 1);
119		if (time(NULL) - start >= RUNTIME * 4) {
120			fprintf(stderr, "test(%d), %d Timed out\n", indx, num);
121			break;
122		}
123	}
124	if (n++ == 0)
125		atomic_add_int(&share[DONE], 1);
126
127	_exit(0);
128}
129
130void
131setup(void)
132{
133
134	parallel = arc4random() % MAXPROC + 1;
135}
136
137int
138main(int argc, char *argv[])
139{
140	size_t len;
141	time_t start;
142	int e, i, n, *pids, status;
143
144	if (argc != 3) {
145		fprintf(stderr, "Usage: %s <in file> <out file>\n", argv[0]);
146		_exit(1);
147	}
148	e = 0;
149	file = argv[1];
150	file2 = argv[2];
151	len = PAGE_SIZE;
152	if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE,
153	    MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
154		err(1, "mmap");
155
156	n = 0;
157	start = time(NULL);
158	while ((time(NULL) - start) < RUNTIME && e == 0) {
159		setup();
160
161		pids = malloc(sizeof(pid_t) * parallel);
162		share[SYNC] = share[DONE] = 0;
163		for (i = 0; i < parallel; i++) {
164			if ((pids[i] = fork()) == 0)
165				test(i, n);
166		}
167		for (i = 0; i < parallel; i++) {
168			if (waitpid(pids[i], &status, 0) != pids[i])
169				err(1, "waitpid %d", pids[i]);
170			e += status == 0 ? 0 : 1;
171		}
172		n++;
173		n = n % 10;
174		free(pids);
175	}
176
177	return (e);
178}
179