only delete space used by inode, on inode deletion; required
[unix-history] / usr / src / sys / kern / uipc_mbuf.c
index 6e6807d..7959e40 100644 (file)
@@ -1,43 +1,33 @@
 /*
  * All rights reserved.
  *
 /*
  * All rights reserved.
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * %sccs.include.redist.c%
  *
  *
- *     @(#)uipc_mbuf.c 7.12 (Berkeley) %G%
+ *     @(#)uipc_mbuf.c 7.22 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
-#include "dir.h"
-#include "user.h"
 #include "proc.h"
 #include "proc.h"
-#include "cmap.h"
 #include "malloc.h"
 #include "map.h"
 #define MBTYPES
 #include "mbuf.h"
 #include "malloc.h"
 #include "map.h"
 #define MBTYPES
 #include "mbuf.h"
-#include "vm.h"
 #include "kernel.h"
 #include "syslog.h"
 #include "domain.h"
 #include "protosw.h"
 #include "kernel.h"
 #include "syslog.h"
 #include "domain.h"
 #include "protosw.h"
-#include "machine/pte.h"
+#include "vm/vm.h"
+
+extern vm_map_t mb_map;
+struct mbuf *mbutl;
+char   *mclrefcnt;
 
 mbinit()
 {
        int s;
 
 
 mbinit()
 {
        int s;
 
-#if MCLBYTES < 4096
-#define NCL_INIT       (4096/MCLBYTES)
+#if CLBYTES < 4096
+#define NCL_INIT       (4096/CLBYTES)
 #else
 #define NCL_INIT       1
 #endif
 #else
 #define NCL_INIT       1
 #endif
@@ -56,8 +46,9 @@ bad:
  * Must be called at splimp.
  */
 /* ARGSUSED */
  * Must be called at splimp.
  */
 /* ARGSUSED */
-m_clalloc(ncl, canwait)
+m_clalloc(ncl, nowait)
        register int ncl;
        register int ncl;
