Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 Aug 2004 21:55:04 GMT
From:      Pawel Jakub Dawidek <pjd@FreeBSD.org>
To:        pjd@FreeBSD.org, ipfw@FreeBSD.org, pjd@FreeBSD.org
Subject:   Re: kern/46557: ipfw pipe show fails with lots of queues
Message-ID:  <200408232155.i7NLt4gF052086@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
Synopsis: ipfw pipe show fails with lots of queues

Responsible-Changed-From-To: ipfw->pjd
Responsible-Changed-By: pjd
Responsible-Changed-When: Mon Aug 23 21:53:44 GMT 2004
Responsible-Changed-Why: 
I'll take this one.

Here is prosposed patch against HEAD:

Index: ip_dummynet.c
===================================================================
RCS file: /private/FreeBSD/src/sys/netinet/ip_dummynet.c,v
retrieving revision 1.82
diff -u -p -r1.82 ip_dummynet.c
--- ip_dummynet.c	15 Jul 2004 08:26:07 -0000	1.82
+++ ip_dummynet.c	23 Aug 2004 21:41:06 -0000
@@ -1895,17 +1895,14 @@ dn_copy_set(struct dn_flow_set *set, cha
     return (char *)qp ;
 }
 
-static int
-dummynet_get(struct sockopt *sopt)
+static size_t
+dn_calc_size(void)
 {
-    char *buf, *bp ; /* bp is the "copy-pointer" */
-    size_t size ;
     struct dn_flow_set *set ;
     struct dn_pipe *p ;
-    int error=0 ;
+    size_t size ;
 
-    /* XXX lock held too long */
-    DUMMYNET_LOCK();
+    DUMMYNET_LOCK_ASSERT();
     /*
      * compute size of data structures: list of pipes and flow_sets.
      */
@@ -1915,8 +1912,35 @@ dummynet_get(struct sockopt *sopt)
     for (set = all_flow_sets ; set ; set = set->next )
 	size += sizeof ( *set ) +
 	    set->rq_elements * sizeof(struct dn_flow_queue);
-    buf = malloc(size, M_TEMP, M_NOWAIT);
-    if (buf == 0) {
+    return size ;
+}
+
+static int
+dummynet_get(struct sockopt *sopt)
+{
+    char *buf, *bp ; /* bp is the "copy-pointer" */
+    size_t size ;
+    struct dn_flow_set *set ;
+    struct dn_pipe *p ;
+    int error=0, i ;
+
+    /* XXX lock held too long */
+    DUMMYNET_LOCK();
+    /*
+     * XXX: Ugly, but we need to allocate memory with M_WAITOK flag and we
+     *      cannot use this flag while holding a mutex.
+     */
+    for (i = 0; i < 10; i++) {
+	size = dn_calc_size();
+	DUMMYNET_UNLOCK();
+	buf = malloc(size, M_TEMP, M_WAITOK);
+	DUMMYNET_LOCK();
+	if (size == dn_calc_size())
+		break;
+	free(buf, M_TEMP);
+	buf = NULL;
+    }
+    if (buf == NULL) {
 	DUMMYNET_UNLOCK();
 	return ENOBUFS ;
     }

http://www.freebsd.org/cgi/query-pr.cgi?pr=46557



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