Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 31 Dec 2004 00:43:24 +0100 (CET)
From:      Antoine Brodin <antoine.brodin@laposte.net>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/75677: [patch] sk(4): plug leaks and fix acquiring duplicate lock of same type: "network driver"
Message-ID:  <200412302343.iBUNhOAD001307@barton.dreadbsd.org>
Resent-Message-ID: <200412302350.iBUNo6bx033041@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         75677
>Category:       kern
>Synopsis:       [patch] sk(4): plug leaks and fix acquiring duplicate lock of same type: "network driver"
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Dec 30 23:50:06 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Antoine Brodin
>Release:        FreeBSD 6.0-CURRENT i386
>Organization:
none
>Environment:
System: FreeBSD barton.dreadbsd.org 6.0-CURRENT FreeBSD 6.0-CURRENT #1: Thu Dec 30 19:02:55 CET 2004 antoine@barton.dreadbsd.org:/usr/obj/usr/src/sys/BARTON i386
>Description:
* Witness reports this on a -current box :

acquiring duplicate lock of same type: "network driver"
 1st nv0 @ /usr/ports/net/nvnet/work/nvnet/module/../src/if_nv.c:1511
 2nd skc0 @ /usr/src/sys/modules/sk/../../pci/if_sk.c:1112
KDB: stack backtrace:
witness_checkorder(c2855c44,9,c07316ba,458) at witness_checkorder+0x500
_mtx_lock_flags(c2855c44,0,c07316ba,458,c2ac4e00) at _mtx_lock_flags+0x40
sk_jfree(e5a44340,c28e3000,0,c2857c00,e3c79c80) at sk_jfree+0x33
mb_free_ext(c2ac4e00) at mb_free_ext+0x36
m_freem(c2ac4e00,c2857c00,e5901000,e56fb0e0,c2857e60) at m_freem+0x21
nv_ospackettx(c2857c00,e56fb0e0,1,e5901000,0) at nv_ospackettx+0x73
UpdateTransmitDescRingData() at UpdateTransmitDescRingData+0xd3

I think this can cause a deadlock an a box with 2 sk(4) interfaces if
the 2 interfaces free a buffer allocated by the other at the same time.
A patch is attached (use an sk_jlist_mtx).

* When compiling if_sk as a module and unloading it, there seems to be
a few leaks.
A patch that fixes some of them is attached, but there is probably more
leaks.
Especially mii_phy_probe() and miibus_probe() allocate things during
a probe routine without freeing them and I suspect it's bad.

>How-To-Repeat:
* Enable witness on a box that acts as a gateway.

* Do kldload/kldunload if_sk and look at vmstat -m|grep devbuf.

>Fix:

--- sk.patch begins here ---
Index: if_sk.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_sk.c,v
retrieving revision 1.94
diff -u -r1.94 if_sk.c
--- if_sk.c	24 Dec 2004 14:13:38 -0000	1.94
+++ if_sk.c	30 Dec 2004 21:43:06 -0000
@@ -1041,6 +1041,7 @@
 
 	SLIST_INIT(&sc_if->sk_jfree_listhead);
 	SLIST_INIT(&sc_if->sk_jinuse_listhead);
