xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 17102)
1*17102Sbloom /*	uipc_mbuf.c	6.3	84/08/29	*/
24585Swnj 
39765Ssam #include "../machine/pte.h"
49765Ssam 
5*17102Sbloom #include "param.h"
6*17102Sbloom #include "dir.h"
7*17102Sbloom #include "user.h"
8*17102Sbloom #include "proc.h"
9*17102Sbloom #include "cmap.h"
10*17102Sbloom #include "map.h"
11*17102Sbloom #include "mbuf.h"
12*17102Sbloom #include "vm.h"
13*17102Sbloom #include "kernel.h"
144585Swnj 
155228Swnj mbinit()
165228Swnj {
175228Swnj 
189765Ssam 	if (m_clalloc(4096/CLBYTES, MPG_MBUFS) == 0)
195228Swnj 		goto bad;
209765Ssam 	if (m_clalloc(8*4096/CLBYTES, MPG_CLUSTERS) == 0)
215228Swnj 		goto bad;
225228Swnj 	return;
235228Swnj bad:
245228Swnj 	panic("mbinit");
255228Swnj }
265228Swnj 
275228Swnj caddr_t
285228Swnj m_clalloc(ncl, how)
295228Swnj 	register int ncl;
305228Swnj 	int how;
315228Swnj {
325228Swnj 	int npg, mbx;
335228Swnj 	register struct mbuf *m;
345228Swnj 	register int i;
355228Swnj 	int s;
365228Swnj 
375228Swnj 	npg = ncl * CLSIZE;
385581Swnj 	s = splimp();		/* careful: rmalloc isn't reentrant */
398792Sroot 	mbx = rmalloc(mbmap, (long)npg);
405581Swnj 	splx(s);
415228Swnj 	if (mbx == 0)
425228Swnj 		return (0);
435228Swnj 	m = cltom(mbx / CLSIZE);
449765Ssam 	if (memall(&Mbmap[mbx], npg, proc, CSYS) == 0) {
459765Ssam 		s = splimp();
469765Ssam 		rmfree(mbmap, (long)npg, (long)mbx);
479765Ssam 		splx(s);
485228Swnj 		return (0);
499765Ssam 	}
505228Swnj 	vmaccess(&Mbmap[mbx], (caddr_t)m, npg);
515228Swnj 	switch (how) {
525228Swnj 
535228Swnj 	case MPG_CLUSTERS:
545228Swnj 		s = splimp();
555228Swnj 		for (i = 0; i < ncl; i++) {
565228Swnj 			m->m_off = 0;
575228Swnj 			m->m_next = mclfree;
585228Swnj 			mclfree = m;
595228Swnj 			m += CLBYTES / sizeof (*m);
606839Ssam 			mbstat.m_clfree++;
615228Swnj 		}
625228Swnj 		mbstat.m_clusters += ncl;
635228Swnj 		splx(s);
645228Swnj 		break;
655228Swnj 
665228Swnj 	case MPG_MBUFS:
675228Swnj 		for (i = ncl * CLBYTES / sizeof (*m); i > 0; i--) {
685228Swnj 			m->m_off = 0;
699634Ssam 			m->m_type = MT_DATA;
709634Ssam 			mbstat.m_mtypes[MT_DATA]++;
716839Ssam 			mbstat.m_mbufs++;
725228Swnj 			(void) m_free(m);
735228Swnj 			m++;
745228Swnj 		}
755232Swnj 		break;
765228Swnj 	}
775228Swnj 	return ((caddr_t)m);
785228Swnj }
795228Swnj 
805228Swnj m_pgfree(addr, n)
815228Swnj 	caddr_t addr;
825228Swnj 	int n;
835228Swnj {
845228Swnj 
856141Ssam #ifdef lint
866141Ssam 	addr = addr; n = n;
876141Ssam #endif
885228Swnj }
895228Swnj 
905228Swnj m_expand()
915228Swnj {
925228Swnj 
935228Swnj 	if (m_clalloc(1, MPG_MBUFS) == 0)
945228Swnj 		goto steal;
955228Swnj 	return (1);
965228Swnj steal:
975228Swnj 	/* should ask protocols to free code */
985228Swnj 	return (0);
995228Swnj }
1005228Swnj 
1015228Swnj /* NEED SOME WAY TO RELEASE SPACE */
1025228Swnj 
1035228Swnj /*
1045228Swnj  * Space allocation routines.
1055228Swnj  * These are also available as macros
1065228Swnj  * for critical paths.
1075228Swnj  */
1084585Swnj struct mbuf *
1099634Ssam m_get(canwait, type)
1109634Ssam 	int canwait, type;
1114585Swnj {
1124585Swnj 	register struct mbuf *m;
1134585Swnj 
1149634Ssam 	MGET(m, canwait, type);
1154585Swnj 	return (m);
1164585Swnj }
1174585Swnj 
1184585Swnj struct mbuf *
1199634Ssam m_getclr(canwait, type)
1209634Ssam 	int canwait, type;
1214890Swnj {
1224890Swnj 	register struct mbuf *m;
1234890Swnj 
1249634Ssam 	m = m_get(canwait, type);
1254890Swnj 	if (m == 0)
1264890Swnj 		return (0);
1274890Swnj 	bzero(mtod(m, caddr_t), MLEN);
1284890Swnj 	return (m);
1294890Swnj }
1304890Swnj 
1314890Swnj struct mbuf *
1324585Swnj m_free(m)
1334585Swnj 	struct mbuf *m;
1344585Swnj {
1354585Swnj 	register struct mbuf *n;
1364585Swnj 
1374585Swnj 	MFREE(m, n);
1384585Swnj 	return (n);
1394585Swnj }
1404585Swnj 
1414916Swnj /*ARGSUSED*/
1424585Swnj struct mbuf *
1439634Ssam m_more(canwait, type)
1449634Ssam 	int canwait, type;
1454585Swnj {
1464585Swnj 	register struct mbuf *m;
1474585Swnj 
1484585Swnj 	if (!m_expand()) {
1494822Swnj 		mbstat.m_drops++;
1504585Swnj 		return (NULL);
1514585Swnj 	}
1529634Ssam #define m_more(x,y) (panic("m_more"), (struct mbuf *)0)
1539634Ssam 	MGET(m, canwait, type);
1545282Sroot #undef m_more
1554585Swnj 	return (m);
1564585Swnj }
1574585Swnj 
1584669Swnj m_freem(m)
1594585Swnj 	register struct mbuf *m;
1604585Swnj {
1614585Swnj 	register struct mbuf *n;
1624927Swnj 	register int s;
1634585Swnj 
1644585Swnj 	if (m == NULL)
1654916Swnj 		return;
1664662Swnj 	s = splimp();
1674585Swnj 	do {
1684585Swnj 		MFREE(m, n);
1694585Swnj 	} while (m = n);
1704585Swnj 	splx(s);
1714585Swnj }
1724585Swnj 
1735228Swnj /*
1745228Swnj  * Mbuffer utility routines.
1755228Swnj  */
1764927Swnj struct mbuf *
1774927Swnj m_copy(m, off, len)
1784927Swnj 	register struct mbuf *m;
1794927Swnj 	int off;
1804927Swnj 	register int len;
1814927Swnj {
1824927Swnj 	register struct mbuf *n, **np;
1834927Swnj 	struct mbuf *top, *p;
1844927Swnj 
1854927Swnj 	if (len == 0)
1864927Swnj 		return (0);
1874927Swnj 	if (off < 0 || len < 0)
1884927Swnj 		panic("m_copy");
1894927Swnj 	while (off > 0) {
1904927Swnj 		if (m == 0)
1914927Swnj 			panic("m_copy");
1924927Swnj 		if (off < m->m_len)
1934927Swnj 			break;
1944927Swnj 		off -= m->m_len;
1954927Swnj 		m = m->m_next;
1964927Swnj 	}
1974927Swnj 	np = &top;
1984927Swnj 	top = 0;
1994927Swnj 	while (len > 0) {
2005609Swnj 		if (m == 0) {
2015609Swnj 			if (len != M_COPYALL)
2025609Swnj 				panic("m_copy");
2035609Swnj 			break;
2045609Swnj 		}
20516075Skarels 		MGET(n, M_WAIT, m->m_type);
2064927Swnj 		*np = n;
2074927Swnj 		if (n == 0)
2084927Swnj 			goto nospace;
2094927Swnj 		n->m_len = MIN(len, m->m_len - off);
2104927Swnj 		if (m->m_off > MMAXOFF) {
2114927Swnj 			p = mtod(m, struct mbuf *);
2124927Swnj 			n->m_off = ((int)p - (int)n) + off;
2135090Swnj 			mclrefcnt[mtocl(p)]++;
2148318Sroot 		} else
2154927Swnj 			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
2164927Swnj 			    (unsigned)n->m_len);
2175609Swnj 		if (len != M_COPYALL)
2185609Swnj 			len -= n->m_len;
2194927Swnj 		off = 0;
2204927Swnj 		m = m->m_next;
2214927Swnj 		np = &n->m_next;
2224927Swnj 	}
2234927Swnj 	return (top);
2244927Swnj nospace:
2254927Swnj 	m_freem(top);
2264927Swnj 	return (0);
2274927Swnj }
2284927Swnj 
2294669Swnj m_cat(m, n)
2304669Swnj 	register struct mbuf *m, *n;
2314669Swnj {
2324669Swnj 	while (m->m_next)
2334669Swnj 		m = m->m_next;
2346091Sroot 	while (n) {
2356091Sroot 		if (m->m_off >= MMAXOFF ||
2366091Sroot 		    m->m_off + m->m_len + n->m_len > MMAXOFF) {
2376091Sroot 			/* just join the two chains */
2384669Swnj 			m->m_next = n;
2396091Sroot 			return;
2404669Swnj 		}
2416091Sroot 		/* splat the data from one into the other */
2426091Sroot 		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
2436091Sroot 		    (u_int)n->m_len);
2446091Sroot 		m->m_len += n->m_len;
2456091Sroot 		n = m_free(n);
2466091Sroot 	}
2474669Swnj }
2484669Swnj 
2494585Swnj m_adj(mp, len)
2504585Swnj 	struct mbuf *mp;
2514916Swnj 	register int len;
2524585Swnj {
2534585Swnj 	register struct mbuf *m, *n;
2544585Swnj 
2554585Swnj 	if ((m = mp) == NULL)
2564585Swnj 		return;
2574822Swnj 	if (len >= 0) {
2584585Swnj 		while (m != NULL && len > 0) {
2594822Swnj 			if (m->m_len <= len) {
2604585Swnj 				len -= m->m_len;
2614585Swnj 				m->m_len = 0;
2624585Swnj 				m = m->m_next;
2634822Swnj 			} else {
2644585Swnj 				m->m_len -= len;
2654585Swnj 				m->m_off += len;
2664585Swnj 				break;
2674585Swnj 			}
2684585Swnj 		}
2694822Swnj 	} else {
2704822Swnj 		/* a 2 pass algorithm might be better */
2714585Swnj 		len = -len;
2724585Swnj 		while (len > 0 && m->m_len != 0) {
2734585Swnj 			while (m != NULL && m->m_len != 0) {
2744585Swnj 				n = m;
2754585Swnj 				m = m->m_next;
2764585Swnj 			}
2774822Swnj 			if (n->m_len <= len) {
2784585Swnj 				len -= n->m_len;
2794585Swnj 				n->m_len = 0;
2804585Swnj 				m = mp;
2814822Swnj 			} else {
2824585Swnj 				n->m_len -= len;
2834585Swnj 				break;
2844585Swnj 			}
2854585Swnj 		}
2864585Swnj 	}
2874585Swnj }
2885228Swnj 
2895310Sroot struct mbuf *
2905310Sroot m_pullup(m0, len)
2915310Sroot 	struct mbuf *m0;
2925228Swnj 	int len;
2935228Swnj {
2945310Sroot 	register struct mbuf *m, *n;
2956164Ssam 	int count;
2965228Swnj 
2975732Sroot 	n = m0;
2985310Sroot 	if (len > MLEN)
2995310Sroot 		goto bad;
3009634Ssam 	MGET(m, M_DONTWAIT, n->m_type);
3015310Sroot 	if (m == 0)
3025310Sroot 		goto bad;
3035310Sroot 	m->m_len = 0;
3045310Sroot 	do {
3056164Ssam 		count = MIN(MLEN - m->m_len, len);
3066164Ssam 		if (count > n->m_len)
3076164Ssam 			count = n->m_len;
3086164Ssam 		bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len,
3096164Ssam 		  (unsigned)count);
3106164Ssam 		len -= count;
3116164Ssam 		m->m_len += count;
3126164Ssam 		n->m_off += count;
3136164Ssam 		n->m_len -= count;
3145310Sroot 		if (n->m_len)
3155310Sroot 			break;
3165310Sroot 		n = m_free(n);
3175310Sroot 	} while (n);
3185310Sroot 	if (len) {
3195310Sroot 		(void) m_free(m);
3205310Sroot 		goto bad;
3215310Sroot 	}
3225310Sroot 	m->m_next = n;
3235310Sroot 	return (m);
3245310Sroot bad:
3255732Sroot 	m_freem(n);
3265228Swnj 	return (0);
3275228Swnj }
328