From owner-p4-projects@FreeBSD.ORG Sat Apr 22 09:25:24 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 9931B16A405; Sat, 22 Apr 2006 09:25:24 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 541A716A401 for ; Sat, 22 Apr 2006 09:25:24 +0000 (UTC) (envelope-from jb@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 1631843D48 for ; Sat, 22 Apr 2006 09:25:24 +0000 (GMT) (envelope-from jb@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id k3M9PNE3026031 for ; Sat, 22 Apr 2006 09:25:23 GMT (envelope-from jb@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id k3M9PNqY026028 for perforce@freebsd.org; Sat, 22 Apr 2006 09:25:23 GMT (envelope-from jb@freebsd.org) Date: Sat, 22 Apr 2006 09:25:23 GMT Message-Id: <200604220925.k3M9PNqY026028@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jb@freebsd.org using -f From: John Birrell To: Perforce Change Reviews Cc: Subject: PERFORCE change 95869 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 22 Apr 2006 09:25:24 -0000 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 /* - Driver cookbook functions */ +#include #include #include #include ==== //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); }