From owner-freebsd-current@FreeBSD.ORG Fri Apr 11 09:11:34 2003 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id F2EDC37B404; Fri, 11 Apr 2003 09:11:33 -0700 (PDT) Received: from mailhub.fokus.fraunhofer.de (mailhub.fokus.fraunhofer.de [193.174.154.14]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2DDB843F85; Fri, 11 Apr 2003 09:11:32 -0700 (PDT) (envelope-from brandt@fokus.fraunhofer.de) Received: from beagle (beagle [193.175.132.100])h3BGBUE10941; Fri, 11 Apr 2003 18:11:30 +0200 (MEST) Date: Fri, 11 Apr 2003 18:11:30 +0200 (CEST) From: Harti Brandt To: "Matthew N. Dodd" In-Reply-To: <20030410175703.O39446@sasami.jurai.net> Message-ID: <20030411175926.U1137@beagle.fokus.fraunhofer.de> References: <200304101251.h3ACphHo021011@mta7.pltn13.pbi.net> <20030410175703.O39446@sasami.jurai.net> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII cc: Jeffrey Hsu cc: freebsd-current@FreeBSD.ORG Subject: Re: LOR in if_detach X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: harti@FreeBSD.ORG List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 11 Apr 2003 16:11:34 -0000 On Thu, 10 Apr 2003, Matthew N. Dodd wrote: MND>On Thu, 10 Apr 2003, Harti Brandt wrote: MND>> What would that lock do? I mean, which, if any, of the exported driver MND>> functions would be called with that lock held? MND> MND>If we're sure that nobody will be caching our function pointers we can MND>call another helper function before if_detach() that sets the function MND>pointers to 'invalid' functions (that is, ones that return an error). Do you think of something like the following? static int if_dead_func(void *arg __unused) { return (ENXIO); } static void if_dead_input(struct ifnet *ifp __unused, struct mbuf *m) { m_freem(m); } void if_dead(struct ifnet *ifp) { ifp->if_output = (int (*)(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *))if_dead_func; ifp->if_input = if_dead_input; ifp->if_start = (void (*)(struct ifnet *))if_dead_func; ifp->if_ioctl = (int (*)(struct ifnet *, u_long, caddr_t))if_dead_func; ifp->if_watchdog = NULL; ifp->if_init = (void (*)(void *))if_dead_func; ifp->if_resolvemulti = (int (*)(struct ifnet *, struct sockaddr **, struct sockaddr *))if_dead_func; /* if_poll_* not set here, because they seem to be unused */ } To be called like: static int foo_detach(device_t dev) { ... LOCK(softc); if_dead(ifp); if (ifp->if_flags & IFF_RUNNING) foo_stop(softc); UNLOCK(softc); if_detach(ifp); ... } This seems to help for the case where another thread could enter, for example, if_ioctl just after the UNLOCK and before the if_detach. What still could happen is a thread entering ioctl just after our LOCK. It would get runnable with our UNLOCK, probably find the interface not running anymore and return an error. If the thread does this faster than the detach routine finishes and the loader unloads the module, everything is fine. But, I suppose, ensuring that no thread is in a module that is beeing unloaded is really outside the scope of the network locking. Does the above make sense? harti -- harti brandt, http://www.fokus.fraunhofer.de/research/cc/cats/employees/hartmut.brandt/private brandt@fokus.fraunhofer.de, harti@freebsd.org