Annotation of 43BSDReno/sys/kern/vfs_bio.c, revision 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.