summaryrefslogtreecommitdiff
path: root/sys/kern/uipc_mbuf.c
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2009-09-13 14:42:53 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2009-09-13 14:42:53 +0000
commit72c9514b3fe03e2af58b7386b4ea1b1b8d03bb73 (patch)
treeddd67747f9e94367b396ade568c730dfa795adb5 /sys/kern/uipc_mbuf.c
parent4eef650080d9b8f29430c67e8bfb02019d822601 (diff)
M_DUP_PKTHDR() define -> m_dup_pkthdr() function to properly deal
with m_tag_copy_chain() failures. Use m_defrag() to eliminate hand rolled defragging of mbufs and some uses of M_DUP_PKTHDR(). Original diff from thib@, claudio@'s feedback integrated by me. Tests kevlo@ claudio@, "reads ok" blambert@ ok thib@ claudio@, "m_defrag() bits ok" kettenis@
Diffstat (limited to 'sys/kern/uipc_mbuf.c')
-rw-r--r--sys/kern/uipc_mbuf.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 96c3b2da5c5..9c9cae4d301 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_mbuf.c,v 1.133 2009/08/12 21:44:49 henning Exp $ */
+/* $OpenBSD: uipc_mbuf.c,v 1.134 2009/09/13 14:42:52 krw Exp $ */
/* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */
/*
@@ -629,7 +629,8 @@ m_copym0(struct mbuf *m, int off, int len, int wait, int deep)
if (n == NULL)
goto nospace;
if (copyhdr) {
- M_DUP_PKTHDR(n, m);
+ if (m_dup_pkthdr(n, m))
+ goto nospace;
if (len != M_COPYALL)
n->m_pkthdr.len = len;
copyhdr = 0;
@@ -1124,7 +1125,10 @@ m_split(struct mbuf *m0, int len0, int wait)
MGETHDR(n, wait, m0->m_type);
if (n == NULL)
return (NULL);
- M_DUP_PKTHDR(n, m0);
+ if (m_dup_pkthdr(n, m0)) {
+ m_freem(n);
+ return (NULL);
+ }
n->m_pkthdr.len -= len0;
olen = m0->m_pkthdr.len;
m0->m_pkthdr.len = len0;
@@ -1315,3 +1319,28 @@ m_trailingspace(struct mbuf *m)
m->m_ext.ext_size - (m->m_data + m->m_len) :
&m->m_dat[MLEN] - (m->m_data + m->m_len));
}
+
+
+/*
+ * Duplicate mbuf pkthdr from from to to.
+ * from must have M_PKTHDR set, and to must be empty.
+ */
+int
+m_dup_pkthdr(struct mbuf *to, struct mbuf *from)
+{
+ KASSERT(from->m_flags & M_PKTHDR);
+
+ to->m_flags = (to->m_flags & (M_EXT | M_CLUSTER));
+ to->m_flags |= (from->m_flags & M_COPYFLAGS);
+ to->m_pkthdr = from->m_pkthdr;
+
+ SLIST_INIT(&to->m_pkthdr.tags);
+
+ if (m_tag_copy_chain(to, from))
+ return (ENOMEM);
+
+ if ((to->m_flags & M_EXT) == 0)
+ to->m_data = to->m_pktdat;
+
+ return (0);
+}