PERFORCE change 127403 for review
Kip Macy
kmacy at FreeBSD.org
Thu Oct 11 20:07:40 PDT 2007
http://perforce.freebsd.org/chv.cgi?CH=127403
Change 127403 by kmacy at kmacy_home:ethng on 2007/10/12 03:06:45
fix handling of case where packet header mbuf contained zero bytes of data
- don't modify initial mbuf chain while iterating through it
- when collapsing mbufs do it from the array and not the chain
- when freeing mbufs do it from the chain and not the array
skip special handling of mbuf chain with only buffer but multiple mbufs
probably not common enough to special case and the way it was being handled
could leak memory
Affected files ...
.. //depot/projects/ethng/src/sys/dev/cxgb/sys/uipc_mvec.c#15 edit
Differences ...
==== //depot/projects/ethng/src/sys/dev/cxgb/sys/uipc_mvec.c#15 (text+ko) ====
@@ -125,7 +125,6 @@
mi->mi_flags = m->m_flags;
mi->mi_len = m->m_len;
-
if (m->m_flags & M_PKTHDR) {
mi->mi_ether_vtag = m->m_pkthdr.ether_vtag;
@@ -141,6 +140,7 @@
mi->mi_size = (m->m_type == EXT_CLIOVEC) ? MCLBYTES : MIOVBYTES;
mi->mi_type = m->m_type;
mi->mi_len = m->m_pkthdr.len;
+ KASSERT(mi->mi_len, ("empty packet"));
mi->mi_refcnt = NULL;
} else if (m->m_flags & M_EXT) {
memcpy(&mi->mi_ext, &m->m_ext, sizeof(struct m_ext_));
@@ -171,11 +171,12 @@
int
busdma_map_sg_collapse(struct mbuf **m, bus_dma_segment_t *segs, int *nsegs)
{
- struct mbuf *m0, *n = *m;
+ struct mbuf *m0, *n = *m, *mhead;
struct mbuf_iovec *mi;
struct mbuf *marray[TX_MAX_SEGS];
int i, type, seg_count, defragged = 0, err = 0;
struct mbuf_vec *mv;
+ uma_zone_t zone;
if (n->m_flags & M_PKTHDR && !SLIST_EMPTY(&n->m_pkthdr.tags))
m_tag_delete_chain(n, NULL);
@@ -221,20 +222,23 @@
/*
* firmware doesn't like empty segments
*/
- if (__predict_false(n->m_len == 0)) {
- n = m_free(n);
- if (seg_count)
- marray[seg_count - 1]->m_next = n;
- continue;
- }
- seg_count++;
+ if (__predict_true(n->m_len != 0))
+ seg_count++;
+
n = n->m_next;
}
+#if 0
+ /*
+ * XXX needs more careful consideration
+ */
if (__predict_false(seg_count == 1)) {
- n = *m;
+ n = marray[0];
+ if (n != *m)
+
/* XXX */
goto retry;
}
+#endif
if (seg_count == 0) {
if (cxgb_debug)
printf("empty segment chain\n");
@@ -257,43 +261,41 @@
goto err_out;
}
if (seg_count > MAX_CL_IOV) {
- if ((m0 = uma_zalloc_arg(zone_jumbop, NULL, M_NOWAIT)) == NULL) {
- err = ENOMEM;
- goto err_out;
- }
+ zone = zone_jumbop;
type = EXT_JMPIOVEC;
} else if (seg_count > MAX_MIOVEC_IOV) {
- DPRINTF("seg count=%d ", seg_count);
- if ((m0 = uma_zalloc_arg(zone_clust, NULL, M_NOWAIT)) == NULL) {
- err = ENOMEM;
- goto err_out;
- }
+ zone = zone_clust;
type = EXT_CLIOVEC;
} else {
- if ((m0 = uma_zalloc_arg(zone_miovec, NULL, M_NOWAIT)) == NULL) {
- err = ENOMEM;
- goto err_out;
- }
type = EXT_IOVEC;
+ zone = zone_miovec;
}
+ if ((m0 = uma_zalloc_arg(zone, NULL, M_NOWAIT)) == NULL) {
+ err = ENOMEM;
+ goto err_out;
+ }
- n = marray[0];
- memcpy(m0, n, sizeof(struct m_hdr) + sizeof(struct pkthdr));
+ memcpy(m0, *m, sizeof(struct m_hdr) + sizeof(struct pkthdr));
m0->m_type = type;
mv = mtomv(m0);
mv->mv_count = seg_count;
mv->mv_first = 0;
-
- for (mi = mv->mv_vec; n; mi++, segs++) {
+ for (i = 0, mi = mv->mv_vec; i < seg_count; mi++, segs++, i++) {
+ n = marray[i];
busdma_map_mbuf_fast(n, segs);
- n = _mcl_collapse_mbuf(mi, n);
+ _mcl_collapse_mbuf(mi, n);
}
- for (i = 0; i < seg_count; i++) {
- marray[i]->m_next = marray[i]->m_nextpkt = NULL;
- if ((marray[i]->m_flags & (M_EXT|M_NOFREE)) == M_EXT) {
- marray[i]->m_flags &= ~M_EXT;
- m_free(marray[i]);
+ n = *m;
+ while (n) {
+ if (((n->m_flags & (M_EXT|M_NOFREE)) == M_EXT) && (n->m_len > 0))
+ n->m_flags &= ~M_EXT;
+ else if (n->m_len > 0) {
+ n = n->m_next;
+ continue;
}
+ mhead = n->m_next;
+ m_free(n);
+ n = mhead;
}
*nsegs = seg_count;
*m = m0;
More information about the p4-projects
mailing list