summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2008-03-05 05:36:09 +0000
committeryongari <yongari@FreeBSD.org>2008-03-05 05:36:09 +0000
commit1982e3e241079fc0b019a6ef6d0e0e5ec2a17d11 (patch)
treef96c5a8772beca67e4d10ac589a7c9872427e51b /sys
parent0abc0885372d5c0a1ddcf71604c747aa76062639 (diff)
downloadFreeBSD-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
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/lge/if_lge.c16
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);
OpenPOWER on IntegriCloud