Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Apr 2003 18:11:30 +0200 (CEST)
From:      Harti Brandt <brandt@fokus.fraunhofer.de>
To:        "Matthew N. Dodd" <mdodd@FreeBSD.ORG>
Cc:        freebsd-current@FreeBSD.ORG
Subject:   Re: LOR in if_detach 
Message-ID:  <20030411175926.U1137@beagle.fokus.fraunhofer.de>
In-Reply-To: <20030410175703.O39446@sasami.jurai.net>
References:  <200304101251.h3ACphHo021011@mta7.pltn13.pbi.net> <20030410175703.O39446@sasami.jurai.net>

next in thread | previous in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030411175926.U1137>