1#!/bin/sh 2 3# 4# Copyright (c) 2015 EMC Corp. 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29# contigmalloc(9) / contigfree(9) test scenario. 30# Regression test for allocations >= 2 GiB. 31# "panic: vm_page_insert_after: mpred doesn't precede pindex" seen. 32# Fixed by r284207. 33 34[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 35[ -d /usr/src/sys ] || exit 0 36builddir=`sysctl kern.version | grep @ | sed 's/.*://'` 37[ -d "$builddir" ] && export KERNBUILDDIR=$builddir || exit 0 38export SYSDIR=`echo $builddir | sed 's#/sys.*#/sys#'` 39 40. ../default.cfg 41 42odir=`pwd` 43dir=/tmp/contigmalloc 44rm -rf $dir; mkdir -p $dir 45cat > $dir/ctest2.c <<EOF 46#include <sys/param.h> 47#include <sys/syscall.h> 48 49#include <err.h> 50#include <errno.h> 51#include <stdio.h> 52#include <stdlib.h> 53#include <unistd.h> 54 55#define TALLOC 1 56#define TFREE 2 57 58void *p; 59long size; 60int n; 61 62void 63test(int argc, char *argv[]) 64{ 65 long mw; 66 int no, ps, res; 67 68 if (argc == 3) { 69 no = atoi(argv[1]); 70 mw = atol(argv[2]); 71 } 72 if (argc != 3 || no == 0 || mw == 0) 73 errx(1, "Usage: %s <syscall number> <max wired>", argv[0]); 74 75 ps = getpagesize(); 76 size = mw / 100 * 80 * ps; /* Use 80% of vm.max_user_wired */ 77 while (size > 0) { 78 res = syscall(no, TALLOC, &p, &size); 79 if (res == -1) { 80 if (errno != ENOMEM) 81 warn("contigmalloc(%lu pages) failed", 82 size); 83 } else { 84#if defined(TEST) 85 fprintf(stderr, "pre contigmalloc(%lu pages): %lu MiB\n", 86 size, size * ps / 1024 / 1024); 87#endif 88 res = syscall(no, TFREE, &p, &size); 89#if defined(TEST) 90 fprintf(stderr, "contigfree(%lu pages)\n", 91 size); 92#endif 93 } 94 size /= 2; 95 } 96} 97 98int 99main(int argc, char *argv[]) 100{ 101 test(argc, argv); 102 103 return (0); 104} 105 106EOF 107mycc -o /tmp/ctest2 -Wall -Wextra -O0 -g $dir/ctest2.c || exit 1 108rm $dir/ctest2.c 109 110cd $dir 111cat > Makefile <<EOF 112KMOD= cmalloc2 113SRCS= cmalloc2.c 114 115.include <bsd.kmod.mk> 116EOF 117 118sed '1,/^EOF2/d' < $odir/$0 > cmalloc2.c 119make depend all || exit 1 120kldload $dir/cmalloc2.ko || exit 1 121 122cd $odir 123mw=$((`sysctl -n vm.max_user_wired` - \ 124 `sysctl -n vm.stats.vm.v_user_wire_count`)) || exit 1 125/tmp/ctest2 `sysctl -n debug.cmalloc_offset` $mw #2>&1 | tail -5 126kldunload $dir/cmalloc2.ko 127rm -rf $dir /tmp/ctest2 128exit 0 129 130EOF2 131#include <sys/param.h> 132#include <sys/kernel.h> 133#include <sys/malloc.h> 134#include <sys/module.h> 135#include <sys/proc.h> 136#include <sys/sysctl.h> 137#include <sys/sysent.h> 138#include <sys/sysproto.h> 139#include <sys/systm.h> 140 141#define TALLOC 1 142#define TFREE 2 143 144/* 145 * Hook up a syscall for contigmalloc testing. 146 */ 147 148struct cmalloc_args { 149 int a_op; 150 void *a_ptr; 151 void *a_size; 152}; 153 154static int 155cmalloc(struct thread *td, struct cmalloc_args *uap) 156{ 157 void *p; 158 unsigned long size; 159 int error; 160 161 error = copyin(uap->a_size, &size, sizeof(size)); 162 if (error != 0) { 163 return (error); 164 } 165 switch (uap->a_op) { 166 case TFREE: 167 error = copyin(uap->a_ptr, &p, sizeof(p)); 168 if (error == 0) { 169 if (p != NULL) 170 contigfree(p, size, M_TEMP); 171 } 172 return (error); 173 174 case TALLOC: 175 p = contigmalloc(size, M_TEMP, M_NOWAIT, 0ul, ~0ul, 4096, 0); 176 if (p != NULL) { 177 error = copyout(&p, uap->a_ptr, sizeof(p)); 178 return (error); 179 } 180 return (ENOMEM); 181 } 182 return (EINVAL); 183} 184 185/* 186 * The sysent for the new syscall 187 */ 188static struct sysent cmalloc_sysent = { 189 .sy_narg = 3, /* sy_narg */ 190 .sy_call = (sy_call_t *) cmalloc /* sy_call */ 191}; 192 193/* 194 * The offset in sysent where the syscall is allocated. 195 */ 196static int cmalloc_offset = NO_SYSCALL; 197 198SYSCTL_INT(_debug, OID_AUTO, cmalloc_offset, CTLFLAG_RD, &cmalloc_offset, 0, 199 "cmalloc syscall number"); 200 201/* 202 * The function called at load/unload. 203 */ 204 205static int 206cmalloc_load(struct module *module, int cmd, void *arg) 207{ 208 int error = 0; 209 210 switch (cmd) { 211 case MOD_LOAD : 212 break; 213 case MOD_UNLOAD : 214 break; 215 default : 216 error = EOPNOTSUPP; 217 break; 218 } 219 return (error); 220} 221 222SYSCALL_MODULE(cmalloc_syscall, &cmalloc_offset, &cmalloc_sysent, 223 cmalloc_load, NULL); 224