summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_dummynet.c
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2004-08-25 09:31:30 +0000
committerpjd <pjd@FreeBSD.org>2004-08-25 09:31:30 +0000
commit8c34a02cfb294efe1309f859c24f2393810bf2ee (patch)
treeff28d28d387c3b2191bacbd98621d361a0557469 /sys/netinet/ip_dummynet.c
parent283ba8210aec6d5924aa7a6a3b3cbf0ece57768e (diff)
downloadFreeBSD-src-8c34a02cfb294efe1309f859c24f2393810bf2ee.zip
FreeBSD-src-8c34a02cfb294efe1309f859c24f2393810bf2ee.tar.gz
Allocate memory when dumping pipes with M_WAITOK flag.
On a system with huge number of pipes, M_NOWAIT failes almost always, because of memory fragmentation. My fix is different than the patch proposed by Pawel Malachowski, because in FreeBSD 5.x we cannot sleep while holding dummynet mutex (in 4.x there is no such lock). My fix is also ugly, but there is no easy way to prepare nice and clean fix. PR: kern/46557 Submitted by: Eugene Grosbein <eugen@grosbein.pp.ru> Reviewed by: mlaier
Diffstat (limited to 'sys/netinet/ip_dummynet.c')
-rw-r--r--sys/netinet/ip_dummynet.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/sys/netinet/ip_dummynet.c b/sys/netinet/ip_dummynet.c
index 6c419ed..71b3299 100644
--- a/sys/netinet/ip_dummynet.c
+++ b/sys/netinet/ip_dummynet.c
@@ -1867,17 +1867,14 @@ dn_copy_set(struct dn_flow_set *set, char *bp)
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.
*/
@@ -1887,8 +1884,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 ;
}
OpenPOWER on IntegriCloud