Annotation of 43BSDReno/sys/kern/uipc_mbuf.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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