summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2007-10-06 21:42:39 +0000
committerkmacy <kmacy@FreeBSD.org>2007-10-06 21:42:39 +0000
commitcaeef6111c8450d350a0926d31968121a5b5ae73 (patch)
tree418691345a5209afc71ef70182373d04f589cdde /sys/kern
parentc00108fd67397129aaed54bbec1d64b7b0cd4259 (diff)
downloadFreeBSD-src-caeef6111c8450d350a0926d31968121a5b5ae73.zip
FreeBSD-src-caeef6111c8450d350a0926d31968121a5b5ae73.tar.gz
This patch adds an M_NOFREE flag which allows one to mark an mbuf as
not being independently freeable. This allows one to embed an mbuf in the cluster itself. This confers the benefits of the packet zone on all cluster sizes. Embedded mbufs currently suffer from the same limitation that packet zone mbufs do in that one cannot disconnect them and pass them around independently of the cluster. It would likely be possible to eliminate this limitation in the future by adding a second reference for the mbuf itself. Approved by: re(gnn)
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_mbuf.c1
-rw-r--r--sys/kern/uipc_mbuf.c11
2 files changed, 12 insertions, 0 deletions
diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c
index a5e1348..9015e24 100644
--- a/sys/kern/kern_mbuf.c
+++ b/sys/kern/kern_mbuf.c
@@ -347,6 +347,7 @@ mb_dtor_mbuf(void *mem, int size, void *arg)
if ((flags & MB_NOTAGS) == 0 && (m->m_flags & M_PKTHDR) != 0)
m_tag_delete_chain(m, NULL);
KASSERT((m->m_flags & M_EXT) == 0, ("%s: M_EXT set", __func__));
+ KASSERT((m->m_flags & M_NOFREE) == 0, ("%s: M_NOFREE set", __func__));
#ifdef INVARIANTS
trash_dtor(mem, size, arg);
#endif
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 2fdb407..3fefecc 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -211,9 +211,17 @@ m_extadd(struct mbuf *mb, caddr_t buf, u_int size,
void
mb_free_ext(struct mbuf *m)
{
+ int skipmbuf;
+
KASSERT((m->m_flags & M_EXT) == M_EXT, ("%s: M_EXT not set", __func__));
KASSERT(m->m_ext.ref_cnt != NULL, ("%s: ref_cnt not set", __func__));
+
+ /*
+ * check if the header is embedded in the cluster
+ */
+ skipmbuf = (m->m_flags & M_NOFREE);
+
/* Free attached storage if this mbuf is the only reference to it. */
if (*(m->m_ext.ref_cnt) == 1 ||
atomic_fetchadd_int(m->m_ext.ref_cnt, -1) == 1) {
@@ -254,6 +262,9 @@ mb_free_ext(struct mbuf *m)
("%s: unknown ext_type", __func__));
}
}
+ if (skipmbuf)
+ return;
+
/*
* Free this mbuf back to the mbuf zone with all m_ext
* information purged.
OpenPOWER on IntegriCloud