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