xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 9634)
1*9634Ssam /*	uipc_mbuf.c	1.41	82/12/14	*/
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 */
388792Sroot 	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;
64*9634Ssam 			m->m_type = MT_DATA;
65*9634Ssam 			mbstat.m_mtypes[MT_DATA]++;
666839Ssam 			mbstat.m_mbufs++;
675228Swnj 			(void) m_free(m);
685228Swnj 			m++;
695228Swnj 		}
705232Swnj 		break;
715228Swnj 	}
725228Swnj 	return ((caddr_t)m);
735228Swnj }
745228Swnj 
755228Swnj m_pgfree(addr, n)
765228Swnj 	caddr_t addr;
775228Swnj 	int n;
785228Swnj {
795228Swnj 
806141Ssam #ifdef lint
816141Ssam 	addr = addr; n = n;
826141Ssam #endif
835228Swnj }
845228Swnj 
855228Swnj m_expand()
865228Swnj {
875228Swnj 
885228Swnj 	if (m_clalloc(1, MPG_MBUFS) == 0)
895228Swnj 		goto steal;
905228Swnj 	return (1);
915228Swnj steal:
925228Swnj 	/* should ask protocols to free code */
935228Swnj 	return (0);
945228Swnj }
955228Swnj 
965228Swnj /* NEED SOME WAY TO RELEASE SPACE */
975228Swnj 
985228Swnj /*
995228Swnj  * Space allocation routines.
1005228Swnj  * These are also available as macros
1015228Swnj  * for critical paths.
1025228Swnj  */
1034585Swnj struct mbuf *
104*9634Ssam m_get(canwait, type)
105*9634Ssam 	int canwait, type;
1064585Swnj {
1074585Swnj 	register struct mbuf *m;
1084585Swnj 
109*9634Ssam 	MGET(m, canwait, type);
1104585Swnj 	return (m);
1114585Swnj }
1124585Swnj 
1134585Swnj struct mbuf *
114*9634Ssam m_getclr(canwait, type)
115*9634Ssam 	int canwait, type;
1164890Swnj {
1174890Swnj 	register struct mbuf *m;
1184890Swnj 
119*9634Ssam 	m = m_get(canwait, type);
1204890Swnj 	if (m == 0)
1214890Swnj 		return (0);
1224890Swnj 	bzero(mtod(m, caddr_t), MLEN);
1234890Swnj 	return (m);
1244890Swnj }
1254890Swnj 
1264890Swnj struct mbuf *
1274585Swnj m_free(m)
1284585Swnj 	struct mbuf *m;
1294585Swnj {
1304585Swnj 	register struct mbuf *n;
1314585Swnj 
1324585Swnj 	MFREE(m, n);
1334585Swnj 	return (n);
1344585Swnj }
1354585Swnj 
1364916Swnj /*ARGSUSED*/
1374585Swnj struct mbuf *
138*9634Ssam m_more(canwait, type)
139*9634Ssam 	int canwait, type;
1404585Swnj {
1414585Swnj 	register struct mbuf *m;
1424585Swnj 
1434585Swnj 	if (!m_expand()) {
1444822Swnj 		mbstat.m_drops++;
1454585Swnj 		return (NULL);
1464585Swnj 	}
147*9634Ssam #define m_more(x,y) (panic("m_more"), (struct mbuf *)0)
148*9634Ssam 	MGET(m, canwait, type);
1495282Sroot #undef m_more
1504585Swnj 	return (m);
1514585Swnj }
1524585Swnj 
1534669Swnj m_freem(m)
1544585Swnj 	register struct mbuf *m;
1554585Swnj {
1564585Swnj 	register struct mbuf *n;
1574927Swnj 	register int s;
1584585Swnj 
1594585Swnj 	if (m == NULL)
1604916Swnj 		return;
1614662Swnj 	s = splimp();
1624585Swnj 	do {
1634585Swnj 		MFREE(m, n);
1644585Swnj 	} while (m = n);
1654585Swnj 	splx(s);
1664585Swnj }
1674585Swnj 
1685228Swnj /*
1695228Swnj  * Mbuffer utility routines.
1705228Swnj  */
1714927Swnj struct mbuf *
1724927Swnj m_copy(m, off, len)
1734927Swnj 	register struct mbuf *m;
1744927Swnj 	int off;
1754927Swnj 	register int len;
1764927Swnj {
1774927Swnj 	register struct mbuf *n, **np;
1784927Swnj 	struct mbuf *top, *p;
179*9634Ssam 	int type;
1804927Swnj 
1814927Swnj 	if (len == 0)
1824927Swnj 		return (0);
1834927Swnj 	if (off < 0 || len < 0)
1844927Swnj 		panic("m_copy");
185*9634Ssam 	type = m->m_type;
1864927Swnj 	while (off > 0) {
1874927Swnj 		if (m == 0)
1884927Swnj 			panic("m_copy");
1894927Swnj 		if (off < m->m_len)
1904927Swnj 			break;
1914927Swnj 		off -= m->m_len;
1924927Swnj 		m = m->m_next;
1934927Swnj 	}
1944927Swnj 	np = &top;
1954927Swnj 	top = 0;
1964927Swnj 	while (len > 0) {
1975609Swnj 		if (m == 0) {
1985609Swnj 			if (len != M_COPYALL)
1995609Swnj 				panic("m_copy");
2005609Swnj 			break;
2015609Swnj 		}
202*9634Ssam 		MGET(n, M_WAIT, type);
2034927Swnj 		*np = n;
2044927Swnj 		if (n == 0)
2054927Swnj 			goto nospace;
2064927Swnj 		n->m_len = MIN(len, m->m_len - off);
2074927Swnj 		if (m->m_off > MMAXOFF) {
2084927Swnj 			p = mtod(m, struct mbuf *);
2094927Swnj 			n->m_off = ((int)p - (int)n) + off;
2105090Swnj 			mclrefcnt[mtocl(p)]++;
2118318Sroot 		} else
2124927Swnj 			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
2134927Swnj 			    (unsigned)n->m_len);
2145609Swnj 		if (len != M_COPYALL)
2155609Swnj 			len -= n->m_len;
2164927Swnj 		off = 0;
2174927Swnj 		m = m->m_next;
2184927Swnj 		np = &n->m_next;
2194927Swnj 	}
2204927Swnj 	return (top);
2214927Swnj nospace:
2224927Swnj 	m_freem(top);
2234927Swnj 	return (0);
2244927Swnj }
2254927Swnj 
2264669Swnj m_cat(m, n)
2274669Swnj 	register struct mbuf *m, *n;
2284669Swnj {
2294669Swnj 	while (m->m_next)
2304669Swnj 		m = m->m_next;
2316091Sroot 	while (n) {
2326091Sroot 		if (m->m_off >= MMAXOFF ||
2336091Sroot 		    m->m_off + m->m_len + n->m_len > MMAXOFF) {
2346091Sroot 			/* just join the two chains */
2354669Swnj 			m->m_next = n;
2366091Sroot 			return;
2374669Swnj 		}
2386091Sroot 		/* splat the data from one into the other */
2396091Sroot 		bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
2406091Sroot 		    (u_int)n->m_len);
2416091Sroot 		m->m_len += n->m_len;
2426091Sroot 		n = m_free(n);
2436091Sroot 	}
2444669Swnj }
2454669Swnj 
2464585Swnj m_adj(mp, len)
2474585Swnj 	struct mbuf *mp;
2484916Swnj 	register int len;
2494585Swnj {
2504585Swnj 	register struct mbuf *m, *n;
2514585Swnj 
2524585Swnj 	if ((m = mp) == NULL)
2534585Swnj 		return;
2544822Swnj 	if (len >= 0) {
2554585Swnj 		while (m != NULL && len > 0) {
2564822Swnj 			if (m->m_len <= len) {
2574585Swnj 				len -= m->m_len;
2584585Swnj 				m->m_len = 0;
2594585Swnj 				m = m->m_next;
2604822Swnj 			} else {
2614585Swnj 				m->m_len -= len;
2624585Swnj 				m->m_off += len;
2634585Swnj 				break;
2644585Swnj 			}
2654585Swnj 		}
2664822Swnj 	} else {
2674822Swnj 		/* a 2 pass algorithm might be better */
2684585Swnj 		len = -len;
2694585Swnj 		while (len > 0 && m->m_len != 0) {
2704585Swnj 			while (m != NULL && m->m_len != 0) {
2714585Swnj 				n = m;
2724585Swnj 				m = m->m_next;
2734585Swnj 			}
2744822Swnj 			if (n->m_len <= len) {
2754585Swnj 				len -= n->m_len;
2764585Swnj 				n->m_len = 0;
2774585Swnj 				m = mp;
2784822Swnj 			} else {
2794585Swnj 				n->m_len -= len;
2804585Swnj 				break;
2814585Swnj 			}
2824585Swnj 		}
2834585Swnj 	}
2844585Swnj }
2855228Swnj 
2865310Sroot struct mbuf *
2875310Sroot m_pullup(m0, len)
2885310Sroot 	struct mbuf *m0;
2895228Swnj 	int len;
2905228Swnj {
2915310Sroot 	register struct mbuf *m, *n;
2926164Ssam 	int count;
2935228Swnj 
2945732Sroot 	n = m0;
2955310Sroot 	if (len > MLEN)
2965310Sroot 		goto bad;
297*9634Ssam 	MGET(m, M_DONTWAIT, n->m_type);
2985310Sroot 	if (m == 0)
2995310Sroot 		goto bad;
3005310Sroot 	m->m_len = 0;
3015310Sroot 	do {
3026164Ssam 		count = MIN(MLEN - m->m_len, len);
3036164Ssam 		if (count > n->m_len)
3046164Ssam 			count = n->m_len;
3056164Ssam 		bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len,
3066164Ssam 		  (unsigned)count);
3076164Ssam 		len -= count;
3086164Ssam 		m->m_len += count;
3096164Ssam 		n->m_off += count;
3106164Ssam 		n->m_len -= count;
3115310Sroot 		if (n->m_len)
3125310Sroot 			break;
3135310Sroot 		n = m_free(n);
3145310Sroot 	} while (n);
3155310Sroot 	if (len) {
3165310Sroot 		(void) m_free(m);
3175310Sroot 		goto bad;
3185310Sroot 	}
3195310Sroot 	m->m_next = n;
3205310Sroot 	return (m);
3215310Sroot bad:
3225732Sroot 	m_freem(n);
3235228Swnj 	return (0);
3245228Swnj }
325