ether_ifdetach() races round 3(?)
John Baldwin
jhb at FreeBSD.org
Fri Nov 4 04:52:37 PST 2005
I had another moment of inspiration regarding the ether_ifdetach() races
during my shower this morning. Maybe this will gives us a viable solution
this time.
The reason we are having races is that once we call foo_stop(), the driver
state is out of sync with the ifnet state because IFF_UP is still set even
though the driver effectively has marked the interface down. The obvious
solution to that is to have the ifnet code "officially" mark the driver down
by clearing IFF_UP. This would result in foo_ioctl() calling foo_stop()
rather than foo_detach() calling it explicitly. I think this is actually
cleaner in that drivers already rely on the ifnet layer calling foo_init()
and don't call foo_init() in foo_attach(). Moving foo_stop() out of
foo_detach() and into the ifnet layer would thus be more consistent.
foo_detach() would go from:
if (device_is_attached(sc)) {
FOO_LOCK(sc);
foo_stop(sc);
FOO_UNLOCK(sc);
callout_drain(&sc->sc_stat_callout);
ether_ifdetach(sc->sc_ifp);
}
to just:
if (device_is_attached(sc)) {
ether_ifdetach(sc->sc_ifp);
callout_drain(&sc->sc_stat_callout);
}
The only question then is when should ether_ifdetach() mark the interface as
down, and this actually ends up nice as it lets us fix all the other races
with BPF and userland ioctls. Basically, we should detach the ifnet from
userland so no more userland requests can come in, then tear down kernel
consumers such as BPF, and mark the interface down resulting in an ioctl()
that clears IFF_UP and calls foo_stop().
--
John Baldwin <jhb at FreeBSD.org> <>< http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve" = http://www.FreeBSD.org
More information about the freebsd-arch
mailing list