summaryrefslogtreecommitdiffstats
path: root/sys/dev/cxgb
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2008-12-02 00:39:50 +0000
committerkmacy <kmacy@FreeBSD.org>2008-12-02 00:39:50 +0000
commit7b9d573ced53545131b0edd8383bbb8c250d6cea (patch)
treed4ea4ebcaa14e0f4bc99e1b00663f522910b49b6 /sys/dev/cxgb
parent89e51258611a31efc2b1a6945c4d2e4db7859b37 (diff)
downloadFreeBSD-src-7b9d573ced53545131b0edd8383bbb8c250d6cea.zip
FreeBSD-src-7b9d573ced53545131b0edd8383bbb8c250d6cea.tar.gz
integrate use after free fixes from private branch
Found by: kkenn@
Diffstat (limited to 'sys/dev/cxgb')
-rw-r--r--sys/dev/cxgb/sys/uipc_mvec.c98
1 files changed, 44 insertions, 54 deletions
diff --git a/sys/dev/cxgb/sys/uipc_mvec.c b/sys/dev/cxgb/sys/uipc_mvec.c
index 1c6f4b2..3d503c6 100644
--- a/sys/dev/cxgb/sys/uipc_mvec.c
+++ b/sys/dev/cxgb/sys/uipc_mvec.c
@@ -1,6 +1,6 @@
/**************************************************************************
*
- * Copyright (c) 2007, Kip Macy kmacy@freebsd.org
+ * Copyright (c) 2007-2008, Kip Macy kmacy@freebsd.org
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -78,7 +78,6 @@ mi_init(void)
return;
else
mi_inited++;
-
zone_miovec = uma_zcreate("MBUF IOVEC", MIOVBYTES,
NULL, NULL, NULL, NULL,
UMA_ALIGN_PTR, UMA_ZONE_MAXBUCKET);
@@ -127,6 +126,8 @@ _mcl_collapse_mbuf(struct mbuf_iovec *mi, struct mbuf *m)
mi->mi_tso_segsz = m->m_pkthdr.tso_segsz;
#ifdef IFNET_MULTIQ
mi->mi_rss_hash = m->m_pkthdr.rss_hash;
+ if(!SLIST_EMPTY(&m->m_pkthdr.tags))
+ m_tag_delete_chain(m, NULL);
#endif
}
if (m->m_type != MT_DATA) {
@@ -147,13 +148,21 @@ _mcl_collapse_mbuf(struct mbuf_iovec *mi, struct mbuf *m)
mi->mi_type = m->m_ext.ext_type;
mi->mi_size = m->m_ext.ext_size;
mi->mi_refcnt = m->m_ext.ref_cnt;
- mi->mi_mbuf = m;
+ if (m->m_ext.ext_type == EXT_PACKET) {
+ mi->mi_mbuf = m;
+#ifdef INVARIANTS
+ cxgb_pack_outstanding++;
+#endif
+ }
} else {
mi->mi_base = (caddr_t)m;
mi->mi_data = m->m_data;
mi->mi_size = MSIZE;
mi->mi_type = EXT_MBUF;
mi->mi_refcnt = NULL;
+#ifdef INVARIANTS
+ cxgb_mbufs_outstanding++;
+#endif
}
KASSERT(mi->mi_len != 0, ("miov has len 0"));
KASSERT(mi->mi_type > 0, ("mi_type is invalid"));
@@ -193,15 +202,9 @@ busdma_map_sg_collapse(struct mbuf **m, bus_dma_segment_t *segs, int *nsegs)
struct mbuf *marray[TX_MAX_SEGS];
int i, type, seg_count, defragged = 0, err = 0;
struct mbuf_vec *mv;
- int skipped, freed, outstanding, pack_outstanding, mbuf_outstanding;
-
-
+ int skipped, freed;
KASSERT(n->m_pkthdr.len, ("packet has zero header len"));
-
- if (n->m_flags & M_PKTHDR && !SLIST_EMPTY(&n->m_pkthdr.tags))
- m_tag_delete_chain(n, NULL);
-
if (n->m_pkthdr.len <= PIO_LEN)
return (0);
retry:
@@ -209,14 +212,9 @@ retry:
if (n->m_next == NULL) {
busdma_map_mbuf_fast(n, segs);
*nsegs = 1;
- if ((n->m_flags & M_EXT) &&
- (n->m_ext.ext_type == EXT_PACKET))
- cxgb_pack_outstanding++;
- else if ((n->m_flags & M_NOFREE) == 0)
- cxgb_mbufs_outstanding++;
return (0);
}
- skipped = freed = outstanding = pack_outstanding = mbuf_outstanding = 0;
+ skipped = freed = 0;
while (n && seg_count < TX_MAX_SEGS) {
marray[seg_count] = n;
@@ -274,11 +272,9 @@ retry:
if (n->m_len == 0)
/* do nothing - free if mbuf or cluster */;
else if ((n->m_flags & M_EXT) == 0) {
- mbuf_outstanding++;
goto skip;
} else if ((n->m_flags & M_EXT) &&
(n->m_ext.ext_type == EXT_PACKET)) {
- pack_outstanding++;
goto skip;
} else if (n->m_flags & M_NOFREE)
goto skip;
@@ -293,15 +289,11 @@ retry:
/*
* is an immediate mbuf or is from the packet zone
*/
- mhead = n->m_next;
- n->m_next = NULL;
- n = mhead;
+ n = n->m_next;
}
*nsegs = seg_count;
*m = m0;
DPRINTF("pktlen=%d m0=%p *m=%p m=%p\n", m0->m_pkthdr.len, m0, *m, m);
- cxgb_mbufs_outstanding += mbuf_outstanding;
- cxgb_pack_outstanding += pack_outstanding;
return (0);
err_out:
m_freem(*m);
@@ -310,41 +302,34 @@ err_out:
}
int
-busdma_map_sg_vec(struct mbuf **m, struct mbuf **mret, bus_dma_segment_t *segs, int count)
+busdma_map_sg_vec(struct mbuf **m, struct mbuf **mret,
+ bus_dma_segment_t *segs, int pkt_count)
{
struct mbuf *m0, **mp;
struct mbuf_iovec *mi;
struct mbuf_vec *mv;
- int i;
-
- if (count > MAX_MIOVEC_IOV) {
- if ((m0 = uma_zalloc_arg(zone_clust, NULL, M_NOWAIT)) == NULL)
- return (ENOMEM);
- m0->m_type = EXT_CLIOVEC;
- } else {
- if ((m0 = uma_zalloc_arg(zone_miovec, NULL, M_NOWAIT)) == NULL)
- return (ENOMEM);
- m0->m_type = EXT_IOVEC;
- }
+ int i, type;
+
+ if ((m0 = mcl_alloc(pkt_count, &type)) == NULL)
+ return (ENOMEM);
- m0->m_flags = 0;
- m0->m_pkthdr.len = m0->m_len = (*m)->m_len; /* not the real length but needs to be non-zero */
+ memcpy(m0, *m, sizeof(struct m_hdr) +
+ sizeof(struct pkthdr));
+ m0->m_type = type;
mv = mtomv(m0);
- mv->mv_count = count;
+ mv->mv_count = pkt_count;
mv->mv_first = 0;
- for (mp = m, i = 0, mi = mv->mv_vec; i < count; mp++, segs++, mi++, i++) {
- if ((*mp)->m_flags & M_PKTHDR && !SLIST_EMPTY(&(*mp)->m_pkthdr.tags))
- m_tag_delete_chain(*mp, NULL);
+ for (mp = m, i = 0, mi = mv->mv_vec; i < pkt_count;
+ mp++, segs++, mi++, i++) {
busdma_map_mbuf_fast(*mp, segs);
_mcl_collapse_mbuf(mi, *mp);
KASSERT(mi->mi_len, ("empty packet"));
}
- for (mp = m, i = 0; i < count; i++, mp++) {
- (*mp)->m_next = (*mp)->m_nextpkt = NULL;
- if (((*mp)->m_flags & (M_EXT|M_NOFREE)) == M_EXT) {
+ for (mp = m, i = 0; i < pkt_count; i++, mp++) {
+ if ((((*mp)->m_flags & (M_EXT|M_NOFREE)) == M_EXT)
+ && ((*mp)->m_ext.ext_type != EXT_PACKET)) {
(*mp)->m_flags &= ~M_EXT;
- cxgb_mbufs_outstanding--;
m_free(*mp);
}
}
@@ -359,17 +344,28 @@ mb_free_ext_fast(struct mbuf_iovec *mi, int type, int idx)
int dofree;
caddr_t cl;
- if (type == EXT_PACKET) {
+ cl = mi->mi_base;
+ switch (type) {
+ case EXT_PACKET:
+#ifdef INVARIANTS
cxgb_pack_outstanding--;
+#endif
m_free(mi->mi_mbuf);
return;
+ case EXT_MBUF:
+ KASSERT((mi->mi_flags & M_NOFREE) == 0, ("no free set on mbuf"));
+#ifdef INVARIANTS
+ cxgb_mbufs_outstanding--;
+#endif
+ m_free_fast((struct mbuf *)cl);
+ return;
+ default:
+ break;
}
/* Account for lazy ref count assign. */
dofree = (mi->mi_refcnt == NULL);
if (dofree == 0) {
- KASSERT(mi->mi_type != EXT_MBUF,
- ("refcnt must be null for mbuf"));
if (*(mi->mi_refcnt) == 1 ||
atomic_fetchadd_int(mi->mi_refcnt, -1) == 1)
dofree = 1;
@@ -377,13 +373,7 @@ mb_free_ext_fast(struct mbuf_iovec *mi, int type, int idx)
if (dofree == 0)
return;
- cl = mi->mi_base;
switch (type) {
- case EXT_MBUF:
- KASSERT((mi->mi_flags & M_NOFREE) == 0, ("no free set on mbuf"));
- cxgb_mbufs_outstanding--;
- m_free_fast((struct mbuf *)cl);
- break;
case EXT_CLUSTER:
cxgb_cache_put(zone_clust, cl);
break;
OpenPOWER on IntegriCloud