18a272653SPeter Holm#!/bin/sh 28a272653SPeter Holm 38a272653SPeter Holm# 48a272653SPeter Holm# Copyright (c) 2013 EMC Corp. 58a272653SPeter Holm# All rights reserved. 68a272653SPeter Holm# 78a272653SPeter Holm# Redistribution and use in source and binary forms, with or without 88a272653SPeter Holm# modification, are permitted provided that the following conditions 98a272653SPeter Holm# are met: 108a272653SPeter Holm# 1. Redistributions of source code must retain the above copyright 118a272653SPeter Holm# notice, this list of conditions and the following disclaimer. 128a272653SPeter Holm# 2. Redistributions in binary form must reproduce the above copyright 138a272653SPeter Holm# notice, this list of conditions and the following disclaimer in the 148a272653SPeter Holm# documentation and/or other materials provided with the distribution. 158a272653SPeter Holm# 168a272653SPeter Holm# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 178a272653SPeter Holm# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 188a272653SPeter Holm# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 198a272653SPeter Holm# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 208a272653SPeter Holm# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 218a272653SPeter Holm# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 228a272653SPeter Holm# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 238a272653SPeter Holm# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 248a272653SPeter Holm# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 258a272653SPeter Holm# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 268a272653SPeter Holm# SUCH DAMAGE. 278a272653SPeter Holm# 288a272653SPeter Holm 298a272653SPeter Holm# Consume VM radix nodes 308a272653SPeter Holm 318a272653SPeter Holm# "panic: default pager with handle" seen with WiP kernel code. 328a272653SPeter Holm# https://people.freebsd.org/~pho/stress/log/kostik1243.txt 338a272653SPeter Holm 348616f8afSPeter Holm# "panic: ASan: Invalid access, 8-byte read at ..., MallocRedZone(fb)" seen 358616f8afSPeter Holm 368a272653SPeter Holm[ `sysctl vm.swap_total | sed 's/.* //'` -eq 0 ] && exit 0 378a272653SPeter Holm 388a272653SPeter Holm. ../default.cfg 398a272653SPeter Holm 408616f8afSPeter Holmlog=/tmp/radix.log 418a272653SPeter Holmdir=/tmp 428a272653SPeter Holmodir=`pwd` 438a272653SPeter Holmcd $dir 448a272653SPeter Holmsed '1,/^EOF/d' < $odir/$0 > $dir/radix.c 458a272653SPeter Holmmycc -o radix -Wall -Wextra radix.c || exit 1 468a272653SPeter Holmrm -f radix.c 478a272653SPeter Holmcd $odir 488a272653SPeter Holm 49*0ec1bbe5SPeter Holmset -u 506b0ab595SPeter Holmtrap "rm -f rendezvous" EXIT INT 518a272653SPeter Holmparallel=1 528a272653SPeter Holmusermem=`sysctl hw.usermem | sed 's/.* //'` 538a272653SPeter Holmpagesize=`pagesize` 548a272653SPeter Holmstart=`date +%s` 558a272653SPeter Holmwhile true; do 56*0ec1bbe5SPeter Holm timeout 20m /tmp/radix $parallel > $log; s=$? 576b0ab595SPeter Holm [ $s -eq 124 ] && { echo "Timed out"; break; } 588616f8afSPeter Holm [ $s -ne 0 ] && cat $log 598616f8afSPeter Holm used=`awk '{print $4}' < $log` 608a272653SPeter Holm [ -z "$used" ] && break 618a272653SPeter Holm [ $((`date +%s` - start)) -gt 300 ] && break 628a272653SPeter Holm [ $used -gt $((usermem / pagesize)) ] && break 638a272653SPeter Holm [ $parallel -eq 1 ] && 648a272653SPeter Holm parallel=$((usermem / pagesize / used)) 658a272653SPeter Holm parallel=$((parallel + 1)) 66*0ec1bbe5SPeter Holm [ $parallel -gt 10 ] && parallel=10 678a272653SPeter Holmdone 688a272653SPeter Holmcat /tmp/radix.log 698a272653SPeter Holm 708616f8afSPeter Holmrm -f /tmp/radix $log 718616f8afSPeter Holmexit $s 728a272653SPeter Holm 738a272653SPeter HolmEOF 748a272653SPeter Holm/* 758a272653SPeter Holm On Wed, 17 Apr 2013 18:57:00 -0500 alc wrote: 768a272653SPeter Holm 778a272653SPeter Holm Suppose that I write a program for i386 that creates giant VM objects, 788a272653SPeter Holm perhaps, using shm_open() + ftruncate(), and touches pages 0, 1, 8, 9, 798a272653SPeter Holm 64, 65, 72, 73, 512, 513, 520, 521, 576, 577, 584, 585, 4096, 4097, 808a272653SPeter Holm 4104, 4105, ... in each of the VM objects. (The sequence would be 818a272653SPeter Holm different on amd64.) I could work around the 32-bit address space 828a272653SPeter Holm limitation by mmap(2)ing and munmap(2)ing windows onto a VM object. 838a272653SPeter Holm Each of the VM objects would have only one less interior node in the 848a272653SPeter Holm radix tree than pages. If I create enough of these VM objects, then I 858a272653SPeter Holm can consume all of the available pages and an almost equal number of 868a272653SPeter Holm interior nodes. (Maybe it's worth writing this program so that some 878a272653SPeter Holm experiments could be done?) 888a272653SPeter Holm*/ 898a272653SPeter Holm 908a272653SPeter Holm#include <sys/param.h> 918a272653SPeter Holm 928a272653SPeter Holm#include <err.h> 938a272653SPeter Holm#include <errno.h> 948a272653SPeter Holm#include <fcntl.h> 958a272653SPeter Holm#include <sched.h> 968a272653SPeter Holm#include <signal.h> 978a272653SPeter Holm#include <stdint.h> 988a272653SPeter Holm#include <stdio.h> 998a272653SPeter Holm#include <stdlib.h> 1008a272653SPeter Holm#include <sys/mman.h> 1018a272653SPeter Holm#include <sys/wait.h> 1028a272653SPeter Holm#include <unistd.h> 1038a272653SPeter Holm 1048a272653SPeter Holm#ifdef __LP64__ 1058a272653SPeter Holm#define WIDTH 4 1068a272653SPeter Holm#else 1078a272653SPeter Holm#define WIDTH 3 1088a272653SPeter Holm#endif 1098a272653SPeter Holm#define N (int)howmany(sizeof(uint64_t) * NBBY, WIDTH) 1108a272653SPeter Holm 1118a272653SPeter Holmtypedef uint64_t state_t[N]; 1128a272653SPeter Holm 1138a272653SPeter Holmstatic uint64_t pgs; 1148a272653SPeter Holmstatic int fds[2]; 1158a272653SPeter Holmstatic int parallel; 1168a272653SPeter Holmstatic volatile sig_atomic_t s1; 1178a272653SPeter Holmstatic int ps; 1188a272653SPeter Holm 1198a272653SPeter Holmstatic void 1208a272653SPeter Holminit(state_t state) 1218a272653SPeter Holm{ 1228a272653SPeter Holm int i; 1238a272653SPeter Holm 1248a272653SPeter Holm for (i = 0; i < N; i++) 1258a272653SPeter Holm state[i] = 0; 1268a272653SPeter Holm} 1278a272653SPeter Holm 1288a272653SPeter Holmstatic uint64_t 1298a272653SPeter Holmgenerator(state_t state) 1308a272653SPeter Holm{ 1318a272653SPeter Holm uint64_t value; 1328a272653SPeter Holm int i; 1338a272653SPeter Holm 1348a272653SPeter Holm value = 0; 1358a272653SPeter Holm for (i = 0; i < N; i++) 1368a272653SPeter Holm value += state[i] << (i * WIDTH); 1378a272653SPeter Holm for (i = 0; i < N; i++) 1388a272653SPeter Holm if (state[i] == 0) 1398a272653SPeter Holm break; 1408a272653SPeter Holm if (i < N) 1418a272653SPeter Holm state[i]++; 1428a272653SPeter Holm for (i--; i >= 0; i--) 1438a272653SPeter Holm state[i]--; 1448a272653SPeter Holm return (value); 1458a272653SPeter Holm} 1468a272653SPeter Holm 1478a272653SPeter Holmstatic int 1488a272653SPeter Holmwr(int fd, off_t pno) 1498a272653SPeter Holm{ 1508a272653SPeter Holm off_t len, offset; 1518a272653SPeter Holm void *p; 1528a272653SPeter Holm 1538a272653SPeter Holm offset = pno * ps; 1548a272653SPeter Holm len = ps; 1558a272653SPeter Holm p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_NOSYNC, 1568a272653SPeter Holm fd, offset); 1578a272653SPeter Holm if (p == MAP_FAILED) { 1588a272653SPeter Holm if (errno == ENOMEM) 1598a272653SPeter Holm return (1); 1608a272653SPeter Holm err(1, "mmap(len 0x%jx, offset 0x%jx). %s:%d", len, offset, 1618a272653SPeter Holm __FILE__, __LINE__); 1628a272653SPeter Holm } 1638a272653SPeter Holm *(char *)p = 1; 1648a272653SPeter Holm pgs++; 1658a272653SPeter Holm 1668a272653SPeter Holm return (0); 1678a272653SPeter Holm} 1688a272653SPeter Holm 1698a272653SPeter Holmstatic void 1708a272653SPeter Holmhandler(int s __unused) 1718a272653SPeter Holm{ 1728a272653SPeter Holm s1++; 1738a272653SPeter Holm} 1748a272653SPeter Holm 1758a272653SPeter Holmstatic void 1768a272653SPeter Holmihandler(int s __unused) 1778a272653SPeter Holm{ 1788616f8afSPeter Holm _exit(1); 1798a272653SPeter Holm} 1808a272653SPeter Holm 1818a272653SPeter Holmstatic int 1828a272653SPeter Holmradix(void) 1838a272653SPeter Holm{ 1848a272653SPeter Holm FILE *f; 1858a272653SPeter Holm int r; 1868a272653SPeter Holm 1878a272653SPeter Holm if ((f = popen("vmstat -z | grep RADIX | awk -F',' '{print $3}'", "r")) == NULL) 1888a272653SPeter Holm err(1, "popen"); 1898a272653SPeter Holm fscanf(f, "%d", &r); 1908a272653SPeter Holm pclose(f); 1918a272653SPeter Holm 1928a272653SPeter Holm return (r); 1938a272653SPeter Holm} 1948a272653SPeter Holm 1958a272653SPeter Holmstatic void 1968a272653SPeter Holmtest(void) 1978a272653SPeter Holm{ 1988a272653SPeter Holm state_t state; 1998a272653SPeter Holm off_t offset; 2008616f8afSPeter Holm int fd, i; 2018a272653SPeter Holm 2028a272653SPeter Holm signal(SIGHUP, ihandler); 2038a272653SPeter Holm for (;;) { 2048a272653SPeter Holm if (access("rendezvous", R_OK) == 0) 2058a272653SPeter Holm break; 2068a272653SPeter Holm usleep(2000); 2078a272653SPeter Holm } 2088a272653SPeter Holm 2098a272653SPeter Holm if ((fd = open("/dev/zero", O_RDWR)) == -1) 2108a272653SPeter Holm err(1, "open()"); 2118a272653SPeter Holm 2128a272653SPeter Holm init(state); 2138a272653SPeter Holm offset = generator(state); 2148a272653SPeter Holm do { 2158a272653SPeter Holm if (wr(fd, offset) != 0) 2168a272653SPeter Holm break; 2178a272653SPeter Holm offset = generator(state); 2188a272653SPeter Holm } while (offset != 0); 2198a272653SPeter Holm 2208a272653SPeter Holm if (write(fds[1], &pgs, sizeof(pgs)) != sizeof(pgs)) 2218a272653SPeter Holm err(1, "ewrite pipe"); 2228a272653SPeter Holm kill(getppid(), SIGHUP); 2238616f8afSPeter Holm for (i = 0; i < 180; i++) 2248a272653SPeter Holm sleep(1); 2258a272653SPeter Holm close(fd); 2268a272653SPeter Holm 2278a272653SPeter Holm _exit(0); 2288a272653SPeter Holm} 2298a272653SPeter Holm 2308a272653SPeter Holmint 2318a272653SPeter Holmmain(int argc, char **argv) 2328a272653SPeter Holm{ 2338a272653SPeter Holm uint64_t pages; 2348a272653SPeter Holm pid_t *pids; 2358a272653SPeter Holm int i, r1, r2, rfd; 2368a272653SPeter Holm 2378a272653SPeter Holm if (argc != 2) 2388a272653SPeter Holm errx(1, "Usage: %s <number of parallel processes>.", argv[0]); 2398a272653SPeter Holm parallel = atoi(argv[1]); 2408a272653SPeter Holm 2418a272653SPeter Holm ps = getpagesize(); 2428616f8afSPeter Holm signal(SIGALRM, ihandler); 2438a272653SPeter Holm signal(SIGHUP, handler); 2448a272653SPeter Holm unlink("rendezvous"); 2458a272653SPeter Holm pids = malloc(parallel * sizeof(pid_t)); 2468a272653SPeter Holm if (pipe(fds) == -1) 2478a272653SPeter Holm err(1, "pipe"); 2488a272653SPeter Holm r1 = radix(); 2498a272653SPeter Holm for (i = 0; i < parallel; i++) { 2508a272653SPeter Holm if ((pids[i] = fork()) == 0) 2518a272653SPeter Holm test(); 2528a272653SPeter Holm } 2538a272653SPeter Holm if ((rfd = open("rendezvous", O_CREAT, 0644)) == -1) 2548a272653SPeter Holm err(1, "open()"); 2558a272653SPeter Holm close(rfd); 2568616f8afSPeter Holm alarm(300); 2578616f8afSPeter Holm while (s1 != parallel) { 2588a272653SPeter Holm usleep(10000); 2598616f8afSPeter Holm } 2608a272653SPeter Holm r2 = radix(); 2618a272653SPeter Holm pages = 0; 2628a272653SPeter Holm for (i = 0; i < parallel; i++) { 2638a272653SPeter Holm kill(pids[i], SIGHUP); 2648a272653SPeter Holm if (read(fds[0], &pgs, sizeof(pgs)) != sizeof(pgs)) 2658a272653SPeter Holm err(1, "read pipe"); 2668a272653SPeter Holm pages += pgs; 2678a272653SPeter Holm } 2688616f8afSPeter Holm fprintf(stdout, "A total of %jd pages (%.1f MB) touched, %d" 2698a272653SPeter Holm " RADIX nodes used, p/r = %.1f, parallel = %d.\n", 2708a272653SPeter Holm pages, pages * ps / 1024. / 1024, r2 - r1, 2718a272653SPeter Holm pages / (r2 - r1 + 0.), parallel); 2728a272653SPeter Holm 2738a272653SPeter Holm for (i = 0; i < parallel; i++) { 2748a272653SPeter Holm wait(NULL); 2758a272653SPeter Holm } 2768a272653SPeter Holm unlink("rendezvous"); 2778a272653SPeter Holm return (0); 2788a272653SPeter Holm} 279