+	mtx_init(&sc_if->sk_jlist_mtx, "sk_jlist_mtx", NULL, MTX_DEF);
 
 	/*
 	 * Now divide it up into 9K pieces and save the addresses
@@ -1053,8 +1054,15 @@
 		entry = malloc(sizeof(struct sk_jpool_entry), 
 		    M_DEVBUF, M_NOWAIT);
 		if (entry == NULL) {
-			free(sc_if->sk_cdata.sk_jumbo_buf, M_DEVBUF);
+			while (!SLIST_EMPTY(&sc_if->sk_jfree_listhead)) {
+				entry = SLIST_FIRST(&sc_if->sk_jfree_listhead);
+				SLIST_REMOVE_HEAD(&sc_if->sk_jfree_listhead, jpool_entries);
+				free(entry, M_DEVBUF);
+			}
+			contigfree(sc_if->sk_cdata.sk_jumbo_buf, SK_JMEM,
+			    M_DEVBUF);
 			sc_if->sk_cdata.sk_jumbo_buf = NULL;
+			mtx_destroy(&sc_if->sk_jlist_mtx);
 			printf("sk%d: no memory for jumbo "
 			    "buffer queue!\n", sc_if->sk_unit);
 			return(ENOBUFS);
@@ -1076,7 +1084,7 @@
 {
 	struct sk_jpool_entry   *entry;
 
-	SK_IF_LOCK_ASSERT(sc_if);
+	SK_JLIST_LOCK(sc_if);
 
 	entry = SLIST_FIRST(&sc_if->sk_jfree_listhead);
 
@@ -1089,6 +1097,9 @@
 
 	SLIST_REMOVE_HEAD(&sc_if->sk_jfree_listhead, jpool_entries);
 	SLIST_INSERT_HEAD(&sc_if->sk_jinuse_listhead, entry, jpool_entries);
+
+	SK_JLIST_UNLOCK(sc_if);
+
 	return(sc_if->sk_cdata.sk_jslots[entry->slot]);
 }
 
@@ -1109,7 +1120,7 @@
 	if (sc_if == NULL)
 		panic("sk_jfree: didn't get softc pointer!");
 
-	SK_IF_LOCK(sc_if);
+	SK_JLIST_LOCK(sc_if);
 
 	/* calculate the slot this buffer belongs to */
 	i = ((vm_offset_t)buf
@@ -1125,7 +1136,7 @@
 	SLIST_REMOVE_HEAD(&sc_if->sk_jinuse_listhead, jpool_entries);
 	SLIST_INSERT_HEAD(&sc_if->sk_jfree_listhead, entry, jpool_entries);
 
-	SK_IF_UNLOCK(sc_if);
+	SK_JLIST_UNLOCK(sc_if);
 	return;
 }
 
@@ -1737,8 +1748,21 @@
 		device_delete_child(dev, sc_if->sk_miibus);
 	*/
 	bus_generic_detach(dev);
-	if (sc_if->sk_cdata.sk_jumbo_buf != NULL)
+	if (sc_if->sk_cdata.sk_jumbo_buf != NULL) {
+		struct sk_jpool_entry	*entry;
+		while (!SLIST_EMPTY(&sc_if->sk_jfree_listhead)) {
+			entry = SLIST_FIRST(&sc_if->sk_jfree_listhead);
+			SLIST_REMOVE_HEAD(&sc_if->sk_jfree_listhead, jpool_entries);
+			free(entry, M_DEVBUF);
+		}
+		while (!SLIST_EMPTY(&sc_if->sk_jinuse_listhead)) {
+			entry = SLIST_FIRST(&sc_if->sk_jinuse_listhead);
+			SLIST_REMOVE_HEAD(&sc_if->sk_jinuse_listhead, jpool_entries);
+			free(entry, M_DEVBUF);
+		}
 		contigfree(sc_if->sk_cdata.sk_jumbo_buf, SK_JMEM, M_DEVBUF);
+		mtx_destroy(&sc_if->sk_jlist_mtx);
+	}
 	if (sc_if->sk_rdata != NULL) {
 		contigfree(sc_if->sk_rdata, sizeof(struct sk_ring_data),
 		    M_DEVBUF);
Index: if_skreg.h
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_skreg.h,v
retrieving revision 1.24
diff -u -r1.24 if_skreg.h
--- if_skreg.h	15 Nov 2004 19:37:21 -0000	1.24
+++ if_skreg.h	30 Dec 2004 17:42:22 -0000
@@ -1468,8 +1468,12 @@
 	int			sk_if_flags;
 	SLIST_HEAD(__sk_jfreehead, sk_jpool_entry)	sk_jfree_listhead;
 	SLIST_HEAD(__sk_jinusehead, sk_jpool_entry)	sk_jinuse_listhead;
+	struct mtx		sk_jlist_mtx;
 };
 
+#define	SK_JLIST_LOCK(_sc)	mtx_lock(&(_sc)->sk_jlist_mtx)
+#define	SK_JLIST_UNLOCK(_sc)	mtx_unlock(&(_sc)->sk_jlist_mtx)
+
 #define SK_MAXUNIT	256
 #define SK_TIMEOUT	1000
 #define ETHER_ALIGN	2
--- sk.patch ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200412302343.iBUNhOAD001307>