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