1*86d7f5d3SJohn Marino#!/bin/sh 2*86d7f5d3SJohn Marino 3*86d7f5d3SJohn Marino# 4*86d7f5d3SJohn Marino# Copyright (c) 2008 Peter Holm <pho@FreeBSD.org> 5*86d7f5d3SJohn Marino# All rights reserved. 6*86d7f5d3SJohn Marino# 7*86d7f5d3SJohn Marino# Redistribution and use in source and binary forms, with or without 8*86d7f5d3SJohn Marino# modification, are permitted provided that the following conditions 9*86d7f5d3SJohn Marino# are met: 10*86d7f5d3SJohn Marino# 1. Redistributions of source code must retain the above copyright 11*86d7f5d3SJohn Marino# notice, this list of conditions and the following disclaimer. 12*86d7f5d3SJohn Marino# 2. Redistributions in binary form must reproduce the above copyright 13*86d7f5d3SJohn Marino# notice, this list of conditions and the following disclaimer in the 14*86d7f5d3SJohn Marino# documentation and/or other materials provided with the distribution. 15*86d7f5d3SJohn Marino# 16*86d7f5d3SJohn Marino# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17*86d7f5d3SJohn Marino# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18*86d7f5d3SJohn Marino# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19*86d7f5d3SJohn Marino# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20*86d7f5d3SJohn Marino# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21*86d7f5d3SJohn Marino# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22*86d7f5d3SJohn Marino# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23*86d7f5d3SJohn Marino# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24*86d7f5d3SJohn Marino# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25*86d7f5d3SJohn Marino# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*86d7f5d3SJohn Marino# SUCH DAMAGE. 27*86d7f5d3SJohn Marino# 28*86d7f5d3SJohn Marino# $FreeBSD$ 29*86d7f5d3SJohn Marino# 30*86d7f5d3SJohn Marino 31*86d7f5d3SJohn Marino# Test scenario by kib@freebsd.org 32*86d7f5d3SJohn Marino 33*86d7f5d3SJohn Marino# Test of patch for Giant trick in cdevsw 34*86d7f5d3SJohn Marino 35*86d7f5d3SJohn Marinoexit # Test moved to fpclone*.sh 36*86d7f5d3SJohn Marino 37*86d7f5d3SJohn Marino[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 38*86d7f5d3SJohn Marino 39*86d7f5d3SJohn Marino. ../default.cfg 40*86d7f5d3SJohn Marino 41*86d7f5d3SJohn Marinoodir=`pwd` 42*86d7f5d3SJohn Marinodir=$RUNDIR/tclone 43*86d7f5d3SJohn Marino[ ! -d $dir ] && mkdir -p $dir 44*86d7f5d3SJohn Marino 45*86d7f5d3SJohn Marinocd $dir 46*86d7f5d3SJohn Marinocat > Makefile <<EOF 47*86d7f5d3SJohn MarinoKMOD= tclone 48*86d7f5d3SJohn MarinoSRCS= tclone.c 49*86d7f5d3SJohn Marino 50*86d7f5d3SJohn Marino.include <bsd.kmod.mk> 51*86d7f5d3SJohn MarinoEOF 52*86d7f5d3SJohn Marino 53*86d7f5d3SJohn Marinosed '1,/^EOF2/d' < $odir/$0 > tclone.c 54*86d7f5d3SJohn Marinomake 55*86d7f5d3SJohn Marinokldload $dir/tclone.ko 56*86d7f5d3SJohn Marino 57*86d7f5d3SJohn Marinocd $odir 58*86d7f5d3SJohn Marinodd if=/dev/tclone bs=1m count=5k > /dev/null 2>&1 & 59*86d7f5d3SJohn Marino 60*86d7f5d3SJohn Marinoexport runRUNTIME=2m 61*86d7f5d3SJohn Marinocd /home/pho/stress2; ./run.sh pty.cfg 62*86d7f5d3SJohn Marino 63*86d7f5d3SJohn Marinokldstat 64*86d7f5d3SJohn Marinokldunload $dir/tclone.ko 65*86d7f5d3SJohn Marinorm -rf $dir 66*86d7f5d3SJohn Marinoexit 67*86d7f5d3SJohn Marino 68*86d7f5d3SJohn MarinoEOF2 69*86d7f5d3SJohn Marino/* $FreeBSD$ */ 70*86d7f5d3SJohn Marino 71*86d7f5d3SJohn Marino#include <sys/param.h> 72*86d7f5d3SJohn Marino#include <sys/systm.h> 73*86d7f5d3SJohn Marino#include <sys/kernel.h> 74*86d7f5d3SJohn Marino#include <sys/module.h> 75*86d7f5d3SJohn Marino#include <sys/conf.h> 76*86d7f5d3SJohn Marino#include <sys/uio.h> 77*86d7f5d3SJohn Marino#include <sys/malloc.h> 78*86d7f5d3SJohn Marino 79*86d7f5d3SJohn Marinostatic d_open_t tclone_open; 80*86d7f5d3SJohn Marinostatic d_close_t tclone_close; 81*86d7f5d3SJohn Marinostatic d_read_t tclone_read; 82*86d7f5d3SJohn Marino 83*86d7f5d3SJohn Marinostatic struct cdevsw tclone_cdevsw = { 84*86d7f5d3SJohn Marino .d_open = tclone_open, 85*86d7f5d3SJohn Marino .d_close = tclone_close, 86*86d7f5d3SJohn Marino .d_read = tclone_read, 87*86d7f5d3SJohn Marino .d_name = "tclone", 88*86d7f5d3SJohn Marino .d_version = D_VERSION, 89*86d7f5d3SJohn Marino .d_flags = D_TRACKCLOSE|D_NEEDGIANT 90*86d7f5d3SJohn Marino}; 91*86d7f5d3SJohn Marino 92*86d7f5d3SJohn Marinostatic eventhandler_tag tclone_ehtag; 93*86d7f5d3SJohn Marinostatic struct clonedevs *tclone_clones; 94*86d7f5d3SJohn Marino 95*86d7f5d3SJohn MarinoMALLOC_DEFINE(M_TCLONESC, "tclone memory", "tclone memory"); 96*86d7f5d3SJohn Marino 97*86d7f5d3SJohn Marinostruct tclone_sc 98*86d7f5d3SJohn Marino{ 99*86d7f5d3SJohn Marino int pos; 100*86d7f5d3SJohn Marino}; 101*86d7f5d3SJohn Marino 102*86d7f5d3SJohn Marinostatic void 103*86d7f5d3SJohn Marinotclone_clone(void *arg, struct ucred *cred, 104*86d7f5d3SJohn Marino char *name, int namelen, struct cdev **dev) 105*86d7f5d3SJohn Marino{ 106*86d7f5d3SJohn Marino int i, clone; 107*86d7f5d3SJohn Marino 108*86d7f5d3SJohn Marino if (*dev != NULL) 109*86d7f5d3SJohn Marino return; 110*86d7f5d3SJohn Marino if (strcmp(name, "tclone") != 0) 111*86d7f5d3SJohn Marino return; 112*86d7f5d3SJohn Marino 113*86d7f5d3SJohn Marino clone = 0; 114*86d7f5d3SJohn Marino do { 115*86d7f5d3SJohn Marino i = clone_create(&tclone_clones, &tclone_cdevsw, 116*86d7f5d3SJohn Marino &clone, dev, 0); 117*86d7f5d3SJohn Marino if (i == 0) 118*86d7f5d3SJohn Marino clone++; 119*86d7f5d3SJohn Marino } while ((clone <= CLONE_UNITMASK) && (i == 0)); 120*86d7f5d3SJohn Marino 121*86d7f5d3SJohn Marino if ((i != 0) && (clone <= CLONE_UNITMASK)) { 122*86d7f5d3SJohn Marino *dev = make_dev_credf(MAKEDEV_REF, 123*86d7f5d3SJohn Marino &tclone_cdevsw, unit2minor(clone), 124*86d7f5d3SJohn Marino cred, UID_ROOT, GID_WHEEL, 0666, 125*86d7f5d3SJohn Marino "tclone.%u", clone); 126*86d7f5d3SJohn Marino if (*dev != NULL) { 127*86d7f5d3SJohn Marino (*dev)->si_flags |= SI_CHEAPCLONE; 128*86d7f5d3SJohn Marino (*dev)->si_drv1 = (void *)1; 129*86d7f5d3SJohn Marino } 130*86d7f5d3SJohn Marino } 131*86d7f5d3SJohn Marino} 132*86d7f5d3SJohn Marino 133*86d7f5d3SJohn Marinostatic int 134*86d7f5d3SJohn Marinotclone_open(struct cdev *dev, int oflags, int devtype, d_thread_t *td) 135*86d7f5d3SJohn Marino{ 136*86d7f5d3SJohn Marino int status; 137*86d7f5d3SJohn Marino 138*86d7f5d3SJohn Marino if (!dev->si_drv2) { 139*86d7f5d3SJohn Marino /* only allow one open() of this file */ 140*86d7f5d3SJohn Marino dev->si_drv2 = malloc(sizeof(struct tclone_sc), M_TCLONESC, 141*86d7f5d3SJohn Marino M_WAITOK | M_ZERO); 142*86d7f5d3SJohn Marino status = 0; 143*86d7f5d3SJohn Marino } else 144*86d7f5d3SJohn Marino status = EBUSY; 145*86d7f5d3SJohn Marino 146*86d7f5d3SJohn Marino if (status == 0) { 147*86d7f5d3SJohn Marino /* XXX Fix me? (clear of SI_CHEAPCLONE) */ 148*86d7f5d3SJohn Marino dev->si_flags &= ~SI_CHEAPCLONE; 149*86d7f5d3SJohn Marino } 150*86d7f5d3SJohn Marino 151*86d7f5d3SJohn Marino return (status); 152*86d7f5d3SJohn Marino} 153*86d7f5d3SJohn Marino 154*86d7f5d3SJohn Marinostatic int 155*86d7f5d3SJohn Marinotclone_close(struct cdev *dev, int fflag, int devtype, d_thread_t *td) 156*86d7f5d3SJohn Marino{ 157*86d7f5d3SJohn Marino void *x; 158*86d7f5d3SJohn Marino 159*86d7f5d3SJohn Marino x = dev->si_drv2; 160*86d7f5d3SJohn Marino dev->si_drv2 = &tclone_cdevsw; 161*86d7f5d3SJohn Marino if (x != &tclone_cdevsw) 162*86d7f5d3SJohn Marino free(x, M_TCLONESC); 163*86d7f5d3SJohn Marino destroy_dev_sched(dev); 164*86d7f5d3SJohn Marino return (0); 165*86d7f5d3SJohn Marino} 166*86d7f5d3SJohn Marino 167*86d7f5d3SJohn Marinostatic char rdata[] = "tclone sample data string\n"; 168*86d7f5d3SJohn Marino 169*86d7f5d3SJohn Marinostatic int 170*86d7f5d3SJohn Marinotclone_read(struct cdev *dev, struct uio *uio, int ioflag) 171*86d7f5d3SJohn Marino{ 172*86d7f5d3SJohn Marino struct tclone_sc *sc; 173*86d7f5d3SJohn Marino int rv, amnt; 174*86d7f5d3SJohn Marino 175*86d7f5d3SJohn Marino sc = dev->si_drv2; 176*86d7f5d3SJohn Marino rv = 0; 177*86d7f5d3SJohn Marino while (uio->uio_resid > 0) { 178*86d7f5d3SJohn Marino amnt = MIN(uio->uio_resid, sizeof(rdata) - sc->pos); 179*86d7f5d3SJohn Marino rv = uiomove(rdata + sc->pos, amnt, uio); 180*86d7f5d3SJohn Marino if (rv != 0) 181*86d7f5d3SJohn Marino break; 182*86d7f5d3SJohn Marino sc->pos += amnt; 183*86d7f5d3SJohn Marino sc->pos %= sizeof(rdata); 184*86d7f5d3SJohn Marino } 185*86d7f5d3SJohn Marino return (rv); 186*86d7f5d3SJohn Marino} 187*86d7f5d3SJohn Marino 188*86d7f5d3SJohn Marinostatic int 189*86d7f5d3SJohn Marinotclone_modevent(module_t mod, int what, void *arg) 190*86d7f5d3SJohn Marino{ 191*86d7f5d3SJohn Marino switch (what) { 192*86d7f5d3SJohn Marino case MOD_LOAD: 193*86d7f5d3SJohn Marino clone_setup(&tclone_clones); 194*86d7f5d3SJohn Marino tclone_ehtag = EVENTHANDLER_REGISTER(dev_clone, 195*86d7f5d3SJohn Marino tclone_clone, 0, 0); 196*86d7f5d3SJohn Marino if (tclone_ehtag == NULL) 197*86d7f5d3SJohn Marino return ENOMEM; 198*86d7f5d3SJohn Marino return(0); 199*86d7f5d3SJohn Marino 200*86d7f5d3SJohn Marino case MOD_UNLOAD: 201*86d7f5d3SJohn Marino EVENTHANDLER_DEREGISTER(dev_clone, tclone_ehtag); 202*86d7f5d3SJohn Marino drain_dev_clone_events(); 203*86d7f5d3SJohn Marino clone_cleanup(&tclone_clones); 204*86d7f5d3SJohn Marino destroy_dev_drain(&tclone_cdevsw); 205*86d7f5d3SJohn Marino return (0); 206*86d7f5d3SJohn Marino default: 207*86d7f5d3SJohn Marino break; 208*86d7f5d3SJohn Marino } 209*86d7f5d3SJohn Marino 210*86d7f5d3SJohn Marino return (0); 211*86d7f5d3SJohn Marino} 212*86d7f5d3SJohn Marino 213*86d7f5d3SJohn Marinomoduledata_t tclone_mdata = { 214*86d7f5d3SJohn Marino "tclone", 215*86d7f5d3SJohn Marino tclone_modevent, 216*86d7f5d3SJohn Marino NULL 217*86d7f5d3SJohn Marino}; 218*86d7f5d3SJohn Marino 219*86d7f5d3SJohn MarinoDECLARE_MODULE(tclone, tclone_mdata, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); 220*86d7f5d3SJohn MarinoMODULE_VERSION(tclone, 1); 221