From 2486872ac446a3cc4596a6daba574f3b7bbbed9f Mon Sep 17 00:00:00 2001 From: dlg Date: Sun, 13 Jul 2014 09:52:48 +0000 Subject: [PATCH] treat external storage allocated by the mbuf layer the same as external storage attached to an mbuf anywhere else. this means it uses MEXTADD to wire it up to the mbuf, and it relies on the ext_free and ext_arg bits in the header to call the right free function against the right pool. M_CLUSTER gets renamed to M_EXTWR. the type field in MEXTADD gets reused as a flags field so anything attaching storage to an mbuf can say if it is writable or not. ok claudio@ --- share/man/man9/mbuf.9 | 9 ++++---- sys/kern/uipc_mbuf.c | 52 ++++++++++++++++++++++--------------------- sys/sys/mbuf.h | 18 +++++++-------- 3 files changed, 41 insertions(+), 38 deletions(-) diff --git a/share/man/man9/mbuf.9 b/share/man/man9/mbuf.9 index ae4cde5f5d8..52a1c98375c 100644 --- a/share/man/man9/mbuf.9 +++ b/share/man/man9/mbuf.9 @@ -1,4 +1,4 @@ -.\" $OpenBSD: mbuf.9,v 1.73 2014/07/13 05:23:24 dlg Exp $ +.\" $OpenBSD: mbuf.9,v 1.74 2014/07/13 09:52:48 dlg Exp $ .\" .\" Copyright (c) 2001 Jean-Jacques Bernard-Gundol .\" All rights reserved. @@ -83,7 +83,7 @@ .Fn MCLGET "struct mbuf *m" "int how" .Ft struct mbuf * .Fn MCLGETI "struct mbuf *m" "int how" "struct ifnet *ifp" "int len" -.Fn MEXTADD "struct mbuf *m" "caddr_t buf" "u_int size" "int type" \ +.Fn MEXTADD "struct mbuf *m" "caddr_t buf" "u_int size" "int flags" \ "void (*free)(caddr_t, u_int, void *)" "void *arg" .Fn M_ALIGN "struct mbuf *m" "int len" .Fn MH_ALIGN "struct mbuf *m" "int len" @@ -636,11 +636,12 @@ See .Fn m_get for a description of .Fa how . -.It Fn MEXTADD "struct mbuf *m" "caddr_t buf" "u_int size" "int type" \ +.It Fn MEXTADD "struct mbuf *m" "caddr_t buf" "u_int size" "int flags" \ "void (*free)(caddr_t, u_int, void *)" "void *arg" Add pre-allocated storage to the mbuf pointed to by .Fa m . -On success, the flag M_EXT is set in the mbuf. +On success, the flag M_EXT is set in the mbuf, and M_EXTWR if specified in +.Fa flags .. .It Fn M_ALIGN "struct mbuf *m" "int len" Set the .Fa m_data diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index a2dcf8af65a..c985968e29e 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_mbuf.c,v 1.190 2014/07/09 13:05:45 dlg Exp $ */ +/* $OpenBSD: uipc_mbuf.c,v 1.191 2014/07/13 09:52:48 dlg Exp $ */ /* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */ /* @@ -112,7 +112,7 @@ u_int mclsizes[] = { static char mclnames[MCLPOOLS][8]; struct pool mclpools[MCLPOOLS]; -int m_clpool(u_int); +struct pool *m_clpool(u_int); int max_linkhdr; /* largest link-level header */ int max_protohdr; /* largest protocol header */ @@ -278,29 +278,32 @@ m_getclr(int nowait, int type) return (m); } -int +struct pool * m_clpool(u_int pktlen) { + struct pool *pp; int pi; - for (pi = 0; pi < MCLPOOLS; pi++) { - if (pktlen <= mclsizes[pi]) - return (pi); + for (pi = 0; pi < nitems(mclpools); pi++) { + pp = &mclpools[pi]; + if (pktlen <= pp->pr_size) + return (pp); } - return (-1); + return (NULL); } struct mbuf * m_clget(struct mbuf *m, int how, struct ifnet *ifp, u_int pktlen) { struct mbuf *m0 = NULL; - int pi; + struct pool *pp; + caddr_t buf; int s; - pi = m_clpool(pktlen); + pp = m_clpool(pktlen); #ifdef DIAGNOSTIC - if (pi == -1) + if (pp == NULL) panic("m_clget: request for %u byte cluster", pktlen); #endif @@ -313,9 +316,8 @@ m_clget(struct mbuf *m, int how, struct ifnet *ifp, u_int pktlen) } m = m0; } - m->m_ext.ext_buf = pool_get(&mclpools[pi], - how == M_WAIT ? PR_WAITOK : PR_NOWAIT); - if (!m->m_ext.ext_buf) { + buf = pool_get(pp, how == M_WAIT ? PR_WAITOK : PR_NOWAIT); + if (buf == NULL) { if (m0) m_freem(m0); splx(s); @@ -323,15 +325,17 @@ m_clget(struct mbuf *m, int how, struct ifnet *ifp, u_int pktlen) } splx(s); - m->m_data = m->m_ext.ext_buf; - m->m_flags |= M_EXT|M_CLUSTER; - m->m_ext.ext_size = mclpools[pi].pr_size; - m->m_ext.ext_free = NULL; - m->m_ext.ext_arg = &mclpools[pi]; - MCLINITREFERENCE(m); + MEXTADD(m, buf, pp->pr_size, M_EXTWR, m_extfree_pool, pp); return (m); } +void +m_extfree_pool(caddr_t buf, u_int size, void *pp) +{ + splassert(IPL_NET); + pool_put(pp, buf); +} + struct mbuf * m_free_unlocked(struct mbuf *m) { @@ -375,15 +379,13 @@ m_extfree(struct mbuf *m) m->m_ext.ext_prevref; m->m_ext.ext_prevref->m_ext.ext_nextref = m->m_ext.ext_nextref; - } else if (m->m_flags & M_CLUSTER) { - pool_put(m->m_ext.ext_arg, m->m_ext.ext_buf); } else if (m->m_ext.ext_free) (*(m->m_ext.ext_free))(m->m_ext.ext_buf, m->m_ext.ext_size, m->m_ext.ext_arg); else panic("unknown type of extension buffer"); m->m_ext.ext_size = 0; - m->m_flags &= ~(M_EXT|M_CLUSTER); + m->m_flags &= ~(M_EXT|M_EXTWR); } void @@ -449,7 +451,7 @@ m_defrag(struct mbuf *m, int how) if (m0->m_flags & M_EXT) { memcpy(&m->m_ext, &m0->m_ext, sizeof(struct mbuf_ext)); MCLINITREFERENCE(m); - m->m_flags |= M_EXT|M_CLUSTER; + m->m_flags |= m0->m_flags & (M_EXT|M_EXTWR); m->m_data = m->m_ext.ext_buf; } else { m->m_data = m->m_pktdat; @@ -457,7 +459,7 @@ m_defrag(struct mbuf *m, int how) } m->m_pkthdr.len = m->m_len = m0->m_len; - m0->m_flags &= ~(M_EXT|M_CLUSTER); /* cluster is gone */ + m0->m_flags &= ~(M_EXT|M_EXTWR); /* cluster is gone */ m_free(m0); return (0); @@ -1186,7 +1188,7 @@ m_dup_pkthdr(struct mbuf *to, struct mbuf *from, int wait) KASSERT(from->m_flags & M_PKTHDR); - to->m_flags = (to->m_flags & (M_EXT | M_CLUSTER)); + to->m_flags = (to->m_flags & (M_EXT | M_EXTWR)); to->m_flags |= (from->m_flags & M_COPYFLAGS); to->m_pkthdr = from->m_pkthdr; diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index cff349331fa..bedfdfe38a4 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mbuf.h,v 1.179 2014/07/09 13:05:45 dlg Exp $ */ +/* $OpenBSD: mbuf.h,v 1.180 2014/07/13 09:52:48 dlg Exp $ */ /* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */ /* @@ -167,7 +167,7 @@ struct mbuf { #define M_EXT 0x0001 /* has associated external storage */ #define M_PKTHDR 0x0002 /* start of record */ #define M_EOR 0x0004 /* end of record */ -#define M_CLUSTER 0x0008 /* external storage is a cluster */ +#define M_EXTWR 0x0008 /* external storage is writable */ #define M_PROTO1 0x0010 /* protocol-specific */ /* mbuf pkthdr flags, also in m_flags */ @@ -185,7 +185,7 @@ struct mbuf { #ifdef _KERNEL #define M_BITS \ - ("\20\1M_EXT\2M_PKTHDR\3M_EOR\4M_CLUSTER\5M_PROTO1\6M_VLANTAG\7M_LOOP" \ + ("\20\1M_EXT\2M_PKTHDR\3M_EOR\4M_EXTWR\5M_PROTO1\6M_VLANTAG\7M_LOOP" \ "\10M_FILDROP\11M_BCAST\12M_MCAST\13M_CONF\14M_AUTH\15M_TUNNEL" \ "\16M_ZEROIZE\17M_COMP\20M_LINK0") #endif @@ -267,7 +267,7 @@ struct mbuf { #define MCLADDREFERENCE(o, n) do { \ int ms = splnet(); \ - (n)->m_flags |= ((o)->m_flags & (M_EXT|M_CLUSTER)); \ + (n)->m_flags |= ((o)->m_flags & (M_EXT|M_EXTWR)); \ (n)->m_ext.ext_nextref = (o)->m_ext.ext_nextref; \ (n)->m_ext.ext_prevref = (o); \ (o)->m_ext.ext_nextref = (n); \ @@ -292,10 +292,9 @@ struct mbuf { * MCLGET allocates and adds an mbuf cluster to a normal mbuf; * the flag M_EXT is set upon success. */ -#define MEXTADD(m, buf, size, type, free, arg) do { \ +#define MEXTADD(m, buf, size, mflags, free, arg) do { \ (m)->m_data = (m)->m_ext.ext_buf = (caddr_t)(buf); \ - (m)->m_flags |= M_EXT; \ - (m)->m_flags &= ~M_CLUSTER; \ + (m)->m_flags |= M_EXT | (mflags & M_EXTWR); \ (m)->m_ext.ext_size = (size); \ (m)->m_ext.ext_free = (free); \ (m)->m_ext.ext_arg = (arg); \ @@ -327,7 +326,7 @@ struct mbuf { * from must have M_PKTHDR set, and to must be empty. */ #define M_MOVE_PKTHDR(to, from) do { \ - (to)->m_flags = ((to)->m_flags & (M_EXT | M_CLUSTER)); \ + (to)->m_flags = ((to)->m_flags & (M_EXT | M_EXTWR)); \ (to)->m_flags |= (from)->m_flags & M_COPYFLAGS; \ M_MOVE_HDR((to), (from)); \ if (((to)->m_flags & M_EXT) == 0) \ @@ -354,7 +353,7 @@ struct mbuf { */ #define M_READONLY(m) \ (((m)->m_flags & M_EXT) != 0 && \ - (((m)->m_flags & M_CLUSTER) == 0 || MCLISREFERENCED(m))) + (((m)->m_flags & M_EXTWR) == 0 || MCLISREFERENCED(m))) /* * Compute the amount of space available @@ -428,6 +427,7 @@ struct mbuf *m_getptr(struct mbuf *, int, int *); int m_leadingspace(struct mbuf *); int m_trailingspace(struct mbuf *); struct mbuf *m_clget(struct mbuf *, int, struct ifnet *, u_int); +void m_extfree_pool(caddr_t, u_int, void *); void m_adj(struct mbuf *, int); int m_copyback(struct mbuf *, int, int, const void *, int); void m_freem(struct mbuf *); -- 2.20.1