1#!/bin/sh 2 3# 4# Copyright (c) 2014 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# Test allocation with 1GB 31 32# "panic: Bad link elm 0x6766fbc next->prev != elm" seen: 33# https://people.freebsd.org/~pho/stress/log/kostik1094.txt 34# Fixed by r331247 35 36[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 37[ -d /usr/src/sys ] || exit 0 38builddir=`sysctl kern.version | grep @ | sed 's/.*://'` 39[ -d "$builddir" ] && export KERNBUILDDIR=$builddir || exit 0 40export SYSDIR=`echo $builddir | sed 's#/sys.*#/sys#'` 41 42. ../default.cfg 43 44odir=`pwd` 45dir=/tmp/contigmalloc 46rm -rf $dir; mkdir -p $dir 47cat > $dir/ctest.c <<EOF 48#include <sys/param.h> 49#include <sys/syscall.h> 50 51#include <err.h> 52#include <stdio.h> 53#include <stdlib.h> 54#include <time.h> 55#include <unistd.h> 56 57#define MAXBUF (1LL * 1024 * 1024 * 1024) /* Max buffer size */ 58#define TALLOC 1 59#define TFREE 2 60 61void 62test(int argc, char *argv[]) 63{ 64 long mw, size; 65 int i, no, ps, res; 66 char *cp; 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 if (mw < MAXBUF / ps) { 77 fprintf(stderr, "max_user_wired too small for this test\n"); 78 exit (0); 79 } 80 i = 0; 81 size = round_page(MAXBUF); 82 res = syscall(no, TALLOC, &cp, &size); 83 if (res == -1) { 84 err(1, "contigmalloc(%lu MB) failed", 85 size / 1024 / 1024); 86 } else { 87#if defined(TEST) 88 fprintf(stderr, "contigmalloc(%lu pages) %luMB\n", 89 size / ps, size / 1024 / 1024); 90#endif 91 } 92 93 res = syscall(no, TFREE, &cp, &size); 94#if defined(TEST) 95 fprintf(stderr, "contigfree(%lu pages) %luMB\n", 96 size / ps, size / 1024 / 1024); 97#endif 98} 99 100int 101main(int argc, char *argv[]) 102{ 103 104 test(argc, argv); 105 106 return (0); 107} 108 109EOF 110mycc -o /tmp/ctest -Wall -Wextra -O0 -g $dir/ctest.c || exit 1 111rm $dir/ctest.c 112 113cd $dir 114cat > Makefile <<EOF 115KMOD= cmalloc 116SRCS= cmalloc.c 117 118.include <bsd.kmod.mk> 119EOF 120 121sed '1,/^EOF2/d' < $odir/$0 > cmalloc.c 122make || exit 1 123kldload $dir/cmalloc.ko || exit 1 124 125cd $odir 126mw=`sysctl -n vm.max_user_wired` || exit 1 127/tmp/ctest `sysctl -n debug.cmalloc_offset` $mw 2>&1 | tail -5 128kldunload $dir/cmalloc.ko 129rm -rf $dir /tmp/ctest 130exit 0 131 132EOF2 133#include <sys/param.h> 134#include <sys/kernel.h> 135#include <sys/malloc.h> 136#include <sys/module.h> 137#include <sys/proc.h> 138#include <sys/sysctl.h> 139#include <sys/sysent.h> 140#include <sys/sysproto.h> 141#include <sys/systm.h> 142 143#define TALLOC 1 144#define TFREE 2 145 146/* 147 * Hook up a syscall for contigmalloc testing. 148 */ 149 150struct cmalloc_args { 151 int a_op; 152 void *a_ptr; 153 void *a_size; 154}; 155 156static int 157cmalloc(struct thread *td, struct cmalloc_args *uap) 158{ 159 void *p; 160 unsigned long size; 161 int error; 162 163 error = copyin(uap->a_size, &size, sizeof(size)); 164 if (error != 0) { 165 return (error); 166 } 167 switch (uap->a_op) { 168 case TFREE: 169 error = copyin(uap->a_ptr, &p, sizeof(p)); 170 if (error == 0) { 171 if (p != NULL) 172 contigfree(p, size, M_TEMP); 173 } 174 return (error); 175 176 case TALLOC: 177 p = contigmalloc(size, M_TEMP, M_NOWAIT, 0ul, ~0ul, 4096, 0); 178 if (p != NULL) { 179 error = copyout(&p, uap->a_ptr, sizeof(p)); 180 return (error); 181 } 182 return (ENOMEM); 183 } 184 return (EINVAL); 185} 186 187/* 188 * The sysent for the new syscall 189 */ 190static struct sysent cmalloc_sysent = { 191 .sy_narg = 3, /* sy_narg */ 192 .sy_call = (sy_call_t *) cmalloc /* sy_call */ 193}; 194 195/* 196 * The offset in sysent where the syscall is allocated. 197 */ 198static int cmalloc_offset = NO_SYSCALL; 199 200SYSCTL_INT(_debug, OID_AUTO, cmalloc_offset, CTLFLAG_RD, &cmalloc_offset, 0, 201 "cmalloc syscall number"); 202 203/* 204 * The function called at load/unload. 205 */ 206 207static int 208cmalloc_load(struct module *module, int cmd, void *arg) 209{ 210 int error = 0; 211 212 switch (cmd) { 213 case MOD_LOAD : 214 break; 215 case MOD_UNLOAD : 216 break; 217 default : 218 error = EOPNOTSUPP; 219 break; 220 } 221 return (error); 222} 223 224SYSCALL_MODULE(cmalloc_syscall, &cmalloc_offset, &cmalloc_sysent, 225 cmalloc_load, NULL); 226