Annotation of Net2/kern/uipc_mbuf.c, revision 1.1.1.3

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 = &top;
                    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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.