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

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989 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:  *     @(#)vfs_bio.c   7.30 (Berkeley) 6/28/90
                     21:  */
                     22: 
                     23: #include "param.h"
                     24: #include "user.h"
                     25: #include "buf.h"
                     26: #include "vnode.h"
                     27: #include "specdev.h"
                     28: #include "mount.h"
                     29: #include "trace.h"
                     30: #include "ucred.h"
                     31: 
                     32: /*
                     33:  * Read in (if necessary) the block and return a buffer pointer.
                     34:  */
                     35: bread(vp, blkno, size, cred, bpp)
                     36:        struct vnode *vp;
                     37:        daddr_t blkno;
                     38:        int size;
                     39:        struct ucred *cred;
                     40:        struct buf **bpp;
                     41: {
                     42:        register struct buf *bp;
                     43: 
                     44:        if (size == 0)
                     45:                panic("bread: size 0");
                     46:        *bpp = bp = getblk(vp, blkno, size);
                     47:        if (bp->b_flags&(B_DONE|B_DELWRI)) {
                     48:                trace(TR_BREADHIT, pack(vp, size), blkno);
                     49:                return (0);
                     50:        }
                     51:        bp->b_flags |= B_READ;
                     52:        if (bp->b_bcount > bp->b_bufsize)
                     53:                panic("bread");
                     54:        if (bp->b_rcred == NOCRED && cred != NOCRED) {
                     55:                crhold(cred);
                     56:                bp->b_rcred = cred;
                     57:        }
                     58:        VOP_STRATEGY(bp);
                     59:        trace(TR_BREADMISS, pack(vp, size), blkno);
                     60:        u.u_ru.ru_inblock++;            /* pay for read */
                     61:        return (biowait(bp));
                     62: }
                     63: 
                     64: /*
                     65:  * Read in the block, like bread, but also start I/O on the
                     66:  * read-ahead block (which is not allocated to the caller)
                     67:  */
                     68: breada(vp, blkno, size, rablkno, rabsize, cred, bpp)
                     69:        struct vnode *vp;
                     70:        daddr_t blkno; int size;
                     71:        daddr_t rablkno; int rabsize;
                     72:        struct ucred *cred;
                     73:        struct buf **bpp;
                     74: {
                     75:        register struct buf *bp, *rabp;
                     76: 
                     77:        bp = NULL;
                     78:        /*
                     79:         * If the block isn't in core, then allocate
                     80:         * a buffer and initiate i/o (getblk checks
                     81:         * for a cache hit).
                     82:         */
                     83:        if (!incore(vp, blkno)) {
                     84:                *bpp = bp = getblk(vp, blkno, size);
                     85:                if ((bp->b_flags&(B_DONE|B_DELWRI)) == 0) {
                     86:                        bp->b_flags |= B_READ;
                     87:                        if (bp->b_bcount > bp->b_bufsize)
                     88:                                panic("breada");
                     89:                        if (bp->b_rcred == NOCRED && cred != NOCRED) {
                     90:                                crhold(cred);
                     91:                                bp->b_rcred = cred;
                     92:                        }
                     93:                        VOP_STRATEGY(bp);
                     94:                        trace(TR_BREADMISS, pack(vp, size), blkno);
                     95:                        u.u_ru.ru_inblock++;            /* pay for read */
                     96:                } else
                     97:                        trace(TR_BREADHIT, pack(vp, size), blkno);
                     98:        }
                     99: 
                    100:        /*
                    101:         * If there's a read-ahead block, start i/o
                    102:         * on it also (as above).
                    103:         */
                    104:        if (!incore(vp, rablkno)) {
                    105:                rabp = getblk(vp, rablkno, rabsize);
                    106:                if (rabp->b_flags & (B_DONE|B_DELWRI)) {
                    107:                        brelse(rabp);
                    108:                        trace(TR_BREADHITRA, pack(vp, rabsize), rablkno);
                    109:                } else {
                    110:                        rabp->b_flags |= B_READ|B_ASYNC;
                    111:                        if (rabp->b_bcount > rabp->b_bufsize)
                    112:                                panic("breadrabp");
                    113:                        if (rabp->b_rcred == NOCRED && cred != NOCRED) {
                    114:                                crhold(cred);
                    115:                                rabp->b_rcred = cred;
                    116:                        }
                    117:                        VOP_STRATEGY(rabp);
                    118:                        trace(TR_BREADMISSRA, pack(vp, rabsize), rablkno);
                    119:                        u.u_ru.ru_inblock++;            /* pay in advance */
                    120:                }
                    121:        }
                    122: 
                    123:        /*
                    124:         * If block was in core, let bread get it.
                    125:         * If block wasn't in core, then the read was started
                    126:         * above, and just wait for it.
                    127:         */
                    128:        if (bp == NULL)
                    129:                return (bread(vp, blkno, size, cred, bpp));
                    130:        return (biowait(bp));
                    131: }
                    132: 
                    133: /*
                    134:  * Write the buffer, waiting for completion.
                    135:  * Then release the buffer.
                    136:  */
                    137: bwrite(bp)
                    138:        register struct buf *bp;
                    139: {
                    140:        register int flag;
                    141:        int s, error;
                    142: 
                    143:        flag = bp->b_flags;
                    144:        bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI);
                    145:        if ((flag&B_DELWRI) == 0)
                    146:                u.u_ru.ru_oublock++;            /* noone paid yet */
                    147:        else
                    148:                reassignbuf(bp, bp->b_vp);
                    149:        trace(TR_BWRITE, pack(bp->b_vp, bp->b_bcount), bp->b_lblkno);
                    150:        if (bp->b_bcount > bp->b_bufsize)
                    151:                panic("bwrite");
                    152:        s = splbio();
                    153:        bp->b_vp->v_numoutput++;
                    154:        splx(s);
                    155:        VOP_STRATEGY(bp);
                    156: 
                    157:        /*
                    158:         * If the write was synchronous, then await i/o completion.
                    159:         * If the write was "delayed", then we put the buffer on
                    160:         * the q of blocks awaiting i/o completion status.
                    161:         */
                    162:        if ((flag&B_ASYNC) == 0) {
                    163:                error = biowait(bp);
                    164:                brelse(bp);
                    165:        } else if (flag & B_DELWRI) {
                    166:                bp->b_flags |= B_AGE;
                    167:                error = 0;
                    168:        }
                    169:        return (error);
                    170: }
                    171: 
                    172: /*
                    173:  * Release the buffer, marking it so that if it is grabbed
                    174:  * for another purpose it will be written out before being
                    175:  * given up (e.g. when writing a partial block where it is
                    176:  * assumed that another write for the same block will soon follow).
                    177:  * This can't be done for magtape, since writes must be done
                    178:  * in the same order as requested.
                    179:  */
                    180: bdwrite(bp)
                    181:        register struct buf *bp;
                    182: {
                    183: 
                    184:        if ((bp->b_flags & B_DELWRI) == 0) {
                    185:                bp->b_flags |= B_DELWRI;
                    186:                reassignbuf(bp, bp->b_vp);
                    187:                u.u_ru.ru_oublock++;            /* noone paid yet */
                    188:        }
                    189:        /*
                    190:         * If this is a tape drive, the write must be initiated.
                    191:         */
                    192:        if (VOP_IOCTL(bp->b_vp, 0, B_TAPE, 0, NOCRED) == 0) {
                    193:                bawrite(bp);
                    194:        } else {
                    195:                bp->b_flags |= B_DELWRI | B_DONE;
                    196:                brelse(bp);
                    197:        }
                    198: }
                    199: 
                    200: /*
                    201:  * Release the buffer, start I/O on it, but don't wait for completion.
                    202:  */
                    203: bawrite(bp)
                    204:        register struct buf *bp;
                    205: {
                    206: 
                    207:        bp->b_flags |= B_ASYNC;
                    208:        (void) bwrite(bp);
                    209: }
                    210: 
                    211: /*
                    212:  * Release the buffer, with no I/O implied.
                    213:  */
                    214: brelse(bp)
                    215:        register struct buf *bp;
                    216: {
                    217:        register struct buf *flist;
                    218:        register s;
                    219: 
                    220:        trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno);
                    221:        /*
                    222:         * If a process is waiting for the buffer, or
                    223:         * is waiting for a free buffer, awaken it.
                    224:         */
                    225:        if (bp->b_flags&B_WANTED)
                    226:                wakeup((caddr_t)bp);
                    227:        if (bfreelist[0].b_flags&B_WANTED) {
                    228:                bfreelist[0].b_flags &= ~B_WANTED;
                    229:                wakeup((caddr_t)bfreelist);
                    230:        }
                    231:        /*
                    232:         * Retry I/O for locked buffers rather than invalidating them.
                    233:         */
                    234:        if ((bp->b_flags & B_ERROR) && (bp->b_flags & B_LOCKED))
                    235:                bp->b_flags &= ~B_ERROR;
                    236: 
                    237:        /*
                    238:         * Disassociate buffers that are no longer valid.
                    239:         */
                    240:        if (bp->b_flags & (B_NOCACHE|B_ERROR))
                    241:                bp->b_flags |= B_INVAL;
                    242:        if ((bp->b_bufsize <= 0) || (bp->b_flags & (B_ERROR|B_INVAL))) {
                    243:                if (bp->b_vp)
                    244:                        brelvp(bp);
                    245:                bp->b_flags &= ~B_DELWRI;
                    246:        }
                    247:        /*
                    248:         * Stick the buffer back on a free list.
                    249:         */
                    250:        s = splbio();
                    251:        if (bp->b_bufsize <= 0) {
                    252:                /* block has no buffer ... put at front of unused buffer list */
                    253:                flist = &bfreelist[BQ_EMPTY];
                    254:                binsheadfree(bp, flist);
                    255:        } else if (bp->b_flags & (B_ERROR|B_INVAL)) {
                    256:                /* block has no info ... put at front of most free list */
                    257:                flist = &bfreelist[BQ_AGE];
                    258:                binsheadfree(bp, flist);
                    259:        } else {
                    260:                if (bp->b_flags & B_LOCKED)
                    261:                        flist = &bfreelist[BQ_LOCKED];
                    262:                else if (bp->b_flags & B_AGE)
                    263:                        flist = &bfreelist[BQ_AGE];
                    264:                else
                    265:                        flist = &bfreelist[BQ_LRU];
                    266:                binstailfree(bp, flist);
                    267:        }
                    268:        bp->b_flags &= ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE|B_NOCACHE);
                    269:        splx(s);
                    270: }
                    271: 
                    272: /*
                    273:  * See if the block is associated with some buffer
                    274:  * (mainly to avoid getting hung up on a wait in breada)
                    275:  */
                    276: incore(vp, blkno)
                    277:        struct vnode *vp;
                    278:        daddr_t blkno;
                    279: {
                    280:        register struct buf *bp;
                    281:        register struct buf *dp;
                    282: 
                    283:        dp = BUFHASH(vp, blkno);
                    284:        for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
                    285:                if (bp->b_lblkno == blkno && bp->b_vp == vp &&
                    286:                    (bp->b_flags & B_INVAL) == 0)
                    287:                        return (1);
                    288:        return (0);
                    289: }
                    290: 
                    291: /*
                    292:  * Return a block if it is in memory.
                    293:  */
                    294: baddr(vp, blkno, size, cred, bpp)
                    295:        struct vnode *vp;
                    296:        daddr_t blkno;
                    297:        int size;
                    298:        struct ucred *cred;
                    299:        struct buf **bpp;
                    300: {
                    301: 
                    302:        if (incore(vp, blkno))
                    303:                return (bread(vp, blkno, size, cred, bpp));
                    304:        *bpp = 0;
                    305:        return (0);
                    306: }
                    307: 
                    308: /*
                    309:  * Assign a buffer for the given block.  If the appropriate
                    310:  * block is already associated, return it; otherwise search
                    311:  * for the oldest non-busy buffer and reassign it.
                    312:  *
                    313:  * We use splx here because this routine may be called
                    314:  * on the interrupt stack during a dump, and we don't
                    315:  * want to lower the ipl back to 0.
                    316:  */
                    317: struct buf *
                    318: getblk(vp, blkno, size)
                    319:        register struct vnode *vp;
                    320:        daddr_t blkno;
                    321:        int size;
                    322: {
                    323:        register struct buf *bp, *dp;
                    324:        int s;
                    325: 
                    326:        if (size > MAXBSIZE)
                    327:                panic("getblk: size too big");
                    328:        /*
                    329:         * Search the cache for the block.  If we hit, but
                    330:         * the buffer is in use for i/o, then we wait until
                    331:         * the i/o has completed.
                    332:         */
                    333:        dp = BUFHASH(vp, blkno);
                    334: loop:
                    335:        for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) {
                    336:                if (bp->b_lblkno != blkno || bp->b_vp != vp ||
                    337:                    bp->b_flags&B_INVAL)
                    338:                        continue;
                    339:                s = splbio();
                    340:                if (bp->b_flags&B_BUSY) {
                    341:                        bp->b_flags |= B_WANTED;
                    342:                        sleep((caddr_t)bp, PRIBIO+1);
                    343:                        splx(s);
                    344:                        goto loop;
                    345:                }
                    346:                bremfree(bp);
                    347:                bp->b_flags |= B_BUSY;
                    348:                splx(s);
                    349:                if (bp->b_bcount != size) {
                    350:                        printf("getblk: stray size");
                    351:                        bp->b_flags |= B_INVAL;
                    352:                        bwrite(bp);
                    353:                        goto loop;
                    354:                }
                    355:                bp->b_flags |= B_CACHE;
                    356:                return (bp);
                    357:        }
                    358:        bp = getnewbuf();
                    359:        bfree(bp);
                    360:        bremhash(bp);
                    361:        bgetvp(vp, bp);
                    362:        bp->b_lblkno = blkno;
                    363:        bp->b_blkno = blkno;
                    364:        bp->b_error = 0;
                    365:        bp->b_resid = 0;
                    366:        binshash(bp, dp);
                    367:        brealloc(bp, size);
                    368:        return (bp);
                    369: }
                    370: 
                    371: /*
                    372:  * get an empty block,
                    373:  * not assigned to any particular device
                    374:  */
                    375: struct buf *
                    376: geteblk(size)
                    377:        int size;
                    378: {
                    379:        register struct buf *bp, *flist;
                    380: 
                    381:        if (size > MAXBSIZE)
                    382:                panic("geteblk: size too big");
                    383:        bp = getnewbuf();
                    384:        bp->b_flags |= B_INVAL;
                    385:        bfree(bp);
                    386:        bremhash(bp);
                    387:        flist = &bfreelist[BQ_AGE];
                    388:        bp->b_error = 0;
                    389:        bp->b_resid = 0;
                    390:        binshash(bp, flist);
                    391:        brealloc(bp, size);
                    392:        return (bp);
                    393: }
                    394: 
                    395: /*
                    396:  * Allocate space associated with a buffer.
                    397:  */
                    398: brealloc(bp, size)
                    399:        register struct buf *bp;
                    400:        int size;
                    401: {
                    402:        daddr_t start, last;
                    403:        register struct buf *ep;
                    404:        struct buf *dp;
                    405:        int s;
                    406: 
                    407:        if (size == bp->b_bcount)
                    408:                return;
                    409:        allocbuf(bp, size);
                    410: }
                    411: 
                    412: /*
                    413:  * Find a buffer which is available for use.
                    414:  * Select something from a free list.
                    415:  * Preference is to AGE list, then LRU list.
                    416:  */
                    417: struct buf *
                    418: getnewbuf()
                    419: {
                    420:        register struct buf *bp, *dp;
                    421:        register struct ucred *cred;
                    422:        int s;
                    423: 
                    424: loop:
                    425:        s = splbio();
                    426:        for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--)
                    427:                if (dp->av_forw != dp)
                    428:                        break;
                    429:        if (dp == bfreelist) {          /* no free blocks */
                    430:                dp->b_flags |= B_WANTED;
                    431:                sleep((caddr_t)dp, PRIBIO+1);
                    432:                splx(s);
                    433:                goto loop;
                    434:        }
                    435:        bp = dp->av_forw;
                    436:        bremfree(bp);
                    437:        bp->b_flags |= B_BUSY;
                    438:        splx(s);
                    439:        if (bp->b_flags & B_DELWRI) {
                    440:                (void) bawrite(bp);
                    441:                goto loop;
                    442:        }
                    443:        trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno);
                    444:        if (bp->b_vp)
                    445:                brelvp(bp);
                    446:        if (bp->b_rcred != NOCRED) {
                    447:                cred = bp->b_rcred;
                    448:                bp->b_rcred = NOCRED;
                    449:                crfree(cred);
                    450:        }
                    451:        if (bp->b_wcred != NOCRED) {
                    452:                cred = bp->b_wcred;
                    453:                bp->b_wcred = NOCRED;
                    454:                crfree(cred);
                    455:        }
                    456:        bp->b_flags = B_BUSY;
                    457:        return (bp);
                    458: }
                    459: 
                    460: /*
                    461:  * Wait for I/O completion on the buffer; return errors
                    462:  * to the user.
                    463:  */
                    464: biowait(bp)
                    465:        register struct buf *bp;
                    466: {
                    467:        int s;
                    468: 
                    469:        s = splbio();
                    470:        while ((bp->b_flags & B_DONE) == 0)
                    471:                sleep((caddr_t)bp, PRIBIO);
                    472:        splx(s);
                    473:        /*
                    474:         * Pick up the device's error number and pass it to the user;
                    475:         * if there is an error but the number is 0 set a generalized code.
                    476:         */
                    477:        if ((bp->b_flags & B_ERROR) == 0)
                    478:                return (0);
                    479:        if (bp->b_error)
                    480:                return (bp->b_error);
                    481:        return (EIO);
                    482: }
                    483: 
                    484: /*
                    485:  * Mark I/O complete on a buffer.
                    486:  * If someone should be called, e.g. the pageout
                    487:  * daemon, do so.  Otherwise, wake up anyone
                    488:  * waiting for it.
                    489:  */
                    490: biodone(bp)
                    491:        register struct buf *bp;
                    492: {
                    493:        register struct vnode *vp;
                    494: 
                    495:        if (bp->b_flags & B_DONE)
                    496:                panic("dup biodone");
                    497:        bp->b_flags |= B_DONE;
                    498:        if ((bp->b_flags & B_READ) == 0) {
                    499:                bp->b_dirtyoff = bp->b_dirtyend = 0;
                    500:                if (vp = bp->b_vp) {
                    501:                        vp->v_numoutput--;
                    502:                        if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
                    503:                                if (vp->v_numoutput < 0)
                    504:                                        panic("biodone: neg numoutput");
                    505:                                vp->v_flag &= ~VBWAIT;
                    506:                                wakeup((caddr_t)&vp->v_numoutput);
                    507:                        }
                    508:                }
                    509:        }
                    510:        if (bp->b_flags & B_CALL) {
                    511:                bp->b_flags &= ~B_CALL;
                    512:                (*bp->b_iodone)(bp);
                    513:                return;
                    514:        }
                    515:        if (bp->b_flags&B_ASYNC)
                    516:                brelse(bp);
                    517:        else {
                    518:                bp->b_flags &= ~B_WANTED;
                    519:                wakeup((caddr_t)bp);
                    520:        }
                    521: }
                    522: 
                    523: /*
                    524:  * Make sure all write-behind blocks associated
                    525:  * with mount point are flushed out (from sync).
                    526:  */
                    527: mntflushbuf(mountp, flags)
                    528:        struct mount *mountp;
                    529:        int flags;
                    530: {
                    531:        register struct vnode *vp;
                    532: 
                    533:        if ((mountp->mnt_flag & MNT_MPBUSY) == 0)
                    534:                panic("mntflushbuf: not busy");
                    535: loop:
                    536:        for (vp = mountp->mnt_mounth; vp; vp = vp->v_mountf) {
                    537:                if (vget(vp))
                    538:                        goto loop;
                    539:                vflushbuf(vp, flags);
                    540:                vput(vp);
                    541:                if (vp->v_mount != mountp)
                    542:                        goto loop;
                    543:        }
                    544: }
                    545: 
                    546: /*
                    547:  * Flush all dirty buffers associated with a vnode.
                    548:  */
                    549: vflushbuf(vp, flags)
                    550:        register struct vnode *vp;
                    551:        int flags;
                    552: {
                    553:        register struct buf *bp;
                    554:        struct buf *nbp;
                    555:        int s;
                    556: 
                    557: loop:
                    558:        s = splbio();
                    559:        for (bp = vp->v_dirtyblkhd; bp; bp = nbp) {
                    560:                nbp = bp->b_blockf;
                    561:                if ((bp->b_flags & B_BUSY))
                    562:                        continue;
                    563:                if ((bp->b_flags & B_DELWRI) == 0)
                    564:                        panic("vflushbuf: not dirty");
                    565:                bremfree(bp);
                    566:                bp->b_flags |= B_BUSY;
                    567:                splx(s);
                    568:                /*
                    569:                 * Wait for I/O associated with indirect blocks to complete,
                    570:                 * since there is no way to quickly wait for them below.
                    571:                 * NB - This is really specific to ufs, but is done here
                    572:                 * as it is easier and quicker.
                    573:                 */
                    574:                if (bp->b_vp == vp || (flags & B_SYNC) == 0) {
                    575:                        (void) bawrite(bp);
                    576:                        s = splbio();
                    577:                } else {
                    578:                        (void) bwrite(bp);
                    579:                        goto loop;
                    580:                }
                    581:        }
                    582:        splx(s);
                    583:        if ((flags & B_SYNC) == 0)
                    584:                return;
                    585:        s = splbio();
                    586:        while (vp->v_numoutput) {
                    587:                vp->v_flag |= VBWAIT;
                    588:                sleep((caddr_t)&vp->v_numoutput, PRIBIO+1);
                    589:        }
                    590:        splx(s);
                    591:        if (vp->v_dirtyblkhd) {
                    592:                vprint("vflushbuf: dirty", vp);
                    593:                goto loop;
                    594:        }
                    595: }
                    596: 
                    597: /*
                    598:  * Invalidate in core blocks belonging to closed or umounted filesystem
                    599:  *
                    600:  * Go through the list of vnodes associated with the file system;
                    601:  * for each vnode invalidate any buffers that it holds. Normally
                    602:  * this routine is preceeded by a bflush call, so that on a quiescent
                    603:  * filesystem there will be no dirty buffers when we are done. Binval
                    604:  * returns the count of dirty buffers when it is finished.
                    605:  */
                    606: mntinvalbuf(mountp)
                    607:        struct mount *mountp;
                    608: {
                    609:        register struct vnode *vp;
                    610:        int dirty = 0;
                    611: 
                    612:        if ((mountp->mnt_flag & MNT_MPBUSY) == 0)
                    613:                panic("mntinvalbuf: not busy");
                    614: loop:
                    615:        for (vp = mountp->mnt_mounth; vp; vp = vp->v_mountf) {
                    616:                if (vget(vp))
                    617:                        goto loop;
                    618:                dirty += vinvalbuf(vp, 1);
                    619:                vput(vp);
                    620:                if (vp->v_mount != mountp)
                    621:                        goto loop;
                    622:        }
                    623:        return (dirty);
                    624: }
                    625: 
                    626: /*
                    627:  * Flush out and invalidate all buffers associated with a vnode.
                    628:  * Called with the underlying object locked.
                    629:  */
                    630: vinvalbuf(vp, save)
                    631:        register struct vnode *vp;
                    632:        int save;
                    633: {
                    634:        register struct buf *bp;
                    635:        struct buf *nbp, *blist;
                    636:        int s, dirty = 0;
                    637: 
                    638:        for (;;) {
                    639:                if (blist = vp->v_dirtyblkhd)
                    640:                        /* void */;
                    641:                else if (blist = vp->v_cleanblkhd)
                    642:                        /* void */;
                    643:                else
                    644:                        break;
                    645:                for (bp = blist; bp; bp = nbp) {
                    646:                        nbp = bp->b_blockf;
                    647:                        s = splbio();
                    648:                        if (bp->b_flags & B_BUSY) {
                    649:                                bp->b_flags |= B_WANTED;
                    650:                                sleep((caddr_t)bp, PRIBIO+1);
                    651:                                splx(s);
                    652:                                break;
                    653:                        }
                    654:                        bremfree(bp);
                    655:                        bp->b_flags |= B_BUSY;
                    656:                        splx(s);
                    657:                        if (save && (bp->b_flags & B_DELWRI)) {
                    658:                                dirty++;
                    659:                                (void) bwrite(bp);
                    660:                                break;
                    661:                        }
                    662:                        if (bp->b_vp != vp)
                    663:                                reassignbuf(bp, bp->b_vp);
                    664:                        else
                    665:                                bp->b_flags |= B_INVAL;
                    666:                        brelse(bp);
                    667:                }
                    668:        }
                    669:        if (vp->v_dirtyblkhd || vp->v_cleanblkhd)
                    670:                panic("vinvalbuf: flush failed");
                    671:        return (dirty);
                    672: }
                    673: 
                    674: /*
                    675:  * Associate a buffer with a vnode.
                    676:  */
                    677: bgetvp(vp, bp)
                    678:        register struct vnode *vp;
                    679:        register struct buf *bp;
                    680: {
                    681: 
                    682:        if (bp->b_vp)
                    683:                panic("bgetvp: not free");
                    684:        VHOLD(vp);
                    685:        bp->b_vp = vp;
                    686:        if (vp->v_type == VBLK || vp->v_type == VCHR)
                    687:                bp->b_dev = vp->v_rdev;
                    688:        else
                    689:                bp->b_dev = NODEV;
                    690:        /*
                    691:         * Insert onto list for new vnode.
                    692:         */
                    693:        if (vp->v_cleanblkhd) {
                    694:                bp->b_blockf = vp->v_cleanblkhd;
                    695:                bp->b_blockb = &vp->v_cleanblkhd;
                    696:                vp->v_cleanblkhd->b_blockb = &bp->b_blockf;
                    697:                vp->v_cleanblkhd = bp;
                    698:        } else {
                    699:                vp->v_cleanblkhd = bp;
                    700:                bp->b_blockb = &vp->v_cleanblkhd;
                    701:                bp->b_blockf = NULL;
                    702:        }
                    703: }
                    704: 
                    705: /*
                    706:  * Disassociate a buffer from a vnode.
                    707:  */
                    708: brelvp(bp)
                    709:        register struct buf *bp;
                    710: {
                    711:        struct buf *bq;
                    712:        struct vnode *vp;
                    713: 
                    714:        if (bp->b_vp == (struct vnode *) 0)
                    715:                panic("brelvp: NULL");
                    716:        /*
                    717:         * Delete from old vnode list, if on one.
                    718:         */
                    719:        if (bp->b_blockb) {
                    720:                if (bq = bp->b_blockf)
                    721:                        bq->b_blockb = bp->b_blockb;
                    722:                *bp->b_blockb = bq;
                    723:                bp->b_blockf = NULL;
                    724:                bp->b_blockb = NULL;
                    725:        }
                    726:        vp = bp->b_vp;
                    727:        bp->b_vp = (struct vnode *) 0;
                    728:        HOLDRELE(vp);
                    729: }
                    730: 
                    731: /*
                    732:  * Reassign a buffer from one vnode to another.
                    733:  * Used to assign file specific control information
                    734:  * (indirect blocks) to the vnode to which they belong.
                    735:  */
                    736: reassignbuf(bp, newvp)
                    737:        register struct buf *bp;
                    738:        register struct vnode *newvp;
                    739: {
                    740:        register struct buf *bq, **listheadp;
                    741: 
                    742:        if (newvp == NULL)
                    743:                panic("reassignbuf: NULL");
                    744:        /*
                    745:         * Delete from old vnode list, if on one.
                    746:         */
                    747:        if (bp->b_blockb) {
                    748:                if (bq = bp->b_blockf)
                    749:                        bq->b_blockb = bp->b_blockb;
                    750:                *bp->b_blockb = bq;
                    751:        }
                    752:        /*
                    753:         * If dirty, put on list of dirty buffers;
                    754:         * otherwise insert onto list of clean buffers.
                    755:         */
                    756:        if (bp->b_flags & B_DELWRI)
                    757:                listheadp = &newvp->v_dirtyblkhd;
                    758:        else
                    759:                listheadp = &newvp->v_cleanblkhd;
                    760:        if (*listheadp) {
                    761:                bp->b_blockf = *listheadp;
                    762:                bp->b_blockb = listheadp;
                    763:                bp->b_blockf->b_blockb = &bp->b_blockf;
                    764:                *listheadp = bp;
                    765:        } else {
                    766:                *listheadp = bp;
                    767:                bp->b_blockb = listheadp;
                    768:                bp->b_blockf = NULL;
                    769:        }
                    770: }

unix.superglobalmegacorp.com

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