Date: Sat, 22 Apr 2006 09:25:23 GMT From: John Birrell <jb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 95869 for review Message-ID: <200604220925.k3M9PNqY026028@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=95869 Change 95869 by jb@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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200604220925.k3M9PNqY026028>