1#!/bin/sh 2 3# 4# Copyright (c) 2008 Peter Holm <pho@FreeBSD.org> 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# Test scenario by kib@freebsd.org 30 31# Test of patch for Giant trick in cdevsw 32 33[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 34[ -d /usr/src/sys ] || exit 0 35builddir=`sysctl kern.version | grep @ | sed 's/.*://'` 36[ -d "$builddir" ] && export KERNBUILDDIR=$builddir || exit 0 37export SYSDIR=`echo $builddir | sed 's#/sys.*#/sys#'` 38kldstat -v | grep -q pty || { kldload pty || exit 0; } 39 40. ../default.cfg 41 42odir=`pwd` 43dir=$RUNDIR/fpclone 44[ ! -d $dir ] && mkdir -p $dir 45 46cd $dir 47cat > Makefile <<EOF 48KMOD= fpclone 49SRCS= fpclone.c 50 51.include <bsd.kmod.mk> 52EOF 53 54sed '1,/^EOF2/d' < $odir/$0 > fpclone.c 55make 56kldload $dir/fpclone.ko 57 58cd $odir 59for i in `jot 10`; do 60 dd if=/dev/fpclone bs=1m count=10 > /dev/null 2>&1 & 61done 62 63export runRUNTIME=2m 64cd ..; ./run.sh pty.cfg 65 66for i in `jot 10`; do 67 wait 68done 69kldstat 70dd if=/dev/fpclone bs=1m count=1k > /dev/null 2>&1 & 71kldunload $dir/fpclone.ko 72rm -rf $dir 73exit 74 75EOF2 76#include <sys/param.h> 77#include <sys/systm.h> 78#include <sys/kernel.h> 79#include <sys/module.h> 80#include <sys/mutex.h> 81#include <sys/conf.h> 82#include <sys/uio.h> 83#include <sys/malloc.h> 84 85static d_open_t fpclone_open; 86static d_close_t fpclone_close; 87static d_read_t fpclone_read; 88 89static struct cdevsw fpclone_cdevsw = { 90 .d_open = fpclone_open, 91 .d_close = fpclone_close, 92 .d_read = fpclone_read, 93 .d_name = "fpclone", 94 .d_version = D_VERSION, 95 .d_flags = D_TRACKCLOSE 96}; 97 98MALLOC_DEFINE(M_FPCLONESC, "fpclone memory", "fpclone memory"); 99 100struct fpclone_sc 101{ 102 int pos; 103}; 104 105static struct cdev *fpclone_dev; 106static struct mtx me; 107 108static void 109fpclone_cdevpriv_dtr(void *data) 110{ 111 free(data, M_FPCLONESC); 112} 113 114static int 115fpclone_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 116{ 117 struct fpclone_sc *sc; 118 int error; 119 120 sc = malloc(sizeof(struct fpclone_sc), M_FPCLONESC, 121 M_WAITOK | M_ZERO); 122 error = devfs_set_cdevpriv(sc, fpclone_cdevpriv_dtr); 123 if (error) 124 fpclone_cdevpriv_dtr(sc); 125 return (error); 126} 127 128static int 129fpclone_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 130{ 131 132 devfs_clear_cdevpriv(); 133 return (0); 134} 135 136static char rdata[] = "fpclone sample data string\n"; 137 138static int 139fpclone_read(struct cdev *dev, struct uio *uio, int ioflag) 140{ 141 struct fpclone_sc *sc; 142 int rv, amnt, svpos, error; 143 144 error = devfs_get_cdevpriv((void **)&sc); 145 if (error) 146 return (error); 147 148 rv = 0; 149 while (uio->uio_resid > 0) { 150 svpos = sc->pos; 151 amnt = MIN(uio->uio_resid, sizeof(rdata) - svpos); 152 rv = uiomove(rdata + svpos, amnt, uio); 153 if (rv != 0) 154 break; 155 mtx_lock(&me); 156 sc->pos += amnt; 157 sc->pos %= sizeof(rdata); 158 mtx_unlock(&me); 159 } 160 return (rv); 161} 162 163static int 164fpclone_modevent(module_t mod, int what, void *arg) 165{ 166 switch (what) { 167 case MOD_LOAD: 168 mtx_init(&me, "fp_ref", NULL, MTX_DEF); 169 fpclone_dev = make_dev(&fpclone_cdevsw, 0, 0, 0, 0666, 170 "fpclone"); 171 return(0); 172 173 case MOD_UNLOAD: 174 destroy_dev(fpclone_dev); 175 mtx_destroy(&me); 176 return (0); 177 178 default: 179 break; 180 } 181 182 return (0); 183} 184 185moduledata_t fpclone_mdata = { 186 "fpclone", 187 fpclone_modevent, 188 NULL 189}; 190 191DECLARE_MODULE(fpclone, fpclone_mdata, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); 192MODULE_VERSION(fpclone, 1); 193