xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 8792)
1*8792Sroot /*	uipc_mbuf.c	1.40	82/10/21	*/
24585Swnj 
34585Swnj #include "../h/param.h"
44585Swnj #include "../h/dir.h"
54585Swnj #include "../h/user.h"
64585Swnj #include "../h/proc.h"
74585Swnj #include "../h/pte.h"
84585Swnj #include "../h/cmap.h"
94585Swnj #include "../h/map.h"
104641Swnj #include "../h/mbuf.h"
114585Swnj #include "../h/vm.h"
128770Sroot #include "../h/kernel.h"
134585Swnj 
145228Swnj mbinit()
155228Swnj {
165228Swnj 
175228Swnj 	if (m_clalloc(4, MPG_MBUFS) == 0)
185228Swnj 		goto bad;
195228Swnj 	if (m_clalloc(32, MPG_CLUSTERS) == 0)
205228Swnj 		goto bad;
215228Swnj 	return;
225228Swnj bad:
235228Swnj 	panic("mbinit");
245228Swnj }
255228Swnj 
265228Swnj caddr_t
275228Swnj m_clalloc(ncl, how)
285228Swnj 	register int ncl;
295228Swnj 	int how;
305228Swnj {
315228Swnj 	int npg, mbx;
325228Swnj 	register struct mbuf *m;
335228Swnj 	register int i;
345228Swnj 	int s;
355228Swnj 
365228Swnj 	npg = ncl * CLSIZE;
375581Swnj 	s = splimp();		/* careful: rmalloc isn't reentrant */
38*8792Sroot 	mbx = rmalloc(mbmap, (long)npg);
395581Swnj 	splx(s);
405228Swnj 	if (mbx == 0)
415228Swnj 		return (0);
425228Swnj 	m = cltom(mbx / CLSIZE);
436850Ssam 	if (memall(&Mbmap[mbx], npg, proc, CSYS) == 0)
445228Swnj 		return (0);
455228Swnj 	vmaccess(&Mbmap[mbx], (caddr_t)m, npg);
465228Swnj 	switch (how) {
475228Swnj 
485228Swnj 	case MPG_CLUSTERS:
495228Swnj 		s = splimp();
505228Swnj 		for (i = 0; i < ncl; i++) {
515228Swnj 			m->m_off = 0;
525228Swnj 			m->m_next = mclfree;
535228Swnj 			mclfree = m;
545228Swnj 			m += CLBYTES / sizeof (*m);
556839Ssam 			mbstat.m_clfree++;
565228Swnj 		}
575228Swnj 		mbstat.m_clusters += ncl;
585228Swnj 		splx(s);
595228Swnj 		break;
605228Swnj 
615228Swnj 	case MPG_MBUFS:
625228Swnj 		for (i = ncl * CLBYTES / sizeof (*m); i > 0; i--) {
635228Swnj 			m->m_off = 0;
645273Sroot 			m->m_free = 0;
656839Ssam 			mbstat.m_mbufs++;
665228Swnj 			(void) m_free(m);
675228Swnj 			m++;
685228Swnj 		}
695232Swnj 		break;
705228Swnj 	}
715228Swnj 	return ((caddr_t)m);
725228Swnj }
735228Swnj 
745228Swnj m_pgfree(addr, n)
755228Swnj 	caddr_t addr;
765228Swnj 	int n;
775228Swnj {
785228Swnj 
796141Ssam #ifdef lint
806141Ssam 	addr = addr; n = n;
816141Ssam #endif
825228Swnj }
835228Swnj 
845228Swnj m_expand()
855228Swnj {
865228Swnj 
875228Swnj 	if (m_clalloc(1, MPG_MBUFS) == 0)
885228Swnj 		goto steal;
895228Swnj 	return (1);
905228Swnj steal:
915228Swnj 	/* should ask protocols to free code */
925228Swnj 	return (0);
935228Swnj }
945228Swnj 
955228Swnj /* NEED SOME WAY TO RELEASE SPACE */
965228Swnj 
975228Swnj /*
985228Swnj  * Space allocation routines.
995228Swnj  * These are also available as macros
1005228Swnj  * for critical paths.
1015228Swnj  */
1024585Swnj struct mbuf *
1034585Swnj m_get(canwait)
1044585Swnj 	int canwait;
1054585Swnj {
1064585Swnj 	register struct mbuf *m;
1074585Swnj 
1084585Swnj 	MGET(m, canwait);
1094585Swnj 	return (m);
1104585Swnj }
1114585Swnj 
1124585Swnj struct mbuf *
1134890Swnj m_getclr(canwait)
1144890Swnj 	int canwait;
1154890Swnj {
1164890Swnj 	register struct mbuf *m;
1174890Swnj 
1184916Swnj 	m = m_get(canwait);
1194890Swnj 	if (m == 0)
1204890Swnj 		return (0);
1214890Swnj 	bzero(mtod(m, caddr_t), MLEN);
1224890Swnj 	return (m);
1234890Swnj }
1244890Swnj 
1254890Swnj struct mbuf *
1264585Swnj m_free(m)
1274585Swnj 	struct mbuf *m;
1284585Swnj {
1294585Swnj 	register struct mbuf *n;
1304585Swnj 
1314585Swnj 	MFREE(m, n);
1324585Swnj 	return (n);
1334585Swnj }
1344585Swnj 
1354916Swnj /*ARGSUSED*/
1364585Swnj struct mbuf *
1374585Swnj m_more(type)
1384585Swnj 	int type;
1394585Swnj {
1404585Swnj 	register struct mbuf *m;
1414585Swnj 
1424585Swnj 	if (!m_expand()) {
1434822Swnj 		mbstat.m_drops++;
1444585Swnj 		return (NULL);
1454585Swnj 	}
1464916Swnj #define m_more(x) (panic("m_more"), (struct mbuf *)0)
1474916Swnj 	MGET(m, type);
1485282Sroot #undef m_more
1494585Swnj 	return (m);
1504585Swnj }
1514585Swnj 
1524669Swnj m_freem(m)
1534585Swnj 	register struct mbuf *m;
1544585Swnj {
1554585Swnj 	register struct mbuf *n;
1564927Swnj 	register int s;
1574585Swnj 
1584585Swnj 	if (m == NULL)
1594916Swnj 		return;
1604662Swnj 	s = splimp();
1614585Swnj 	do {
1624585Swnj 		MFREE(m, n);
1634585Swnj 	} while (m = n);
1644585Swnj 	splx(s);
1654585Swnj }
1664585Swnj 
1675228Swnj /*
1685228Swnj  * Mbuffer utility routines.
1695228Swnj  */
1704927Swnj struct mbuf *
1714927Swnj m_copy(m, off, len)
1724927Swnj 	register struct mbuf *m;
1734927Swnj 	int off;
1744927Swnj 	register int len;
1754927Swnj {
1764927Swnj 	register struct mbuf *n, **np;
1774927Swnj 	struct mbuf *top, *p;
1784927Swnj 
1794927Swnj 	if (len == 0)
1804927Swnj 		return (0);
1814927Swnj 	if (off < 0 || len < 0)
1824927Swnj 		panic("m_copy");
1834927Swnj 	while (off > 0) {
1844927Swnj 		if (m == 0)
1854927Swnj 			panic("m_copy");
1864927Swnj 		if (off < m->m_len)
1874927Swnj 			break;
1884927Swnj 		off -= m->m_len;
1894927Swnj 		m = m->m_next;
1904927Swnj 	}
1914927Swnj 	np = &top;
1924927Swnj 	top = 0;
1934927Swnj 	while (len > 0) {
1945609Swnj 		if (m == 0) {
1955609Swnj 			if (len != M_COPYALL)
1965609Swnj 				panic("m_copy");
1975609Swnj 			break;
1985609Swnj 		}
1994927Swnj 		MGET(n, 1);
2004927Swnj 		*np = n;
2014927Swnj 		if (n == 0)
2024927Swnj 			goto nospace;
2034927Swnj 		n->m_len = MIN(len, m->m_len - off);
2044927Swnj 		if (m->m_off > MMAXOFF) {
2054927Swnj 			p = mtod(m, struct mbuf *);
2064927Swnj 			n->m_off = ((int)p - (int)n) + off;
2075090Swnj 			mclrefcnt[mtocl(p)]++;
2088318Sroot 		} else
2094927Swnj 			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
2104927Swnj 			    (unsigned)n->m_len);
2115609Swnj 		if (len != M_COPYALL)
2125609Swnj 			len -= n->m_len;
2134927Swnj 		off = 0;
2144927Swnj 		m = m->m_next;
2154927Swnj 		np = &n->m_next;
2164927Swnj 	}
2174927Swnj 	return (top);
2184927Swnj nospace:
2194927Swnj 	m_freem(top);
2204927Swnj 	return (0);
2214927Swnj }
2224927Swnj 
2234669Swnj m_cat(m, n)
2244669Swnj 	register struct mbuf *m, *n;
2254669Swnj {
2264669Swnj 	while (m->m_next)
2274669Swnj 		m = m->m_next;
2286091Sroot 	while (n) {
2296091Sroot 		if (m->m_off >= MMAXOFF ||
2306091Sroot 		    m->m_off + m->m_len + n->m_len > MMAXOFF) {
2316091Sroot 			/* just join the two chains */
2324669Swnj 			m->m_next = n;
2336091Sroot 			return;
2344669Swnj 		}
2356091Sroot 		/* splat the data from one into the other */
2366091Sroot 		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
2376091Sroot 		    (u_int)n->m_len);
2386091Sroot 		m->m_len += n->m_len;
2396091Sroot 		n = m_free(n);
2406091Sroot 	}
2414669Swnj }
2424669Swnj 
2434585Swnj m_adj(mp, len)
2444585Swnj 	struct mbuf *mp;
2454916Swnj 	register int len;
2464585Swnj {
2474585Swnj 	register struct mbuf *m, *n;
2484585Swnj 
2494585Swnj 	if ((m = mp) == NULL)
2504585Swnj 		return;
2514822Swnj 	if (len >= 0) {
2524585Swnj 		while (m != NULL && len > 0) {
2534822Swnj 			if (m->m_len <= len) {
2544585Swnj 				len -= m->m_len;
2554585Swnj 				m->m_len = 0;
2564585Swnj 				m = m->m_next;
2574822Swnj 			} else {
2584585Swnj 				m->m_len -= len;
2594585Swnj 				m->m_off += len;
2604585Swnj 				break;
2614585Swnj 			}
2624585Swnj 		}
2634822Swnj 	} else {
2644822Swnj 		/* a 2 pass algorithm might be better */
2654585Swnj 		len = -len;
2664585Swnj 		while (len > 0 && m->m_len != 0) {
2674585Swnj 			while (m != NULL && m->m_len != 0) {
2684585Swnj 				n = m;
2694585Swnj 				m = m->m_next;
2704585Swnj 			}
2714822Swnj 			if (n->m_len <= len) {
2724585Swnj 				len -= n->m_len;
2734585Swnj 				n->m_len = 0;
2744585Swnj 				m = mp;
2754822Swnj 			} else {
2764585Swnj 				n->m_len -= len;
2774585Swnj 				break;
2784585Swnj 			}
2794585Swnj 		}
2804585Swnj 	}
2814585Swnj }
2825228Swnj 
2835310Sroot struct mbuf *
2845310Sroot m_pullup(m0, len)
2855310Sroot 	struct mbuf *m0;
2865228Swnj 	int len;
2875228Swnj {
2885310Sroot 	register struct mbuf *m, *n;
2896164Ssam 	int count;
2905228Swnj 
2915732Sroot 	n = m0;
2925310Sroot 	if (len > MLEN)
2935310Sroot 		goto bad;
2948318Sroot 	MGET(m, M_DONTWAIT);
2955310Sroot 	if (m == 0)
2965310Sroot 		goto bad;
2975310Sroot 	m->m_len = 0;
2985310Sroot 	do {
2996164Ssam 		count = MIN(MLEN - m->m_len, len);
3006164Ssam 		if (count > n->m_len)
3016164Ssam 			count = n->m_len;
3026164Ssam 		bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len,
3036164Ssam 		  (unsigned)count);
3046164Ssam 		len -= count;
3056164Ssam 		m->m_len += count;
3066164Ssam 		n->m_off += count;
3076164Ssam 		n->m_len -= count;
3085310Sroot 		if (n->m_len)
3095310Sroot 			break;
3105310Sroot 		n = m_free(n);
3115310Sroot 	} while (n);
3125310Sroot 	if (len) {
3135310Sroot 		(void) m_free(m);
3145310Sroot 		goto bad;
3155310Sroot 	}
3165310Sroot 	m->m_next = n;
3175310Sroot 	return (m);
3185310Sroot bad:
3195732Sroot 	m_freem(n);
3205228Swnj 	return (0);
3215228Swnj }
322