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