tech-net archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: squid, DNS and no buffer space
> I'm no expert, but...is it normal to have lots more packet header mbufs
> than data mbufs? It looks suspicious to me. On my (much older)
> systems, either they're close to equal or there are more data mbufs.
Duno if it's related, but I found two mbuf leaks a while ago and just ported
the patches to -10.
A huge one is in lltable_drop_entry_queue(), diff to sys/net/if_llatbl.c
attached; another one (probably) in m_ext_free() (in sys/kern/uipc_mbuf.c),
replacement code attached (my diff contains additional instrumentation
needing further patches).
Index: sys/net/if_llatbl.c
===================================================================
RCS file: /cvsroot/src/sys/net/if_llatbl.c,v
retrieving revision 1.35
diff -u -r1.35 if_llatbl.c
--- sys/net/if_llatbl.c 19 Nov 2022 08:00:51 -0000 1.35
+++ sys/net/if_llatbl.c 3 Dec 2024 16:35:00 -0000
@@ -322,6 +322,8 @@
LLE_WLOCK_ASSERT(lle);
pkts_dropped = 0;
+
+#if 0 /* XXX la_numheld isn't (properly) incremented */
while ((lle->la_numheld > 0) && (lle->la_hold != NULL)) {
next = lle->la_hold->m_nextpkt;
m_freem(lle->la_hold);
@@ -333,6 +335,15 @@
KASSERTMSG(lle->la_numheld == 0,
"la_numheld %d > 0, pkts_dropped %zd",
lle->la_numheld, pkts_dropped);
+#else
+ while (lle->la_hold != NULL) {
+ next = lle->la_hold->m_nextpkt;
+ m_freem(lle->la_hold);
+ lle->la_hold = next;
+ pkts_dropped++;
+ }
+ lle->la_numheld = 0;
+#endif
return (pkts_dropped);
}
/*
* Release a reference to the mbuf external storage.
*
* => free the mbuf m itself as well.
*/
static void
m_ext_free(struct mbuf *m)
{
struct mbuf *m1 = m->m_ext_ref; /* may well be m itself */
u_int refcnt;
KASSERT((m->m_flags & M_EXT) != 0);
KASSERT(MEXT_ISEMBEDDED(m1));
KASSERT((m1->m_flags & M_EXT) != 0);
KASSERT((m->m_flags & M_EXT_CLUSTER) ==
(m1->m_flags & M_EXT_CLUSTER));
if (__predict_false(m->m_type == MT_FREE)) {
panic("mbuf %p already freed", m);
}
if (__predict_true(m1->m_ext_storage.ext_refcnt == 1)) {
refcnt = m1->m_ext_storage.ext_refcnt = 0;
} else {
#ifndef __HAVE_ATOMIC_AS_MEMBAR
membar_release();
#endif
refcnt = atomic_dec_uint_nv(&m1->m_ext_storage.ext_refcnt);
}
if (refcnt == 0) {
#ifndef __HAVE_ATOMIC_AS_MEMBAR
membar_acquire();
#endif
if ((m1->m_flags & M_EXT_CLUSTER) != 0) {
pool_cache_put_paddr(mcl_cache,
m1->m_ext_storage.ext_buf, m1->m_ext_storage.ext_paddr);
m1->m_type = MT_FREE;
pool_cache_put(mb_cache, m1);
} else if (m1->m_ext_storage.ext_free) {
(*m1->m_ext_storage.ext_free)(m1,
m1->m_ext_storage.ext_buf, m1->m_ext_storage.ext_size,
m1->m_ext_storage.ext_arg);
/*
* m1 is already freed by the ext_free callback.
*/
} else {
free(m1->m_ext_storage.ext_buf, 0);
m1->m_type = MT_FREE;
pool_cache_put(mb_cache, m1);
}
}
if (__predict_false(m1 != m)) {
KASSERT(m->m_ext_storage.ext_refcnt == 0);
m->m_type = MT_FREE;
m->m_data = NULL;
pool_cache_put(mb_cache, m);
}
}
Home |
Main Index |
Thread Index |
Old Index