PERFORCE change 95869 for review
John Birrell
jb at FreeBSD.org
Sat Apr 22 09:25:24 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=95869
Change 95869 by jb at jb_freebsd2 on 2006/04/22 09:24:24
Implement device cloning.
This works quite differently on FreeBSD than it does on Solaris.
On Solaris, the base device /dev/dtrace/dtrace is opened and it
creates a new dev_t (uint32_t) based on the current major number and
a new minor number which is allocates using the vmem-this-is-not-really-
virtual-memory-but-we-can-allocate-resource-numbers-this-way
interface and then it writes back and resets the dev_t passed to the
open() call so that the minor number changes for future calls. I don't
know what happens if you try to change the major number at the same time.
On FreeBSD, device cloning works BEFORE the open call which is passed
a struct cdev pointer which it can't change. The FreeBSD device cloning
is implemented via an event handler callback to the dtrace_clone()
function added here. That function uses the vmem-this-is-not-...etc
interface to get a manor number and a new device is created. When the
dtrace_open() function is called, the new device struct cdev pointer
is passed. Finally the dtrace_close() call has to destroy the device
(and free the vmem-this-is-not-...etc number allocated to it).
I'm not quite sure what is going on at the moment, but I see the open()
call being called twice -- first with the new minor number and then
with the base minor number (zero). This happens even if device cloning
isn't used. I think it might be a bug outside my DTrace port. Ugh.
Affected files ...
.. //depot/projects/dtrace/src/sys/cddl/dev/dtrace/dtrace.c#9 edit
.. //depot/projects/dtrace/src/sys/cddl/dev/dtrace/dtrace_clone.c#1 add
.. //depot/projects/dtrace/src/sys/cddl/dev/dtrace/dtrace_close.c#2 edit
.. //depot/projects/dtrace/src/sys/cddl/dev/dtrace/dtrace_modevent.c#3 edit
.. //depot/projects/dtrace/src/sys/cddl/dev/dtrace/dtrace_open.c#2 edit
Differences ...
==== //depot/projects/dtrace/src/sys/cddl/dev/dtrace/dtrace.c#9 (text+ko) ====
@@ -79,6 +79,7 @@
static d_open_t dtrace_open;
static int dtrace_load(void);
static int dtrace_unload(void);
+static void dtrace_clone(void *, struct ucred *, char *, int , struct cdev **);
static struct cdevsw dtrace_cdevsw = {
.d_version = D_VERSION,
@@ -158,9 +159,8 @@
/*
* DTrace Internal Variables
*/
-#ifdef DOODAD
-static dev_info_t *dtrace_devi; /* device info */
-#endif
+static struct clonedevs *dtrace_clones; /* Ptr to the array of cloned devices. */
+static eventhandler_tag eh_tag; /* Event handler tag. */
static vmem_t *dtrace_arena; /* probe ID arena */
static vmem_t *dtrace_minor; /* minor number arena */
static taskq_t *dtrace_taskq; /* task queue */
@@ -170,9 +170,6 @@
static dtrace_meta_t *dtrace_meta_pid; /* user-land meta provider */
static int dtrace_opens; /* number of opens */
static int dtrace_helpers; /* number of helpers */
-#ifdef DOODAD
-static void *dtrace_softstate; /* softstate pointer */
-#endif
static dtrace_hash_t *dtrace_bymod; /* probes hashed by module */
static dtrace_hash_t *dtrace_byfunc; /* probes hashed by function */
static dtrace_hash_t *dtrace_byname; /* probes hashed by name */
@@ -633,6 +630,7 @@
#include <cddl/dev/dtrace/dtrace_hook.c>
/* - Driver cookbook functions */
+#include <cddl/dev/dtrace/dtrace_clone.c>
#include <cddl/dev/dtrace/dtrace_close.c>
#include <cddl/dev/dtrace/dtrace_ioctl.c>
#include <cddl/dev/dtrace/dtrace_load.c>
==== //depot/projects/dtrace/src/sys/cddl/dev/dtrace/dtrace_close.c#2 (text+ko) ====
@@ -27,5 +27,13 @@
dtrace_close(struct cdev *dev __unused, int flags, int fmt __unused,
struct thread *td)
{
+ /* Check if this is a cloned device. */
+ if (minor(dev) > 0) {
+ /* XXX Do the state destruction cleanup here. */
+
+ /* Destroy the cloned device. */
+ destroy_dev(dev);
+ }
+
return (0);
}
==== //depot/projects/dtrace/src/sys/cddl/dev/dtrace/dtrace_modevent.c#3 (text+ko) ====
@@ -30,10 +30,22 @@
switch (type) {
case MOD_LOAD:
- error = dtrace_load();
+ if ((error = dtrace_load()) == 0) {
+ /* Enable device cloning. */
+ clone_setup(&dtrace_clones);
+
+ /* Setup device cloning events. */
+ eh_tag = EVENTHANDLER_REGISTER(dev_clone, dtrace_clone, 0, 1000);
+ }
break;
case MOD_UNLOAD:
+ /* De-register the device cloning event handler. */
+ EVENTHANDLER_DEREGISTER(dev_clone, eh_tag);
+
+ /* Stop device cloning. */
+ clone_cleanup(&dtrace_clones);
+
error = dtrace_unload();
break;
==== //depot/projects/dtrace/src/sys/cddl/dev/dtrace/dtrace_open.c#2 (text+ko) ====
@@ -27,5 +27,14 @@
dtrace_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
{
int error = 0;
+
+ /*
+ * The first minor device is the one that is cloned so there is
+ * nothing more to do here.
+ */
+ if (minor(dev) == 0)
+ return 0;
+
+printf("%s: struct cdev %p curthread %p si_drv0 %u\n",__FUNCTION__,dev,curthread,dev->si_drv0);
return (error);
}
More information about the p4-projects
mailing list