|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1988, 1991 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)uipc_mbuf.c 7.19 (Berkeley) 4/20/91
1.1.1.3 ! root 34: *
! 35: * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
! 36: * -------------------- ----- ----------------------
! 37: * CURRENT PATCH LEVEL: 1 00009
! 38: * -------------------- ----- ----------------------
! 39: *
! 40: * 31 Aug 92 Wolfgang Solfrank Fixed mbuf allocation code
1.1 root 41: */
42:
43: #include "param.h"
44: #include "proc.h"
45: #include "malloc.h"
46: #define MBTYPES
47: #include "mbuf.h"
48: #include "kernel.h"
49: #include "syslog.h"
50: #include "domain.h"
51: #include "protosw.h"
52: #include "vm/vm.h"
53:
54: extern vm_map_t mb_map;
55: struct mbuf *mbutl;
56: char *mclrefcnt;
57:
58: mbinit()
59: {
60: int s;
61:
62: #if CLBYTES < 4096
63: #define NCL_INIT (4096/CLBYTES)
64: #else
65: #define NCL_INIT 1
66: #endif
67: s = splimp();
68: if (m_clalloc(NCL_INIT, M_DONTWAIT) == 0)
69: goto bad;
70: splx(s);
71: return;
72: bad:
73: panic("mbinit");
74: }
75:
76: /*
77: * Allocate some number of mbuf clusters
78: * and place on cluster free list.
79: * Must be called at splimp.
80: */
81: /* ARGSUSED */
1.1.1.3 ! root 82: m_clalloc(ncl, how) /* 31 Aug 92*/
1.1 root 83: register int ncl;
84: {
85: int npg, mbx;
86: register caddr_t p;
87: register int i;
88: static int logged;
89:
90: npg = ncl * CLSIZE;
1.1.1.3 ! root 91: /* 31 Aug 92*/
! 92: p = (caddr_t)kmem_malloc(mb_map, ctob(npg), !(how&M_DONTWAIT));
1.1 root 93: if (p == NULL) {
94: if (logged == 0) {
95: logged++;
96: log(LOG_ERR, "mb_map full\n");
97: }
98: return (0);
99: }
100: ncl = ncl * CLBYTES / MCLBYTES;
101: for (i = 0; i < ncl; i++) {
102: ((union mcluster *)p)->mcl_next = mclfree;
103: mclfree = (union mcluster *)p;
104: p += MCLBYTES;
105: mbstat.m_clfree++;
106: }
107: mbstat.m_clusters += ncl;
108: return (1);
109: }
110:
111: /*
112: * When MGET failes, ask protocols to free space when short of memory,
113: * then re-attempt to allocate an mbuf.
114: */
115: struct mbuf *
116: m_retry(i, t)
117: int i, t;
118: {
119: register struct mbuf *m;
120:
121: m_reclaim();
122: #define m_retry(i, t) (struct mbuf *)0
123: MGET(m, i, t);
124: #undef m_retry
125: return (m);
126: }
127:
128: /*
129: * As above; retry an MGETHDR.
130: */
131: struct mbuf *
132: m_retryhdr(i, t)
133: int i, t;
134: {
135: register struct mbuf *m;
136:
137: m_reclaim();
138: #define m_retryhdr(i, t) (struct mbuf *)0
139: MGETHDR(m, i, t);
140: #undef m_retryhdr
141: return (m);
142: }
143:
144: m_reclaim()
145: {
146: register struct domain *dp;
147: register struct protosw *pr;
148: int s = splimp();
149:
150: for (dp = domains; dp; dp = dp->dom_next)
151: for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
152: if (pr->pr_drain)
153: (*pr->pr_drain)();
154: splx(s);
155: mbstat.m_drain++;
156: }
157:
158: /*
159: * Space allocation routines.
160: * These are also available as macros
161: * for critical paths.
162: */
163: struct mbuf *
1.1.1.3 ! root 164: m_get(how, type) /* 31 Aug 92*/
! 165: int how, type;
1.1 root 166: {
167: register struct mbuf *m;
168:
1.1.1.3 ! root 169: MGET(m, how, type);
1.1 root 170: return (m);
171: }
172:
173: struct mbuf *
1.1.1.3 ! root 174: m_gethdr(how, type) /* 31 Aug 92*/
! 175: int how, type;
1.1 root 176: {
177: register struct mbuf *m;
178:
1.1.1.3 ! root 179: MGETHDR(m, how, type);
1.1 root 180: return (m);
181: }
182:
183: struct mbuf *
1.1.1.3 ! root 184: m_getclr(how, type) /* 31 Aug 92*/
! 185: int how, type;
1.1 root 186: {
187: register struct mbuf *m;
188:
1.1.1.3 ! root 189: MGET(m, how, type);
1.1 root 190: if (m == 0)
191: return (0);
192: bzero(mtod(m, caddr_t), MLEN);
193: return (m);
194: }
195:
196: struct mbuf *
197: m_free(m)
198: struct mbuf *m;
199: {
200: register struct mbuf *n;
201:
202: MFREE(m, n);
203: return (n);
204: }
205:
206: m_freem(m)
207: register struct mbuf *m;
208: {
209: register struct mbuf *n;
210:
211: if (m == NULL)
212: return;
213: do {
214: MFREE(m, n);
215: } while (m = n);
216: }
217:
218: /*
219: * Mbuffer utility routines.
220: */
221:
222: /*
223: * Lesser-used path for M_PREPEND:
224: * allocate new mbuf to prepend to chain,
225: * copy junk along.
226: */
227: struct mbuf *
228: m_prepend(m, len, how)
229: register struct mbuf *m;
230: int len, how;
231: {
232: struct mbuf *mn;
233:
234: MGET(mn, how, m->m_type);
235: if (mn == (struct mbuf *)NULL) {
236: m_freem(m);
237: return ((struct mbuf *)NULL);
238: }
239: if (m->m_flags & M_PKTHDR) {
240: M_COPY_PKTHDR(mn, m);
241: m->m_flags &= ~M_PKTHDR;
242: }
243: mn->m_next = m;
244: m = mn;
245: if (len < MHLEN)
246: MH_ALIGN(m, len);
247: m->m_len = len;
248: return (m);
249: }
250:
251: /*
252: * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
253: * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf.
254: * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
255: */
256: int MCFail;
257:
258: struct mbuf *
259: m_copym(m, off0, len, wait)
260: register struct mbuf *m;
261: int off0, wait;
262: register int len;
263: {
264: register struct mbuf *n, **np;
265: register int off = off0;
266: struct mbuf *top;
267: int copyhdr = 0;
268:
269: if (off < 0 || len < 0)
270: panic("m_copym");
271: if (off == 0 && m->m_flags & M_PKTHDR)
272: copyhdr = 1;
273: while (off > 0) {
274: if (m == 0)
275: panic("m_copym");
276: if (off < m->m_len)
277: break;
278: off -= m->m_len;
279: m = m->m_next;
280: }
281: np = ⊤
282: top = 0;
283: while (len > 0) {
284: if (m == 0) {
285: if (len != M_COPYALL)
286: panic("m_copym");
287: break;
288: }
289: MGET(n, wait, m->m_type);
290: *np = n;
291: if (n == 0)
292: goto nospace;
293: if (copyhdr) {
294: M_COPY_PKTHDR(n, m);
295: if (len == M_COPYALL)
296: n->m_pkthdr.len -= off0;
297: else
298: n->m_pkthdr.len = len;
299: copyhdr = 0;
300: }
301: n->m_len = MIN(len, m->m_len - off);
302: if (m->m_flags & M_EXT) {
303: n->m_data = m->m_data + off;
304: mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
305: n->m_ext = m->m_ext;
306: n->m_flags |= M_EXT;
307: } else
308: bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
309: (unsigned)n->m_len);
310: if (len != M_COPYALL)
311: len -= n->m_len;
312: off = 0;
313: m = m->m_next;
314: np = &n->m_next;
315: }
316: if (top == 0)
317: MCFail++;
318: return (top);
319: nospace:
320: m_freem(top);
321: MCFail++;
322: return (0);
323: }
324:
325: /*
326: * Copy data from an mbuf chain starting "off" bytes from the beginning,
327: * continuing for "len" bytes, into the indicated buffer.
328: */
329: m_copydata(m, off, len, cp)
330: register struct mbuf *m;
331: register int off;
332: register int len;
333: caddr_t cp;
334: {
335: register unsigned count;
336:
337: if (off < 0 || len < 0)
338: panic("m_copydata");
339: while (off > 0) {
340: if (m == 0)
341: panic("m_copydata");
342: if (off < m->m_len)
343: break;
344: off -= m->m_len;
345: m = m->m_next;
346: }
347: while (len > 0) {
348: if (m == 0)
349: panic("m_copydata");
350: count = MIN(m->m_len - off, len);
351: bcopy(mtod(m, caddr_t) + off, cp, count);
352: len -= count;
353: cp += count;
354: off = 0;
355: m = m->m_next;
356: }
357: }
358:
359: /*
360: * Concatenate mbuf chain n to m.
361: * Both chains must be of the same type (e.g. MT_DATA).
362: * Any m_pkthdr is not updated.
363: */
364: m_cat(m, n)
365: register struct mbuf *m, *n;
366: {
367: while (m->m_next)
368: m = m->m_next;
369: while (n) {
370: if (m->m_flags & M_EXT ||
371: m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
372: /* just join the two chains */
373: m->m_next = n;
374: return;
375: }
376: /* splat the data from one into the other */
377: bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
378: (u_int)n->m_len);
379: m->m_len += n->m_len;
380: n = m_free(n);
381: }
382: }
383:
384: m_adj(mp, req_len)
385: struct mbuf *mp;
386: {
387: register int len = req_len;
388: register struct mbuf *m;
389: register count;
390:
391: if ((m = mp) == NULL)
392: return;
393: if (len >= 0) {
394: /*
395: * Trim from head.
396: */
397: while (m != NULL && len > 0) {
398: if (m->m_len <= len) {
399: len -= m->m_len;
400: m->m_len = 0;
401: m = m->m_next;
402: } else {
403: m->m_len -= len;
404: m->m_data += len;
405: len = 0;
406: }
407: }
408: m = mp;
409: if (mp->m_flags & M_PKTHDR)
410: m->m_pkthdr.len -= (req_len - len);
411: } else {
412: /*
413: * Trim from tail. Scan the mbuf chain,
414: * calculating its length and finding the last mbuf.
415: * If the adjustment only affects this mbuf, then just
416: * adjust and return. Otherwise, rescan and truncate
417: * after the remaining size.
418: */
419: len = -len;
420: count = 0;
421: for (;;) {
422: count += m->m_len;
423: if (m->m_next == (struct mbuf *)0)
424: break;
425: m = m->m_next;
426: }
427: if (m->m_len >= len) {
428: m->m_len -= len;
429: if ((mp = m)->m_flags & M_PKTHDR)
430: m->m_pkthdr.len -= len;
431: return;
432: }
433: count -= len;
434: if (count < 0)
435: count = 0;
436: /*
437: * Correct length for chain is "count".
438: * Find the mbuf with last data, adjust its length,
439: * and toss data from remaining mbufs on chain.
440: */
441: m = mp;
442: if (m->m_flags & M_PKTHDR)
443: m->m_pkthdr.len = count;
444: for (; m; m = m->m_next) {
445: if (m->m_len >= count) {
446: m->m_len = count;
447: break;
448: }
449: count -= m->m_len;
450: }
451: while (m = m->m_next)
452: m->m_len = 0;
453: }
454: }
455:
456: /*
457: * Rearange an mbuf chain so that len bytes are contiguous
458: * and in the data area of an mbuf (so that mtod and dtom
459: * will work for a structure of size len). Returns the resulting
460: * mbuf chain on success, frees it and returns null on failure.
461: * If there is room, it will add up to max_protohdr-len extra bytes to the
462: * contiguous region in an attempt to avoid being called next time.
463: */
464: int MPFail;
465:
466: struct mbuf *
467: m_pullup(n, len)
468: register struct mbuf *n;
469: int len;
470: {
471: register struct mbuf *m;
472: register int count;
473: int space;
474:
475: /*
476: * If first mbuf has no cluster, and has room for len bytes
477: * without shifting current data, pullup into it,
478: * otherwise allocate a new mbuf to prepend to the chain.
479: */
480: if ((n->m_flags & M_EXT) == 0 &&
481: n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
482: if (n->m_len >= len)
483: return (n);
484: m = n;
485: n = n->m_next;
486: len -= m->m_len;
487: } else {
488: if (len > MHLEN)
489: goto bad;
490: MGET(m, M_DONTWAIT, n->m_type);
491: if (m == 0)
492: goto bad;
493: m->m_len = 0;
494: if (n->m_flags & M_PKTHDR) {
495: M_COPY_PKTHDR(m, n);
496: n->m_flags &= ~M_PKTHDR;
497: }
498: }
499: space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
500: do {
501: count = min(min(max(len, max_protohdr), space), n->m_len);
502: bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
503: (unsigned)count);
504: len -= count;
505: m->m_len += count;
506: n->m_len -= count;
507: space -= count;
508: if (n->m_len)
509: n->m_data += count;
510: else
511: n = m_free(n);
512: } while (len > 0 && n);
513: if (len > 0) {
514: (void) m_free(m);
515: goto bad;
516: }
517: m->m_next = n;
518: return (m);
519: bad:
520: m_freem(n);
521: MPFail++;
522: return (0);
523: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.