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