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