xref: /freebsd/tools/test/stress2/misc/radix.sh (revision 0ec1bbe579fa1b81cbb6b7dbbbea38397a56274a)
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