xref: /dragonfly/test/stress/stress2/misc/cdevsw.sh (revision 9348a738)
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 patch for Giant trick in cdevsw
34
35exit 	# Test moved to fpclone*.sh
36
37[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
38
39. ../default.cfg
40
41odir=`pwd`
42dir=$RUNDIR/tclone
43[ ! -d $dir ] && mkdir -p $dir
44
45cd $dir
46cat > Makefile <<EOF
47KMOD= tclone
48SRCS= tclone.c
49
50.include <bsd.kmod.mk>
51EOF
52
53sed '1,/^EOF2/d' < $odir/$0 > tclone.c
54make
55kldload $dir/tclone.ko
56
57cd $odir
58dd if=/dev/tclone bs=1m count=5k > /dev/null 2>&1 &
59
60export runRUNTIME=2m
61cd /home/pho/stress2; ./run.sh pty.cfg
62
63kldstat
64kldunload $dir/tclone.ko
65rm -rf $dir
66exit
67
68EOF2
69/* $FreeBSD$ */
70
71#include <sys/param.h>
72#include <sys/systm.h>
73#include <sys/kernel.h>
74#include <sys/module.h>
75#include <sys/conf.h>
76#include <sys/uio.h>
77#include <sys/malloc.h>
78
79static d_open_t		tclone_open;
80static d_close_t	tclone_close;
81static d_read_t		tclone_read;
82
83static struct cdevsw tclone_cdevsw = {
84	.d_open =	tclone_open,
85	.d_close =	tclone_close,
86	.d_read =	tclone_read,
87	.d_name =	"tclone",
88	.d_version =	D_VERSION,
89	.d_flags =	D_TRACKCLOSE|D_NEEDGIANT
90};
91
92static eventhandler_tag tclone_ehtag;
93static struct clonedevs *tclone_clones;
94
95MALLOC_DEFINE(M_TCLONESC, "tclone memory", "tclone memory");
96
97struct tclone_sc
98{
99	int pos;
100};
101
102static void
103tclone_clone(void *arg, struct ucred *cred,
104	     char *name, int namelen, struct cdev **dev)
105{
106	int i, clone;
107
108	if (*dev != NULL)
109		return;
110	if (strcmp(name, "tclone") != 0)
111		return;
112
113	clone = 0;
114	do {
115		i = clone_create(&tclone_clones, &tclone_cdevsw,
116				 &clone, dev, 0);
117		if (i == 0)
118			clone++;
119	} while ((clone <= CLONE_UNITMASK) && (i == 0));
120
121	if ((i != 0) && (clone <= CLONE_UNITMASK)) {
122		*dev = make_dev_credf(MAKEDEV_REF,
123		    &tclone_cdevsw, unit2minor(clone),
124		    cred, UID_ROOT, GID_WHEEL, 0666,
125		    "tclone.%u", clone);
126		if (*dev != NULL) {
127			(*dev)->si_flags |= SI_CHEAPCLONE;
128			(*dev)->si_drv1 = (void *)1;
129		}
130	}
131}
132
133static int
134tclone_open(struct cdev *dev, int oflags, int devtype, d_thread_t *td)
135{
136	int status;
137
138	if (!dev->si_drv2) {
139		/* only allow one open() of this file */
140		dev->si_drv2 = malloc(sizeof(struct tclone_sc), M_TCLONESC,
141		    M_WAITOK | M_ZERO);
142		status = 0;
143	} else
144		status = EBUSY;
145
146	if (status == 0) {
147		/* XXX Fix me? (clear of SI_CHEAPCLONE) */
148		dev->si_flags &= ~SI_CHEAPCLONE;
149	}
150
151	return (status);
152}
153
154static int
155tclone_close(struct cdev *dev, int fflag, int devtype, d_thread_t *td)
156{
157	void *x;
158
159	x = dev->si_drv2;
160	dev->si_drv2 = &tclone_cdevsw;
161	if (x != &tclone_cdevsw)
162		free(x, M_TCLONESC);
163	destroy_dev_sched(dev);
164	return (0);
165}
166
167static char rdata[] = "tclone sample data string\n";
168
169static int
170tclone_read(struct cdev *dev, struct uio *uio, int ioflag)
171{
172	struct tclone_sc *sc;
173	int rv, amnt;
174
175	sc = dev->si_drv2;
176	rv = 0;
177	while (uio->uio_resid > 0) {
178		amnt = MIN(uio->uio_resid, sizeof(rdata) - sc->pos);
179		rv = uiomove(rdata + sc->pos, amnt, uio);
180		if (rv != 0)
181			break;
182		sc->pos += amnt;
183		sc->pos %= sizeof(rdata);
184	}
185	return (rv);
186}
187
188static int
189tclone_modevent(module_t mod, int what, void *arg)
190{
191	switch (what) {
192        case MOD_LOAD:
193		clone_setup(&tclone_clones);
194		tclone_ehtag = EVENTHANDLER_REGISTER(dev_clone,
195						     tclone_clone, 0, 0);
196		if (tclone_ehtag == NULL)
197			return ENOMEM;
198		return(0);
199
200        case MOD_UNLOAD:
201		EVENTHANDLER_DEREGISTER(dev_clone, tclone_ehtag);
202		drain_dev_clone_events();
203		clone_cleanup(&tclone_clones);
204		destroy_dev_drain(&tclone_cdevsw);
205		return (0);
206        default:
207		break;
208	}
209
210	return (0);
211}
212
213moduledata_t tclone_mdata = {
214	"tclone",
215	tclone_modevent,
216	NULL
217};
218
219DECLARE_MODULE(tclone, tclone_mdata, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
220MODULE_VERSION(tclone, 1);
221