igb diver crashes in head at 241037

Karim Fodil-Lemelin fodillemlinkarim at gmail.com
Mon Nov 19 19:57:34 UTC 2012


Hello -net,

While testing the latest igb driver in CURRENT I came across an issue 
with igb_mq_start(). More specifically this code:

...

         struct mbuf *pm = NULL;
         /*
         ** Try to queue first to avoid
         ** out-of-order delivery, but
         ** settle for it if that fails
         */
         if (m && drbr_enqueue(ifp, txr->br, m))
             pm = m;
         err = igb_mq_start_locked(ifp, txr, pm);

...


The problem comes from the fact that drbr_enqueue() can return an error 
and delete the mbuf as seen in drbr_enqueue():

...
error = buf_ring_enqueue(br, m);
     if (error)
         m_freem(m);
...

When this happens pm is set to m then igb_mq_start_locked() will enqueue 
an already freed mbuf with the outcome you can imagine.

When I reverted only that part of r241037 that problem disappeared. I 
have attached a patch for those interested.

Best regards,

Karim.
-------------- next part --------------
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index 1318910..be1719a 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -961,15 +961,7 @@ igb_mq_start(struct ifnet *ifp, struct mbuf *m)
 	que = &adapter->queues[i];
 	if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) &&
 	    IGB_TX_TRYLOCK(txr)) {
-		struct mbuf *pm = NULL;
-		/*
-		** Try to queue first to avoid
-		** out-of-order delivery, but 
-		** settle for it if that fails
-		*/
-		if (m && drbr_enqueue(ifp, txr->br, m))
-			pm = m;
-		err = igb_mq_start_locked(ifp, txr, pm);
+		err = igb_mq_start_locked(ifp, txr, m);
 		IGB_TX_UNLOCK(txr);
 	} else {
 		err = drbr_enqueue(ifp, txr->br, m);


More information about the freebsd-net mailing list