Re: squid, DNS and no buffer space

Edgar Fuß <[email protected]>
Newsgroups gmane.os.netbsd.devel.network
Message-ID <[email protected]>
> 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).
if_llatbl.c.diff (text/plain, 888 B)
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);
 }
m_ext_free (text/plain, 1.5 KB)
/*
 * 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);
	}
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.