+       int nowait;
 {
        int npg, mbx;
        register caddr_t p;
 {
        int npg, mbx;
        register caddr_t p;
@@ -65,20 +56,14 @@ m_clalloc(ncl, canwait)
        static int logged;
 
        npg = ncl * CLSIZE;
        static int logged;
 
        npg = ncl * CLSIZE;
-       mbx = rmalloc(mbmap, (long)npg);
-       if (mbx == 0) {
+       p = (caddr_t)kmem_malloc(mb_map, ctob(npg), !nowait);
+       if (p == NULL) {
                if (logged == 0) {
                        logged++;
                if (logged == 0) {
                        logged++;
-                       log(LOG_ERR, "mbuf map full\n");
+                       log(LOG_ERR, "mb_map full\n");
                }
                return (0);
        }
                }
                return (0);
        }
-       p = cltom(mbx * NBPG / MCLBYTES);
-       if (memall(&Mbmap[mbx], npg, proc, CSYS) == 0) {
-               rmfree(mbmap, (long)npg, (long)mbx);
-               return (0);
-       }
-       vmaccess(&Mbmap[mbx], p, npg);
        ncl = ncl * CLBYTES / MCLBYTES;
        for (i = 0; i < ncl; i++) {
                ((union mcluster *)p)->mcl_next = mclfree;
        ncl = ncl * CLBYTES / MCLBYTES;
        for (i = 0; i < ncl; i++) {
                ((union mcluster *)p)->mcl_next = mclfree;
@@ -143,32 +128,32 @@ m_reclaim()
  * for critical paths.
  */
 struct mbuf *
  * for critical paths.
  */
 struct mbuf *
-m_get(canwait, type)
-       int canwait, type;
+m_get(nowait, type)
+       int nowait, type;
 {
        register struct mbuf *m;
 
 {
        register struct mbuf *m;
 
-       MGET(m, canwait, type);
+       MGET(m, nowait, type);
        return (m);
 }
 
 struct mbuf *
        return (m);
 }
 
 struct mbuf *
-m_gethdr(canwait, type)
-       int canwait, type;
+m_gethdr(nowait, type)
+       int nowait, type;
 {
        register struct mbuf *m;
 
 {
        register struct mbuf *m;
 
-       MGETHDR(m, canwait, type);
+       MGETHDR(m, nowait, type);
        return (m);
 }
 
 struct mbuf *
        return (m);
 }
 
 struct mbuf *
-m_getclr(canwait, type)
-       int canwait, type;
+m_getclr(nowait, type)
+       int nowait, type;
 {
        register struct mbuf *m;
 
 {
        register struct mbuf *m;
 
-       MGET(m, canwait, type);
+       MGET(m, nowait, type);
        if (m == 0)
                return (0);
        bzero(mtod(m, caddr_t), MLEN);
        if (m == 0)
                return (0);
        bzero(mtod(m, caddr_t), MLEN);
@@ -185,6 +170,7 @@ m_free(m)
        return (n);
 }
 
        return (n);
 }
 
+void
 m_freem(m)
        register struct mbuf *m;
 {
 m_freem(m)
        register struct mbuf *m;
 {
@@ -230,12 +216,13 @@ m_prepend(m, len, how)
        return (m);
 }
 
        return (m);
 }
 
-/*
 /*
  * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
  * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
  * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
  */
 /*
  * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
  * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
  * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
  */
+int MCFail;
+
 struct mbuf *
 m_copym(m, off0, len, wait)
        register struct mbuf *m;
 struct mbuf *
 m_copym(m, off0, len, wait)
        register struct mbuf *m;
@@ -294,9 +281,12 @@ m_copym(m, off0, len, wait)
                m = m->m_next;
                np = &n->m_next;
        }
                m = m->m_next;
                np = &n->m_next;
        }
+       if (top == 0)
+               MCFail++;
        return (top);
 nospace:
        m_freem(top);
        return (top);
 nospace:
        m_freem(top);
+       MCFail++;
        return (0);
 }
 
        return (0);
 }
 
@@ -361,6 +351,7 @@ m_cat(m, n)
 
 m_adj(mp, req_len)
        struct mbuf *mp;
 
 m_adj(mp, req_len)
        struct mbuf *mp;
+       int req_len;
 {
        register int len = req_len;
        register struct mbuf *m;
 {
        register int len = req_len;
        register struct mbuf *m;
@@ -439,6 +430,8 @@ m_adj(mp, req_len)
  * If there is room, it will add up to max_protohdr-len extra bytes to the
  * contiguous region in an attempt to avoid being called next time.
  */
  * If there is room, it will add up to max_protohdr-len extra bytes to the
  * contiguous region in an attempt to avoid being called next time.
  */
+int MPFail;
+
 struct mbuf *
 m_pullup(n, len)
        register struct mbuf *n;
 struct mbuf *
 m_pullup(n, len)
        register struct mbuf *n;
@@ -467,8 +460,10 @@ m_pullup(n, len)
                if (m == 0)
                        goto bad;
                m->m_len = 0;
                if (m == 0)
                        goto bad;
                m->m_len = 0;
-               if (n->m_flags & M_PKTHDR)
+               if (n->m_flags & M_PKTHDR) {
                        M_COPY_PKTHDR(m, n);
                        M_COPY_PKTHDR(m, n);
+                       n->m_flags &= ~M_PKTHDR;
+               }
        }
        space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
        do {
        }
        space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
        do {
@@ -492,5 +487,140 @@ m_pullup(n, len)
        return (m);
 bad:
        m_freem(n);
        return (m);
 bad:
        m_freem(n);
+       MPFail++;
        return (0);
 }
        return (0);
 }
