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