only delete space used by inode, on inode deletion; required
[unix-history] / usr / src / sys / kern / uipc_mbuf.c
index de6a39d..7959e40 100644 (file)
@@ -3,7 +3,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)uipc_mbuf.c 7.19 (Berkeley) %G%
+ *     @(#)uipc_mbuf.c 7.22 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -46,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;
@@ -55,7 +56,7 @@ m_clalloc(ncl, canwait)
        static int logged;
 
        npg = ncl * CLSIZE;
        static int logged;
 
        npg = ncl * CLSIZE;
-       p = (caddr_t)kmem_malloc(mb_map, ctob(npg), canwait);
+       p = (caddr_t)kmem_malloc(mb_map, ctob(npg), !nowait);
        if (p == NULL) {
                if (logged == 0) {
                        logged++;
        if (p == NULL) {
                if (logged == 0) {
                        logged++;
@@ -127,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);
@@ -169,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;
 {
@@ -349,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;
@@ -487,3 +490,137 @@ bad:
        MPFail++;
        return (0);
 }
        MPFail++;
        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 = ⊤
+       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);
+}