On Mon, Aug 31, 2009 at 09:01:44AM -0400, Wade, Daniel wrote:
> > -----Original Message-----
> > From: Theo de Raadt [mailto:dera...@cvs.openbsd.org]
> > Sent: Thursday, August 27, 2009 1:11 PM
> > To: Wade, Daniel
> > Subject: Re: Leaking mbufs
> >
> > > So more a kernel side problem than a userland issue?  Bret
> > Lambert was poin=
> > > ting me down the userland software side of things.  I'll pull the
> > ep(4) car=
> > > d and give that a shot.  Thanks for the suggestion
> >
> > It is a leak, in the kernel.
> >
> > It is probably in a driver.
> >
> 
> 
> It's my ep(4) card that is leaking.  I think this issue started about 5 or 6
> months ago, but I didn't figure out it was an mbuf problem until just
> recently.  I'll be glad to help test any diffs.
> 

Can't you use something less pathetic then ep(4)? This driver is so alien
and so bad it makes even rl(4) look good.

But you could try this diff that tries to get rid of some of the insane
magic in this driver.
-- 
:wq Claudio

Index: elink3.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/elink3.c,v
retrieving revision 1.73
diff -u -r1.73 elink3.c
--- elink3.c    28 Nov 2008 02:44:17 -0000      1.73
+++ elink3.c    9 Aug 2009 16:33:29 -0000
@@ -1372,36 +1372,27 @@
        bus_space_tag_t iot = sc->sc_iot;
        bus_space_handle_t ioh = sc->sc_ioh;
        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
-       struct mbuf *top, **mp, *m;
+       struct mbuf *m;
        int len, pad, sh, rxreg;
 
        m = sc->mb[sc->next_mb];
        sc->mb[sc->next_mb] = NULL;
-       if (m == NULL) {
-               MGETHDR(m, M_DONTWAIT, MT_DATA);
-               if (m == NULL)
-                       return (NULL);
-       } else {
-               /* If the queue is no longer full, refill. */
-               if (sc->last_mb == sc->next_mb)
-                       timeout_add(&sc->sc_epmbuffill_tmo, 1);
-               /* Convert one of our saved mbuf's. */
-               sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
-               m = m_inithdr(m);
-       }
+       if (m == NULL)
+               m = MCLGETI(NULL, M_DONTWAIT, NULL, MCLBYTES);
+       if (!m)
+               return (NULL);
+
+       /* If the queue is no longer full, refill. */
+       if (sc->last_mb == sc->next_mb)
+               timeout_add(&sc->sc_epmbuffill_tmo, 1);
+       sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
+
+       len = MCLBYTES;
        m->m_pkthdr.rcvif = ifp;
        m->m_pkthdr.len = totlen;
        pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
-       len = MHLEN;
-       if (totlen >= MINCLSIZE) {
-               MCLGET(m, M_DONTWAIT);
-               if (m->m_flags & M_EXT)
-                       len = MCLBYTES;
-       }
        m->m_data += pad;
        len -= pad;
-       top = 0;
-       mp = ⊤
 
        /*
         * We read the packet at splhigh() so that an interrupt from another
@@ -1412,56 +1403,31 @@
 
        rxreg = ep_w1_reg(sc, EP_W1_RX_PIO_RD_1);
 
-       while (totlen > 0) {
-               if (top) {
-                       m = sc->mb[sc->next_mb];
-                       sc->mb[sc->next_mb] = NULL;
-                       if (m == NULL) {
-                               MGET(m, M_DONTWAIT, MT_DATA);
-                               if (m == NULL) {
-                                       splx(sh);
-                                       m_freem(top);
-                                       return (NULL);
-                               }
-                       } else
-                               sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
-
-                       len = MLEN;
-               }
-               if (top && totlen >= MINCLSIZE) {
-                       MCLGET(m, M_DONTWAIT);
-                       if (m->m_flags & M_EXT)
-                               len = MCLBYTES;
-               }
-               len = min(totlen, len);
-               if (EP_IS_BUS_32(sc->bustype)) {
-                       if (len > 3) {
-                               len &= ~3;
-                               bus_space_read_raw_multi_4(iot, ioh, rxreg,
-                                   mtod(m, u_int8_t *), len);
-                       } else
-                               bus_space_read_multi_1(iot, ioh, rxreg,
-                                   mtod(m, u_int8_t *), len);
-               } else {
-                       if (len > 1) {
-                               len &= ~1;
-                               bus_space_read_raw_multi_2(iot, ioh, rxreg,
-                                   mtod(m, u_int8_t *), len);
-                       } else
-                               *(mtod(m, u_int8_t *)) =
-                                   bus_space_read_1(iot, ioh, rxreg);
-               }
-               m->m_len = len;
-               totlen -= len;
-               *mp = m;
-               mp = &m->m_next;
+       len = min(totlen, len);
+       if (EP_IS_BUS_32(sc->bustype)) {
+               if (len > 3) {
+                       len &= ~3;
+                       bus_space_read_raw_multi_4(iot, ioh, rxreg,
+                           mtod(m, u_int8_t *), len);
+               } else
+                       bus_space_read_multi_1(iot, ioh, rxreg,
+                           mtod(m, u_int8_t *), len);
+       } else {
+               if (len > 1) {
+                       len &= ~1;
+                       bus_space_read_raw_multi_2(iot, ioh, rxreg,
+                           mtod(m, u_int8_t *), len);
+               } else
+                       *(mtod(m, u_int8_t *)) =
+                           bus_space_read_1(iot, ioh, rxreg);
        }
+       m->m_len = len;
 
        ep_discard_rxtop(iot, ioh);
 
        splx(sh);
 
-       return top;
+       return m;
 }
 
 int
@@ -1695,10 +1661,11 @@
        s = splnet();
        i = sc->last_mb;
        do {
-               if (sc->mb[i] == NULL)
-                       MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
-               if (sc->mb[i] == NULL)
-                       break;
+               if (sc->mb[i] == NULL) {
+                       sc->mb[i] = MCLGETI(NULL, M_DONTWAIT, NULL, MCLBYTES);
+                       if (sc->mb[i] == NULL)
+                               break;
+               }
                i = (i + 1) % MAX_MBS;
        } while (i != sc->next_mb);
        sc->last_mb = i;

Reply via email to