xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 5609)
1*5609Swnj /*	uipc_mbuf.c	1.27	82/01/24	*/
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"
115090Swnj #include "../net/in_systm.h"		/* XXX */
124585Swnj #include "../h/vm.h"
134585Swnj 
145228Swnj mbinit()
155228Swnj {
165228Swnj 
175228Swnj COUNT(MBINIT);
185228Swnj 	if (m_reserve(32) == 0)
195228Swnj 		goto bad;
205228Swnj 	if (m_clalloc(4, MPG_MBUFS) == 0)
215228Swnj 		goto bad;
225228Swnj 	if (m_clalloc(32, MPG_CLUSTERS) == 0)
235228Swnj 		goto bad;
245228Swnj 	return;
255228Swnj bad:
265228Swnj 	panic("mbinit");
275228Swnj }
285228Swnj 
295228Swnj caddr_t
305228Swnj m_clalloc(ncl, how)
315228Swnj 	register int ncl;
325228Swnj 	int how;
335228Swnj {
345228Swnj 	int npg, mbx;
355228Swnj 	register struct mbuf *m;
365228Swnj 	register int i;
375228Swnj 	int s;
385228Swnj 
395228Swnj COUNT(M_CLALLOC);
405228Swnj 	npg = ncl * CLSIZE;
415581Swnj 	s = splimp();		/* careful: rmalloc isn't reentrant */
425228Swnj 	mbx = rmalloc(mbmap, npg);
435581Swnj 	splx(s);
445228Swnj 	if (mbx == 0)
455228Swnj 		return (0);
465228Swnj 	m = cltom(mbx / CLSIZE);
475228Swnj 	if (memall(&Mbmap[mbx], ncl * CLSIZE, proc, CSYS) == 0)
485228Swnj 		return (0);
495228Swnj 	vmaccess(&Mbmap[mbx], (caddr_t)m, npg);
505228Swnj 	switch (how) {
515228Swnj 
525228Swnj 	case MPG_CLUSTERS:
535228Swnj 		s = splimp();
545228Swnj 		for (i = 0; i < ncl; i++) {
555228Swnj 			m->m_off = 0;
565228Swnj 			m->m_next = mclfree;
575228Swnj 			mclfree = m;
585228Swnj 			m += CLBYTES / sizeof (*m);
595228Swnj 			nmclfree++;
605228Swnj 		}
615228Swnj 		mbstat.m_clusters += ncl;
625228Swnj 		splx(s);
635228Swnj 		break;
645228Swnj 
655228Swnj 	case MPG_MBUFS:
665228Swnj 		for (i = ncl * CLBYTES / sizeof (*m); i > 0; i--) {
675228Swnj 			m->m_off = 0;
685273Sroot 			m->m_free = 0;
695228Swnj 			(void) m_free(m);
705228Swnj 			m++;
715228Swnj 		}
725228Swnj 		mbstat.m_clusters += ncl;
735232Swnj 		break;
745228Swnj 	}
755228Swnj 	return ((caddr_t)m);
765228Swnj }
775228Swnj 
785228Swnj m_pgfree(addr, n)
795228Swnj 	caddr_t addr;
805228Swnj 	int n;
815228Swnj {
825228Swnj 
835228Swnj COUNT(M_PGFREE);
845228Swnj }
855228Swnj 
865228Swnj m_expand()
875228Swnj {
885228Swnj 
895228Swnj COUNT(M_EXPAND);
905228Swnj 	if (mbstat.m_bufs >= mbstat.m_hiwat)
915228Swnj 		return (0);
925228Swnj 	if (m_clalloc(1, MPG_MBUFS) == 0)
935228Swnj 		goto steal;
945228Swnj 	return (1);
955228Swnj steal:
965228Swnj 	/* should ask protocols to free code */
975228Swnj 	return (0);
985228Swnj }
995228Swnj 
1005228Swnj /* NEED SOME WAY TO RELEASE SPACE */
1015228Swnj 
1025228Swnj /*
1035228Swnj  * Space reservation routines
1045228Swnj  */
1055015Sroot m_reserve(mbufs)
1065015Sroot 	int mbufs;
1074732Swnj {
1084732Swnj 
1095147Swnj 	if (mbstat.m_lowat + (mbufs>>1) > (NMBCLUSTERS-32) * CLBYTES)
1104732Swnj 		return (0);
1115016Swnj 	mbstat.m_hiwat += mbufs;
1125016Swnj 	mbstat.m_lowat = mbstat.m_hiwat >> 1;
1134916Swnj 	return (1);
1144732Swnj }
1154732Swnj 
1165015Sroot m_release(mbufs)
1175015Sroot 	int mbufs;
1184732Swnj {
1194732Swnj 
1205016Swnj 	mbstat.m_hiwat -= mbufs;
1215016Swnj 	mbstat.m_lowat = mbstat.m_hiwat >> 1;
1224732Swnj }
1234732Swnj 
1245228Swnj /*
1255228Swnj  * Space allocation routines.
1265228Swnj  * These are also available as macros
1275228Swnj  * for critical paths.
1285228Swnj  */
1294585Swnj struct mbuf *
1304585Swnj m_get(canwait)
1314585Swnj 	int canwait;
1324585Swnj {
1334585Swnj 	register struct mbuf *m;
1344585Swnj 
1354585Swnj COUNT(M_GET);
1364585Swnj 	MGET(m, canwait);
1374585Swnj 	return (m);
1384585Swnj }
1394585Swnj 
1404585Swnj struct mbuf *
1414890Swnj m_getclr(canwait)
1424890Swnj 	int canwait;
1434890Swnj {
1444890Swnj 	register struct mbuf *m;
1454890Swnj 
1464890Swnj COUNT(M_GETCLR);
1474916Swnj 	m = m_get(canwait);
1484890Swnj 	if (m == 0)
1494890Swnj 		return (0);
1504890Swnj 	m->m_off = MMINOFF;
1514890Swnj 	bzero(mtod(m, caddr_t), MLEN);
1524890Swnj 	return (m);
1534890Swnj }
1544890Swnj 
1554890Swnj struct mbuf *
1564585Swnj m_free(m)
1574585Swnj 	struct mbuf *m;
1584585Swnj {
1594585Swnj 	register struct mbuf *n;
1604585Swnj 
1614585Swnj COUNT(M_FREE);
1624585Swnj 	MFREE(m, n);
1634585Swnj 	return (n);
1644585Swnj }
1654585Swnj 
1664916Swnj /*ARGSUSED*/
1674585Swnj struct mbuf *
1684585Swnj m_more(type)
1694585Swnj 	int type;
1704585Swnj {
1714585Swnj 	register struct mbuf *m;
1724585Swnj 
1734585Swnj COUNT(M_MORE);
1744585Swnj 	if (!m_expand()) {
1754822Swnj 		mbstat.m_drops++;
1764585Swnj 		return (NULL);
1774585Swnj 	}
1784916Swnj #define m_more(x) (panic("m_more"), (struct mbuf *)0)
1794916Swnj 	MGET(m, type);
1805282Sroot #undef m_more
1814585Swnj 	return (m);
1824585Swnj }
1834585Swnj 
1844669Swnj m_freem(m)
1854585Swnj 	register struct mbuf *m;
1864585Swnj {
1874585Swnj 	register struct mbuf *n;
1884927Swnj 	register int s;
1894585Swnj 
1904585Swnj COUNT(M_FREEM);
1914585Swnj 	if (m == NULL)
1924916Swnj 		return;
1934662Swnj 	s = splimp();
1944585Swnj 	do {
1954585Swnj 		MFREE(m, n);
1964585Swnj 	} while (m = n);
1974585Swnj 	splx(s);
1984585Swnj }
1994585Swnj 
2005228Swnj /*
2015228Swnj  * Mbuffer utility routines.
2025228Swnj  */
2034927Swnj struct mbuf *
2044927Swnj m_copy(m, off, len)
2054927Swnj 	register struct mbuf *m;
2064927Swnj 	int off;
2074927Swnj 	register int len;
2084927Swnj {
2094927Swnj 	register struct mbuf *n, **np;
2104927Swnj 	struct mbuf *top, *p;
2114927Swnj COUNT(M_COPY);
2124927Swnj 
2134927Swnj 	if (len == 0)
2144927Swnj 		return (0);
2154927Swnj 	if (off < 0 || len < 0)
2164927Swnj 		panic("m_copy");
2174927Swnj 	while (off > 0) {
2184927Swnj 		if (m == 0)
2194927Swnj 			panic("m_copy");
2204927Swnj 		if (off < m->m_len)
2214927Swnj 			break;
2224927Swnj 		off -= m->m_len;
2234927Swnj 		m = m->m_next;
2244927Swnj 	}
2254927Swnj 	np = &top;
2264927Swnj 	top = 0;
2274927Swnj 	while (len > 0) {
228*5609Swnj 		if (m == 0) {
229*5609Swnj 			if (len != M_COPYALL)
230*5609Swnj 				panic("m_copy");
231*5609Swnj 			break;
232*5609Swnj 		}
2334927Swnj 		MGET(n, 1);
2344927Swnj 		*np = n;
2354927Swnj 		if (n == 0)
2364927Swnj 			goto nospace;
2374927Swnj 		n->m_len = MIN(len, m->m_len - off);
2384927Swnj 		if (m->m_off > MMAXOFF) {
2394927Swnj 			p = mtod(m, struct mbuf *);
2404927Swnj 			n->m_off = ((int)p - (int)n) + off;
2415090Swnj 			mclrefcnt[mtocl(p)]++;
2424927Swnj 		} else {
2434927Swnj 			n->m_off = MMINOFF;
2444927Swnj 			bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
2454927Swnj 			    (unsigned)n->m_len);
2464927Swnj 		}
247*5609Swnj 		if (len != M_COPYALL)
248*5609Swnj 			len -= n->m_len;
2494927Swnj 		off = 0;
2504927Swnj 		m = m->m_next;
2514927Swnj 		np = &n->m_next;
2524927Swnj 	}
2534927Swnj 	return (top);
2544927Swnj nospace:
2554927Swnj 	m_freem(top);
2564927Swnj 	return (0);
2574927Swnj }
2584927Swnj 
2594669Swnj m_cat(m, n)
2604669Swnj 	register struct mbuf *m, *n;
2614669Swnj {
2624669Swnj 
2634669Swnj 	while (m->m_next)
2644669Swnj 		m = m->m_next;
2654669Swnj 	while (n)
2664669Swnj 		if (m->m_off + m->m_len + n->m_len <= MMAXOFF) {
2674916Swnj 			bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
2684916Swnj 			    (u_int)n->m_len);
2694669Swnj 			m->m_len += n->m_len;
2704669Swnj 			n = m_free(n);
2714669Swnj 		} else {
2724669Swnj 			m->m_next = n;
2734669Swnj 			m = n;
2744669Swnj 			n = m->m_next;
2754669Swnj 		}
2764669Swnj }
2774669Swnj 
2784585Swnj m_adj(mp, len)
2794585Swnj 	struct mbuf *mp;
2804916Swnj 	register int len;
2814585Swnj {
2824585Swnj 	register struct mbuf *m, *n;
2834585Swnj 
2844585Swnj COUNT(M_ADJ);
2854585Swnj 	if ((m = mp) == NULL)
2864585Swnj 		return;
2874822Swnj 	if (len >= 0) {
2884585Swnj 		while (m != NULL && len > 0) {
2894822Swnj 			if (m->m_len <= len) {
2904585Swnj 				len -= m->m_len;
2914585Swnj 				m->m_len = 0;
2924585Swnj 				m = m->m_next;
2934822Swnj 			} else {
2944585Swnj 				m->m_len -= len;
2954585Swnj 				m->m_off += len;
2964585Swnj 				break;
2974585Swnj 			}
2984585Swnj 		}
2994822Swnj 	} else {
3004822Swnj 		/* a 2 pass algorithm might be better */
3014585Swnj 		len = -len;
3024585Swnj 		while (len > 0 && m->m_len != 0) {
3034585Swnj 			while (m != NULL && m->m_len != 0) {
3044585Swnj 				n = m;
3054585Swnj 				m = m->m_next;
3064585Swnj 			}
3074822Swnj 			if (n->m_len <= len) {
3084585Swnj 				len -= n->m_len;
3094585Swnj 				n->m_len = 0;
3104585Swnj 				m = mp;
3114822Swnj 			} else {
3124585Swnj 				n->m_len -= len;
3134585Swnj 				break;
3144585Swnj 			}
3154585Swnj 		}
3164585Swnj 	}
3174585Swnj }
3185228Swnj 
3195310Sroot struct mbuf *
3205310Sroot m_pullup(m0, len)
3215310Sroot 	struct mbuf *m0;
3225228Swnj 	int len;
3235228Swnj {
3245310Sroot 	register struct mbuf *m, *n;
3255310Sroot 	int cnt;
3265228Swnj 
3275310Sroot 	if (len > MLEN)
3285310Sroot 		goto bad;
3295310Sroot 	MGET(m, 0);
3305310Sroot 	if (m == 0)
3315310Sroot 		goto bad;
3325310Sroot 	m->m_off = MMINOFF;
3335310Sroot 	m->m_len = 0;
3345310Sroot 	n = m0;
3355310Sroot 	do {
3365310Sroot 		cnt = MIN(MLEN - m->m_len, len);
3375310Sroot 		if (cnt > n->m_len)
3385310Sroot 			cnt = n->m_len;
3395310Sroot 		bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, cnt);
3405310Sroot 		len -= cnt;
3415310Sroot 		m->m_len += cnt;
3425310Sroot 		n->m_off += cnt;
3435310Sroot 		n->m_len -= cnt;
3445310Sroot 		if (n->m_len)
3455310Sroot 			break;
3465310Sroot 		n = m_free(n);
3475310Sroot 	} while (n);
3485310Sroot 	if (len) {
3495310Sroot 		(void) m_free(m);
3505310Sroot 		goto bad;
3515310Sroot 	}
3525310Sroot 	m->m_next = n;
3535310Sroot 	return (m);
3545310Sroot bad:
3555310Sroot 	m_freem(m0);
3565228Swnj 	return (0);
3575228Swnj }
358