diff options
author | yongari <yongari@FreeBSD.org> | 2008-03-05 05:36:09 +0000 |
---|---|---|
committer | yongari <yongari@FreeBSD.org> | 2008-03-05 05:36:09 +0000 |
commit | 1982e3e241079fc0b019a6ef6d0e0e5ec2a17d11 (patch) | |
tree | f96c5a8772beca67e4d10ac589a7c9872427e51b | |
parent | 0abc0885372d5c0a1ddcf71604c747aa76062639 (diff) | |
download | FreeBSD-src-1982e3e241079fc0b019a6ef6d0e0e5ec2a17d11.zip FreeBSD-src-1982e3e241079fc0b019a6ef6d0e0e5ec2a17d11.tar.gz |
Plug memory leak in jumbo buffer allocation failure path.
Patch in the PR was modified to check active jumbo buffers in use
and other possible jumbo buffer leak.
Jumbo buffer usage in lge(4) still wouldn't be reliable due to lack
of driver lock in local jumbo buffer allocator. Either introduce
a new lock to protect jumbo buffer or switch to UMA backed page
allocator for jumbo frame is required.
PR: kern/78072
-rw-r--r-- | sys/dev/lge/if_lge.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/sys/dev/lge/if_lge.c b/sys/dev/lge/if_lge.c index 1313990..438a501 100644 --- a/sys/dev/lge/if_lge.c +++ b/sys/dev/lge/if_lge.c @@ -535,7 +535,6 @@ lge_attach(dev) ifp = sc->lge_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(dev, "can not if_alloc()\n"); - lge_free_jumbo_mem(sc); error = ENOSPC; goto fail; } @@ -562,7 +561,6 @@ lge_attach(dev) if (mii_phy_probe(dev, &sc->lge_miibus, lge_ifmedia_upd, lge_ifmedia_sts)) { device_printf(dev, "MII without any PHY!\n"); - lge_free_jumbo_mem(sc); error = ENXIO; goto fail; } @@ -583,6 +581,7 @@ lge_attach(dev) return (0); fail: + lge_free_jumbo_mem(sc); if (sc->lge_ldata) contigfree(sc->lge_ldata, sizeof(struct lge_list_data), M_DEVBUF); @@ -804,10 +803,19 @@ static void lge_free_jumbo_mem(sc) struct lge_softc *sc; { - int i; struct lge_jpool_entry *entry; - for (i = 0; i < LGE_JSLOTS; i++) { + if (sc->lge_cdata.lge_jumbo_buf == NULL) + return; + + while ((entry = SLIST_FIRST(&sc->lge_jinuse_listhead))) { + device_printf(sc->lge_dev, + "asked to free buffer that is in use!\n"); + SLIST_REMOVE_HEAD(&sc->lge_jinuse_listhead, jpool_entries); + SLIST_INSERT_HEAD(&sc->lge_jfree_listhead, entry, + jpool_entries); + } + while (!SLIST_EMPTY(&sc->lge_jfree_listhead)) { entry = SLIST_FIRST(&sc->lge_jfree_listhead); SLIST_REMOVE_HEAD(&sc->lge_jfree_listhead, jpool_entries); free(entry, M_DEVBUF); |