treat external storage allocated by the mbuf layer the same as
authordlg <dlg@openbsd.org>
Sun, 13 Jul 2014 09:52:48 +0000 (09:52 +0000)
committerdlg <dlg@openbsd.org>
Sun, 13 Jul 2014 09:52:48 +0000 (09:52 +0000)
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
sys/kern/uipc_mbuf.c
sys/sys/mbuf.h

index ae4cde5..52a1c98 100644 (file)
@@ -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 <jjbg@openbsd.org>
 .\" 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
index a2dcf8a..c985968 100644 (file)
@@ -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;
 
index cff3493..bedfdfe 100644 (file)
@@ -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 *);