1*d7ff2dedSPeter Holm#!/bin/sh 2*d7ff2dedSPeter Holm 3*d7ff2dedSPeter Holm# 4*d7ff2dedSPeter Holm# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> 5*d7ff2dedSPeter Holm# 6*d7ff2dedSPeter Holm# SPDX-License-Identifier: BSD-2-Clause 7*d7ff2dedSPeter Holm# 8*d7ff2dedSPeter Holm 9*d7ff2dedSPeter Holm# A kqueuex(KQUEUE_CPONFORK) test scenario 10*d7ff2dedSPeter Holm# Test scenario suggestion by: kib 11*d7ff2dedSPeter Holm 12*d7ff2dedSPeter Holm. ../default.cfg 13*d7ff2dedSPeter Holm[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 14*d7ff2dedSPeter Holm 15*d7ff2dedSPeter Holmdir=/tmp 16*d7ff2dedSPeter Holmodir=`pwd` 17*d7ff2dedSPeter Holmprog=$(basename "$0" .sh) 18*d7ff2dedSPeter Holmcd $dir 19*d7ff2dedSPeter Holmsed '1,/^EOF/d' < $odir/$0 > $dir/$prog.c 20*d7ff2dedSPeter Holmmycc -o $prog -Wall -Wextra -O0 -g $prog.c || exit 1 21*d7ff2dedSPeter Holmrm -f $prog.c 22*d7ff2dedSPeter Holmcd $odir 23*d7ff2dedSPeter Holm 24*d7ff2dedSPeter Holmset -e 25*d7ff2dedSPeter Holmmount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint 26*d7ff2dedSPeter Holm[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart 27*d7ff2dedSPeter Holmmdconfig -a -t swap -s 2g -u $mdstart 28*d7ff2dedSPeter Holmnewfs $newfs_flags md$mdstart > /dev/null 29*d7ff2dedSPeter Holmmount /dev/md$mdstart $mntpoint 30*d7ff2dedSPeter Holmset +e 31*d7ff2dedSPeter Holm 32*d7ff2dedSPeter Holm(cd $odir/../testcases/swap; ./swap -t 5m -i 20 -h -l 100 > /dev/null) & 33*d7ff2dedSPeter Holmcd $mntpoint 34*d7ff2dedSPeter Holm$dir/$prog 35*d7ff2dedSPeter Holms=$? 36*d7ff2dedSPeter Holm[ -f $prog.core -a $s -eq 0 ] && 37*d7ff2dedSPeter Holm { ls -l $prog.core; mv $prog.core /tmp; s=1; } 38*d7ff2dedSPeter Holmcd $odir 39*d7ff2dedSPeter Holmwhile pkill -9 swap; do :; done 40*d7ff2dedSPeter Holmwait 41*d7ff2dedSPeter Holm 42*d7ff2dedSPeter Holmfor i in `jot 6`; do 43*d7ff2dedSPeter Holm mount | grep -q "on $mntpoint " || break 44*d7ff2dedSPeter Holm umount $mntpoint && break || sleep 10 45*d7ff2dedSPeter Holmdone 46*d7ff2dedSPeter Holm[ $i -eq 6 ] && exit 1 47*d7ff2dedSPeter Holmmdconfig -d -u $mdstart 48*d7ff2dedSPeter Holmrm -rf $dir/$prog 49*d7ff2dedSPeter Holmexit $s 50*d7ff2dedSPeter Holm 51*d7ff2dedSPeter HolmEOF 52*d7ff2dedSPeter Holm#include <sys/param.h> 53*d7ff2dedSPeter Holm#include <sys/event.h> 54*d7ff2dedSPeter Holm#include <sys/mman.h> 55*d7ff2dedSPeter Holm#include <sys/stat.h> 56*d7ff2dedSPeter Holm#include <sys/wait.h> 57*d7ff2dedSPeter Holm 58*d7ff2dedSPeter Holm#include <machine/atomic.h> 59*d7ff2dedSPeter Holm 60*d7ff2dedSPeter Holm#include <err.h> 61*d7ff2dedSPeter Holm#include <errno.h> 62*d7ff2dedSPeter Holm#include <fcntl.h> 63*d7ff2dedSPeter Holm#include <stdio.h> 64*d7ff2dedSPeter Holm#include <stdlib.h> 65*d7ff2dedSPeter Holm#include <string.h> 66*d7ff2dedSPeter Holm#include <time.h> 67*d7ff2dedSPeter Holm#include <unistd.h> 68*d7ff2dedSPeter Holm 69*d7ff2dedSPeter Holmstatic volatile u_int *share; 70*d7ff2dedSPeter Holmstatic int loops; 71*d7ff2dedSPeter Holmstatic char *file = "file"; 72*d7ff2dedSPeter Holm 73*d7ff2dedSPeter Holm#define MAXLOOPS 100 74*d7ff2dedSPeter Holm#define PARALLEL 1 75*d7ff2dedSPeter Holm#define RUNTIME (2 * 60) 76*d7ff2dedSPeter Holm#define SYNC 0 77*d7ff2dedSPeter Holm 78*d7ff2dedSPeter Holmstatic void 79*d7ff2dedSPeter Holmtest(void) 80*d7ff2dedSPeter Holm{ 81*d7ff2dedSPeter Holm pid_t pid; 82*d7ff2dedSPeter Holm struct kevent ev[2]; 83*d7ff2dedSPeter Holm struct timespec ts; 84*d7ff2dedSPeter Holm int kq, fd, n; 85*d7ff2dedSPeter Holm 86*d7ff2dedSPeter Holm if ((fd = open(file, O_RDONLY, 0)) == -1) 87*d7ff2dedSPeter Holm err(1, "open(%s). %s:%d", file, __func__, __LINE__); 88*d7ff2dedSPeter Holm 89*d7ff2dedSPeter Holm atomic_add_int(&share[SYNC], 1); 90*d7ff2dedSPeter Holm while (share[SYNC] != PARALLEL) 91*d7ff2dedSPeter Holm usleep(10000); 92*d7ff2dedSPeter Holm 93*d7ff2dedSPeter Holm if ((kq = kqueuex(KQUEUE_CPONFORK)) < 0) 94*d7ff2dedSPeter Holm err(1, "kqueuex"); 95*d7ff2dedSPeter Holm 96*d7ff2dedSPeter Holm ts.tv_sec = 5; 97*d7ff2dedSPeter Holm ts.tv_nsec = 0; 98*d7ff2dedSPeter Holm n = 0; 99*d7ff2dedSPeter Holm EV_SET(&ev[n], fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, 100*d7ff2dedSPeter Holm NOTE_DELETE, 0, 0); 101*d7ff2dedSPeter Holm n++; 102*d7ff2dedSPeter Holm 103*d7ff2dedSPeter Holm if (kevent(kq, ev, n, NULL, 0, NULL) < 0) 104*d7ff2dedSPeter Holm err(1, "kevent()"); 105*d7ff2dedSPeter Holm if (loops >= MAXLOOPS) { /* start using fork(2) */ 106*d7ff2dedSPeter Holm if ((pid = fork()) == 0) { 107*d7ff2dedSPeter Holm n = kevent(kq, NULL, 0, ev, 1, &ts); 108*d7ff2dedSPeter Holm if (n == -1) 109*d7ff2dedSPeter Holm err(1, "kevent() in fork\n"); 110*d7ff2dedSPeter Holm close(fd); 111*d7ff2dedSPeter Holm close(kq); 112*d7ff2dedSPeter Holm _exit(0); 113*d7ff2dedSPeter Holm } 114*d7ff2dedSPeter Holm if (waitpid(pid, NULL, 0) != pid) 115*d7ff2dedSPeter Holm err(1, "waitpid(%d)\n", pid); 116*d7ff2dedSPeter Holm } 117*d7ff2dedSPeter Holm 118*d7ff2dedSPeter Holm n = kevent(kq, NULL, 0, ev, 1, &ts); 119*d7ff2dedSPeter Holm if (n == -1) 120*d7ff2dedSPeter Holm err(1, "kevent()"); 121*d7ff2dedSPeter Holm close(fd); 122*d7ff2dedSPeter Holm close(kq); 123*d7ff2dedSPeter Holm 124*d7ff2dedSPeter Holm _exit(0); 125*d7ff2dedSPeter Holm} 126*d7ff2dedSPeter Holm 127*d7ff2dedSPeter Holmint 128*d7ff2dedSPeter Holmmain(void) 129*d7ff2dedSPeter Holm{ 130*d7ff2dedSPeter Holm pid_t pids[PARALLEL]; 131*d7ff2dedSPeter Holm size_t len; 132*d7ff2dedSPeter Holm time_t start; 133*d7ff2dedSPeter Holm int e, fd, i, status; 134*d7ff2dedSPeter Holm 135*d7ff2dedSPeter Holm e = 0; 136*d7ff2dedSPeter Holm len = PAGE_SIZE; 137*d7ff2dedSPeter Holm loops = 0; 138*d7ff2dedSPeter Holm if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 139*d7ff2dedSPeter Holm MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 140*d7ff2dedSPeter Holm err(1, "mmap"); 141*d7ff2dedSPeter Holm 142*d7ff2dedSPeter Holm start = time(NULL); 143*d7ff2dedSPeter Holm while ((time(NULL) - start) < RUNTIME && e == 0) { 144*d7ff2dedSPeter Holm loops++; 145*d7ff2dedSPeter Holm if ((fd = open(file, O_CREAT | O_TRUNC | O_RDWR, 0660)) == 146*d7ff2dedSPeter Holm -1) 147*d7ff2dedSPeter Holm err(1, "open(%s)", file); 148*d7ff2dedSPeter Holm close(fd); 149*d7ff2dedSPeter Holm share[SYNC] = 0; 150*d7ff2dedSPeter Holm for (i = 0; i < PARALLEL; i++) { 151*d7ff2dedSPeter Holm 152*d7ff2dedSPeter Holm if ((pids[i] = fork()) == 0) 153*d7ff2dedSPeter Holm test(); 154*d7ff2dedSPeter Holm if (pids[i] == -1) 155*d7ff2dedSPeter Holm err(1, "fork()"); 156*d7ff2dedSPeter Holm } 157*d7ff2dedSPeter Holm while (share[SYNC] != PARALLEL) 158*d7ff2dedSPeter Holm usleep(10000); 159*d7ff2dedSPeter Holm if (unlink(file) == -1) 160*d7ff2dedSPeter Holm err(1, "unlink(%s). %s:%d\n", file, 161*d7ff2dedSPeter Holm __FILE__, __LINE__); 162*d7ff2dedSPeter Holm for (i = 0; i < PARALLEL; i++) { 163*d7ff2dedSPeter Holm if (waitpid(pids[i], &status, 0) == -1) 164*d7ff2dedSPeter Holm err(1, "waitpid(%d)", pids[i]); 165*d7ff2dedSPeter Holm if (status != 0) { 166*d7ff2dedSPeter Holm if (WIFSIGNALED(status)) 167*d7ff2dedSPeter Holm fprintf(stderr, 168*d7ff2dedSPeter Holm "pid %d exit signal %d\n", 169*d7ff2dedSPeter Holm pids[i], WTERMSIG(status)); 170*d7ff2dedSPeter Holm } 171*d7ff2dedSPeter Holm e += status == 0 ? 0 : 1; 172*d7ff2dedSPeter Holm } 173*d7ff2dedSPeter Holm } 174*d7ff2dedSPeter Holm 175*d7ff2dedSPeter Holm return (e); 176*d7ff2dedSPeter Holm} 177