1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5# 6# Copyright (c) 2020 Mark Johnston 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# Variation of swapoff3.sh 31 32# Deadlock seen: 33# https://people.freebsd.org/~pho/stress/log/log0005.txt 34# This is a "known" low memory deadlocks caused by using md(4) as a swap 35# device. 36 37. ../default.cfg 38[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 39dir=`dirname $diskimage` 40[ `df -k $dir | tail -1 | awk '{print $4}'` -lt \ 41 $((20 * 1024 * 1024)) ] && 42 { echo "Need 20GB on $dir"; exit 0; } 43 44cat > /tmp/swapoff5.c <<EOF 45#include <sys/param.h> 46#include <sys/mman.h> 47#include <sys/sysctl.h> 48 49#include <assert.h> 50#include <err.h> 51#include <stdlib.h> 52#include <unistd.h> 53 54int 55main(void) 56{ 57 char *addr, *naddr, *res; 58 size_t i, len, swap, vsz; 59 u_int free; 60 61 vsz = sizeof(free); 62 if (sysctlbyname("vm.stats.vm.v_free_count", &free, &vsz, NULL, 0) != 0) 63 err(1, "sysctl(vm.stats.vm.v_free_count)"); 64 vsz = sizeof(swap); 65 if (sysctlbyname("vm.swap_total", &swap, &vsz, NULL, 0) != 0) 66 err(1, "sysctl(vm.swap_total)"); 67 68 len = (size_t)free * PAGE_SIZE + swap / 4; 69 addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 70 -1, 0); 71 if (addr == MAP_FAILED) 72 err(1, "mmap"); 73 74 res = malloc(howmany(len, PAGE_SIZE)); 75 if (res == NULL) 76 err(1, "malloc"); 77 78 for (i = 0; i < len; i += PAGE_SIZE) 79 addr[i] = 1; 80 81 for (;;) { 82 if (mincore(addr, len, res) != 0) 83 err(1, "mincore"); 84 for (i = 0; i < howmany(len, PAGE_SIZE); i++) 85 if ((res[i] & MINCORE_INCORE) == 0) { 86 naddr = addr + i * PAGE_SIZE; 87 if (munmap(naddr, PAGE_SIZE) != 0) 88 err(1, "munmap"); 89 if (mmap(naddr, PAGE_SIZE, 90 PROT_READ | PROT_WRITE, 91 MAP_ANON | MAP_PRIVATE | MAP_FIXED, 92 -1, 0) == MAP_FAILED) 93 err(1, "mmap"); 94 assert(*naddr == 0); 95 *naddr = 1; 96 } 97 } 98 99 return (0); 100} 101EOF 102mycc -o /tmp/swapoff5 -Wall -Wextra -O2 -g /tmp/swapoff5.c || exit 103 104cat > /tmp/swapoff5x.c <<EOF 105#include <sys/mman.h> 106 107#include <err.h> 108#include <stdio.h> 109#include <stdlib.h> 110#include <time.h> 111 112int 113main(int argc, char *argv[]) 114{ 115 time_t start; 116 int n, r; 117 char off1[80], off2[80], on1[80], on2[80]; 118 119 if ( argc != 3) { 120 fprintf(stderr, "Usage: %s <dev1> <dev2>\n", argv[0]); 121 exit(1); 122 } 123 124 snprintf(off1, sizeof(off1), "swapoff %s", argv[1]); 125 snprintf(off2, sizeof(off2), "swapoff %s", argv[2]); 126 snprintf(on1, sizeof(on1), "swapon %s", argv[1]); 127 snprintf(on2, sizeof(on2), "swapon %s", argv[2]); 128 129 start = time(NULL); 130 if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) 131 err(1, "mlockall(MCL_CURRENT) | MCL_FUTURE"); 132 n = 0; 133 while (time(NULL) - start < 240) { 134 if ((r = system(off1)) != 0) 135 errx(1, "%s failed with %d", off1, r); 136 if ((r = system(on1)) != 0) 137 errx(1, "%s failed with %d", on1, r); 138 if ((r = system(off2)) != 0) 139 errx(1, "%s failed with %d", off2, r); 140 if ((r = system(on2)) != 0) 141 errx(1, "%s failed with %d", on2, r); 142 n++; 143 } 144 if (n < 100) 145 fprintf(stderr, "%d swapoffs\n", n); 146 147 return (0); 148} 149EOF 150mycc -o /tmp/swapoff5x -Wall -Wextra -O2 -g /tmp/swapoff5x.c || exit 151 152set -e 153md1=$mdstart 154md2=$((md1 + 1)) 155[ `sysctl -n vm.swap_total` -gt 0 ] && { swapoff -a > /dev/null; off=1; } 156truncate -s 10G $dir/swap1 157mdconfig -a -t vnode -f $dir/swap1 -u $md1 158swapon /dev/md$md1 159truncate -s 10G $dir/swap2 160mdconfig -a -t vnode -f $dir/swap2 -u $md2 161swapon /dev/md$md2 162set +e 163 164timeout 4m /tmp/swapoff5 & 165for i in `jot 60`; do 166 n=`swapinfo | tail -1 | awk '{print $3}'` 167 [ $n -gt 0 ] && break 168 sleep 1 169done 170 171/tmp/swapoff5x /dev/md$md1 /dev/md$md2 172kill $! > /dev/null 2>&1 173wait 174for dev in /dev/md$md1 /dev/md$md2; do 175 swapoff $dev 176done 177mdconfig -d -u $md1 178mdconfig -d -u $md2 179rm -f $dir/swap1 $dir/swap2 /tmp/swapoff5 /tmp/swapoff5.c /tmp/swapoff5x \ 180 /tmp/swapoff5x.c 181[ $off ] && swapon -a > /dev/null 182exit $s 183