+
+/*
+ * Partition an mbuf chain in two pieces, returning the tail --
+ * all but the first len0 bytes.  In case of failure, it returns NULL and
+ * attempts to restore the chain to its original state.
+ */
+struct mbuf *
+m_split(m0, len0, wait)
+       register struct mbuf *m0;
+       int len0, wait;
+{
+       register struct mbuf *m, *n;
+       unsigned len = len0, remain;
+
+       for (m = m0; m && len > m->m_len; m = m->m_next)
+               len -= m->m_len;
+       if (m == 0)
+               return (0);
+       remain = m->m_len - len;
+       if (m0->m_flags & M_PKTHDR) {
+               MGETHDR(n, wait, m0->m_type);
+               if (n == 0)
+                       return (0);
+               n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
+               n->m_pkthdr.len = m0->m_pkthdr.len - len0;
+               m0->m_pkthdr.len = len0;
+               if (m->m_flags & M_EXT)
+                       goto extpacket;
+               if (remain > MHLEN) {
+                       /* m can't be the lead packet */
+                       MH_ALIGN(n, 0);
+                       n->m_next = m_split(m, len, wait);
+                       if (n->m_next == 0) {
+                               (void) m_free(n);
+                               return (0);
+                       } else
+                               return (n);
+               } else
+                       MH_ALIGN(n, remain);
+       } else if (remain == 0) {
+               n = m->m_next;
+               m->m_next = 0;
+               return (n);
+       } else {
+               MGET(n, wait, m->m_type);
+               if (n == 0)
+                       return (0);
+               M_ALIGN(n, remain);
+       }
+extpacket:
+       if (m->m_flags & M_EXT) {
+               n->m_flags |= M_EXT;
+               n->m_ext = m->m_ext;
+               mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
+               m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
+               n->m_data = m->m_data + len;
+       } else {
+               bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
+       }
+       n->m_len = remain;
+       m->m_len = len;
+       n->m_next = m->m_next;
+       m->m_next = 0;
+       return (n);
+}
+/*
+ * Routine to copy from device local memory into mbufs.
+ */
+struct mbuf *
+m_devget(buf, totlen, off0, ifp, copy)
+       char *buf;
+       int totlen, off0;
+       struct ifnet *ifp;
+       void (*copy)();
+{
+       register struct mbuf *m;
+       struct mbuf *top = 0, **mp = &top;
+       register int off = off0, len;
+       register char *cp;
+       char *epkt;
+
+       cp = buf;
+       epkt = cp + totlen;
+       if (off) {
+               cp += off + 2 * sizeof(u_short);
+               totlen -= 2 * sizeof(u_short);
+       }
+       MGETHDR(m, M_DONTWAIT, MT_DATA);
+       if (m == 0)
+               return (0);
+       m->m_pkthdr.rcvif = ifp;
+       m->m_pkthdr.len = totlen;
+       m->m_len = MHLEN;
+
+       while (totlen > 0) {
+               if (top) {
+                       MGET(m, M_DONTWAIT, MT_DATA);
+                       if (m == 0) {
+                               m_freem(top);
+                               return (0);
+                       }
+                       m->m_len = MLEN;
+               }
+               len = min(totlen, epkt - cp);
+               if (len >= MINCLSIZE) {
+                       MCLGET(m, M_DONTWAIT);
+                       if (m->m_flags & M_EXT)
+                               m->m_len = len = min(len, MCLBYTES);
+                       else
+                               len = m->m_len;
+               } else {
+                       /*
+                        * Place initial small packet/header at end of mbuf.
+                        */
+                       if (len < m->m_len) {
+                               if (top == 0 && len + max_linkhdr <= m->m_len)
+                                       m->m_data += max_linkhdr;
+                               m->m_len = len;
+                       } else
+                               len = m->m_len;
+               }
+               if (copy)
+                       copy(cp, mtod(m, caddr_t), (unsigned)len);
+               else
+                       bcopy(cp, mtod(m, caddr_t), (unsigned)len);
+               cp += len;
+               *mp = m;
+               mp = &m->m_next;
+               totlen -= len;
+               if (cp == epkt)
+                       cp = buf;
+       }
+       return (top);
+}