fix.diff - DF-4270: handle wb_encap() failure in wb_start(). wb_start() ignored wb_encap()'s return; the two coalesce-failure paths (MGETHDR/MCLGET under M_NOWAIT) leak the already-dequeued packet and leave a half-programmed, unterminated fragment chain that the NIC can be started on. Applies on top of sys/dev/netif/wb/if_wb.c (read-only audit tree; never applied). --- a/sys/dev/netif/wb/if_wb.c +++ b/sys/dev/netif/wb/if_wb.c @@ -1322,11 +1322,32 @@ wb_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) sc->wb_cdata.wb_tx_free = cur_tx->wb_nextdesc; /* Pack the data into the descriptor. */ - wb_encap(sc, cur_tx, m_head); + if (wb_encap(sc, cur_tx, m_head) != 0) { + int fidx; + + /* + * wb_encap() failed (mbuf shortage): free the + * dequeued packet, disarm the partially programmed + * fragments so the NIC never walks the unterminated + * chain, and put the descriptor back on the free + * list. + */ + m_freem(m_head); + cur_tx->wb_mbuf = NULL; + for (fidx = 0; fidx < WB_MAXFRAGS; fidx++) + cur_tx->wb_ptr->wb_frag[fidx].wb_status = 0; + sc->wb_cdata.wb_tx_free = cur_tx; + if (cur_tx == start_tx) + return; /* nothing was queued */ + break; + } if (cur_tx != start_tx) WB_TXOWN(cur_tx) = WB_TXSTAT_OWN;