Add a dying flag to prevent races at detach.
I tried re-ordering ether_ifdetach(), but this created a new race where sometimes, when under heavy receive load (>1Mpps) and running tcpdump, the machine would panic. At panic, the ithread was still in the original (not dead) if_input() path, and was accessing stale BPF data structs. By using a dying flag, I can close the interface prior to if_detach() to be certain the interface cannot send packets up in the middle of ether_ifdetach.
This commit is contained in:
parent
aeb56f0662
commit
8c5d766cd7
@ -3906,6 +3906,10 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||
|
||||
case SIOCSIFFLAGS:
|
||||
mtx_lock(&sc->driver_mtx);
|
||||
if (sc->dying) {
|
||||
mtx_unlock(&sc->driver_mtx);
|
||||
return EINVAL;
|
||||
}
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
err = mxge_open(sc);
|
||||
@ -4590,6 +4594,7 @@ mxge_attach(device_t dev)
|
||||
mxge_media_status);
|
||||
mxge_set_media(sc, IFM_ETHER | IFM_AUTO);
|
||||
mxge_media_probe(sc);
|
||||
sc->dying = 0;
|
||||
ether_ifattach(ifp, sc->mac_addr);
|
||||
/* ether_ifattach sets mtu to ETHERMTU */
|
||||
if (mxge_initial_mtu != ETHERMTU)
|
||||
@ -4637,6 +4642,7 @@ mxge_detach(device_t dev)
|
||||
return EBUSY;
|
||||
}
|
||||
mtx_lock(&sc->driver_mtx);
|
||||
sc->dying = 1;
|
||||
if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
mxge_close(sc);
|
||||
mtx_unlock(&sc->driver_mtx);
|
||||
|
@ -266,6 +266,7 @@ struct mxge_softc {
|
||||
int need_media_probe;
|
||||
int num_slices;
|
||||
int rx_ring_size;
|
||||
int dying;
|
||||
mxge_dma_t dmabench_dma;
|
||||
struct callout co_hdl;
|
||||
struct sysctl_oid *slice_sysctl_tree;
|
||||
|
Loading…
Reference in New Issue
Block a user