1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause 5# 6# Copyright (c) 2020 Peter Holm <pho@FreeBSD.org> 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27# SUCH DAMAGE. 28# 29 30# Attempt to reproduce "vm_page_assert_xbusied: page XXXX not exclusive busy" 31# No problems seen. 32 33# Test scenario idea by markj@ 34 35. ../default.cfg 36[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 37[ `sysctl -n vm.swap_total` -eq 0 ] && exit 0 38 39dir=/tmp 40odir=`pwd` 41cd $dir 42sed '1,/^EOF/d' < $odir/$0 > $dir/mmap40.c 43mycc -o mmap40 -Wall -Wextra -O0 -g mmap40.c || exit 1 44rm -f mmap40.c 45cd $odir 46 47set -e 48mount | grep "on $mntpoint " | grep -q /dev/md && umount -f $mntpoint 49[ -c /dev/md$mdstart ] && mdconfig -d -u $mdstart 50mdconfig -a -t swap -s 2g -u $mdstart 51newfs $newfs_flags md$mdstart > /dev/null 52mount /dev/md$mdstart $mntpoint 53set +e 54 55u1=`swapinfo | tail -1 | awk '{print $3}'` 56(nice $odir/../testcases/swap/swap -t 10m -i 30 -h -l 100) > /dev/null & 57for i in `jot 120`; do 58 u2=`swapinfo | tail -1 | awk '{print $3}'` 59 [ $u2 -lt $u1 ] && u1=$u2 60 [ $((u2 - $u1)) -gt 100 ] && break 61 sleep 1 62done 63/usr/bin/timeout 10m $dir/mmap40; s=$? 64while pkill swap; do :; done 65wait 66[ -f mmap40.core -a $s -eq 0 ] && 67 { ls -l mmap40.core; mv mmap40.core $dir; s=1; } 68cd $odir 69 70for i in `jot 6`; do 71 mount | grep -q "on $mntpoint " || break 72 umount $mntpoint && break || sleep 10 73 [ $i -eq 6 ] && 74 { echo FATAL; fstat -mf $mntpoint; exit 1; } 75done 76mdconfig -d -u $mdstart 77rm -rf $dir/mmap40 78exit $s 79 80EOF 81#include <sys/param.h> 82#include <sys/mman.h> 83#include <sys/wait.h> 84 85#include <err.h> 86#include <stdlib.h> 87#include <stdio.h> 88#include <string.h> 89#include <time.h> 90#include <unistd.h> 91 92#define PARALLEL 512 93#define RUNTIME 300 94 95void 96test(void) 97{ 98 pid_t pid; 99 size_t i, len; 100 time_t start; 101 void *p; 102 char *vec; 103 104 len = 1024 * 1024; 105 if ((p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0)) == 106 MAP_FAILED) 107 err(1, "mmap"); 108 memset(p, 0, len); /* dirty the memory */ 109 if ((vec = malloc(len / PAGE_SIZE)) == NULL) 110 err(1, "malloc"); 111 112 start = time(NULL); 113 while (time(NULL) - start < RUNTIME) { 114 usleep(arc4random() % 1000); 115 if (mincore(p, len, vec) == -1) 116 err(1, "mincore"); 117 for (i = 0; i < len / PAGE_SIZE; i++) { 118 if ((vec[i] & MINCORE_MODIFIED) == 0) { 119 _exit(0); 120 } 121 } 122 if ((pid = fork()) == 0) { 123 _exit(0); 124 } 125 if (waitpid(pid, NULL, 0) != pid) 126 err(1, "waitpid)"); 127 } 128 129 _exit(0); 130} 131 132int 133main(void) 134{ 135 pid_t pids[PARALLEL]; 136 time_t start; 137 int i; 138 139 for (i = 0; i < PARALLEL; i++) { 140 if ((pids[i] = fork()) == 0) 141 test(); 142 } 143 144 start = time(NULL); 145 while (time(NULL) - start < RUNTIME) { 146 for (i = 0; i < PARALLEL; i++) { 147 if (waitpid(pids[i], NULL, WNOHANG) == pids[i]) { 148 if ((pids[i] = fork()) == 0) 149 test(); 150 } 151 } 152 } 153 154 for (i = 0; i < PARALLEL; i++) { 155 if (waitpid(pids[i], NULL, 0) != pids[i]) 156 err(1, "waitpid"); 157 } 158 159 return (0); 160} 161