Fix iflib_encap() EFBIG handling bugs

1) Don't give up if m_collapse() fails.  Rather than giving up, try
m_defrag() immediately.

2) Fix a leak where, if the NIC driver rejected the defrag'ed chain
as having too many segments, we would fail to free the chain.

Reviewed by:  Matthew Macy <mmacy@mattmacy.io> (this version of patch)
Submitted by: Matthew Macy <mmacy@mattmacy.io> (early version of leak fix)
This commit is contained in:
Andrew Gallatin 2018-04-30 23:53:27 +00:00
parent e134ecdcfc
commit f759470750
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=333131

View File

@ -3244,8 +3244,12 @@ iflib_encap(iflib_txq_t txq, struct mbuf **m_headp)
switch (err) {
case EFBIG:
/* try collapse once and defrag once */
if (remap == 0)
if (remap == 0) {
m_head = m_collapse(*m_headp, M_NOWAIT, max_segs);
/* try defrag if collapsing fails */
if (m_head == NULL)
remap++;
}
if (remap == 1)
m_head = m_defrag(*m_headp, M_NOWAIT);
remap++;
@ -3333,13 +3337,18 @@ iflib_encap(iflib_txq_t txq, struct mbuf **m_headp)
*/
txq->ift_pidx = pi.ipi_new_pidx;
txq->ift_npending += pi.ipi_ndescs;
} else if (__predict_false(err == EFBIG && remap < 2)) {
} else {
*m_headp = m_head = iflib_remove_mbuf(txq);
remap = 1;
txq->ift_txd_encap_efbig++;
goto defrag;
} else
if (err == EFBIG) {
txq->ift_txd_encap_efbig++;
if (remap < 2) {
remap = 1;
goto defrag;
}
}
DBG_COUNTER_INC(encap_txd_encap_fail);
goto defrag_failed;
}
return (err);
defrag_failed: