1*c2b51333SPeter Holm#!/bin/sh 2*c2b51333SPeter Holm 3*c2b51333SPeter Holm# 4*c2b51333SPeter Holm# Copyright (c) 2026 Peter Holm <pho@FreeBSD.org> 5*c2b51333SPeter Holm# 6*c2b51333SPeter Holm# SPDX-License-Identifier: BSD-2-Clause 7*c2b51333SPeter Holm# 8*c2b51333SPeter Holm 9*c2b51333SPeter Holm# sendfile over tmpfs 10*c2b51333SPeter Holm 11*c2b51333SPeter Holm# "panic: vm_page_assert_busied: page 0xfffffe000015fb88 not busy @ ../../../vm/vm_page.c:5845" seen 12*c2b51333SPeter Holm# Triggered by: 72ddb6de1028 - main - unix: increase net.local.(stream|seqpacket).(recv|send)space to 64 KiB 13*c2b51333SPeter Holm# Fixed by: d198ad51ea73 - main - swap_pager_getpages(): some pages from ma[] might be bogus 14*c2b51333SPeter Holm 15*c2b51333SPeter Holm[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 16*c2b51333SPeter Holm[ `sysctl -n vm.swap_total` -eq 0 ] && exit 0 17*c2b51333SPeter Holm 18*c2b51333SPeter Holm. ../default.cfg 19*c2b51333SPeter Holm 20*c2b51333SPeter Holmprog=$(basename "$0" .sh) 21*c2b51333SPeter Holm 22*c2b51333SPeter Holmcat > /tmp/$prog.c <<EOF 23*c2b51333SPeter Holm#include <sys/types.h> 24*c2b51333SPeter Holm#include <sys/fcntl.h> 25*c2b51333SPeter Holm#include <sys/mman.h> 26*c2b51333SPeter Holm#include <sys/socket.h> 27*c2b51333SPeter Holm#include <sys/stat.h> 28*c2b51333SPeter Holm#include <sys/uio.h> 29*c2b51333SPeter Holm#include <sys/wait.h> 30*c2b51333SPeter Holm 31*c2b51333SPeter Holm#include <err.h> 32*c2b51333SPeter Holm#include <errno.h> 33*c2b51333SPeter Holm#include <stdio.h> 34*c2b51333SPeter Holm#include <stdlib.h> 35*c2b51333SPeter Holm#include <unistd.h> 36*c2b51333SPeter Holm 37*c2b51333SPeter Holmstatic int use_sendfile = 1; 38*c2b51333SPeter Holm 39*c2b51333SPeter Holmint 40*c2b51333SPeter Holmmain(int argc, char *argv[]) 41*c2b51333SPeter Holm{ 42*c2b51333SPeter Holm off_t rsize, wsize, pos; 43*c2b51333SPeter Holm ssize_t n; 44*c2b51333SPeter Holm struct stat st; 45*c2b51333SPeter Holm int from, pair[2], pid, status; 46*c2b51333SPeter Holm const char *from_name; 47*c2b51333SPeter Holm char *buf, *cp; 48*c2b51333SPeter Holm 49*c2b51333SPeter Holm if (argc != 2) 50*c2b51333SPeter Holm errx(1, "Usage: %s from", argv[0]); 51*c2b51333SPeter Holm from_name = argv[1]; 52*c2b51333SPeter Holm 53*c2b51333SPeter Holm if ((from = open(from_name, O_RDONLY)) == -1) 54*c2b51333SPeter Holm err(1, "open read %s", from_name); 55*c2b51333SPeter Holm 56*c2b51333SPeter Holm if (fstat(from, &st) == -1) 57*c2b51333SPeter Holm err(1, "stat %s", from_name); 58*c2b51333SPeter Holm 59*c2b51333SPeter Holm if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) 60*c2b51333SPeter Holm err(1, "socketpair"); 61*c2b51333SPeter Holm 62*c2b51333SPeter Holm pid = fork(); 63*c2b51333SPeter Holm if (pid == -1) 64*c2b51333SPeter Holm err(1, "fork"); 65*c2b51333SPeter Holm if (pid == 0) { /* child */ 66*c2b51333SPeter Holm setproctitle("reader"); 67*c2b51333SPeter Holm close(pair[0]); 68*c2b51333SPeter Holm buf = malloc(st.st_size); 69*c2b51333SPeter Holm if (buf == NULL) 70*c2b51333SPeter Holm err(1, "malloc %jd", st.st_size); 71*c2b51333SPeter Holm pos = 0; 72*c2b51333SPeter Holm sleep(1); 73*c2b51333SPeter Holm for (;;) { 74*c2b51333SPeter Holm rsize = 413; /* arbitrary small block size */ 75*c2b51333SPeter Holm if (rsize > st.st_size - pos) 76*c2b51333SPeter Holm rsize = st.st_size - pos; 77*c2b51333SPeter Holm n = read(pair[1], buf + pos, rsize); 78*c2b51333SPeter Holm if (n == -1) 79*c2b51333SPeter Holm err(1, "read()"); 80*c2b51333SPeter Holm else if (n == 0) 81*c2b51333SPeter Holm errx(1, "Short read: Read %jd bytes out of %jd\n", 82*c2b51333SPeter Holm (intmax_t)pos, (intmax_t)st.st_size); 83*c2b51333SPeter Holm pos += n; 84*c2b51333SPeter Holm if (pos == st.st_size) 85*c2b51333SPeter Holm break; 86*c2b51333SPeter Holm } 87*c2b51333SPeter Holm close(pair[1]); 88*c2b51333SPeter Holm _exit(0); 89*c2b51333SPeter Holm } 90*c2b51333SPeter Holm setproctitle("writer"); 91*c2b51333SPeter Holm close(pair[1]); 92*c2b51333SPeter Holm 93*c2b51333SPeter Holm if (use_sendfile == 1) { 94*c2b51333SPeter Holm pos = 0; 95*c2b51333SPeter Holm for (;;) { 96*c2b51333SPeter Holm n = sendfile(from, pair[0], pos, st.st_size - pos, 97*c2b51333SPeter Holm NULL, &wsize, 0); 98*c2b51333SPeter Holm if (n == -1) { 99*c2b51333SPeter Holm if (errno != EAGAIN) 100*c2b51333SPeter Holm err(1, "sendfile()"); 101*c2b51333SPeter Holm } 102*c2b51333SPeter Holm if (wsize != st.st_size) 103*c2b51333SPeter Holm fprintf(stderr, "sendfile() wrote %jd bytes\n", (intmax_t)wsize); 104*c2b51333SPeter Holm pos += wsize; 105*c2b51333SPeter Holm if (pos == st.st_size) 106*c2b51333SPeter Holm break; 107*c2b51333SPeter Holm } 108*c2b51333SPeter Holm } else { 109*c2b51333SPeter Holm fprintf(stderr, "Not using sendfile().\n"); 110*c2b51333SPeter Holm if ((cp = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, from, 0)) == MAP_FAILED) 111*c2b51333SPeter Holm err(1, "mmap"); 112*c2b51333SPeter Holm 113*c2b51333SPeter Holm if ((n = write(pair[0], cp, st.st_size)) == -1) 114*c2b51333SPeter Holm err(1, "write()"); 115*c2b51333SPeter Holm if (n != st.st_size) 116*c2b51333SPeter Holm errx(1, "short write: %jd of %jd\n", (intmax_t)n, (intmax_t)st.st_size); 117*c2b51333SPeter Holm if (munmap(cp, st.st_size) == -1) 118*c2b51333SPeter Holm err(1, "munmap()"); 119*c2b51333SPeter Holm } 120*c2b51333SPeter Holm if (waitpid(pid, &status, 0) != pid) 121*c2b51333SPeter Holm err(1, "waitpid()"); 122*c2b51333SPeter Holm close(pair[0]); 123*c2b51333SPeter Holm 124*c2b51333SPeter Holm return (status != 0); 125*c2b51333SPeter Holm} 126*c2b51333SPeter HolmEOF 127*c2b51333SPeter Holmmycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c || exit 1 128*c2b51333SPeter Holm 129*c2b51333SPeter Holmmount | grep -q "on $mntpoint " && umount -f $mntpoint 130*c2b51333SPeter Holmmount -t tmpfs dummy $mntpoint || exit 1 131*c2b51333SPeter Holmdd if=/dev/zero of=$mntpoint/file bs=1m count=1024 status=none # 1Gb 132*c2b51333SPeter Holm 133*c2b51333SPeter Holm../testcases/swap/swap -t 5m -i 40 > /dev/null 2>&1 & 134*c2b51333SPeter Holmsleep 5 135*c2b51333SPeter Holm/tmp/$prog $mntpoint/file 136*c2b51333SPeter Holmwhile pkill swap; do :; done 137*c2b51333SPeter Holmwait 138*c2b51333SPeter Holm 139*c2b51333SPeter Holmumount $mntpoint 140*c2b51333SPeter Holmrm -f /tmp/$prog /tmp/$prog.c $diskimage 141*c2b51333SPeter Holmexit 0 142